From a7d0217d78fcca5175947100d890095d5b439c27 Mon Sep 17 00:00:00 2001 From: Dave Townsend Date: Tue, 4 Nov 2014 19:20:52 -0800 Subject: [PATCH] Bug 1084558: Switch the web installer interfaces to use browsers instead of DOM windows. r=Unfocused --- browser/base/content/browser-addons.js | 15 +---- browser/base/content/urlbarBindings.xml | 3 +- mobile/android/chrome/content/browser.js | 3 +- mobile/android/components/XPIDialogService.js | 4 +- toolkit/mozapps/extensions/AddonManager.jsm | 32 +++++------ toolkit/mozapps/extensions/addonManager.js | 23 ++------ .../mozapps/extensions/amContentHandler.js | 5 +- .../extensions/amIWebInstallListener.idl | 34 +++++------ .../mozapps/extensions/amIWebInstaller.idl | 11 ++-- .../mozapps/extensions/amInstallTrigger.js | 6 +- .../extensions/amWebInstallListener.js | 57 +++++++++---------- .../mozapps/extensions/content/extensions.js | 10 +++- .../extensions/internal/XPIProvider.jsm | 32 +++++------ .../test/browser/browser_bug567127.js | 5 +- .../test/browser/browser_dragdrop.js | 5 +- .../extensions/test/xpinstall/browser.ini | 2 +- .../test/xpinstall/browser_bug645699.js | 6 +- .../test/xpinstall/browser_httphash6.js | 2 +- .../test/xpinstall/browser_switchtab.js | 49 ++++++++++++++++ .../test/xpinstall/browser_whitelist.js | 6 +- .../test/xpinstall/browser_whitelist2.js | 6 +- .../test/xpinstall/browser_whitelist4.js | 6 +- .../test/xpinstall/browser_whitelist5.js | 6 +- .../test/xpinstall/browser_whitelist6.js | 6 +- 24 files changed, 168 insertions(+), 166 deletions(-) create mode 100644 toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js index 542f62f7ff18..fecfc32b90f2 100644 --- a/browser/base/content/browser-addons.js +++ b/browser/base/content/browser-addons.js @@ -32,20 +32,9 @@ const gXPInstallObserver = { { var brandBundle = document.getElementById("bundle_brand"); var installInfo = aSubject.QueryInterface(Components.interfaces.amIWebInstallInfo); - var winOrBrowser = installInfo.originator; + var browser = installInfo.browser; - var browser; - try { - var shell = winOrBrowser.QueryInterface(Components.interfaces.nsIDOMWindow) - .QueryInterface(Components.interfaces.nsIInterfaceRequestor) - .getInterface(Components.interfaces.nsIWebNavigation) - .QueryInterface(Components.interfaces.nsIDocShell); - browser = this._getBrowser(shell); - } catch (e) { - browser = winOrBrowser; - } - // Note that the above try/catch will pass through dead object proxies and - // other degenerate objects. Make sure the browser is bonafide. + // Make sure the browser is still alive. if (!browser || gBrowser.browsers.indexOf(browser) == -1) return; diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index 6cf6c8723a48..2ff749fb0bf5 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -1180,7 +1180,6 @@ // Cache these as cancelling the installs will remove this // notification which will drop these references let browser = this.notification.browser; - let contentWindow = this.notification.options.contentWindow; let sourceURI = this.notification.options.sourceURI; let installs = this.notification.options.installs; @@ -1206,7 +1205,7 @@ callback: function() { let weblistener = Cc["@mozilla.org/addons/web-install-listener;1"]. getService(Ci.amIWebInstallListener); - if (weblistener.onWebInstallRequested(contentWindow, sourceURI, + if (weblistener.onWebInstallRequested(browser, sourceURI, installs, installs.length)) { installs.forEach(function(aInstall) { aInstall.install(); diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 23a6f1c266ae..74535d8ca339 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -6020,8 +6020,7 @@ var XPInstallObserver = { break; case "addon-install-blocked": let installInfo = aSubject.QueryInterface(Ci.amIWebInstallInfo); - let win = installInfo.originator; - let tab = BrowserApp.getTabForWindow(win.top); + let tab = BrowserApp.getTabForBrowser(installInfo.browser); if (!tab) return; diff --git a/mobile/android/components/XPIDialogService.js b/mobile/android/components/XPIDialogService.js index 88a8821eac84..3d180e63bb1f 100644 --- a/mobile/android/components/XPIDialogService.js +++ b/mobile/android/components/XPIDialogService.js @@ -18,7 +18,7 @@ WebInstallPrompt.prototype = { classID: Components.ID("{c1242012-27d8-477e-a0f1-0b098ffc329b}"), QueryInterface: XPCOMUtils.generateQI([Ci.amIWebInstallPrompt]), - confirm: function(aWindow, aURL, aInstalls) { + confirm: function(aBrowser, aURL, aInstalls) { let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties"); let prompt = Services.prompt; @@ -27,7 +27,7 @@ WebInstallPrompt.prototype = { let button = bundle.GetStringFromName("addonsConfirmInstall.install"); aInstalls.forEach(function(install) { - let result = (prompt.confirmEx(aWindow, title, install.name, flags, button, null, null, null, {value: false}) == 0); + let result = (prompt.confirmEx(aBrowser.contentWindow, title, install.name, flags, button, null, null, null, {value: false}) == 0); if (result) install.install(); else diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index 2def0b4769d6..8d9dcf724ea9 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -1628,7 +1628,7 @@ var AddonManagerInternal = { */ getInstallForURL: function AMI_getInstallForURL(aUrl, aCallback, aMimetype, aHash, aName, aIcons, - aVersion, aLoadGroup) { + aVersion, aBrowser) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1667,15 +1667,15 @@ var AddonManagerInternal = { throw Components.Exception("aVersion must be a string or null", Cr.NS_ERROR_INVALID_ARG); - if (aLoadGroup && (!(aLoadGroup instanceof Ci.nsILoadGroup))) - throw Components.Exception("aLoadGroup must be a nsILoadGroup or null", + if (aBrowser && (!(aBrowser instanceof Ci.nsIDOMElement))) + throw Components.Exception("aBrowser must be a nsIDOMElement or null", Cr.NS_ERROR_INVALID_ARG); let providers = this.providers.slice(0); for (let provider of providers) { if (callProvider(provider, "supportsMimetype", false, aMimetype)) { callProviderAsync(provider, "getInstallForURL", - aUrl, aHash, aName, aIcons, aVersion, aLoadGroup, + aUrl, aHash, aName, aIcons, aVersion, aBrowser, function getInstallForURL_safeCall(aInstall) { safeCall(aCallback, aInstall); }); @@ -1878,15 +1878,15 @@ var AddonManagerInternal = { * * @param aMimetype * The mimetype of add-ons being installed - * @param aSource - * The optional nsIDOMWindow that started the installs + * @param aBrowser + * The optional browser element that started the installs * @param aURI * The optional nsIURI that started the installs * @param aInstalls * The array of AddonInstalls to be installed */ installAddonsFromWebpage: function AMI_installAddonsFromWebpage(aMimetype, - aSource, + aBrowser, aURI, aInstalls) { if (!gStarted) @@ -1897,8 +1897,8 @@ var AddonManagerInternal = { throw Components.Exception("aMimetype must be a non-empty string", Cr.NS_ERROR_INVALID_ARG); - if (aSource && !(aSource instanceof Ci.nsIDOMWindow) && !(aSource instanceof Ci.nsIDOMNode)) - throw Components.Exception("aSource must be a nsIDOMWindow, a XUL element, or null", + if (aBrowser && !(aBrowser instanceof Ci.nsIDOMElement)) + throw Components.Exception("aSource must be a nsIDOMElement, or null", Cr.NS_ERROR_INVALID_ARG); if (aURI && !(aURI instanceof Ci.nsIURI)) @@ -1922,18 +1922,18 @@ var AddonManagerInternal = { getService(Ci.amIWebInstallListener); if (!this.isInstallEnabled(aMimetype, aURI)) { - weblistener.onWebInstallDisabled(aSource, aURI, aInstalls, + weblistener.onWebInstallDisabled(aBrowser, aURI, aInstalls, aInstalls.length); } else if (!this.isInstallAllowed(aMimetype, aURI)) { - if (weblistener.onWebInstallBlocked(aSource, aURI, aInstalls, + if (weblistener.onWebInstallBlocked(aBrowser, aURI, aInstalls, aInstalls.length)) { aInstalls.forEach(function(aInstall) { aInstall.install(); }); } } - else if (weblistener.onWebInstallRequested(aSource, aURI, aInstalls, + else if (weblistener.onWebInstallRequested(aBrowser, aURI, aInstalls, aInstalls.length)) { aInstalls.forEach(function(aInstall) { aInstall.install(); @@ -2720,9 +2720,9 @@ this.AddonManager = { getInstallForURL: function AM_getInstallForURL(aUrl, aCallback, aMimetype, aHash, aName, aIcons, - aVersion, aLoadGroup) { + aVersion, aBrowser) { AddonManagerInternal.getInstallForURL(aUrl, aCallback, aMimetype, aHash, - aName, aIcons, aVersion, aLoadGroup); + aName, aIcons, aVersion, aBrowser); }, getInstallForFile: function AM_getInstallForFile(aFile, aCallback, aMimetype) { @@ -2787,9 +2787,9 @@ this.AddonManager = { return AddonManagerInternal.isInstallAllowed(aType, aUri); }, - installAddonsFromWebpage: function AM_installAddonsFromWebpage(aType, aSource, + installAddonsFromWebpage: function AM_installAddonsFromWebpage(aType, aBrowser, aUri, aInstalls) { - AddonManagerInternal.installAddonsFromWebpage(aType, aSource, aUri, aInstalls); + AddonManagerInternal.installAddonsFromWebpage(aType, aBrowser, aUri, aInstalls); }, addManagerListener: function AM_addManagerListener(aListener) { diff --git a/toolkit/mozapps/extensions/addonManager.js b/toolkit/mozapps/extensions/addonManager.js index 1983e7cfdebd..3a3da98260b1 100644 --- a/toolkit/mozapps/extensions/addonManager.js +++ b/toolkit/mozapps/extensions/addonManager.js @@ -74,7 +74,7 @@ amManager.prototype = { * @see amIWebInstaller.idl */ installAddonsFromWebpage: function AMC_installAddonsFromWebpage(aMimetype, - aOriginator, + aBrowser, aReferer, aUris, aHashes, aNames, aIcons, aCallback) { @@ -87,21 +87,10 @@ amManager.prototype = { retval = false; } - let loadGroup = null; - - try { - loadGroup = aOriginator.QueryInterface(Ci.nsIDOMWindow) - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocumentLoader).loadGroup; - } - catch (e) { - } - let installs = []; function buildNextInstall() { if (aUris.length == 0) { - AddonManager.installAddonsFromWebpage(aMimetype, aOriginator, aReferer, installs); + AddonManager.installAddonsFromWebpage(aMimetype, aBrowser, aReferer, installs); return; } let uri = aUris.shift(); @@ -144,7 +133,7 @@ amManager.prototype = { aCallback.onInstallEnded(uri, UNSUPPORTED_TYPE); } buildNextInstall(); - }, aMimetype, aHashes.shift(), aNames.shift(), aIcons.shift(), null, loadGroup); + }, aMimetype, aHashes.shift(), aNames.shift(), aIcons.shift(), null, aBrowser); } buildNextInstall(); @@ -183,12 +172,8 @@ amManager.prototype = { }; } - // If aMessage.objects.window exists, then we're same-process and we - // can target any modal prompts more correctly. Otherwise, we use the - // browser element for the remote browser as the best bet. - let originator = aMessage.objects.window || aMessage.target; return this.installAddonsFromWebpage(payload.mimetype, - originator, referer, payload.uris, payload.hashes, + aMessage.target, referer, payload.uris, payload.hashes, payload.names, payload.icons, callback); } } diff --git a/toolkit/mozapps/extensions/amContentHandler.js b/toolkit/mozapps/extensions/amContentHandler.js index e5c65d9590ae..74f682ca54da 100644 --- a/toolkit/mozapps/extensions/amContentHandler.js +++ b/toolkit/mozapps/extensions/amContentHandler.js @@ -66,9 +66,12 @@ amContentHandler.prototype = { Ci.nsIURI); } + let browser = window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDocShell) + .chromeEventHandler; let manager = Cc["@mozilla.org/addons/integration;1"]. getService(Ci.amIWebInstaller); - manager.installAddonsFromWebpage(aMimetype, window, referer, [uri.spec], + manager.installAddonsFromWebpage(aMimetype, browser, referer, [uri.spec], [null], [null], [null], null, 1); } }, diff --git a/toolkit/mozapps/extensions/amIWebInstallListener.idl b/toolkit/mozapps/extensions/amIWebInstallListener.idl index e12f1fda0504..33adf75c4452 100644 --- a/toolkit/mozapps/extensions/amIWebInstallListener.idl +++ b/toolkit/mozapps/extensions/amIWebInstallListener.idl @@ -4,7 +4,7 @@ #include "nsISupports.idl" -interface nsIDOMWindow; +interface nsIDOMElement; interface nsIURI; interface nsIVariant; @@ -13,10 +13,10 @@ interface nsIVariant; * amIWebInstallListener to communicate with the running application and allow * it to warn the user about blocked installs and start the installs running. */ -[scriptable, uuid(502f206a-c6b4-4e98-b442-e335792e2594)] +[scriptable, uuid(fa0b47a3-f819-47ac-bc66-4bd1d7f67b1d)] interface amIWebInstallInfo : nsISupports { - readonly attribute nsISupports originator; + readonly attribute nsIDOMElement browser; readonly attribute nsIURI originatingURI; readonly attribute nsIVariant installs; @@ -32,14 +32,14 @@ interface amIWebInstallInfo : nsISupports * dialog when add-ons are ready to install and uses the observer service to * notify when installations are blocked. */ -[scriptable, uuid(a5503979-89c8-441e-9e4a-321df379c172)] +[scriptable, uuid(d9240d4b-6b3a-4cad-b402-de6c93337e0c)] interface amIWebInstallListener : nsISupports { /** * Called when installation by websites is currently disabled. * - * @param aOriginator - * The window or browser that triggered the installs + * @param aBrowser + * The browser that triggered the installs * @param aUri * The URI of the site that triggered the installs * @param aInstalls @@ -47,7 +47,7 @@ interface amIWebInstallListener : nsISupports * @param aCount * The number of AddonInstalls */ - void onWebInstallDisabled(in nsISupports aOriginator, in nsIURI aUri, + void onWebInstallDisabled(in nsIDOMElement aBrowser, in nsIURI aUri, [array, size_is(aCount)] in nsIVariant aInstalls, [optional] in uint32_t aCount); @@ -55,8 +55,8 @@ interface amIWebInstallListener : nsISupports * Called when the website is not allowed to directly prompt the user to * install add-ons. * - * @param aWindow - * The window or browser that triggered the installs + * @param aBrowser + * The browser that triggered the installs * @param aUri * The URI of the site that triggered the installs * @param aInstalls @@ -65,15 +65,15 @@ interface amIWebInstallListener : nsISupports * The number of AddonInstalls * @return true if the caller should start the installs */ - boolean onWebInstallBlocked(in nsISupports aOriginator, in nsIURI aUri, + boolean onWebInstallBlocked(in nsIDOMElement aBrowser, in nsIURI aUri, [array, size_is(aCount)] in nsIVariant aInstalls, [optional] in uint32_t aCount); /** * Called when a website wants to ask the user to install add-ons. * - * @param aWindow - * The window or browser that triggered the installs + * @param aBrowser + * The browser that triggered the installs * @param aUri * The URI of the site that triggered the installs * @param aInstalls @@ -82,7 +82,7 @@ interface amIWebInstallListener : nsISupports * The number of AddonInstalls * @return true if the caller should start the installs */ - boolean onWebInstallRequested(in nsISupports aOriginator, in nsIURI aUri, + boolean onWebInstallRequested(in nsIDOMElement aBrowser, in nsIURI aUri, [array, size_is(aCount)] in nsIVariant aInstalls, [optional] in uint32_t aCount); }; @@ -92,14 +92,14 @@ interface amIWebInstallListener : nsISupports * amIWebInstallInfo to display a confirmation UI to the user before running * installs. */ -[scriptable, uuid(c5529918-4291-4b56-bd46-e9268900f2a3)] +[scriptable, uuid(386906f1-4d18-45bf-bc81-5dcd68e42c3b)] interface amIWebInstallPrompt : nsISupports { /** * Get a confirmation that the user wants to start the installs. * - * @param aWindow - * The window that triggered the installs + * @param aBrowser + * The browser that triggered the installs * @param aUri * The URI of the site that triggered the installs * @param aInstalls @@ -107,7 +107,7 @@ interface amIWebInstallPrompt : nsISupports * @param aCount * The number of AddonInstalls */ - void confirm(in nsIDOMWindow aWindow, in nsIURI aUri, + void confirm(in nsIDOMElement aBrowser, in nsIURI aUri, [array, size_is(aCount)] in nsIVariant aInstalls, [optional] in uint32_t aCount); }; diff --git a/toolkit/mozapps/extensions/amIWebInstaller.idl b/toolkit/mozapps/extensions/amIWebInstaller.idl index 37d525776f24..6c5ebca67c32 100644 --- a/toolkit/mozapps/extensions/amIWebInstaller.idl +++ b/toolkit/mozapps/extensions/amIWebInstaller.idl @@ -4,7 +4,7 @@ #include "nsISupports.idl" -interface nsIDOMWindow; +interface nsIDOMElement; interface nsIVariant; interface nsIURI; @@ -32,7 +32,7 @@ interface amIInstallCallback : nsISupports /** * This interface is used to allow webpages to start installing add-ons. */ -[scriptable, uuid(8565a9c7-daf9-4af5-aae0-b272afcbccaa)] +[scriptable, uuid(658d6c09-15e0-4688-bee8-8551030472a9)] interface amIWebInstaller : nsISupports { /** @@ -51,9 +51,8 @@ interface amIWebInstaller : nsISupports * * @param aMimetype * The mimetype for the add-ons - * @param aOriginator - * If not e10s, the window installing the add-ons, otherwise the - * browser installing the add-ons. + * @param aBrowser + * The browser installing the add-ons. * @param aReferer * The URI for the webpage installing the add-ons * @param aUris @@ -72,7 +71,7 @@ interface amIWebInstaller : nsISupports * @return true if the installation was successfully started */ boolean installAddonsFromWebpage(in AString aMimetype, - in nsISupports aOriginator, + in nsIDOMElement aBrowser, in nsIURI aReferer, [array, size_is(aInstallCount)] in wstring aUris, [array, size_is(aInstallCount)] in wstring aHashes, diff --git a/toolkit/mozapps/extensions/amInstallTrigger.js b/toolkit/mozapps/extensions/amInstallTrigger.js index d3110b74b712..5a3d6c7aab49 100644 --- a/toolkit/mozapps/extensions/amInstallTrigger.js +++ b/toolkit/mozapps/extensions/amInstallTrigger.js @@ -80,11 +80,7 @@ RemoteMediator.prototype = { installs.referer = referer; installs.callbackID = callbackID; - let objects = { window: null }; - if (Services.appinfo.processType === Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) - objects.window = window; - - return messageManager.sendSyncMessage(MSG_INSTALL_ADDONS, installs, objects)[0]; + return messageManager.sendSyncMessage(MSG_INSTALL_ADDONS, installs)[0]; }, _addCallback: function(callback, urls) { diff --git a/toolkit/mozapps/extensions/amWebInstallListener.js b/toolkit/mozapps/extensions/amWebInstallListener.js index cf3e9789221b..45fed0582e7a 100644 --- a/toolkit/mozapps/extensions/amWebInstallListener.js +++ b/toolkit/mozapps/extensions/amWebInstallListener.js @@ -20,6 +20,8 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/AddonManager.jsm"); Cu.import("resource://gre/modules/Services.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "PromptUtils", "resource://gre/modules/SharedPromptUtils.jsm"); + const URI_XPINSTALL_DIALOG = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul"; // Installation can begin from any of these states @@ -37,9 +39,9 @@ const LOGGER_ID = "addons.weblistener"; // (Requires AddonManager.jsm) let logger = Log.repository.getLogger(LOGGER_ID); -function notifyObservers(aTopic, aOriginator, aUri, aInstalls) { +function notifyObservers(aTopic, aBrowser, aUri, aInstalls) { let info = { - originator: aOriginator, + browser: aBrowser, originatingURI: aUri, installs: aInstalls, @@ -52,20 +54,20 @@ function notifyObservers(aTopic, aOriginator, aUri, aInstalls) { * Creates a new installer to monitor downloads and prompt to install when * ready * - * @param aOriginator - * The window or browser that started the installations + * @param aBrowser + * The browser that started the installations * @param aUrl * The URL that started the installations * @param aInstalls * An array of AddonInstalls */ -function Installer(aOriginator, aUrl, aInstalls) { - this.originator = aOriginator; +function Installer(aBrowser, aUrl, aInstalls) { + this.browser = aBrowser; this.url = aUrl; this.downloads = aInstalls; this.installed = []; - notifyObservers("addon-install-started", aOriginator, aUrl, aInstalls); + notifyObservers("addon-install-started", aBrowser, aUrl, aInstalls); aInstalls.forEach(function(aInstall) { aInstall.addListener(this); @@ -79,7 +81,7 @@ function Installer(aOriginator, aUrl, aInstalls) { } Installer.prototype = { - originator: null, + browser: null, downloads: null, installed: null, isDownloading: true, @@ -145,29 +147,20 @@ Installer.prototype = { aInstall.cancel(); } }, this); - notifyObservers("addon-install-failed", this.originator, this.url, failed); + notifyObservers("addon-install-failed", this.browser, this.url, failed); } // If none of the downloads were successful then exit early if (this.downloads.length == 0) return; - let parentWindow = null; - try { - parentWindow = this.originator.QueryInterface(Ci.nsIDOMWindow); - } catch (e) { - // If we're remote, then originator will be a browser. In that case, - // we're showing our dialog on behalf of a content process and passing - // null is the best we can do for now. - } - // Check for a custom installation prompt that may be provided by the // applicaton if ("@mozilla.org/addons/web-install-prompt;1" in Cc) { try { let prompt = Cc["@mozilla.org/addons/web-install-prompt;1"]. getService(Ci.amIWebInstallPrompt); - prompt.confirm(parentWindow, this.url, this.downloads, this.downloads.length); + prompt.confirm(this.browser, this.url, this.downloads, this.downloads.length); return; } catch (e) {} @@ -183,16 +176,22 @@ Installer.prototype = { getService(Ci.nsITelemetry). getHistogramById("SECURITY_UI"). add(Ci.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL); + let parentWindow = null; + if (this.browser) { + parentWindow = this.browser.ownerDocument.defaultView; + PromptUtils.fireDialogEvent(parentWindow, "DOMWillOpenModalDialog", this.browser); + } Services.ww.openWindow(parentWindow, URI_XPINSTALL_DIALOG, null, "chrome,modal,centerscreen", args); } catch (e) { + logger.warn("Exception showing install confirmation dialog", e); this.downloads.forEach(function(aInstall) { aInstall.removeListener(this); // Cancel the installs, as currently there is no way to make them fail // from here. aInstall.cancel(); }, this); - notifyObservers("addon-install-cancelled", this.originator, this.url, + notifyObservers("addon-install-cancelled", this.browser, this.url, this.downloads); } }, @@ -219,10 +218,10 @@ Installer.prototype = { this.downloads = null; if (failed.length > 0) - notifyObservers("addon-install-failed", this.originator, this.url, failed); + notifyObservers("addon-install-failed", this.browser, this.url, failed); if (this.installed.length > 0) - notifyObservers("addon-install-complete", this.originator, this.url, this.installed); + notifyObservers("addon-install-complete", this.browser, this.url, this.installed); this.installed = null; }, @@ -273,9 +272,9 @@ extWebInstallListener.prototype = { /** * @see amIWebInstallListener.idl */ - onWebInstallDisabled: function extWebInstallListener_onWebInstallDisabled(aOriginator, aUri, aInstalls) { + onWebInstallDisabled: function extWebInstallListener_onWebInstallDisabled(aBrowser, aUri, aInstalls) { let info = { - originator: aOriginator, + browser: aBrowser, originatingURI: aUri, installs: aInstalls, @@ -287,14 +286,14 @@ extWebInstallListener.prototype = { /** * @see amIWebInstallListener.idl */ - onWebInstallBlocked: function extWebInstallListener_onWebInstallBlocked(aOriginator, aUri, aInstalls) { + onWebInstallBlocked: function extWebInstallListener_onWebInstallBlocked(aBrowser, aUri, aInstalls) { let info = { - originator: aOriginator, + browser: aBrowser, originatingURI: aUri, installs: aInstalls, install: function onWebInstallBlocked_install() { - new Installer(this.originator, this.originatingURI, this.installs); + new Installer(this.browser, this.originatingURI, this.installs); }, QueryInterface: XPCOMUtils.generateQI([Ci.amIWebInstallInfo]) @@ -307,8 +306,8 @@ extWebInstallListener.prototype = { /** * @see amIWebInstallListener.idl */ - onWebInstallRequested: function extWebInstallListener_onWebInstallRequested(aOriginator, aUri, aInstalls) { - new Installer(aOriginator, aUri, aInstalls); + onWebInstallRequested: function extWebInstallListener_onWebInstallRequested(aBrowser, aUri, aInstalls) { + new Installer(aBrowser, aUri, aInstalls); // We start the installs ourself return false; diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index 34b6a37cc652..625fc4fd8dec 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -243,6 +243,12 @@ function getMainWindow() { .getInterface(Ci.nsIDOMWindow); } +function getBrowserElement() { + return window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDocShell) + .chromeEventHandler; +} + /** * Obtain the DOMWindow that can open a preferences pane. * @@ -1215,7 +1221,7 @@ var gViewController = { if (installs.length > 0) { // Display the normal install confirmation for the installs AddonManager.installAddonsFromWebpage("application/x-xpinstall", - window, null, installs); + getBrowserElement(), null, installs); } return; } @@ -3613,7 +3619,7 @@ var gDragDrop = { if (installs.length > 0) { // Display the normal install confirmation for the installs AddonManager.installAddonsFromWebpage("application/x-xpinstall", - window, null, installs); + getBrowserElement(), null, installs); } return; } diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm index b9de7bce9510..7119778b4f0d 100644 --- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm @@ -3750,16 +3750,16 @@ this.XPIProvider = { * Icon URLs for the install * @param aVersion * A version for the install - * @param aLoadGroup - * An nsILoadGroup to associate requests with + * @param aBrowser + * The browser performing the install * @param aCallback * A callback to pass the AddonInstall to */ getInstallForURL: function XPI_getInstallForURL(aUrl, aHash, aName, aIcons, - aVersion, aLoadGroup, aCallback) { + aVersion, aBrowser, aCallback) { AddonInstall.createDownload(function getInstallForURL_createDownload(aInstall) { aCallback(aInstall.wrapper); - }, aUrl, aHash, aName, aIcons, aVersion, aLoadGroup); + }, aUrl, aHash, aName, aIcons, aVersion, aBrowser); }, /** @@ -4755,13 +4755,13 @@ function getHashStringForCrypto(aCrypto) { * An optional nsIURI of release notes for the add-on * @param aExistingAddon * The add-on this install will update if known - * @param aLoadGroup - * The nsILoadGroup to associate any requests with + * @param aBrowser + * The browser performing the install * @throws if the url is the url of a local file and the hash does not match * or the add-on does not contain an valid install manifest */ function AddonInstall(aInstallLocation, aUrl, aHash, aReleaseNotesURI, - aExistingAddon, aLoadGroup) { + aExistingAddon, aBrowser) { this.wrapper = new AddonInstallWrapper(this); this.installLocation = aInstallLocation; this.sourceURI = aUrl; @@ -4774,16 +4774,12 @@ function AddonInstall(aInstallLocation, aUrl, aHash, aReleaseNotesURI, }; } this.hash = this.originalHash; - this.loadGroup = aLoadGroup; + this.browser = aBrowser; this.listeners = []; this.icons = {}; this.existingAddon = aExistingAddon; this.error = 0; - if (aLoadGroup) - this.window = aLoadGroup.notificationCallbacks - .getInterface(Ci.nsIDOMWindow); - else - this.window = null; + this.window = aBrowser ? aBrowser.contentWindow : null; // Giving each instance of AddonInstall a reference to the logger. this.logger = logger; @@ -4796,7 +4792,7 @@ AddonInstall.prototype = { crypto: null, originalHash: null, hash: null, - loadGroup: null, + browser: null, badCertHandler: null, listeners: null, restartDownload: false, @@ -5920,15 +5916,15 @@ AddonInstall.createInstall = function AI_createInstall(aCallback, aFile) { * An icon URLs for the add-on * @param aVersion * A version for the add-on - * @param aLoadGroup - * An nsILoadGroup to associate the download with + * @param aBrowser + * The browser performing the install */ AddonInstall.createDownload = function AI_createDownload(aCallback, aUri, aHash, aName, aIcons, - aVersion, aLoadGroup) { + aVersion, aBrowser) { let location = XPIProvider.installLocationsByName[KEY_APP_PROFILE]; let url = NetUtil.newURI(aUri); - let install = new AddonInstall(location, url, aHash, null, null, aLoadGroup); + let install = new AddonInstall(location, url, aHash, null, null, aBrowser); if (url instanceof Ci.nsIFileURL) install.initLocalInstall(aCallback); else diff --git a/toolkit/mozapps/extensions/test/browser/browser_bug567127.js b/toolkit/mozapps/extensions/test/browser/browser_bug567127.js index 224616982ec3..11e70421821a 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_bug567127.js +++ b/toolkit/mozapps/extensions/test/browser/browser_bug567127.js @@ -73,7 +73,10 @@ WindowOpenListener.prototype = { var gInstallNotificationObserver = { observe: function(aSubject, aTopic, aData) { var installInfo = aSubject.QueryInterface(Ci.amIWebInstallInfo); - isnot(installInfo.originator, null, "Notification should have non-null originator"); + if (gTestInWindow) + is(installInfo.browser, null, "Notification should have a null browser"); + else + isnot(installInfo.browser, null, "Notification should have non-null browser"); gSawInstallNotification = true; Services.obs.removeObserver(this, "addon-install-started"); } diff --git a/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js b/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js index c91ab27ea571..1df288323ef3 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js +++ b/toolkit/mozapps/extensions/test/browser/browser_dragdrop.js @@ -79,7 +79,10 @@ var gSawInstallNotification = false; var gInstallNotificationObserver = { observe: function(aSubject, aTopic, aData) { var installInfo = aSubject.QueryInterface(Ci.amIWebInstallInfo); - isnot(installInfo.originator, null, "Notification should have non-null originator"); + if (gTestInWindow) + is(installInfo.browser, null, "Notification should have a null browser"); + else + isnot(installInfo.browser, null, "Notification should have non-null browser"); gSawInstallNotification = true; Services.obs.removeObserver(this, "addon-install-started"); } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser.ini b/toolkit/mozapps/extensions/test/xpinstall/browser.ini index b9f18e39df90..0ee3b329c8f3 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser.ini +++ b/toolkit/mozapps/extensions/test/xpinstall/browser.ini @@ -64,7 +64,6 @@ skip-if = true # Bug 1084646 [browser_httphash4.js] [browser_httphash5.js] [browser_httphash6.js] -skip-if = e10s # Bug 1084558 [browser_installchrome.js] [browser_localfile.js] skip-if = e10s # Bug 1082764 @@ -86,6 +85,7 @@ skip-if = e10s # bug 1082764 [browser_signed_url.js] skip-if = e10s # bug 1082764 [browser_softwareupdate.js] +[browser_switchtab.js] [browser_trigger_redirect.js] [browser_unsigned_trigger.js] [browser_unsigned_trigger_iframe.js] diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js b/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js index ed396602fd36..a5c188c03875 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_bug645699.js @@ -16,11 +16,7 @@ function test() { } function allow_blocked(installInfo) { - // installInfo.originator is different depending on whether we are in e10s(!) - if (gMultiProcessBrowser) - is(installInfo.originator, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); - else - is(installInfo.originator, gBrowser.contentWindow, "Install should have been triggered by the right window"); + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); return false; } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js index 5516805da771..5244fefefc32 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_httphash6.js @@ -64,7 +64,7 @@ function finish_failed_download() { // Restart the install as a regular webpage install so the harness tracks it AddonManager.installAddonsFromWebpage("application/x-xpinstall", - gBrowser.contentWindow, + gBrowser.selectedBrowser, gBrowser.currentURI, [gInstall]); } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js b/toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js new file mode 100644 index 000000000000..9672de9bd354 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_switchtab.js @@ -0,0 +1,49 @@ +// ---------------------------------------------------------------------------- +// Tests installing an unsigned add-on through an InstallTrigger call in web +// content. +let expectedTab = null; + +function test() { + Harness.installConfirmCallback = confirm_install; + Harness.installEndedCallback = install_ended; + Harness.installsCompletedCallback = finish_test; + Harness.setup(); + + var pm = Services.perms; + pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION); + + var triggers = encodeURIComponent(JSON.stringify({ + "Unsigned XPI": { + URL: TESTROOT + "unsigned.xpi", + IconURL: TESTROOT + "icon.png", + toString: function() { return this.URL; } + } + })); + expectedTab = gBrowser.addTab(); + expectedTab.linkedBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers); +} + +function confirm_install(window) { + var items = window.document.getElementById("itemList").childNodes; + is(items.length, 1, "Should only be 1 item listed in the confirmation dialog"); + is(items[0].name, "XPI Test", "Should have seen the name"); + is(items[0].url, TESTROOT + "unsigned.xpi", "Should have listed the correct url for the item"); + is(items[0].icon, TESTROOT + "icon.png", "Should have listed the correct icon for the item"); + is(items[0].signed, "false", "Should have listed the item as unsigned"); + + is(gBrowser.selectedTab, expectedTab, "Should have switched to the installing tab."); + return true; +} + +function install_ended(install, addon) { + install.cancel(); +} + +function finish_test(count) { + is(count, 1, "1 Add-on should have been successfully installed"); + + Services.perms.remove("example.com", "install"); + + gBrowser.removeTab(expectedTab); + Harness.finish(); +} diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js index 31e44b95dffa..448ce3a5cea7 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist.js @@ -17,11 +17,7 @@ function test() { } function allow_blocked(installInfo) { - // installInfo.originator is different depending on whether we are in e10s(!) - if (gMultiProcessBrowser) - is(installInfo.originator, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); - else - is(installInfo.originator, gBrowser.contentWindow, "Install should have been triggered by the right window"); + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); return true; } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js index 9d60ddc66663..168a31ef3e9a 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist2.js @@ -18,11 +18,7 @@ function test() { } function allow_blocked(installInfo) { - // installInfo.originator is different depending on whether we are in e10s(!) - if (gMultiProcessBrowser) - is(installInfo.originator, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); - else - is(installInfo.originator, gBrowser.contentWindow, "Install should have been triggered by the right window"); + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); return false; } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js index e94d6b5c7832..59d51350bbac 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist4.js @@ -17,11 +17,7 @@ function test() { } function allow_blocked(installInfo) { - // installInfo.originator is different depending on whether we are in e10s(!) - if (gMultiProcessBrowser) - is(installInfo.originator, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); - else - is(installInfo.originator, gBrowser.contentWindow, "Install should have been triggered by the right window"); + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); is(installInfo.originatingURI.spec, TESTROOT2 + "test.html", "Install should have been triggered by the right uri"); return false; } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js index 5267fc1caa06..97448d803a2a 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist5.js @@ -12,11 +12,7 @@ function test() { } function allow_blocked(installInfo) { - // installInfo.originator is different depending on whether we are in e10s(!) - if (gMultiProcessBrowser) - is(installInfo.originator, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); - else - is(installInfo.originator, gBrowser.contentWindow, "Install should have been triggered by the right window"); + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); return false; } diff --git a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js index 79d1f5c0bdf2..f2f3641e4e06 100644 --- a/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js +++ b/toolkit/mozapps/extensions/test/xpinstall/browser_whitelist6.js @@ -12,11 +12,7 @@ function test() { } function allow_blocked(installInfo) { - // installInfo.originator is different depending on whether we are in e10s(!) - if (gMultiProcessBrowser) - is(installInfo.originator, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); - else - is(installInfo.originator, gBrowser.contentWindow, "Install should have been triggered by the right window"); + is(installInfo.browser, gBrowser.selectedBrowser, "Install should have been triggered by the right browser"); is(installInfo.originatingURI.spec, gBrowser.currentURI.spec, "Install should have been triggered by the right uri"); return false; }