Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; |
michael@0 | 7 | |
michael@0 | 8 | Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
michael@0 | 9 | Cu.import("resource://gre/modules/Services.jsm"); |
michael@0 | 10 | |
michael@0 | 11 | XPCOMUtils.defineLazyModuleGetter(this, "Downloads", |
michael@0 | 12 | "resource://gre/modules/Downloads.jsm"); |
michael@0 | 13 | |
michael@0 | 14 | XPCOMUtils.defineLazyModuleGetter(this, "Task", |
michael@0 | 15 | "resource://gre/modules/Task.jsm"); |
michael@0 | 16 | |
michael@0 | 17 | // ----------------------------------------------------------------------- |
michael@0 | 18 | // HelperApp Launcher Dialog |
michael@0 | 19 | // |
michael@0 | 20 | // For now on b2g we never prompt and just download to the default |
michael@0 | 21 | // location. |
michael@0 | 22 | // |
michael@0 | 23 | // ----------------------------------------------------------------------- |
michael@0 | 24 | |
michael@0 | 25 | function HelperAppLauncherDialog() { } |
michael@0 | 26 | |
michael@0 | 27 | HelperAppLauncherDialog.prototype = { |
michael@0 | 28 | classID: Components.ID("{710322af-e6ae-4b0c-b2c9-1474a87b077e}"), |
michael@0 | 29 | QueryInterface: XPCOMUtils.generateQI([Ci.nsIHelperAppLauncherDialog]), |
michael@0 | 30 | |
michael@0 | 31 | show: function(aLauncher, aContext, aReason) { |
michael@0 | 32 | aLauncher.MIMEInfo.preferredAction = Ci.nsIMIMEInfo.saveToDisk; |
michael@0 | 33 | aLauncher.saveToDisk(null, false); |
michael@0 | 34 | }, |
michael@0 | 35 | |
michael@0 | 36 | promptForSaveToFile: function(aLauncher, |
michael@0 | 37 | aContext, |
michael@0 | 38 | aDefaultFile, |
michael@0 | 39 | aSuggestedFileExt, |
michael@0 | 40 | aForcePrompt) { |
michael@0 | 41 | throw Cr.NS_ERROR_NOT_AVAILABLE; |
michael@0 | 42 | }, |
michael@0 | 43 | |
michael@0 | 44 | promptForSaveToFileAsync: function(aLauncher, |
michael@0 | 45 | aContext, |
michael@0 | 46 | aDefaultFile, |
michael@0 | 47 | aSuggestedFileExt, |
michael@0 | 48 | aForcePrompt) { |
michael@0 | 49 | // Retrieve the user's default download directory. |
michael@0 | 50 | Task.spawn(function() { |
michael@0 | 51 | let file = null; |
michael@0 | 52 | try { |
michael@0 | 53 | let defaultFolder = yield Downloads.getPreferredDownloadsDirectory(); |
michael@0 | 54 | let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); |
michael@0 | 55 | dir.initWithPath(defaultFolder); |
michael@0 | 56 | file = this.validateLeafName(dir, aDefaultFile, aSuggestedFileExt); |
michael@0 | 57 | } catch(e) { } |
michael@0 | 58 | aLauncher.saveDestinationAvailable(file); |
michael@0 | 59 | }.bind(this)).then(null, Cu.reportError); |
michael@0 | 60 | }, |
michael@0 | 61 | |
michael@0 | 62 | validateLeafName: function(aLocalFile, aLeafName, aFileExt) { |
michael@0 | 63 | if (!(aLocalFile && this.isUsableDirectory(aLocalFile))) |
michael@0 | 64 | return null; |
michael@0 | 65 | |
michael@0 | 66 | // Remove any leading periods, since we don't want to save hidden files |
michael@0 | 67 | // automatically. |
michael@0 | 68 | aLeafName = aLeafName.replace(/^\.+/, ""); |
michael@0 | 69 | |
michael@0 | 70 | if (aLeafName == "") |
michael@0 | 71 | aLeafName = "unnamed" + (aFileExt ? "." + aFileExt : ""); |
michael@0 | 72 | aLocalFile.append(aLeafName); |
michael@0 | 73 | |
michael@0 | 74 | this.makeFileUnique(aLocalFile); |
michael@0 | 75 | return aLocalFile; |
michael@0 | 76 | }, |
michael@0 | 77 | |
michael@0 | 78 | makeFileUnique: function(aLocalFile) { |
michael@0 | 79 | try { |
michael@0 | 80 | // Note - this code is identical to that in |
michael@0 | 81 | // toolkit/content/contentAreaUtils.js. |
michael@0 | 82 | // If you are updating this code, update that code too! We can't share code |
michael@0 | 83 | // here since this is called in a js component. |
michael@0 | 84 | let collisionCount = 0; |
michael@0 | 85 | while (aLocalFile.exists()) { |
michael@0 | 86 | collisionCount++; |
michael@0 | 87 | if (collisionCount == 1) { |
michael@0 | 88 | // Append "(2)" before the last dot in (or at the end of) the filename |
michael@0 | 89 | // special case .ext.gz etc files so we don't wind up with .tar(2).gz |
michael@0 | 90 | if (aLocalFile.leafName.match(/\.[^\.]{1,3}\.(gz|bz2|Z)$/i)) |
michael@0 | 91 | aLocalFile.leafName = aLocalFile.leafName.replace(/\.[^\.]{1,3}\.(gz|bz2|Z)$/i, "(2)$&"); |
michael@0 | 92 | else |
michael@0 | 93 | aLocalFile.leafName = aLocalFile.leafName.replace(/(\.[^\.]*)?$/, "(2)$&"); |
michael@0 | 94 | } |
michael@0 | 95 | else { |
michael@0 | 96 | // replace the last (n) in the filename with (n+1) |
michael@0 | 97 | aLocalFile.leafName = aLocalFile.leafName.replace(/^(.*\()\d+\)/, "$1" + (collisionCount+1) + ")"); |
michael@0 | 98 | } |
michael@0 | 99 | } |
michael@0 | 100 | aLocalFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0600); |
michael@0 | 101 | } |
michael@0 | 102 | catch (e) { |
michael@0 | 103 | dump("*** exception in makeFileUnique: " + e + "\n"); |
michael@0 | 104 | |
michael@0 | 105 | if (e.result == Cr.NS_ERROR_FILE_ACCESS_DENIED) |
michael@0 | 106 | throw e; |
michael@0 | 107 | |
michael@0 | 108 | if (aLocalFile.leafName == "" || aLocalFile.isDirectory()) { |
michael@0 | 109 | aLocalFile.append("unnamed"); |
michael@0 | 110 | if (aLocalFile.exists()) |
michael@0 | 111 | aLocalFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600); |
michael@0 | 112 | } |
michael@0 | 113 | } |
michael@0 | 114 | }, |
michael@0 | 115 | |
michael@0 | 116 | isUsableDirectory: function(aDirectory) { |
michael@0 | 117 | return aDirectory.exists() && |
michael@0 | 118 | aDirectory.isDirectory() && |
michael@0 | 119 | aDirectory.isWritable(); |
michael@0 | 120 | }, |
michael@0 | 121 | }; |
michael@0 | 122 | |
michael@0 | 123 | this.NSGetFactory = XPCOMUtils.generateNSGetFactory([HelperAppLauncherDialog]); |