/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is HelperApp Launcher Dialog. * * The Initial Developer of the Original Code is Mozilla Foundation. * Portions created by the Initial Developer are Copyright (C) 2009 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Mark Finkle * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ const Cc = Components.classes; const Ci = Components.interfaces; const PREF_BD_USEDOWNLOADDIR = "browser.download.useDownloadDir"; Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); // ----------------------------------------------------------------------- // HelperApp Launcher Dialog // ----------------------------------------------------------------------- function HelperAppLauncherDialog() { } HelperAppLauncherDialog.prototype = { classDescription: "HelperApp Launcher Dialog", contractID: "@mozilla.org/helperapplauncherdialog;1", classID: Components.ID("{e9d277a0-268a-4ec2-bb8c-10fdf3e44611}"), QueryInterface: XPCOMUtils.generateQI([Ci.nsIHelperAppLauncherDialog]), show: function hald_show(aLauncher, aContext, aReason) { this._launcher = aLauncher; this._context = aContext; let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); let browser = wm.getMostRecentWindow("navigator:browser"); browser.HelperAppDialog.show(aLauncher); }, promptForSaveToFile: function hald_promptForSaveToFile(aLauncher, aContext, aDefaultFile, aSuggestedFileExt, aForcePrompt) { let file = null; let prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); if (!aForcePrompt) { // Check to see if the user wishes to auto save to the default download // folder without prompting. Note that preference might not be set. let autodownload = true; try { autodownload = prefs.getBoolPref(PREF_BD_USEDOWNLOADDIR); } catch (e) { } if (autodownload) { // Retrieve the user's default download directory let dnldMgr = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager); let defaultFolder = dnldMgr.userDownloadsDirectory; try { file = this.validateLeafName(defaultFolder, aDefaultFile, aSuggestedFileExt); } catch (e) { } // Check to make sure we have a valid directory, otherwise, prompt if (file) return file; } } // Use file picker to show dialog. let picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); let windowTitle = ""; let parent = aContext.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal); picker.init(parent, windowTitle, Ci.nsIFilePicker.modeSave); picker.defaultString = aDefaultFile; if (aSuggestedFileExt) { // aSuggestedFileExtension includes the period, so strip it picker.defaultExtension = aSuggestedFileExt.substring(1); } else { try { picker.defaultExtension = this.mLauncher.MIMEInfo.primaryExtension; } catch (e) { } } var wildCardExt = "*"; if (aSuggestedFileExt) { wildCardExtension += aSuggestedFileExt; picker.appendFilter(this.mLauncher.MIMEInfo.description, wildCardExtension); } picker.appendFilters(Ci.nsIFilePicker.filterAll); // Default to lastDir if it is valid, otherwise use the user's default // downloads directory. userDownloadsDirectory should always return a // valid directory, so we can safely default to it. var dnldMgr = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager); picker.displayDirectory = dnldMgr.userDownloadsDirectory; // The last directory preference may not exist, which will throw. try { let lastDir = prefs.getComplexValue("browser.download.lastDir", Ci.nsILocalFile); if (isUsableDirectory(lastDir)) picker.displayDirectory = lastDir; } catch (e) { } if (picker.show() == Ci.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 since the old one // didn't exist. file = picker.file; if (file) { try { // Remove the file so that it's not there when we ensure non-existence later; // this is safe because for the file to exist, the user would have had to // confirm that he wanted the file overwritten. if (file.exists()) file.remove(false); } catch (e) { } var newDir = file.parent.QueryInterface(Ci.nsILocalFile); prefs.setComplexValue("browser.download.lastDir", Ci.nsILocalFile, newDir); file = this.validateLeafName(newDir, file.leafName, null); } return file; }, validateLeafName: function hald_validateLeafName(aLocalFile, aLeafName, aFileExt) { if (!(aLocalFile && this.isUsableDirectory(aLocalFile))) return null; // Remove any leading periods, since we don't want to save hidden files // automatically. aLeafName = aLeafName.replace(/^\.+/, ""); if (aLeafName == "") aLeafName = "unnamed" + (aFileExt ? "." + aFileExt : ""); aLocalFile.append(aLeafName); this.makeFileUnique(aLocalFile); return aLocalFile; }, makeFileUnique: function hald_makeFileUnique(aLocalFile) { try { // Note - this code is identical to that in // toolkit/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. var collisionCount = 0; while (aLocalFile.exists()) { collisionCount++; if (collisionCount == 1) { // Append "(2)" before the last dot in (or at the end of) the filename // special case .ext.gz etc files so we don't wind up with .tar(2).gz if (aLocalFile.leafName.match(/\.[^\.]{1,3}\.(gz|bz2|Z)$/i)) aLocalFile.leafName = aLocalFile.leafName.replace(/\.[^\.]{1,3}\.(gz|bz2|Z)$/i, "(2)$&"); else aLocalFile.leafName = aLocalFile.leafName.replace(/(\.[^\.]*)?$/, "(2)$&"); } else { // replace the last (n) in the filename with (n+1) aLocalFile.leafName = aLocalFile.leafName.replace(/^(.*\()\d+\)/, "$1" + (collisionCount+1) + ")"); } } aLocalFile.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0600); } catch (e) { dump("*** exception in validateLeafName: " + e + "\n"); if (e.result == Components.results.NS_ERROR_FILE_ACCESS_DENIED) throw e; if (aLocalFile.leafName == "" || aLocalFile.isDirectory()) { aLocalFile.append("unnamed"); if (aLocalFile.exists()) aLocalFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0600); } } }, isUsableDirectory: function hald_isUsableDirectory(aDirectory) { return aDirectory.exists() && aDirectory.isDirectory() && aDirectory.isWritable(); } }; // The toolkit helper service uses a delayed registration, so we can't use XPCOMUtils // since it doesn't support delayed registration yet. //function NSGetModule(aCompMgr, aFileSpec) { // return XPCOMUtils.generateModule([HelperAppLauncherDialog]); //} var module = { firstTime: true, registerSelf: function(compMgr, fileSpec, location, type) { if (this.firstTime) { this.firstTime = false; throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN; } compMgr = compMgr.QueryInterface(Ci.nsIComponentRegistrar); compMgr.registerFactoryLocation(this.classID, this.classDescription, this.contractID, fileSpec, location, type); }, getClassObject: function(compMgr, cid, iid) { if (!cid.equals(this.classID)) throw Components.results.NS_ERROR_NO_INTERFACE; if (!iid.equals(Ci.nsIFactory)) throw Components.results.NS_ERROR_NOT_IMPLEMENTED; return this.factory; }, classDescription: "HelperApp Launcher Dialog", contractID: "@mozilla.org/helperapplauncherdialog;1", classID: Components.ID("{e9d277a0-268a-4ec2-bb8c-10fdf3e44611}"), factory: { createInstance: function(outer, iid) { if (outer != null) throw Components.results.NS_ERROR_NO_AGGREGATION; return (new HelperAppLauncherDialog()).QueryInterface(iid); } }, canUnload: function(compMgr) { return true; } }; function NSGetModule(compMgr, fileSpec) { return module; }