Bug 1557386 - Testing CORS content and errors for beacon. r=ckerschb
authorJonathan Kingston <jonathan@jooped.co.uk>
Fri, 22 May 2020 11:51:46 +0000
changeset 531759 625f46790646368f7aa9163db21121b90c6cd593
parent 531758 f4da1835858c0db71e18276baea926f75c710fe4
child 531760 6cd8944abc662799cf0b1d273e5f3013abc6d49f
push id37443
push usercbrindusan@mozilla.com
push dateSat, 23 May 2020 21:42:57 +0000
treeherdermozilla-central@9a2f741cef6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb
bugs1557386
milestone78.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 1557386 - Testing CORS content and errors for beacon. r=ckerschb Differential Revision: https://phabricator.services.mozilla.com/D75804
dom/tests/mochitest/beacon/beacon-handler.sjs
dom/tests/mochitest/beacon/chrome.ini
dom/tests/mochitest/beacon/file_beaconSafelist.html
dom/tests/mochitest/beacon/test_beaconWithSafelistedContentType.html
--- a/dom/tests/mochitest/beacon/beacon-handler.sjs
+++ b/dom/tests/mochitest/beacon/beacon-handler.sjs
@@ -49,16 +49,23 @@ function handleRequest(request, response
     response.write(JSON.stringify(result));
     setOurState(null);
   }
 
   if (request.method == "GET") {
     DEBUG(" ------------ GET --------------- ");
     response.setHeader("Content-Type", "application/json", false);
     switch (request.queryString) {
+    case "getLastBeaconCors":
+      // Allow CORS responses of the last beacon
+      var originHeader = request.getHeader("origin");
+      response.setHeader("Access-Control-Allow-Headers", "content-type", false);
+      response.setHeader("Access-Control-Allow-Methods", "POST, GET", false);
+      response.setHeader("Access-Control-Allow-Origin", originHeader, false);
+      response.setHeader("Access-Control-Allow-Credentials", "true", false);
     case "getLastBeacon":
       var state = getOurState();
       if (state === "unblocked") {
         finishControlResponse(response);
       } else {
         DEBUG("GET has  arrived, but POST has not, blocking response!");
         setOurState(response);
         response.processAsync();
--- a/dom/tests/mochitest/beacon/chrome.ini
+++ b/dom/tests/mochitest/beacon/chrome.ini
@@ -1,7 +1,10 @@
 [DEFAULT]
 skip-if = os == 'android'
 
 [test_beaconCookies.html]
 skip-if = (verify && !debug && (os == 'win'))
 support-files = beacon-set-cookie.sjs
                 file_beaconCookies.html
+[test_beaconWithSafelistedContentType.html]
+support-files = beacon-handler.sjs
+                file_beaconSafelist.html
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/beacon/file_beaconSafelist.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<script class="testbody" type="text/javascript">
+
+var beaconUrl = "http://example.com/tests/dom/tests/mochitest/beacon/beacon-handler.sjs?beacon";
+
+var value = ["text"];
+var blob = new Blob(value, {type: "application/x-www-form-urlencoded"});
+navigator.sendBeacon(beaconUrl, blob);
+var intervalID = null;
+
+</script>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/beacon/test_beaconWithSafelistedContentType.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1557386
+-->
+<head>
+  <title>Test for Bug 1557386</title>
+  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1557386">Mozilla Bug 1557386</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+// not enabled by default yet.
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({'set': [["beacon.enabled", true]]}, beginTest);
+
+const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const {BrowserTestUtils} = ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
+const { clearInterval, setInterval } = ChromeUtils.import(
+  "resource://gre/modules/Timer.jsm"
+);
+
+function whenDelayedStartupFinished(aWindow, aCallback) {
+  Services.obs.addObserver(function observer(aSubject, aTopic) {
+    if (aWindow == aSubject) {
+      Services.obs.removeObserver(observer, aTopic);
+      setTimeout(aCallback, 0);
+    }
+  }, "browser-delayed-startup-finished");
+}
+
+let baseURL = "http://mochi.test:8888/chrome/dom/tests/mochitest/beacon/";
+let windowsToClose = [];
+let listener = msg => {
+  if (!(msg instanceof Ci.nsIConsoleMessage)) {
+    return;
+  }
+  if (msg.message.match("Cross-Origin Request Blocked:")) {
+    ok(false, "CORS response console warning found");
+  }
+};
+
+function beginTest() {
+  Services.console.registerListener(listener);
+
+  let mainWindow = window.docShell.rootTreeItem.domWindow;
+
+  let win = mainWindow.OpenBrowserWindow({});
+  windowsToClose.push(win);
+  whenDelayedStartupFinished(win, async function() {
+    Services.obs.addObserver(function waitCookie() {
+      Services.obs.removeObserver(waitCookie, "cookie-changed");
+      ok(true, "cookie set by beacon request in normal window");
+      testOnPrivateWindow();
+    }, "cookie-changed");
+    let testURL = baseURL + "file_beaconSafelist.html";
+    await BrowserTestUtils.loadURI(win.gBrowser.selectedBrowser, testURL);
+    await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser, false, testURL);
+    await SpecialPowers.spawn(win.gBrowser.selectedBrowser, [], async () => {
+      await new Promise((resolve, reject) => {
+        let intervalId;
+        function queryIfBeaconSucceeded() {
+          content.clearInterval(intervalId);
+          let xhr = new content.XMLHttpRequest();
+          let baseURL = "http://example.com/tests/dom/tests/mochitest/beacon/";
+          let checkUrl = baseURL + "beacon-handler.sjs?getLastBeaconCors";
+          xhr.open("GET", checkUrl, true);
+          xhr.onload = function() {
+            let res = JSON.parse(xhr.responseText);
+            is(res.data, "text", "Got correct data");
+            resolve();
+          };
+          xhr.onerror = function() {
+            ok(false, "Error getting last beacon");
+            reject();
+          };
+          xhr.send();
+        }
+        intervalID = content.setInterval(queryIfBeaconSucceeded, 2000);
+      });
+    });
+    cleanup();
+  });
+}
+
+function cleanup() {
+  Services.console.unregisterListener(listener);
+  for (let i = 0; i < windowsToClose.length; ++i) {
+    windowsToClose[i].close();
+  }
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>