home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2006 December
/
PCWorld_2006-12_cd.bin
/
komunikace
/
netscape
/
nsb-install-8-1-2.exe
/
components
/
nsHelperAppDlg.js
< prev
next >
Wrap
Text File
|
2006-01-06
|
36KB
|
935 lines
/*
*/
/* This file implements the nsIHelperAppLauncherDialog interface.
*
* The implementation consists of a JavaScript "class" named nsUnknownContentTypeDialog,
* comprised of:
* - a JS constructor function
* - a prototype providing all the interface methods and implementation stuff
*
* In addition, this file implements an nsIModule object that registers the
* nsUnknownContentTypeDialog component.
*/
/* ctor
*/
function nsUnknownContentTypeDialog() {
// Initialize data properties.
this.mLauncher = null;
this.mContext = null;
this.mSourcePath = null;
this.chosenApp = null;
this.givenDefaultApp = false;
this.updateSelf = true;
this.mTitle = "";
}
nsUnknownContentTypeDialog.prototype = {
nsIMIMEInfo : Components.interfaces.nsIMIMEInfo,
// This "class" supports nsIHelperAppLauncherDialog, and nsISupports.
QueryInterface: function (iid) {
if (!iid.equals(Components.interfaces.nsIHelperAppLauncherDialog) &&
!iid.equals(Components.interfaces.nsIHelperAppLauncherDialogExtension) &&
!iid.equals(Components.interfaces.nsISupports)) {
throw Components.results.NS_ERROR_NO_INTERFACE;
}
return this;
},
// ---------- nsIHelperAppLauncherDialog methods ----------
// show: Open XUL dialog using window watcher. Since the dialog is not
// modal, it needs to be a top level window and the way to open
// one of those is via that route).
show: function(aLauncher, aContext) {
this.mLauncher = aLauncher;
this.mContext = aContext;
// Display the dialog using the Window Watcher interface.
var ir = aContext.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
var dwi = ir.getInterface(Components.interfaces.nsIDOMWindowInternal);
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
this.mDialog = ww.openWindow(dwi,
"chrome://mozapps/content/downloads/unknownContentType.xul",
null,
"chrome,centerscreen,titlebar,dialog=yes,dependent",
null);
// Hook this object to the dialog.
this.mDialog.dialog = this;
// Hook up utility functions.
this.getSpecialFolderKey = this.mDialog.getSpecialFolderKey;
// Watch for error notifications.
this.progressListener.helperAppDlg = this;
this.mLauncher.setWebProgressListener(this.progressListener);
},
// promptForSaveToFile: Display file picker dialog and return selected file.
// This is called by the External Helper App Service
// after the ucth dialog calls |saveToDisk| with a null
// target filename (no target, therefore user must pick).
//
// Alternatively, if the user has selected to have all
// files download to a specific location, return that
// location and don't ask via the dialog.
//
// Note - this function is called without a dialog, so it cannot access any part
// of the dialog XUL as other functions on this object do.
promptForSaveToFile: function(aLauncher, aContext, aDefaultFile, aSuggestedFileExtension) {
var result = "";
this.mLauncher = aLauncher;
// If the user is always downloading to the same location, the default download
// folder is stored in preferences. If a value is found stored, use that
// automatically and don't ask via a dialog.
const kDownloadFolderPref = "browser.download.defaultFolder";
var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
try {
result = prefs.getComplexValue(kDownloadFolderPref, Components.interfaces.nsILocalFile);
result = this.validateLeafName(result, aDefaultFile, aSuggestedFileExtension);
}
catch (e) {
// If we get here, it's because we have a new profile and the user has never configured download
// options, so "browser.download.defaultFolder" is not set yet. If the default is autodownload,
// we need to discover the default save location.
var autodownload = prefs.getBoolPref("browser.download.useDownloadDir");
if (autodownload) {
function getSpecialFolderKey(aFolderType)
{
return aFolderType == "Desktop" ? "DeskP" : "Pers";
return "Home";
}
function getDownloadsFolder(aFolder)
{
var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
var dir = fileLocator.get(getSpecialFolderKey(aFolder), Components.interfaces.nsILocalFile);
var bundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
bundle = bundle.createBundle("chrome://mozapps/locale/downloads/unknownContentType.properties");
var description = bundle.GetStringFromName("myDownloads");
if (aFolder != "Desktop")
dir.append(description);
return dir;
}
var defaultFolder = null;
switch (prefs.getIntPref("browser.download.folderList")) {
case 0:
defaultFolder = getDownloadsFolder("Desktop")
break;
case 1:
defaultFolder = getDownloadsFolder("Downloads");
break;
case 2:
defaultFolder = prefs.getComplexValue("browser.download.dir", Components.interfaces.nsILocalFile);
break;
}
// While we're here, set the pref too so that we don't keep coming back into this less efficient
// code block.
prefs.setComplexValue("browser.download.defaultFolder", Components.interfaces.nsILocalFile, defaultFolder);
result = this.validateLeafName(defaultFolder, aDefaultFile, aSuggestedFileExtension);
}
}
if (!result) {
// Use file picker to show dialog.
var nsIFilePicker = Components.interfaces.nsIFilePicker;
var picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
var bundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
bundle = bundle.createBundle("chrome://mozapps/locale/downloads/unknownContentType.properties");
var windowTitle = bundle.GetStringFromName("saveDialogTitle");
var parent = aContext.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowInternal);
picker.init(parent, windowTitle, nsIFilePicker.modeSave);
picker.defaultString = aDefaultFile;
if (aSuggestedFileExtension) {
// aSuggestedFileExtension includes the period, so strip it
picker.defaultExtension = aSuggestedFileExtension.substring(1);
}
else {
try {
picker.defaultExtension = this.mLauncher.MIMEInfo.primaryExtension;
}
catch (ex) { }
}
var wildCardExtension = "*";
if (aSuggestedFileExtension) {
wildCardExtension += aSuggestedFileExtension;
picker.appendFilter(this.mLauncher.MIMEInfo.Description, wildCardExtension);
}
picker.appendFilters( nsIFilePicker.filterAll );
// Pull in the user's preferences and get the default download directory.
var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
try {
var startDir = prefs.getComplexValue("browser.download.dir", Components.interfaces.nsILocalFile);
if (startDir.exists()) {
picker.displayDirectory = startDir;
}
}
catch(exception) { }
var dlgResult = picker.show();
if (dlgResult == nsIFilePicker.returnCancel) {
// null result means user cancelled.
return null;
}
// Be sure to save the directory the user chose through the Save As...
// dialog as the new browser.download.dir
result = picker.file;
if (result) {
var newDir = result.parent;
prefs.setComplexValue("browser.download.dir", Components.interfaces.nsILocalFile, newDir);
}
}
return result;
},
validateLeafName: function (aLocalFile, aLeafName, aFileExt)
{
if (aLeafName == "")
aLeafName = "unnamed" + (aFileExt ? "." + aFileExt : "");
aLocalFile.append(aLeafName);
this.makeFileUnique(aLocalFile);
if (aLocalFile.isExecutable() && !this.mLauncher.targetFile.isExecutable()) {
var f = aLocalFile.clone();
aLocalFile.leafName = aLocalFile.leafName + "." + this.mLauncher.MIMEInfo.primaryExtension;
f.remove(false);
this.makeFileUnique(aLocalFile);
}
return aLocalFile;
},
makeFileUnique: function (aLocalFile)
{
try {
// Since we're automatically downloading, we don't get the file picker's
// logic to check for existing files, so we need to do that here.
//
// Note - this code is identical to that in
// browser/base/content/contentAreaUtils.js.
// If you are updating this code, update that code too! We can't share code
// here since this is called in a js component.
while (aLocalFile.exists()) {
var parts = /.+-(\d+)(\..*)?$/.exec(aLocalFile.leafName);
if (parts) {
aLocalFile.leafName = aLocalFile.leafName.replace(/((\d+)\.)|((\d+)$)/,
function (str, dot, dotNum, noDot, noDotNum, pos, s) {
return (parseInt(str) + 1) + (dot ? "." : "");
});
}
else {
aLocalFile.leafName = aLocalFile.leafName.replace(/\.|$/, "-1$&");
}
}
aLocalFile.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0600);
}
catch (e) {
dump("*** exception in validateLeafName: " + e + "\n");
if (aLocalFile.leafName == "" || aLocalFile.isDirectory()) {
aLocalFile.append("unnamed");
if (aLocalFile.exists())
aLocalFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0600);
}
}
},
// ---------- nsIHelperAppLauncherDialog methods ----------
// MERC: AAM (BLT 196088 and 196516)
// abort - allow the dialog to be aborted and closed
// This is important for spyware file download processing. If the file
// is detected as spyware and the file is then deleted, we have to force
// this dialog to be closed.
abort : function() {
this.onCancel();
if ( this.mDialog ) {
this.mDialog.close();
}
},
// ---------- implementation methods ----------
// Web progress listener so we can detect errors while mLauncher is
// streaming the data to a temporary file.
progressListener: {
// Implementation properties.
NS_ERROR_FILE_SPYWARE_DETECTED : 0x80520016,
helperAppDlg: null,
// nsIWebProgressListener methods.
// Look for error notifications and display alert to user.
onStatusChange: function( aWebProgress, aRequest, aStatus, aMessage ) {
if ( (aStatus != Components.results.NS_OK) && (aStatus != this.NS_ERROR_FILE_SPYWARE_DETECTED) ) {
// Get prompt service.
var prompter = Components.classes[ "@mozilla.org/embedcomp/prompt-service;1" ]
.getService( Components.interfaces.nsIPromptService );
// Display error alert (using text supplied by back-end).
prompter.alert( this.dialog, this.helperAppDlg.mTitle, aMessage );
// Close the dialog.
this.helperAppDlg.onCancel();
if ( this.helperAppDlg.mDialog ) {
this.helperAppDlg.mDialog.close();
}
}
},
// Ignore onProgressChange, onStateChange, onLocationChange, and onSecurityChange notifications.
onProgressChange: function( aWebProgress,
aRequest,
aCurSelfProgress,
aMaxSelfProgress,
aCurTotalProgress,
aMaxTotalProgress ) {
},
onStateChange: function( aWebProgress, aRequest, aStateFlags, aStatus ) {
},
onLocationChange: function( aWebProgress, aRequest, aLocation ) {
},
onSecurityChange: function( aWebProgress, aRequest, state ) {
}
},
// initDialog: Fill various dialog fields with initial content.
initDialog : function() {
// Put file name in window title.
var win = this.dialogElement( "unknownContentType" );
var suggestedFileName = this.mLauncher.suggestedFileName;
// Some URIs do not implement nsIURL, so we can't just QI.
var url = this.mLauncher.source;
var fname = "";
this.mSourcePath = url.prePath;
try {
url = url.QueryInterface( Components.interfaces.nsIURL );
// A url, use file name from it.
fname = url.fileName;
this.mSourcePath += url.directory;
} catch (ex) {
// A generic uri, use path.
fname = url.path;
this.mSourcePath += url.path;
}
if (suggestedFileName)
fname = suggestedFileName;
var displayName = fname.replace(/ +/g, " ");
this.mTitle = this.dialogElement("strings").getFormattedString("title", [displayName]);
win.setAttribute( "title", this.mTitle );
// Put content type, filename and location into intro.
this.initIntro(url, fname, displayName);
var iconString = "moz-icon://" + fname + "?size=16&contentType=" + this.mLauncher.MIMEInfo.MIMEType;
this.dialogElement("contentTypeImage").setAttribute("src", iconString);
this.initAppAndSaveToDiskValues();
// Initialize "always ask me" box. This should always be disabled
// and set to true for the ambiguous type application/octet-stream.
// We don't also check for application/x-msdownload here since we
// want users to be able to autodownload .exe files.
var rememberChoice = this.dialogElement("rememberChoice");
var mimeType = this.mLauncher.MIMEInfo.MIMEType;
if (mimeType == "application/octet-stream" ||
mimeType == "application/x-msdownload" ||
this.mLauncher.targetFile.isExecutable()) {
rememberChoice.checked = false;
rememberChoice.disabled = true;
}
else {
rememberChoice.checked = !this.mLauncher.MIMEInfo.alwaysAskBeforeHandling;
}
this.toggleRememberChoice(rememberChoice);
// XXXben - menulist won't init properly, hack.
var openHandler = this.dialogElement("openHandler");
openHandler.parentNode.removeChild(openHandler);
var openHandlerBox = this.dialogElement("openHandlerBox");
openHandlerBox.appendChild(openHandler);
this.mDialog.setTimeout("dialog.postShowCallback()", 0);
this.mDialog.document.documentElement.getButton("accept").disabled = true;
const nsITimer = Components.interfaces.nsITimer;
this._timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(nsITimer);
this._timer.initWithCallback(this, 250, nsITimer.TYPE_ONE_SHOT);
},
_timer: null,
notify: function (aTimer) {
if (!this._blurred)
this.mDialog.document.documentElement.getButton('accept').disabled = false;
this._delayExpired = true;
},
postShowCallback: function () {
this.mDialog.sizeToContent();
// Set initial focus
this.dialogElement("mode").focus();
},
// initIntro:
initIntro: function(url, filename, displayname) {
this.dialogElement( "location" ).value = displayname;
this.dialogElement( "location" ).setAttribute("realname", filename);
this.dialogElement( "location" ).setAttribute("tooltiptext", displayname);
// if mSourcePath is a local file, then let's use the pretty path name instead of an ugly
// url...
var pathString = this.mSourcePath;
try
{
var fileURL = url.QueryInterface(Components.interfaces.nsIFileURL);
if (fileURL)
{
var fileObject = fileURL.file;
if (fileObject)
{
var parentObject = fileObject.parent;
if (parentObject)
{
pathString = parentObject.path;
}
}
}
} catch(ex) {}
if (pathString == this.mSourcePath)
{
// wasn't a fileURL
var tmpurl = url.clone(); // don't want to change the real url
tmpurl.userPass = "";
pathString = tmpurl.prePath;
}
// Set the location text, which is separate from the intro text so it can be cropped
var location = this.dialogElement( "source" );
location.value = pathString;
location.setAttribute("tooltiptext", this.mSourcePath);
// Show the type of file.
var type = this.dialogElement("type");
var mimeInfo = this.mLauncher.MIMEInfo;
// 1. Try to use the pretty description of the type, if one is available.
var typeString = mimeInfo.Description;
if (typeString == "") {
// 2. If there is none, use the extension to identify the file, e.g. "ZIP file"
var primaryExtension = "";
try {
primaryExtension = mimeInfo.primaryExtension;
}
catch (ex) {
}
if (primaryExtension != "")
typeString = primaryExtension.toUpperCase() + " file";
// 3. If we can't even do that, just give up and show the MIME type.
else
typeString = mimeInfo.MIMEType;
}
type.value = typeString;
},
_blurred: false,
_delayExpired: false,
onBlur: function(aEvent) {
if (aEvent.target != this.mDialog.document)
return;
this._blurred = true;
this.mDialog.document.documentElement.getButton("accept").disabled = true;
},
onFocus: function(aEvent) {
if (aEvent.target != this.mDialog.document)
return;
this._blurred = false;
if (this._delayExpired) {
var script = "document.documentElement.getButton('accept').disabled = false";
this.mDialog.setTimeout(script, 250);
}
},
// Returns true if opening the default application makes sense.
openWithDefaultOK: function() {
var result;
// The checking is different on Windows...
// Windows presents some special cases.
// We need to prevent use of "system default" when the file is
// executable (so the user doesn't launch nasty programs downloaded
// from the web), and, enable use of "system default" if it isn't
// executable (because we will prompt the user for the default app
// in that case).
// Need to get temporary file and check for executable-ness.
var tmpFile = this.mLauncher.targetFile;
// Default is Ok if the file isn't executable (and vice-versa).
return !tmpFile.isExecutable();
},
// Set "default" application description field.
initDefaultApp: function() {
// Use description, if we can get one.
var desc = this.mLauncher.MIMEInfo.defaultDescription;
if (desc) {
var defaultApp = this.dialogElement("strings").getFormattedString("defaultApp", [desc]);
this.dialogElement("defaultHandler").label = defaultApp;
}
else {
this.dialogElement("modeDeck").setAttribute("selectedIndex", "1");
// Hide the default handler item too, in case the user picks a
// custom handler at a later date which triggers the menulist to show.
this.dialogElement("defaultHandler").hidden = true;
}
},
// getPath:
getPath: function (aFile) {
return aFile.path;
},
// initAppAndSaveToDiskValues:
initAppAndSaveToDiskValues: function() {
var modeGroup = this.dialogElement("mode");
// We don't let users open .exe files or random binary data directly
// from the browser at the moment because of security concerns.
var openWithDefaultOK = this.openWithDefaultOK();
var mimeType = this.mLauncher.MIMEInfo.MIMEType;
if (this.mLauncher.targetFile.isExecutable() || (
(mimeType == "application/octet-stream" ||
mimeType == "application/x-msdownload") &&
!openWithDefaultOK)) {
this.dialogElement("open").disabled = true;
var openHandler = this.dialogElement("openHandler");
openHandler.disabled = true;
openHandler.label = "";
modeGroup.selectedItem = this.dialogElement("save");
return;
}
// Fill in helper app info, if there is any.
this.chosenApp = this.mLauncher.MIMEInfo.preferredApplicationHandler;
// Initialize "default application" field.
this.initDefaultApp();
var otherHandler = this.dialogElement("otherHandler");
// Fill application name textbox.
if (this.chosenApp && this.chosenApp.path) {
otherHandler.setAttribute("path", this.getPath(this.chosenApp));
otherHandler.label = this.chosenApp.leafName;
otherHandler.hidden = false;
}
var useDefault = this.dialogElement("useSystemDefault");
var openHandler = this.dialogElement("openHandler");
openHandler.selectedIndex = 0;
if (this.mLauncher.MIMEInfo.preferredAction == this.nsIMIMEInfo.useSystemDefault) {
// Open (using system default).
modeGroup.selectedItem = this.dialogElement("open");
} else if (this.mLauncher.MIMEInfo.preferredAction == this.nsIMIMEInfo.useHelperApp) {
// Open with given helper app.
modeGroup.selectedItem = this.dialogElement("open");
openHandler.selectedIndex = 1;
} else {
// Save to disk.
modeGroup.selectedItem = this.dialogElement("save");
}
// If we don't have a "default app" then disable that choice.
if (!openWithDefaultOK) {
var useDefault = this.dialogElement("defaultHandler");
var isSelected = useDefault.selected;
// Disable that choice.
useDefault.hidden = true;
// If that's the default, then switch to "save to disk."
if (isSelected) {
openHandler.selectedIndex = 1;
modeGroup.selectedItem = this.dialogElement("save");
}
}
// otherHandler is always disabled on Mac
otherHandler.nextSibling.hidden = otherHandler.nextSibling.nextSibling.hidden = false;
this.updateOKButton();
},
// Returns the user-selected application
helperAppChoice: function() {
return this.chosenApp;
},
get saveToDisk() {
return this.dialogElement("save").selected;
},
get useOtherHandler() {
return this.dialogElement("open").selected && this.dialogElement("openHandler").selectedIndex == 1;
},
get useSystemDefault() {
return this.dialogElement("open").selected && this.dialogElement("openHandler").selectedIndex == 0;
},
toggleRememberChoice: function (aCheckbox) {
this.dialogElement("settingsChange").hidden = !aCheckbox.checked;
this.mDialog.sizeToContent();
},
openHandlerCommand: function () {
var openHandler = this.dialogElement("openHandler");
if (openHandler.selectedItem.id == "choose")
this.chooseApp();
else
openHandler.setAttribute("lastSelectedItemID", openHandler.selectedItem.id);
},
updateOKButton: function() {
var ok = false;
if (this.dialogElement("save").selected) {
// This is always OK.
ok = true;
}
else if (this.dialogElement("open").selected) {
switch (this.dialogElement("openHandler").selectedIndex) {
case 0:
// No app need be specified in this case.
ok = true;
break;
case 1:
// only enable the OK button if we have a default app to use or if
// the user chose an app....
ok = this.chosenApp || /\S/.test(this.dialogElement("otherHandler").getAttribute("path"));
break;
}
}
// Enable Ok button if ok to press.
this.mDialog.document.documentElement.getButton("accept").disabled = !ok;
},
// Returns true iff the user-specified helper app has been modified.
appChanged: function() {
return this.helperAppChoice() != this.mLauncher.MIMEInfo.preferredApplicationHandler;
},
updateMIMEInfo: function() {
var needUpdate = false;
// If current selection differs from what's in the mime info object,
// then we need to update.
if (this.saveToDisk) {
needUpdate = this.mLauncher.MIMEInfo.preferredAction != this.nsIMIMEInfo.saveToDisk;
if (needUpdate)
this.mLauncher.MIMEInfo.preferredAction = this.nsIMIMEInfo.saveToDisk;
}
else if (this.useSystemDefault) {
needUpdate = this.mLauncher.MIMEInfo.preferredAction != this.nsIMIMEInfo.useSystemDefault;
if (needUpdate)
this.mLauncher.MIMEInfo.preferredAction = this.nsIMIMEInfo.useSystemDefault;
}
else {
// For "open with", we need to check both preferred action and whether the user chose
// a new app.
needUpdate = this.mLauncher.MIMEInfo.preferredAction != this.nsIMIMEInfo.useHelperApp || this.appChanged();
if (needUpdate) {
this.mLauncher.MIMEInfo.preferredAction = this.nsIMIMEInfo.useHelperApp;
// App may have changed - Update application and description
var app = this.helperAppChoice();
this.mLauncher.MIMEInfo.preferredApplicationHandler = app;
this.mLauncher.MIMEInfo.applicationDescription = "";
}
}
// We will also need to update if the "always ask" flag has changed.
needUpdate = needUpdate || this.mLauncher.MIMEInfo.alwaysAskBeforeHandling != (!this.dialogElement("rememberChoice").checked);
// One last special case: If the input "always ask" flag was false, then we always
// update. In that case we are displaying the helper app dialog for the first
// time for this mime type and we need to store the user's action in the mimeTypes.rdf
// data source (whether that action has changed or not; if it didn't change, then we need
// to store the "always ask" flag so the helper app dialog will or won't display
// next time, per the user's selection).
needUpdate = needUpdate || !this.mLauncher.MIMEInfo.alwaysAskBeforeHandling;
// Make sure mime info has updated setting for the "always ask" flag.
this.mLauncher.MIMEInfo.alwaysAskBeforeHandling = !this.dialogElement("rememberChoice").checked;
return needUpdate;
},
// See if the user changed things, and if so, update the
// mimeTypes.rdf entry for this mime type.
updateHelperAppPref: function() {
var ha = new this.mDialog.HelperApps();
ha.updateTypeInfo(this.mLauncher.MIMEInfo);
},
// onOK:
onOK: function() {
// Verify typed app path, if necessary.
if (this.useOtherHandler) {
var helperApp = this.helperAppChoice();
if (!helperApp || !helperApp.exists()) {
// Show alert and try again.
var bundle = this.dialogElement("strings");
var msg = bundle.getFormattedString("badApp", [this.dialogElement("otherHandler").path]);
var svc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
svc.alert(this.mDialog, bundle.getString("badApp.title"), msg);
// Disable the OK button.
this.mDialog.document.documentElement.getButton("accept").disabled = true;
this.dialogElement("mode").focus();
// Clear chosen application.
this.chosenApp = null;
// Leave dialog up.
return false;
}
}
// Remove our web progress listener (a progress dialog will be
// taking over).
this.mLauncher.setWebProgressListener(null);
// saveToDisk and launchWithApplication can return errors in
// certain circumstances (e.g. The user clicks cancel in the
// "Save to Disk" dialog. In those cases, we don't want to
// update the helper application preferences in the RDF file.
try {
var needUpdate = this.updateMIMEInfo();
if (this.dialogElement("save").selected) {
// If we're using a default download location, create a path
// for the file to be saved to to pass to |saveToDisk| - otherwise
// we must ask the user to pick a save name.
this.mLauncher.saveToDisk(null, false);
}
else
{
//Merc BH: fix for blt#202269: When opening a Word file through the browser, it opens beneath the browser instead of giving it top focus
//this changes the app lauch context to the parent window to prevent the parent from taking focus when the dialog
//closes after the app launches. This isn't just for Word files but for any file opened in an external app
this.mDialog.opener.setTimeout(function(lnchr){lnchr.launchWithApplication(null, false);},0,this.mLauncher);
}
// Update user pref for this mime type (if necessary). We do not
// store anything in the mime type preferences for the ambiguous
// type application/octet-stream. We do NOT do this for
// application/x-msdownload since we want users to be able to
// autodownload these to disk.
if (needUpdate && this.mLauncher.MIMEInfo.MIMEType != "application/octet-stream")
this.updateHelperAppPref();
} catch(e) { }
// Unhook dialog from this object.
this.mDialog.dialog = null;
// Close up dialog by returning true.
return true;
},
// onCancel:
onCancel: function() {
// Remove our web progress listener.
this.mLauncher.setWebProgressListener(null);
// Cancel app launcher.
try {
this.mLauncher.Cancel();
} catch(exception) {
}
// Unhook dialog from this object.
this.mDialog.dialog = null;
// Close up dialog by returning true.
return true;
},
// dialogElement: Convenience.
dialogElement: function(id) {
return this.mDialog.document.getElementById(id);
},
// chooseApp: Open file picker and prompt user for application.
chooseApp: function() {
var nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
fp.init(this.mDialog,
this.dialogElement("strings").getString("chooseAppFilePickerTitle"),
nsIFilePicker.modeOpen);
fp.appendFilters(nsIFilePicker.filterApps);
if (fp.show() == nsIFilePicker.returnOK && fp.file) {
// Show the "handler" menulist since we have a (user-specified)
// application now.
this.dialogElement("modeDeck").setAttribute("selectedIndex", "0");
// Remember the file they chose to run.
this.chosenApp = fp.file;
// Update dialog.
var otherHandler = this.dialogElement("otherHandler");
otherHandler.removeAttribute("hidden");
otherHandler.setAttribute("path", this.getPath(this.chosenApp));
otherHandler.label = this.chosenApp.leafName;
this.dialogElement("openHandler").selectedIndex = 1;
this.dialogElement("openHandler").setAttribute("lastSelectedItemID", "otherHandler");
this.dialogElement("mode").selectedItem = this.dialogElement("open");
}
else {
var openHandler = this.dialogElement("openHandler");
var lastSelectedID = openHandler.getAttribute("lastSelectedItemID");
if (!lastSelectedID)
lastSelectedID = "defaultHandler";
openHandler.selectedItem = this.dialogElement(lastSelectedID);
}
},
// Turn this on to get debugging messages.
debug: false,
// Dump text (if debug is on).
dump: function( text ) {
if ( this.debug ) {
dump( text );
}
},
// dumpInfo:
doDebug: function() {
const nsIProgressDialog = Components.interfaces.nsIProgressDialog;
// Open new progress dialog.
var progress = Components.classes[ "@mozilla.org/progressdialog;1" ]
.createInstance( nsIProgressDialog );
// Show it.
progress.open( this.mDialog );
},
// dumpObj:
dumpObj: function( spec ) {
var val = "<undefined>";
try {
val = eval( "this."+spec ).toString();
} catch( exception ) {
}
this.dump( spec + "=" + val + "\n" );
},
// dumpObjectProperties
dumpObjectProperties: function( desc, obj ) {
for( prop in obj ) {
this.dump( desc + "." + prop + "=" );
var val = "<undefined>";
try {
val = obj[ prop ];
} catch ( exception ) {
}
this.dump( val + "\n" );
}
}
}
// This Component's module implementation. All the code below is used to get this
// component registered and accessible via XPCOM.
var module = {
firstTime: true,
// registerSelf: Register this component.
registerSelf: function (compMgr, fileSpec, location, type) {
if (this.firstTime) {
this.firstTime = false;
throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
}
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
compMgr.registerFactoryLocation( this.cid,
"Unknown Content Type Dialog",
this.contractId,
fileSpec,
location,
type );
},
// getClassObject: Return this component's factory object.
getClassObject: function (compMgr, cid, iid) {
if (!cid.equals(this.cid)) {
throw Components.results.NS_ERROR_NO_INTERFACE;
}
if (!iid.equals(Components.interfaces.nsIFactory)) {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
}
return this.factory;
},
/* CID for this class */
cid: Components.ID("{F68578EB-6EC2-4169-AE19-8C6243F0ABE1}"),
/* Contract ID for this class */
contractId: "@mozilla.org/helperapplauncherdialog;1",
/* factory object */
factory: {
// createInstance: Return a new nsProgressDialog object.
createInstance: function (outer, iid) {
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return (new nsUnknownContentTypeDialog()).QueryInterface(iid);
}
},
// canUnload: n/a (returns true)
canUnload: function(compMgr) {
return true;
}
};
// NSGetModule: Return the nsIModule object.
function NSGetModule(compMgr, fileSpec) {
return module;
}