Bug 1264573 - Add blob url isolation tests, adapted from Tor Browser patch 15502. r=baku, r=arthuredelstein
authorJonathan Hao <jhao@mozilla.com>
Wed, 07 Sep 2016 11:36:07 +0800
changeset 313149 6d002007a8f1e7b44a73de082437d85b98a48936
parent 313148 888c7dec3cae94f06b6690684408e11b3ec3a57a
child 313150 4c154c6cbf4bfb274630731c750742e2405b2c3c
push id30673
push usercbook@mozilla.com
push dateThu, 08 Sep 2016 10:01:33 +0000
treeherdermozilla-central@938ce16be25f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku, arthuredelstein
bugs1264573, 15502
milestone51.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 1264573 - Add blob url isolation tests, adapted from Tor Browser patch 15502. r=baku, r=arthuredelstein
browser/components/originattributes/test/browser/browser.ini
browser/components/originattributes/test/browser/browser_blobURLIsolation.js
browser/components/originattributes/test/browser/worker_blobify.js
browser/components/originattributes/test/browser/worker_deblobify.js
--- a/browser/components/originattributes/test/browser/browser.ini
+++ b/browser/components/originattributes/test/browser/browser.ini
@@ -14,11 +14,14 @@ support-files =
   test_firstParty.html
   test_firstParty_cookie.html
   test_firstParty_html_redirect.html
   test_firstParty_http_redirect.html
   test_firstParty_http_redirect.html^headers^
   test_firstParty_iframe_http_redirect.html
   test_firstParty_postMessage.html
   window.html
+  worker_blobify.js
+  worker_deblobify.js
 
 [browser_firstPartyIsolation.js]
 [browser_localStorageIsolation.js]
+[browser_blobURLIsolation.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/browser_blobURLIsolation.js
@@ -0,0 +1,94 @@
+/**
+ * Bug 1264573 - A test case for blob url isolation.
+ */
+
+const TEST_PAGE = "http://mochi.test:8888/browser/browser/components/" +
+                  "originattributes/test/browser/file_firstPartyBasic.html";
+const SCRIPT_WORKER_BLOBIFY = "worker_blobify.js";
+const SCRIPT_WORKER_DEBLOBIFY = "worker_deblobify.js";
+
+function page_blobify(browser, input) {
+  return ContentTask.spawn(browser, input, function(input) {
+    return { blobURL: content.URL.createObjectURL(new content.Blob([input])) };
+  });
+}
+
+function page_deblobify(browser, blobURL) {
+  return ContentTask.spawn(browser, blobURL, function* (blobURL) {
+    if ("error" in blobURL) {
+      return blobURL;
+    }
+    blobURL = blobURL.blobURL;
+
+    function blobURLtoBlob(blobURL) {
+      return new content.Promise(function (resolve) {
+        let xhr = new content.XMLHttpRequest();
+        xhr.open("GET", blobURL, true);
+        xhr.onload = function () {
+          resolve(xhr.response);
+        };
+        xhr.onerror = function () {
+          resolve("xhr error");
+        };
+        xhr.responseType = "blob";
+        xhr.send();
+      });
+    }
+
+    function blobToString(blob) {
+      return new content.Promise(function (resolve) {
+        let fileReader = new content.FileReader();
+        fileReader.onload = function () {
+          resolve(fileReader.result);
+        };
+        fileReader.readAsText(blob);
+      });
+    }
+
+    let blob = yield blobURLtoBlob(blobURL);
+    if (blob == "xhr error") {
+      return "xhr error";
+    }
+
+    return yield blobToString(blob);
+  });
+}
+
+function workerIO(browser, scriptFile, message) {
+  return ContentTask.spawn(browser, {scriptFile, message}, function* (args) {
+    let worker = new content.Worker(args.scriptFile);
+    let promise = new content.Promise(function(resolve) {
+      let listenFunction = function(event) {
+        worker.removeEventListener("message", listenFunction, false);
+        worker.terminate();
+        resolve(event.data);
+      };
+      worker.addEventListener("message", listenFunction, false);
+    });
+    worker.postMessage(args.message);
+    return yield promise;
+  });
+}
+
+let worker_blobify = (browser, input) => workerIO(browser, SCRIPT_WORKER_BLOBIFY, input);
+let worker_deblobify = (browser, blobURL) => workerIO(browser, SCRIPT_WORKER_DEBLOBIFY, blobURL);
+
+function doTest(blobify, deblobify) {
+  let blobURL = null;
+  return function* (browser) {
+    if (blobURL === null) {
+      let input = Math.random().toString();
+      blobURL = yield blobify(browser, input);
+      return input;
+    }
+    let result = yield deblobify(browser, blobURL);
+    blobURL = null;
+    return result;
+  }
+}
+
+for (let blobify of [page_blobify, worker_blobify]) {
+  for (let deblobify of [page_deblobify, worker_deblobify]) {
+    IsolationTestTools.runTests(TEST_PAGE, doTest(blobify, deblobify));
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/worker_blobify.js
@@ -0,0 +1,11 @@
+// Wait for a string to be posted to this worker.
+// Create a blob containing this string, and then
+// post back a blob URL pointing to the blob.
+self.addEventListener("message", function (e) {
+  try {
+    var blobURL = URL.createObjectURL(new Blob([e.data]));
+    postMessage({ blobURL });
+  } catch (e) {
+    postMessage({ error: e.message });
+  }
+}, false);
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/worker_deblobify.js
@@ -0,0 +1,31 @@
+// Wait for a blob URL to be posted to this worker.
+// Obtain the blob, and read the string contained in it.
+// Post back the string.
+
+var postStringInBlob = function (blobObject) {
+  var fileReader = new FileReaderSync();
+  var result = fileReader.readAsText(blobObject);
+  postMessage(result);
+};
+
+self.addEventListener("message", function (e) {
+  if ("error" in e.data) {
+    postMessage(e.data);
+    return;
+  }
+  var blobURL = e.data.blobURL,
+      xhr = new XMLHttpRequest();
+  try {
+    xhr.open("GET", blobURL, true);
+    xhr.onload = function () {
+      postStringInBlob(xhr.response);
+    };
+    xhr.onerror = function () {
+      postMessage({ error: "xhr error" });
+    };
+    xhr.responseType = "blob";
+    xhr.send();
+  } catch (e) {
+    postMessage({ error: e.message });
+  }
+}, false);