Bug 1498343 - Fix and re-enable userScript test disabled in Bug 1498343. r=zombie
authorLuca Greco <lgreco@mozilla.com>
Thu, 18 Oct 2018 12:19:51 +0000
changeset 500650 c68fc2d0347185ab54ef90462b9b294f82cc50be
parent 500649 b466e005ccbb79b108abb8d0083ef5a2ca928057
child 500651 a0aa0b0aa078f7135e7d7032687e4a38e6c378f8
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerszombie
bugs1498343
milestone64.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 1498343 - Fix and re-enable userScript test disabled in Bug 1498343. r=zombie Differential Revision: https://phabricator.services.mozilla.com/D8537
toolkit/components/extensions/extension-process-script.js
toolkit/components/extensions/test/xpcshell/test_ext_userScripts.js
--- a/toolkit/components/extensions/extension-process-script.js
+++ b/toolkit/components/extensions/extension-process-script.js
@@ -158,24 +158,25 @@ ExtensionManager = {
 
       // Register any existent dynamically registered content script for the extension
       // when a content process is started for the first time (which also cover
       // a content process that crashed and it has been recreated).
       const registeredContentScripts = this.registeredContentScripts.get(policy);
 
       for (let [scriptId, options] of getData(extension, "contentScripts") || []) {
         const script = new WebExtensionContentScript(policy, options);
-        policy.registerContentScript(script);
-        registeredContentScripts.set(scriptId, script);
 
         // If the script is a userScript, add the additional userScriptOptions
         // property to the WebExtensionContentScript instance.
         if ("userScriptOptions" in options) {
           script.userScriptOptions = options.userScriptOptions;
         }
+
+        policy.registerContentScript(script);
+        registeredContentScripts.set(scriptId, script);
       }
 
       policy.active = true;
       policy.instanceId = extension.instanceId;
       policy.optionalPermissions = extension.optionalPermissions;
     }
     return policy;
   },
--- a/toolkit/components/extensions/test/xpcshell/test_ext_userScripts.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_userScripts.js
@@ -1,24 +1,32 @@
 "use strict";
 
+const PROCESS_COUNT_PREF = "dom.ipc.processCount";
+
 const {
   createAppInfo,
 } = AddonTestUtils;
 
 AddonTestUtils.init(this);
 
 createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "49");
 
 const server = createHttpServer();
 server.registerDirectory("/data/", do_get_file("data"));
 
 const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`;
 
 add_task(async function setup_test_environment() {
+  if (ExtensionTestUtils.remoteContentScripts) {
+    // Start with one content process so that we can increase the number
+    // later and test the behavior of a fresh content process.
+    Services.prefs.setIntPref(PROCESS_COUNT_PREF, 1);
+  }
+
   // Grant the optional permissions requested.
   function permissionObserver(subject, topic, data) {
     if (topic == "webextension-optional-permission-prompt") {
       let {resolve} = subject.wrappedJSObject;
       resolve(true);
     }
   }
   Services.obs.addObserver(permissionObserver, "webextension-optional-permission-prompt");
@@ -152,70 +160,74 @@ add_task(async function test_userScripts
   // Test that all the matches are now subsumed by the extension permissions.
   extension.sendMessage("test-allowed-matches");
   await extension.awaitMessage("test-allowed-matches:done");
 
   await extension.unload();
 });
 
 // Test that userScripts sandboxes:
-// - can be registered/unregistered from an extension page
+// - can be registered/unregistered from an extension page (and they are registered on both new and
+//   existing processes).
 // - have no WebExtensions APIs available
 // - are able to access the target window and document
-
-// Temporarily disabled due to bug 1498364
-/* eslint-disable indent */
-if (false) {
 add_task(async function test_userScripts_no_webext_apis() {
   async function background() {
-    const matches = ["http://localhost/*/file_sample.html"];
+    const matches = ["http://localhost/*/file_sample.html*"];
 
     const sharedCode = {code: "console.log(\"js code shared by multiple userScripts\");"};
 
-    let script = await browser.userScripts.register({
+    const userScriptOptions = {
       js: [sharedCode, {
         code: `
           window.addEventListener("load", () => {
             const webextAPINamespaces = this.browser ? Object.keys(this.browser) : undefined;
             document.body.innerHTML = "userScript loaded - " + JSON.stringify(webextAPINamespaces);
           }, {once: true});
         `,
       }],
       runAt: "document_start",
       matches,
       scriptMetadata: {
         name: "test-user-script",
         arrayProperty: ["el1"],
         objectProperty: {nestedProp: "nestedValue"},
         nullProperty: null,
       },
-    });
+    };
+
+    let script = await browser.userScripts.register(userScriptOptions);
 
     // Unregister and then register the same js code again, to verify that the last registered
     // userScript doesn't get assigned a revoked blob url (otherwise Extensioncontent.jsm
     // ScriptCache raises an error because it fails to compile the revoked blob url and the user
     // script will never be loaded).
     script.unregister();
-    script = await browser.userScripts.register({
-      js: [sharedCode, {
-        code: `
+    script = await browser.userScripts.register(userScriptOptions);
+
+    browser.test.onMessage.addListener(async msg => {
+      if (msg !== "register-new-script") {
+        return;
+      }
+
+      await script.unregister();
+      await browser.userScripts.register({
+        ...userScriptOptions,
+        scriptMetadata: {name: "test-new-script"},
+        js: [sharedCode, {
+          code: `
           window.addEventListener("load", () => {
             const webextAPINamespaces = this.browser ? Object.keys(this.browser) : undefined;
-            document.body.innerHTML = "userScript loaded - " + JSON.stringify(webextAPINamespaces);
+            document.body.innerHTML = "new userScript loaded - " + JSON.stringify(webextAPINamespaces);
           }, {once: true});
         `,
-      }],
-      runAt: "document_start",
-      matches,
-      scriptMetadata: {
-        name: "test-user-script",
-        arrayProperty: ["el1"],
-        objectProperty: {nestedProp: "nestedValue"},
-        nullProperty: null,
-      },
+        }],
+      });
+
+      browser.test.sendMessage("script-registered");
     });
 
     const scriptToRemove = await browser.userScripts.register({
       js: [sharedCode, {
         code: `
           window.addEventListener("load", () => {
             document.body.innerHTML = "unexpected unregistered userScript loaded";
           }, {once: true});
@@ -248,61 +260,66 @@ add_task(async function test_userScripts
   };
 
   let extension = ExtensionTestUtils.loadExtension(extensionData);
 
   await extension.startup();
 
   await extension.awaitMessage("background-ready");
 
-  // Test in an existing process (where the registered userScripts has been received from the
-  // Extension:RegisterContentScript message sent to all the processes).
-  info("Test content script loaded in a process created before any registered userScript");
-  let url = `${BASE_URL}/file_sample.html#remote-false`;
-  let contentPage = await ExtensionTestUtils.loadContentPage(url, {remote: false});
+  let url = `${BASE_URL}/file_sample.html?testpage=1`;
+  let contentPage = await ExtensionTestUtils.loadContentPage(
+    url, ExtensionTestUtils.remoteContentScripts ? {remote: true} : undefined);
   let result = await contentPage.spawn(undefined, async () => {
     return {
       textContent: this.content.document.body.textContent,
       url: this.content.location.href,
       readyState: this.content.document.readyState,
     };
   });
   Assert.deepEqual(result, {
     textContent: "userScript loaded - undefined",
     url,
     readyState: "complete",
   }, "The userScript executed on the expected url and no access to the WebExtensions APIs");
-  await contentPage.close();
+
+  // If the tests is running with "remote content process" mode, test that the userScript
+  // are being correctly registered in newly created processes (received as part of the sharedData).
+  if (ExtensionTestUtils.remoteContentScripts) {
+    info("Test content script are correctly created on a newly created process");
 
-  // Test in a new process (where the registered userScripts has to be retrieved from the extension
-  // representation from the shared memory data).
-  // NOTE: this part is currently skipped on Android, where e10s content is not yet supported and
-  // the xpcshell test crash when we create contentPage2 with `remote = true`.
-  if (ExtensionTestUtils.remoteContentScripts) {
-    info("Test content script loaded in a process created after the userScript has been registered");
-    let url2 = `${BASE_URL}/file_sample.html#remote-true`;
+    await extension.sendMessage("register-new-script");
+    await extension.awaitMessage("script-registered");
+
+    // Update the process count preference, so that we can test that the newly registered user script
+    // is propagated as expected into the newly created process.
+    Services.prefs.setIntPref(PROCESS_COUNT_PREF, 2);
+
+    const url2 = `${BASE_URL}/file_sample.html?testpage=2`;
     let contentPage2 = await ExtensionTestUtils.loadContentPage(url2, {remote: true});
     let result2 = await contentPage2.spawn(undefined, async () => {
       return {
         textContent: this.content.document.body.textContent,
         url: this.content.location.href,
         readyState: this.content.document.readyState,
       };
     });
     Assert.deepEqual(result2, {
-      textContent: "userScript loaded - undefined",
+      textContent: "new userScript loaded - undefined",
       url: url2,
       readyState: "complete",
     }, "The userScript executed on the expected url and no access to the WebExtensions APIs");
+
     await contentPage2.close();
   }
 
+  await contentPage.close();
+
   await extension.unload();
 });
-}
 
 add_task(async function test_userScripts_exported_APIs() {
   async function background() {
     const matches = ["http://localhost/*/file_sample.html"];
 
     await browser.runtime.onMessage.addListener(async (msg, sender) => {
       return {bgPageReply: true};
     });