Bug 1369771 - Confirm launch of executables other than .exe on Windows r?paolo
MozReview-Commit-ID: 2TbLbdMc3d3
--- a/browser/components/downloads/DownloadsCommon.jsm
+++ b/browser/components/downloads/DownloadsCommon.jsm
@@ -36,16 +36,18 @@ const { classes: Cc, interfaces: Ci, uti
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
+ "resource://gre/modules/AppConstants.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AppMenuNotifications",
"resource://gre/modules/AppMenuNotifications.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
"resource://gre/modules/Downloads.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUIHelper",
"resource://gre/modules/DownloadUIHelper.jsm");
@@ -421,18 +423,22 @@ this.DownloadsCommon = {
}
if (aMimeInfo && !(aMimeInfo instanceof Ci.nsIMIMEInfo)) {
throw new Error("Invalid value passed for aMimeInfo");
}
if (!(aOwnerWindow instanceof Ci.nsIDOMWindow)) {
throw new Error("aOwnerWindow must be a dom-window object");
}
+ let isWindowsExe = AppConstants.platform == "win" &&
+ aFile.leafName.toLowerCase().endsWith(".exe");
+
let promiseShouldLaunch;
- if (aFile.isExecutable()) {
+ // Don't prompt on Windows for .exe since there will be a native prompt.
+ if (aFile.isExecutable() && !isWindowsExe) {
// We get a prompter for the provided window here, even though anchoring
// to the most recently active window should work as well.
promiseShouldLaunch =
DownloadUIHelper.getPrompter(aOwnerWindow)
.confirmLaunchExecutable(aFile.path);
} else {
promiseShouldLaunch = Promise.resolve(true);
}
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
@@ -23,16 +23,18 @@ const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource://gre/modules/Integration.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
"resource://gre/modules/AsyncShutdown.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
+ "resource://gre/modules/AppConstants.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
"resource://gre/modules/DeferredTask.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
"resource://gre/modules/Downloads.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadStore",
"resource://gre/modules/DownloadStore.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadImport",
"resource://gre/modules/DownloadImport.jsm");
@@ -630,39 +632,40 @@ this.DownloadIntegration = {
* the OS might still take a while until the file is actually
* launched.
* @rejects JavaScript exception if there was an error trying to launch
* the file.
*/
async launchDownload(aDownload) {
let file = new FileUtils.File(aDownload.target.path);
-#ifndef XP_WIN
- // Ask for confirmation if the file is executable, except on Windows where
- // the operating system will show the prompt based on the security zone.
- // We do this here, instead of letting the caller handle the prompt
- // separately in the user interface layer, for two reasons. The first is
- // because of its security nature, so that add-ons cannot forget to do
- // this check. The second is that the system-level security prompt would
- // be displayed at launch time in any case.
- if (file.isExecutable() &&
- !(await this.confirmLaunchExecutable(file.path))) {
- return;
- }
-#endif
-
// In case of a double extension, like ".tar.gz", we only
// consider the last one, because the MIME service cannot
// handle multiple extensions.
let fileExtension = null, mimeInfo = null;
let match = file.leafName.match(/\.([^.]+)$/);
if (match) {
fileExtension = match[1];
}
+ let isWindowsExe = AppConstants.platform == "win" &&
+ fileExtension.toLowerCase() == "exe";
+
+ // Ask for confirmation if the file is executable, except for .exe on
+ // Windows where the operating system will show the prompt based on the
+ // security zone. We do this here, instead of letting the caller handle
+ // the prompt separately in the user interface layer, for two reasons. The
+ // first is because of its security nature, so that add-ons cannot forget
+ // to do this check. The second is that the system-level security prompt
+ // would be displayed at launch time in any case.
+ if (file.isExecutable() && !isWindowsExe &&
+ !(await this.confirmLaunchExecutable(file.path))) {
+ return;
+ }
+
try {
// The MIME service might throw if contentType == "" and it can't find
// a MIME type for the given extension, so we'll treat this case as
// an unknown mimetype.
mimeInfo = gMIMEService.getFromTypeAndExtension(aDownload.contentType,
fileExtension);
} catch (e) { }