Backed out changeset 641430a49682 (bug 1402066)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 26 Sep 2017 11:37:44 +0200
changeset 433732 998dd0100a61ba5ceafe8fe27b13753b3537a8bd
parent 433731 f9df54bc39999524555f6d24ff609627fdc7553c
child 433733 6a9d008002efc9044416d5fff5713f899c954ebb
push id8114
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 16:33:21 +0000
treeherdermozilla-beta@73e0d89a540f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1402066
milestone58.0a1
backs out641430a496824e34170786f6f3bc5e587f2056eb
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
Backed out changeset 641430a49682 (bug 1402066)
toolkit/components/extensions/ExtensionXPCShellUtils.jsm
toolkit/components/extensions/test/xpcshell/test_ext_permissions.js
toolkit/components/extensions/test/xpcshell/test_ext_redirects.js
toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
toolkit/components/extensions/test/xpcshell/xpcshell.ini
--- a/toolkit/components/extensions/ExtensionXPCShellUtils.jsm
+++ b/toolkit/components/extensions/ExtensionXPCShellUtils.jsm
@@ -90,19 +90,18 @@ function promiseBrowserLoaded(browser, u
     // use one. But we also need to make sure it stays alive until we're
     // done with it, so thunk away a strong reference to keep it alive.
     kungFuDeathGrip.add(listener);
     browser.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
   });
 }
 
 class ContentPage {
-  constructor(remote = REMOTE_CONTENT_SCRIPTS, extension = null) {
+  constructor(remote = REMOTE_CONTENT_SCRIPTS) {
     this.remote = remote;
-    this.extension = extension;
 
     this.browserReady = this._initBrowser();
   }
 
   async _initBrowser() {
     this.windowlessBrowser = Services.appShell.createWindowlessBrowser(true);
 
     let system = Services.scriptSecurityManager.getSystemPrincipal();
@@ -119,22 +118,16 @@ class ContentPage {
                           win => win.document == chromeShell.document);
 
     let chromeDoc = await promiseDocumentLoaded(chromeShell.document);
 
     let browser = chromeDoc.createElement("browser");
     browser.setAttribute("type", "content");
     browser.setAttribute("disableglobalhistory", "true");
 
-    if (this.extension && this.extension.remote) {
-      browser.setAttribute("remote", "true");
-      browser.setAttribute("remoteType", "extension");
-      browser.sameProcessAsFrameLoader = this.extension.groupFrameLoader;
-    }
-
     let awaitFrameLoader = Promise.resolve();
     if (this.remote) {
       awaitFrameLoader = promiseEvent(browser, "XULFrameLoaderCreated");
       browser.setAttribute("remote", "true");
     }
 
     chromeDoc.documentElement.appendChild(browser);
 
@@ -690,34 +683,16 @@ var ExtensionTestUtils = {
   get remoteContentScripts() {
     return REMOTE_CONTENT_SCRIPTS;
   },
 
   set remoteContentScripts(val) {
     REMOTE_CONTENT_SCRIPTS = !!val;
   },
 
-  /**
-   * Loads a content page into a hidden docShell.
-   *
-   * @param {string} url
-   *        The URL to load.
-   * @param {object} [options = {}]
-   * @param {ExtensionWrapper} [options.extension]
-   *        If passed, load the URL as an extension page for the given
-   *        extension.
-   * @param {boolean} [options.remote]
-   *        If true, load the URL in a content process. If false, load
-   *        it in the parent process.
-   * @param {string} [options.redirectUrl]
-   *        An optional URL that the initial page is expected to
-   *        redirect to.
-   *
-   * @returns {ContentPage}
-   */
-  loadContentPage(url, {extension = undefined, remote = undefined, redirectUrl = undefined} = {}) {
-    let contentPage = new ContentPage(remote, extension && extension.extension);
+  loadContentPage(url, remote = undefined, redirectUrl = undefined) {
+    let contentPage = new ContentPage(remote);
 
     return contentPage.loadURL(url, redirectUrl).then(() => {
       return contentPage;
     });
   },
 };
--- a/toolkit/components/extensions/test/xpcshell/test_ext_permissions.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_permissions.js
@@ -1,52 +1,36 @@
 "use strict";
 
+XPCOMUtils.defineLazyGetter(this, "ExtensionManager", () => {
+  const {ExtensionManager}
+    = Cu.import("resource://gre/modules/ExtensionChild.jsm", {});
+  return ExtensionManager;
+});
 Cu.import("resource://gre/modules/ExtensionPermissions.jsm");
-Cu.import("resource://gre/modules/MessageChannel.jsm");
 
 const BROWSER_PROPERTIES = "chrome://browser/locale/browser.properties";
 
 AddonTestUtils.init(this);
 AddonTestUtils.overrideCertDB();
 AddonTestUtils.createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
 
-let extensionHandlers = new WeakSet();
-
-function frameScript() {
-  /* globals content */
-  const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-  Cu.import("resource://gre/modules/MessageChannel.jsm");
-
-  let handle;
-  MessageChannel.addListener(this, "ExtensionTest:HandleUserInput", {
-    receiveMessage({name, data}) {
-      if (data) {
-        handle = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                        .getInterface(Ci.nsIDOMWindowUtils)
-                        .setHandlingUserInput(true);
-      } else if (handle) {
-        handle.destruct();
-        handle = null;
-      }
-    },
-  });
-}
-
-async function withHandlingUserInput(extension, fn) {
-  let {messageManager} = extension.extension.groupFrameLoader;
-
-  if (!extensionHandlers.has(extension)) {
-    messageManager.loadFrameScript(`data:,(${frameScript})(this)`, false);
-    extensionHandlers.add(extension);
+// Find the DOMWindowUtils for the background page for the given
+// extension (wrapper)
+function findWinUtils(extension) {
+  let extensionChild = ExtensionManager.extensions.get(extension.extension.id);
+  let bgwin = null;
+  for (let view of extensionChild.views) {
+    if (view.viewType == "background") {
+      bgwin = view.contentWindow;
+    }
   }
-
-  await MessageChannel.sendMessage(messageManager, "ExtensionTest:HandleUserInput", true);
-  await fn();
-  await MessageChannel.sendMessage(messageManager, "ExtensionTest:HandleUserInput", false);
+  notEqual(bgwin, null, "Found background window for the test extension");
+  return bgwin.QueryInterface(Ci.nsIInterfaceRequestor)
+              .getInterface(Ci.nsIDOMWindowUtils);
 }
 
 let sawPrompt = false;
 let acceptPrompt = false;
 const observer = {
   observe(subject, topic, data) {
     if (topic == "webextension-optional-permission-prompt") {
       sawPrompt = true;
@@ -105,16 +89,17 @@ add_task(async function test_permissions
     manifest: {
       permissions: [...REQUIRED_PERMISSIONS, ...REQUIRED_ORIGINS],
       optional_permissions: [...OPTIONAL_PERMISSIONS, ...OPTIONAL_ORIGINS],
     },
     useAddonManager: "permanent",
   });
 
   await extension.startup();
+  let winUtils = findWinUtils(extension);
 
   function call(method, arg) {
     extension.sendMessage(method, arg);
     return extension.awaitMessage(`${method}.result`);
   }
 
   let result = await call("getAll");
   deepEqual(result.permissions, REQUIRED_PERMISSIONS);
@@ -147,41 +132,42 @@ add_task(async function test_permissions
   let perm = OPTIONAL_PERMISSIONS[0];
   result = await call("request", {permissions: [perm]});
   equal(result.status, "error", "request() fails if not called from an event handler");
   ok(/request may only be called from a user input handler/.test(result.message),
      "error message for calling request() outside an event handler is reasonable");
   result = await call("contains", {permissions: [perm]});
   equal(result, false, "Permission requested outside an event handler was not granted");
 
-  await withHandlingUserInput(extension, async () => {
-    result = await call("request", {permissions: ["notifications"]});
-    equal(result.status, "error", "request() for permission not in optional_permissions should fail");
-    ok(/since it was not declared in optional_permissions/.test(result.message),
-       "error message for undeclared optional_permission is reasonable");
+  let userInputHandle = winUtils.setHandlingUserInput(true);
 
-    // Check request() when the prompt is canceled.
-    acceptPrompt = false;
-    result = await call("request", {permissions: [perm]});
-    equal(result.status, "success", "request() returned cleanly");
-    equal(result.result, false, "request() returned false for rejected permission");
+  result = await call("request", {permissions: ["notifications"]});
+  equal(result.status, "error", "request() for permission not in optional_permissions should fail");
+  ok(/since it was not declared in optional_permissions/.test(result.message),
+     "error message for undeclared optional_permission is reasonable");
+
+  // Check request() when the prompt is canceled.
+  acceptPrompt = false;
+  result = await call("request", {permissions: [perm]});
+  equal(result.status, "success", "request() returned cleanly");
+  equal(result.result, false, "request() returned false for rejected permission");
 
-    result = await call("contains", {permissions: [perm]});
-    equal(result, false, "Rejected permission was not granted");
+  result = await call("contains", {permissions: [perm]});
+  equal(result, false, "Rejected permission was not granted");
 
-    // Call request() and accept the prompt
-    acceptPrompt = true;
-    let allOptional = {
-      permissions: OPTIONAL_PERMISSIONS,
-      origins: OPTIONAL_ORIGINS,
-    };
-    result = await call("request", allOptional);
-    equal(result.status, "success", "request() returned cleanly");
-    equal(result.result, true, "request() returned true for accepted permissions");
-  });
+  // Call request() and accept the prompt
+  acceptPrompt = true;
+  let allOptional = {
+    permissions: OPTIONAL_PERMISSIONS,
+    origins: OPTIONAL_ORIGINS,
+  };
+  result = await call("request", allOptional);
+  equal(result.status, "success", "request() returned cleanly");
+  equal(result.result, true, "request() returned true for accepted permissions");
+  userInputHandle.destruct();
 
   let allPermissions = {
     permissions: [...REQUIRED_PERMISSIONS, ...OPTIONAL_PERMISSIONS],
     origins: [...REQUIRED_ORIGINS_NORMALIZED, ...OPTIONAL_ORIGINS_NORMALIZED],
   };
 
   result = await call("getAll");
   deepEqual(result, allPermissions, "getAll() returns required and runtime requested permissions");
@@ -249,25 +235,27 @@ add_task(async function test_startup() {
   });
 
   await extension1.startup();
   await extension2.startup();
 
   let perms = await extension1.awaitMessage("perms");
   perms = await extension2.awaitMessage("perms");
 
-  await withHandlingUserInput(extension1, async () => {
-    extension1.sendMessage(PERMS1);
-    await extension1.awaitMessage("requested");
-  });
+  let winUtils = findWinUtils(extension1);
+  let handle = winUtils.setHandlingUserInput(true);
+  extension1.sendMessage(PERMS1);
+  await extension1.awaitMessage("requested");
+  handle.destruct();
 
-  await withHandlingUserInput(extension2, async () => {
-    extension2.sendMessage(PERMS2);
-    await extension2.awaitMessage("requested");
-  });
+  winUtils = findWinUtils(extension2);
+  handle = winUtils.setHandlingUserInput(true);
+  extension2.sendMessage(PERMS2);
+  await extension2.awaitMessage("requested");
+  handle.destruct();
 
   // Restart everything, and force the permissions store to be
   // re-read on startup
   ExtensionPermissions._uninit();
   await AddonTestUtils.promiseRestartManager();
   await extension1.awaitStartup();
   await extension2.awaitStartup();
 
@@ -330,55 +318,57 @@ add_task(async function test_alreadyGran
         </head></html>`,
 
       "page.js": pageScript,
     },
   });
 
   await extension.startup();
 
-  await withHandlingUserInput(extension, async () => {
-    let url = await extension.awaitMessage("ready");
-    await ExtensionTestUtils.loadContentPage(url, {extension});
-    await extension.awaitMessage("page-ready");
+  let winUtils = findWinUtils(extension);
+  let handle = winUtils.setHandlingUserInput(true);
+
+  let url = await extension.awaitMessage("ready");
+  await ExtensionTestUtils.loadContentPage(url);
+  await extension.awaitMessage("page-ready");
 
-    async function checkRequest(arg, expectPrompt, msg) {
-      sawPrompt = false;
-      extension.sendMessage("request", arg);
-      let result = await extension.awaitMessage("request.result");
-      ok(result, "request() call succeeded");
-      equal(sawPrompt, expectPrompt,
-            `Got ${expectPrompt ? "" : "no "}permission prompt for ${msg}`);
-    }
+  async function checkRequest(arg, expectPrompt, msg) {
+    sawPrompt = false;
+    extension.sendMessage("request", arg);
+    let result = await extension.awaitMessage("request.result");
+    ok(result, "request() call succeeded");
+    equal(sawPrompt, expectPrompt,
+          `Got ${expectPrompt ? "" : "no "}permission prompt for ${msg}`);
+  }
 
-    await checkRequest({permissions: ["geolocation"]}, false,
-                       "required permission from manifest");
-    await checkRequest({origins: ["http://required-host.com/"]}, false,
-                       "origin permission from manifest");
-    await checkRequest({origins: ["http://host.required-domain.com/"]}, false,
-                       "wildcard origin permission from manifest");
+  await checkRequest({permissions: ["geolocation"]}, false,
+                     "required permission from manifest");
+  await checkRequest({origins: ["http://required-host.com/"]}, false,
+                     "origin permission from manifest");
+  await checkRequest({origins: ["http://host.required-domain.com/"]}, false,
+                     "wildcard origin permission from manifest");
 
-    await checkRequest({permissions: ["clipboardRead"]}, true,
-                       "optional permission");
-    await checkRequest({permissions: ["clipboardRead"]}, false,
-                       "already granted optional permission");
+  await checkRequest({permissions: ["clipboardRead"]}, true,
+                     "optional permission");
+  await checkRequest({permissions: ["clipboardRead"]}, false,
+                     "already granted optional permission");
 
-    await checkRequest({origins: ["http://optional-host.com/"]}, true,
-                       "optional origin");
-    await checkRequest({origins: ["http://optional-host.com/"]}, false,
-                       "already granted origin permission");
+  await checkRequest({origins: ["http://optional-host.com/"]}, true,
+                     "optional origin");
+  await checkRequest({origins: ["http://optional-host.com/"]}, false,
+                     "already granted origin permission");
 
-    await checkRequest({origins: ["http://*.optional-domain.com/"]}, true,
-                       "optional wildcard origin");
-    await checkRequest({origins: ["http://*.optional-domain.com/"]}, false,
-                       "already granted optional wildcard origin");
-    await checkRequest({origins: ["http://host.optional-domain.com/"]}, false,
-                       "host matching optional wildcard origin");
-  });
+  await checkRequest({origins: ["http://*.optional-domain.com/"]}, true,
+                     "optional wildcard origin");
+  await checkRequest({origins: ["http://*.optional-domain.com/"]}, false,
+                     "already granted optional wildcard origin");
+  await checkRequest({origins: ["http://host.optional-domain.com/"]}, false,
+                     "host matching optional wildcard origin");
 
+  handle.destruct();
   await extension.unload();
 });
 
 // IMPORTANT: Do not change this list without review from a Web Extensions peer!
 
 const GRANTED_WITHOUT_USER_PROMPT = [
   "activeTab",
   "alarms",
--- a/toolkit/components/extensions/test/xpcshell/test_ext_redirects.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_redirects.js
@@ -143,44 +143,44 @@ add_task(async function test_channel_red
 add_task(async function test_content_redirect_to_non_accessible_resource() {
   let extension = getExtension();
   await extension.startup();
   let redirectUrl = await extension.awaitMessage("redirectURI");
   let url = `${gServerUrl}/redirect?redirect_uri=${redirectUrl}`;
   let watcher = onModifyListener(url).then(channel => {
     return onStopListener(channel);
   });
-  let contentPage = await ExtensionTestUtils.loadContentPage(url, {redirectURL: "about:blank"});
+  let contentPage = await ExtensionTestUtils.loadContentPage(url, undefined, "about:blank");
   equal(contentPage.browser.documentURI.spec, "about:blank", `expected no redirect`);
   equal(await watcher, url, "expected no redirect");
   await contentPage.close();
   await extension.unload();
 });
 
 // This test makes a request against a server that redirects with a 302.
 add_task(async function test_content_302_redirect_to_extension() {
   let extension = getExtension(true);
   await extension.startup();
   let redirectUrl = await extension.awaitMessage("redirectURI");
   let url = `${gServerUrl}/redirect?redirect_uri=${redirectUrl}`;
-  let contentPage = await ExtensionTestUtils.loadContentPage(url, {redirectUrl});
+  let contentPage = await ExtensionTestUtils.loadContentPage(url, undefined, redirectUrl);
   equal(contentPage.browser.documentURI.spec, redirectUrl, `expected redirect`);
   await contentPage.close();
   await extension.unload();
 });
 
 // This test uses channel.redirectTo during http-on-modify to redirect to the
 // moz-extension url.
 add_task(async function test_content_channel_redirect_to_extension() {
   let extension = getExtension(true);
   await extension.startup();
   let redirectUrl = await extension.awaitMessage("redirectURI");
   let url = `${gServerUrl}/dummy?r=${Math.random()}`;
   onModifyListener(url, redirectUrl);
-  let contentPage = await ExtensionTestUtils.loadContentPage(url, {redirectUrl});
+  let contentPage = await ExtensionTestUtils.loadContentPage(url, undefined, redirectUrl);
   equal(contentPage.browser.documentURI.spec, redirectUrl, `expected redirect`);
   await contentPage.close();
   await extension.unload();
 });
 
 // This test makes a request against a server and tests webrequest.  Currently
 // disabled due to NS_BINDING_ABORTED happening.
 add_task(async function test_extension_302_redirect() {
@@ -200,17 +200,17 @@ add_task(async function test_extension_3
     }, {urls: ["<all_urls>", myuri]});
     // send the extensions public uri to the test.
     browser.test.sendMessage("redirectURI", exturi);
   });
   await extension.startup();
   let redirectUrl = await extension.awaitMessage("redirectURI");
   let completed = extension.awaitFinish("requestCompleted");
   let url = `${gServerUrl}/redirect?r=${Math.random()}&redirect_uri=${redirectUrl}`;
-  let contentPage = await ExtensionTestUtils.loadContentPage(url, {redirectUrl});
+  let contentPage = await ExtensionTestUtils.loadContentPage(url, undefined, redirectUrl);
   equal(contentPage.browser.documentURI.spec, redirectUrl, `expected content redirect`);
   await completed;
   await contentPage.close();
   await extension.unload();
 }).skip();
 
 // This test makes a request and uses onBeforeRequet to redirect to moz-ext.
 // Currently disabled due to NS_BINDING_ABORTED happening.
@@ -234,14 +234,14 @@ add_task(async function test_extension_r
     }, {urls: ["<all_urls>", myuri]});
     // send the extensions public uri to the test.
     browser.test.sendMessage("redirectURI", exturi);
   });
   await extension.startup();
   let redirectUrl = await extension.awaitMessage("redirectURI");
   let completed = extension.awaitFinish("requestCompleted");
   let url = `${gServerUrl}/dummy?r=${Math.random()}`;
-  let contentPage = await ExtensionTestUtils.loadContentPage(url, {redirectUrl});
+  let contentPage = await ExtensionTestUtils.loadContentPage(url, undefined, redirectUrl);
   equal(contentPage.browser.documentURI.spec, redirectUrl, `expected redirect`);
   await completed;
   await contentPage.close();
   await extension.unload();
 }).skip();
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
@@ -69,13 +69,11 @@ skip-if = os == "android"
 [test_ext_storage_sync_crypto.js]
 skip-if = os == "android"
 [test_ext_storage_telemetry.js]
 skip-if = os == "android" # checking for telemetry needs to be updated: 1384923
 [test_ext_topSites.js]
 skip-if = os == "android"
 [test_native_manifests.js]
 skip-if = os == "android"
-[test_ext_permissions.js]
-skip-if = os == "android" # Bug 1350559
 [test_proxy_scripts.js]
 skip-if = os == "linux" # bug 1393940
 [test_proxy_scripts_results.js]
--- a/toolkit/components/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell.ini
@@ -43,12 +43,14 @@ tags = webextensions in-process-webexten
 [test_ext_schemas_allowed_contexts.js]
 [test_ext_schemas_interactive.js]
 [test_ext_schemas_revoke.js]
 [test_ext_themes_supported_properties.js]
 [test_ext_unknown_permissions.js]
 [test_locale_converter.js]
 [test_locale_data.js]
 
+[test_ext_permissions.js]
+skip-if = os == "android" # Bug 1350559
 [test_ext_runtime_sendMessage_args.js]
 
 [include:xpcshell-common.ini]
 [include:xpcshell-content.ini]