Bug 1528335, r=aswan
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Wed, 03 Apr 2019 21:01:19 +0000
changeset 467871 c032b60a872e3946caa7308f120b91ed477103b9
parent 467870 ee208901e86a56aedd617948d652b1134a72824c
child 467872 3fb9140b5e81a7caef45e118be9208c273b7f654
push id82252
push usergijskruitbosch@gmail.com
push dateWed, 03 Apr 2019 22:16:44 +0000
treeherderautoland@c032b60a872e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1528335
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1528335, r=aswan Differential Revision: https://phabricator.services.mozilla.com/D25775
toolkit/components/extensions/parent/ext-management.js
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/addonManager.js
toolkit/mozapps/extensions/amWebAPI.jsm
toolkit/mozapps/extensions/internal/XPIInstall.jsm
--- a/toolkit/components/extensions/parent/ext-management.js
+++ b/toolkit/components/extensions/parent/ext-management.js
@@ -196,17 +196,21 @@ this.management = class extends Extensio
               }
             },
           };
 
           let telemetryInfo = {
             source: "extension",
             method: "management-webext-api",
           };
-          let install = await AddonManager.getInstallForURL(url, {hash, telemetryInfo});
+          let install = await AddonManager.getInstallForURL(url, {
+            hash,
+            telemetryInfo,
+            triggeringPrincipal: extension.principal,
+          });
           install.addListener(listener);
           try {
             await install.install();
           } catch (e) {
             Cu.reportError(e);
             throw new ExtensionError("Incompatible addon");
           }
           await install.addon.enable();
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -1559,16 +1559,18 @@ var AddonManagerInternal = {
    * @param  {string} [aOptions.name]
    *         An optional placeholder name while the add-on is being downloaded
    * @param  {string|Object} [aOptions.icons]
    *         Optional placeholder icons while the add-on is being downloaded
    * @param  {string} [aOptions.version]
    *         An optional placeholder version while the add-on is being downloaded
    * @param  {XULElement} [aOptions.browser]
    *         An optional <browser> element for download permissions prompts.
+   * @param  {nsIPrincipal} [aOptions.triggeringPrincipal]
+   *         The principal which is attempting to install the add-on.
    * @param  {Object} [aOptions.telemetryInfo]
    *         An optional object which provides details about the installation source
    *         included in the addon manager telemetry events.
    * @throws if aUrl is not specified or if an optional argument of
    *         an improper type is passed.
    */
   async getInstallForURL(aUrl, aOptions = {}) {
     if (!gStarted)
@@ -2681,25 +2683,27 @@ var AddonManagerInternal = {
         });
 
         // We create the promise here since this is where we're setting
         // up the InstallListener, but if the install is never started,
         // no handlers will be attached so make sure we terminate errors.
         installPromise.catch(() => {});
 
         return {listener, installPromise};
-     };
+      };
 
       try {
         checkInstallUrl(options.url);
       } catch (err) {
         return Promise.reject({message: err.message});
       }
 
       return AddonManagerInternal.getInstallForURL(options.url, {
+        browser: target,
+        triggeringPrincipal: options.triggeringPrincipal,
         hash: options.hash,
         telemetryInfo: {
           source: AddonManager.getInstallSourceFromHost(options.sourceHost),
           method: "amWebAPI",
         },
       }).then(install => {
         AddonManagerInternal.setupPromptHandler(target, null, install, false, "AMO");
 
--- a/toolkit/mozapps/extensions/addonManager.js
+++ b/toolkit/mozapps/extensions/addonManager.js
@@ -97,16 +97,17 @@ amManager.prototype = {
       telemetryInfo.method = aPayload.method;
     }
 
     AddonManager.getInstallForURL(uri, {
       hash,
       name,
       icon,
       browser: aBrowser,
+      triggeringPrincipal,
       telemetryInfo,
       sendCookies: true,
     }).then(aInstall => {
       function callCallback(status) {
         try {
           aCallback.onInstallEnded(uri, status);
         } catch (e) {
           Cu.reportError(e);
--- a/toolkit/mozapps/extensions/amWebAPI.jsm
+++ b/toolkit/mozapps/extensions/amWebAPI.jsm
@@ -232,16 +232,17 @@ class WebAPI extends APIObject {
     let installOptions = {
       ...options,
       // Provide the host from which the amWebAPI is being called
       // (so that we can detect if the API is being used from the disco pane,
       // AMO, testpilot or another unknown webpage).
       sourceHost: this.window.document.nodePrincipal.URI &&
         this.window.document.nodePrincipal.URI.host,
     };
+    installOptions.triggeringPrincipal = this.window.document.nodePrincipal;
     return this._apiTask("createInstall", [installOptions], installInfo => {
       if (!installInfo) {
         return null;
       }
       let install = new AddonInstall(this.window, this.broker, installInfo);
       this.allInstalls.push(installInfo.id);
       return this.window.AddonInstall._create(this.window, install);
     });
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -1798,16 +1798,18 @@ var DownloadAddonInstall = class extends
    *        Additional options for the install
    * @param {string} [options.hash]
    *        An optional hash for the add-on
    * @param {AddonInternal} [options.existingAddon]
    *        The add-on this install will update if known
    * @param {XULElement} [options.browser]
    *        The browser performing the install, used to display
    *        authentication prompts.
+   * @param {nsIPrincipal} [options.principal]
+   *        The principal to use. If not present, will default to browser.contentPrincipal.
    * @param {string} [options.name]
    *        An optional name for the add-on
    * @param {string} [options.type]
    *        An optional type for the add-on
    * @param {Object} [options.icons]
    *        Optional icons for the add-on
    * @param {string} [options.version]
    *        An optional version for the add-on
@@ -1815,16 +1817,20 @@ var DownloadAddonInstall = class extends
    *        A callback to prompt the user before installing.
    * @param {boolean} [options.sendCookies]
    *        Whether cookies should be sent when downloading the add-on.
    */
   constructor(installLocation, url, options = {}) {
     super(installLocation, url, options);
 
     this.browser = options.browser;
+    this.loadingPrincipal =
+      options.triggeringPrincipal ||
+      (this.browser && this.browser.contentPrincipal) ||
+      Services.scriptSecurityManager.getSystemPrincipal();
     this.sendCookies = Boolean(options.sendCookies);
 
     this.state = AddonManager.STATE_AVAILABLE;
 
     this.stream = null;
     this.crypto = null;
     this.badCertHandler = null;
     this.restartDownload = false;
@@ -1923,17 +1929,19 @@ var DownloadAddonInstall = class extends
     let listener = Cc["@mozilla.org/network/stream-listener-tee;1"].createInstance(Ci.nsIStreamListenerTee);
     listener.init(this, this.stream);
     try {
       let requireBuiltIn = Services.prefs.getBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, true);
       this.badCertHandler = new CertUtils.BadCertHandler(!requireBuiltIn);
 
       this.channel = NetUtil.newChannel({
         uri: this.sourceURI,
-        loadUsingSystemPrincipal: true,
+        securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS,
+        contentPolicyType: Ci.nsIContentPolicy.TYPE_SAVEAS_DOWNLOAD,
+        loadingPrincipal: this.loadingPrincipal,
       });
       this.channel.notificationCallbacks = this;
       if (this.sendCookies) {
         if (this.channel instanceof Ci.nsIHttpChannelInternal) {
           this.channel.forceAllowThirdPartyCookie = true;
         }
       } else {
         this.channel.loadFlags |= Ci.nsIRequest.LOAD_ANONYMOUS;