Bug 1444680: Part 2: Convert test_ext_webRequest_suspend to xpcshell. r?mixedpuppy draft
authorKris Maglione <maglione.k@gmail.com>
Sat, 10 Mar 2018 18:02:50 -0800
changeset 765936 2ccde4e7978cfdc26c68a738a16258e5a45433f9
parent 765935 7f84a6f61ffc2ac626f810b6f32d5a52b5725fa6
child 765937 27188a28141f967aa14e32acfe7b7f6a6261a624
push id102183
push usermaglione.k@gmail.com
push dateSun, 11 Mar 2018 06:57:39 +0000
reviewersmixedpuppy
bugs1444680
milestone60.0a1
Bug 1444680: Part 2: Convert test_ext_webRequest_suspend to xpcshell. r?mixedpuppy MozReview-Commit-ID: 8SoEdllfzSG
toolkit/components/extensions/test/mochitest/mochitest-common.ini
toolkit/components/extensions/test/mochitest/test_ext_webrequest_suspend.html
toolkit/components/extensions/test/xpcshell/test_ext_webRequest_suspend.js
toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
--- a/toolkit/components/extensions/test/mochitest/mochitest-common.ini
+++ b/toolkit/components/extensions/test/mochitest/mochitest-common.ini
@@ -162,16 +162,15 @@ skip-if = os == 'android'
 skip-if = os == 'android' && debug # bug 1397615
 [test_ext_webrequest_errors.html]
 [test_ext_webrequest_filter.html]
 [test_ext_webrequest_frameId.html]
 [test_ext_webrequest_hsts.html]
 [test_ext_webrequest_permission.html]
 [test_ext_webrequest_responseBody.html]
 skip-if = os == 'android' || os == 'linux' # linux, bug 1398120
-[test_ext_webrequest_suspend.html]
 [test_ext_webrequest_upgrade.html]
 [test_ext_webrequest_upload.html]
 skip-if = os == 'android' # Currently fails in emulator tests
 [test_ext_webrequest_websocket.html]
 [test_ext_webrequest_redirect_data_uri.html]
 [test_ext_window_postMessage.html]
 [test_ext_xhr_capabilities.html]
rename from toolkit/components/extensions/test/mochitest/test_ext_webrequest_suspend.html
rename to toolkit/components/extensions/test/xpcshell/test_ext_webRequest_suspend.js
--- a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_suspend.html
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_webRequest_suspend.js
@@ -1,33 +1,44 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for simple WebExtension</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
-  <script type="text/javascript" src="head.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-
-<script type="text/javascript">
 "use strict";
 
-// This file defines content scripts.
-/* eslint-env mozilla/frame-script */
+const HOSTS = new Set([
+  "example.com",
+]);
+
+const server = createHttpServer({hosts: HOSTS});
+
+const BASE_URL = "http://example.com";
+const FETCH_ORIGIN = "http://example.com/dummy";
+
+server.registerPathHandler("/return_headers.sjs", (request, response) => {
+  response.setHeader("Content-Type", "text/plain", false);
+
+  let headers = {};
+  // Why on earth is this a nsISimpleEnumerator...
+  for (let {data: header} of XPCOMUtils.IterSimpleEnumerator(request.headers,
+                                                             Ci.nsISupportsString)) {
+    headers[header.toLowerCase()] = request.getHeader(header);
+  }
+
+  response.write(JSON.stringify(headers));
+});
+
+server.registerPathHandler("/dummy", (request, response) => {
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write("ok");
+});
 
 add_task(async function test_suspend() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: [
         "webRequest",
         "webRequestBlocking",
-        "http://mochi.test/",
+        `${BASE_URL}/`,
       ],
     },
 
     background() {
       browser.webRequest.onBeforeSendHeaders.addListener(
         details => {
           // Make sure that returning undefined or a promise that resolves to
           // undefined does not break later handlers.
@@ -42,106 +53,104 @@ add_task(async function test_suspend() {
         {urls: ["<all_urls>"]},
         ["blocking", "requestHeaders"]);
 
       browser.webRequest.onBeforeSendHeaders.addListener(
         details => {
           let requestHeaders = details.requestHeaders.concat({name: "Foo", value: "Bar"});
 
           return new Promise(resolve => {
+            // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
             setTimeout(resolve, 500);
           }).then(() => {
             return {requestHeaders};
           });
         },
         {urls: ["<all_urls>"]},
         ["blocking", "requestHeaders"]);
     },
   });
 
   await extension.startup();
 
-  let result = await fetch(SimpleTest.getTestFileURL("return_headers.sjs"));
+  let headers = JSON.parse(await ExtensionTestUtils.fetch(FETCH_ORIGIN, `${BASE_URL}/return_headers.sjs`));
 
-  let headers = JSON.parse(await result.text());
-
-  is(headers.foo, "Bar", "Request header was correctly set on suspended request");
+  equal(headers.foo, "Bar", "Request header was correctly set on suspended request");
 
   await extension.unload();
 });
 
 
 // Test that requests that were canceled while suspended for a blocking
 // listener are correctly resumed.
 add_task(async function test_error_resume() {
-  let chromeScript = SpecialPowers.loadChromeScript(() => {
-    ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-    let observer = channel => {
-      if (channel instanceof Ci.nsIHttpChannel && channel.URI.spec === "http://example.com/") {
-        Services.obs.removeObserver(observer, "http-on-before-connect");
+  let observer = channel => {
+    if (channel instanceof Ci.nsIHttpChannel && channel.URI.spec === "http://example.com/dummy") {
+      Services.obs.removeObserver(observer, "http-on-before-connect");
 
-        // Wait until the next tick to make sure this runs after WebRequest observers.
-        Promise.resolve().then(() => {
-          channel.cancel(Cr.NS_BINDING_ABORTED);
-        });
-      }
-    };
+      // Wait until the next tick to make sure this runs after WebRequest observers.
+      Promise.resolve().then(() => {
+        channel.cancel(Cr.NS_BINDING_ABORTED);
+      });
+    }
+  };
 
-    Services.obs.addObserver(observer, "http-on-before-connect");
-  });
+  Services.obs.addObserver(observer, "http-on-before-connect");
+
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: [
         "webRequest",
         "webRequestBlocking",
-        "http://example.com/",
-        "http://mochi.test/",
+        `${BASE_URL}/`,
       ],
     },
 
     background() {
       browser.webRequest.onBeforeSendHeaders.addListener(
         details => {
           browser.test.log(`onBeforeSendHeaders({url: ${details.url}})`);
 
-          if (details.url === "http://example.com/") {
+          if (details.url === "http://example.com/dummy") {
             browser.test.sendMessage("got-before-send-headers");
           }
         },
         {urls: ["<all_urls>"]},
         ["blocking"]);
 
       browser.webRequest.onErrorOccurred.addListener(
         details => {
           browser.test.log(`onErrorOccurred({url: ${details.url}})`);
 
-          if (details.url === "http://example.com/") {
+          if (details.url === "http://example.com/dummy") {
             browser.test.sendMessage("got-error-occurred");
           }
         },
         {urls: ["<all_urls>"]});
     },
   });
 
   await extension.startup();
 
   try {
-    await fetch("http://example.com/");
+    await ExtensionTestUtils.fetch(FETCH_ORIGIN, `${BASE_URL}/dummy`);
     ok(false, "Fetch should have failed.");
   } catch (e) {
     ok(true, "Got expected error.");
   }
 
   await extension.awaitMessage("got-before-send-headers");
   await extension.awaitMessage("got-error-occurred");
 
+  // Wait for the next tick so the onErrorRecurred response can be
+  // processed before shutting down the extension.
+  await new Promise(resolve => executeSoon(resolve));
+
   await extension.unload();
-  chromeScript.destroy();
 });
 
 
 // Test that response header modifications take effect before onStartRequest fires.
 add_task(async function test_set_responseHeaders() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: [
@@ -164,18 +173,19 @@ add_task(async function test_set_respons
         ["blocking", "responseHeaders"]);
     },
   });
 
   await extension.startup();
 
   await new Promise(resolve => setTimeout(resolve, 0));
 
-  let chromeScript = SpecialPowers.loadChromeScript(() => {
-    ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
+  let resolveHeaderPromise;
+  let headerPromise = new Promise(resolve => { resolveHeaderPromise = resolve; });
+  {
     ChromeUtils.import("resource://gre/modules/Services.jsm");
     ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
     let ssm = Services.scriptSecurityManager;
 
     let channel = NetUtil.newChannel({
       uri: "http://example.com/?modify_headers",
       loadingPrincipal: ssm.createCodebasePrincipalFromOrigin("http://example.com"),
@@ -185,48 +195,47 @@ add_task(async function test_set_respons
 
     channel.asyncOpen2({
       QueryInterface: XPCOMUtils.generateQI([Ci.nsIStreamListener]),
 
       onStartRequest(request, context) {
         request.QueryInterface(Ci.nsIHttpChannel);
 
         try {
-          sendAsyncMessage("response-header-foo", request.getResponseHeader("foo"));
+          resolveHeaderPromise(request.getResponseHeader("foo"));
         } catch (e) {
-          sendAsyncMessage("response-header-foo", null);
+          resolveHeaderPromise(null);
         }
         request.cancel(Cr.NS_BINDING_ABORTED);
       },
 
       onStopRequest() {
       },
 
       onDataAvailable() {
         throw new Components.Exception("", Cr.NS_ERROR_FAILURE);
       },
     });
-  });
+  }
 
-  let headerValue = await chromeScript.promiseOneMessage("response-header-foo");
-  is(headerValue, "bar", "Expected Foo header value");
+  let headerValue = await headerPromise;
+  equal(headerValue, "bar", "Expected Foo header value");
 
   await extension.unload();
-  chromeScript.destroy();
 });
 
 // Test that exceptions raised from a blocking webRequest listener that returns
 // a promise are logged as expected.
 add_task(async function test_logged_error_on_promise_result() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: [
         "webRequest",
         "webRequestBlocking",
-        "http://mochi.test/*",
+        `${BASE_URL}/`,
       ],
     },
 
     background() {
       async function onBeforeRequest() {
         throw new Error("Expected webRequest exception from a promise result");
       }
 
@@ -236,45 +245,34 @@ add_task(async function test_logged_erro
         if (exceptionRaised) {
           return;
         }
 
         // We only need to raise the exception once.
         exceptionRaised = true;
         return onBeforeRequest();
       }, {
-        urls: ["http://mochi.test/*"],
+        urls: ["http://example.com/*"],
         types: ["main_frame"],
       }, ["blocking"]);
 
       browser.webRequest.onBeforeRequest.addListener(() => {
         browser.test.sendMessage("web-request-event-received");
       }, {
-        urls: ["http://mochi.test/*"],
+        urls: ["http://example.com/*"],
         types: ["main_frame"],
       }, ["blocking"]);
-
-      browser.test.sendMessage("background-ready");
     },
   });
 
-  // Start to monitor the console service for the expected console message.
-  consoleMonitor.start([{message: /Expected webRequest exception from a promise result/}]);
-
-  await extension.startup();
-
-  await extension.awaitMessage("background-ready");
+  let {messages} = await promiseConsoleOutput(async () => {
+    await extension.startup();
 
-  const testWin = window.open("http://mochi.test:8888/", "_blank", "width=100,height=100");
-  await waitForLoad(testWin);
-  await extension.awaitMessage("web-request-event-received");
-  testWin.close();
+    let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/dummy`, {remote: true});
+    await extension.awaitMessage("web-request-event-received");
+    await contentPage.close();
+  });
 
-  // Check that the collected messages contains the expected console message, and fails
-  // otherwise.
-  await consoleMonitor.finished();
+  ok(messages.some(msg => /Expected webRequest exception from a promise result/.test(msg.message)),
+     "Got expected console message");
 
   await extension.unload();
 });
-
-</script>
-</body>
-</html>
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
@@ -77,16 +77,17 @@ 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_trustworthy_origin.js]
 [test_ext_topSites.js]
 skip-if = os == "android"
 [test_ext_webRequest_filterResponseData.js]
+[test_ext_webRequest_suspend.js]
 [test_native_manifests.js]
 subprocess = true
 skip-if = os == "android"
 [test_ext_permissions.js]
 skip-if = os == "android" # Bug 1350559
 [test_proxy_listener.js]
 [test_proxy_scripts.js]
 [test_proxy_scripts_results.js]