summaryrefslogtreecommitdiffstats
path: root/dom/file/ipc/tests
diff options
context:
space:
mode:
Diffstat (limited to 'dom/file/ipc/tests')
-rw-r--r--dom/file/ipc/tests/browser.ini7
-rw-r--r--dom/file/ipc/tests/browser_ipcBlob.js253
-rw-r--r--dom/file/ipc/tests/browser_ipcBlob_temporary.js115
-rw-r--r--dom/file/ipc/tests/empty.html0
-rw-r--r--dom/file/ipc/tests/green.jpgbin0 -> 361 bytes
-rw-r--r--dom/file/ipc/tests/mochitest.ini12
-rw-r--r--dom/file/ipc/tests/ok.sjs11
-rw-r--r--dom/file/ipc/tests/script_file.js53
-rw-r--r--dom/file/ipc/tests/temporary.sjs6
-rw-r--r--dom/file/ipc/tests/test_ipcBlob_createImageBitmap.html84
-rw-r--r--dom/file/ipc/tests/test_ipcBlob_emptyMultiplex.html45
-rw-r--r--dom/file/ipc/tests/test_ipcBlob_fileReaderSync.html100
-rw-r--r--dom/file/ipc/tests/test_ipcBlob_mixedMultiplex.html41
-rw-r--r--dom/file/ipc/tests/test_ipcBlob_workers.html121
14 files changed, 848 insertions, 0 deletions
diff --git a/dom/file/ipc/tests/browser.ini b/dom/file/ipc/tests/browser.ini
new file mode 100644
index 0000000000..f6fcdc37a4
--- /dev/null
+++ b/dom/file/ipc/tests/browser.ini
@@ -0,0 +1,7 @@
+[DEFAULT]
+support-files =
+ empty.html
+
+[browser_ipcBlob.js]
+[browser_ipcBlob_temporary.js]
+support-files = temporary.sjs
diff --git a/dom/file/ipc/tests/browser_ipcBlob.js b/dom/file/ipc/tests/browser_ipcBlob.js
new file mode 100644
index 0000000000..17fe31e0bd
--- /dev/null
+++ b/dom/file/ipc/tests/browser_ipcBlob.js
@@ -0,0 +1,253 @@
+/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */
+
+requestLongerTimeout(3);
+
+const BASE_URI = "http://mochi.test:8888/browser/dom/file/ipc/tests/empty.html";
+
+add_task(async function setup() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["privacy.partition.bloburl_per_agent_cluster", false]],
+ });
+});
+
+// More than 1mb memory blob childA-parent-childB.
+add_task(async function test_CtoPtoC_big() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+
+ let blob = await SpecialPowers.spawn(browser1, [], function () {
+ Cu.importGlobalProperties(["Blob"]);
+ let blob = new Blob([new Array(1024 * 1024).join("123456789ABCDEF")]);
+ return blob;
+ });
+
+ ok(blob, "CtoPtoC-big: We have a blob!");
+ is(
+ blob.size,
+ new Array(1024 * 1024).join("123456789ABCDEF").length,
+ "CtoPtoC-big: The size matches"
+ );
+
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser2 = gBrowser.getBrowserForTab(tab2);
+
+ let status = await SpecialPowers.spawn(browser2, [blob], function (blob) {
+ return new Promise(resolve => {
+ let fr = new content.FileReader();
+ fr.readAsText(blob);
+ fr.onloadend = function () {
+ resolve(fr.result == new Array(1024 * 1024).join("123456789ABCDEF"));
+ };
+ });
+ });
+
+ ok(status, "CtoPtoC-big: Data match!");
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+});
+
+// Less than 1mb memory blob childA-parent-childB.
+add_task(async function test_CtoPtoC_small() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+
+ let blob = await SpecialPowers.spawn(browser1, [], function () {
+ Cu.importGlobalProperties(["Blob"]);
+ let blob = new Blob(["hello world!"]);
+ return blob;
+ });
+
+ ok(blob, "CtoPtoC-small: We have a blob!");
+ is(blob.size, "hello world!".length, "CtoPtoC-small: The size matches");
+
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser2 = gBrowser.getBrowserForTab(tab2);
+
+ let status = await SpecialPowers.spawn(browser2, [blob], function (blob) {
+ return new Promise(resolve => {
+ let fr = new content.FileReader();
+ fr.readAsText(blob);
+ fr.onloadend = function () {
+ resolve(fr.result == "hello world!");
+ };
+ });
+ });
+
+ ok(status, "CtoPtoC-small: Data match!");
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+});
+
+// More than 1mb memory blob childA-parent-childB: BroadcastChannel
+add_task(async function test_CtoPtoC_bc_big() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+
+ await SpecialPowers.spawn(browser1, [], function () {
+ Cu.importGlobalProperties(["Blob"]);
+ var bc = new content.BroadcastChannel("test");
+ bc.onmessage = function () {
+ bc.postMessage(
+ new Blob([new Array(1024 * 1024).join("123456789ABCDEF")])
+ );
+ };
+ });
+
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser2 = gBrowser.getBrowserForTab(tab2);
+
+ let status = await SpecialPowers.spawn(browser2, [], function () {
+ return new Promise(resolve => {
+ var bc = new content.BroadcastChannel("test");
+ bc.onmessage = function (e) {
+ let fr = new content.FileReader();
+ fr.readAsText(e.data);
+ fr.onloadend = function () {
+ resolve(fr.result == new Array(1024 * 1024).join("123456789ABCDEF"));
+ };
+ };
+
+ bc.postMessage("GO!");
+ });
+ });
+
+ ok(status, "CtoPtoC-broadcastChannel-big: Data match!");
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+});
+
+// Less than 1mb memory blob childA-parent-childB: BroadcastChannel
+add_task(async function test_CtoPtoC_bc_small() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+
+ await SpecialPowers.spawn(browser1, [], function () {
+ Cu.importGlobalProperties(["Blob"]);
+ var bc = new content.BroadcastChannel("test");
+ bc.onmessage = function () {
+ bc.postMessage(new Blob(["hello world!"]));
+ };
+ });
+
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser2 = gBrowser.getBrowserForTab(tab2);
+
+ let status = await SpecialPowers.spawn(browser2, [], function () {
+ return new Promise(resolve => {
+ var bc = new content.BroadcastChannel("test");
+ bc.onmessage = function (e) {
+ let fr = new content.FileReader();
+ fr.readAsText(e.data);
+ fr.onloadend = function () {
+ resolve(fr.result == "hello world!");
+ };
+ };
+
+ bc.postMessage("GO!");
+ });
+ });
+
+ ok(status, "CtoPtoC-broadcastChannel-small: Data match!");
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+});
+
+// blob URL childA-parent-childB
+add_task(async function test_CtoPtoC_bc_small() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+
+ let blobURL = await SpecialPowers.spawn(browser1, [], function () {
+ Cu.importGlobalProperties(["Blob"]);
+ return content.URL.createObjectURL(new content.Blob(["hello world!"]));
+ });
+
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser2 = gBrowser.getBrowserForTab(tab2);
+
+ let status = await SpecialPowers.spawn(
+ browser2,
+ [blobURL],
+ function (blobURL) {
+ return new Promise(resolve => {
+ var xhr = new content.XMLHttpRequest();
+ xhr.open("GET", blobURL);
+ xhr.onloadend = function () {
+ resolve(xhr.response == "hello world!");
+ };
+
+ xhr.send();
+ });
+ }
+ );
+
+ ok(status, "CtoPtoC-blobURL: Data match!");
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+});
+
+// Multipart Blob childA-parent-childB.
+add_task(async function test_CtoPtoC_multipart() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+
+ let blob = await SpecialPowers.spawn(browser1, [], function () {
+ Cu.importGlobalProperties(["Blob"]);
+ return new Blob(["!"]);
+ });
+
+ ok(blob, "CtoPtoC-multipart: We have a blob!");
+ is(blob.size, "!".length, "CtoPtoC-multipart: The size matches");
+
+ let newBlob = new Blob(["world", blob]);
+
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser2 = gBrowser.getBrowserForTab(tab2);
+
+ let status = await SpecialPowers.spawn(browser2, [newBlob], function (blob) {
+ Cu.importGlobalProperties(["Blob"]);
+ return new Promise(resolve => {
+ let fr = new content.FileReader();
+ fr.readAsText(new Blob(["hello ", blob]));
+ fr.onloadend = function () {
+ resolve(fr.result == "hello world!");
+ };
+ });
+ });
+
+ ok(status, "CtoPtoC-multipart: Data match!");
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+});
+
+// Multipart Blob childA-parent with a max size
+add_task(async function test_CtoPsize_multipart() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser = gBrowser.getBrowserForTab(tab);
+
+ let blob = await SpecialPowers.spawn(browser, [], function () {
+ Cu.importGlobalProperties(["Blob"]);
+
+ let data = new Array(1024 * 512).join("A");
+ let blob1 = new Blob([data]);
+ let blob2 = new Blob([data]);
+ let blob3 = new Blob([data]);
+
+ return new Blob([blob1, blob2, blob3]);
+ });
+
+ ok(blob, "CtoPsize-multipart: We have a blob!");
+ is(
+ blob.size,
+ new Array(1024 * 512).join("A").length * 3,
+ "CtoPsize-multipart: The size matches"
+ );
+
+ BrowserTestUtils.removeTab(tab);
+});
diff --git a/dom/file/ipc/tests/browser_ipcBlob_temporary.js b/dom/file/ipc/tests/browser_ipcBlob_temporary.js
new file mode 100644
index 0000000000..cc65768140
--- /dev/null
+++ b/dom/file/ipc/tests/browser_ipcBlob_temporary.js
@@ -0,0 +1,115 @@
+/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */
+
+requestLongerTimeout(3);
+
+const BASE_URI = "http://mochi.test:8888/browser/dom/file/ipc/tests/empty.html";
+
+add_task(async function test() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["dom.blob.memoryToTemporaryFile", 1],
+ ["dom.ipc.processCount", 4],
+ ],
+ });
+
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser1 = gBrowser.getBrowserForTab(tab1);
+
+ let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, BASE_URI);
+ let browser2 = gBrowser.getBrowserForTab(tab2);
+
+ await SpecialPowers.spawn(browser2, [], function () {
+ content.window.testPromise = new content.window.Promise(resolve => {
+ let bc = new content.window.BroadcastChannel("foobar");
+ bc.onmessage = e => {
+ function realTest() {
+ return new content.window.Promise(resolve => {
+ let count = 10;
+ for (let i = 0; i < count; ++i) {
+ info("FileReader at the same time: " + i);
+ let fr = new content.window.FileReader();
+ fr.readAsText(e.data);
+ fr.onerror = () => {
+ ok(false, "Something wrong happened.");
+ };
+
+ fr.onloadend = () => {
+ is(fr.result.length, e.data.size, "FileReader worked fine.");
+ if (!--count) {
+ resolve(true);
+ }
+ };
+ }
+ });
+ }
+
+ let promises = [];
+ for (let i = 0; i < 5; ++i) {
+ promises.push(realTest());
+ }
+
+ Promise.all(promises).then(() => {
+ resolve(true);
+ });
+ };
+ });
+ });
+
+ let status = await SpecialPowers.spawn(browser1, [], function () {
+ let p = new content.window.Promise(resolve => {
+ let xhr = new content.window.XMLHttpRequest();
+ xhr.open("GET", "temporary.sjs", true);
+ xhr.responseType = "blob";
+ xhr.onload = () => {
+ resolve(xhr.response);
+ };
+ xhr.send();
+ });
+
+ return p.then(blob => {
+ function realTest() {
+ return new content.window.Promise(resolve => {
+ info("Let's broadcast the blob...");
+ let bc = new content.window.BroadcastChannel("foobar");
+ bc.postMessage(blob);
+
+ info("Here the test...");
+ let count = 10;
+ for (let i = 0; i < count; ++i) {
+ info("FileReader at the same time: " + i);
+ let fr = new content.window.FileReader();
+ fr.readAsText(blob);
+ fr.onerror = () => {
+ ok(false, "Something wrong happened.");
+ };
+
+ fr.onloadend = () => {
+ is(fr.result.length, blob.size, "FileReader worked fine.");
+ if (!--count) {
+ resolve(true);
+ }
+ };
+ }
+ });
+ }
+
+ let promises = [];
+ for (let i = 0; i < 5; ++i) {
+ promises.push(realTest());
+ }
+
+ return Promise.all(promises);
+ });
+ });
+
+ ok(status, "All good for tab1!");
+
+ status = await SpecialPowers.spawn(browser2, [], function () {
+ return content.window.testPromise;
+ });
+
+ ok(status, "All good for tab2!");
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+});
diff --git a/dom/file/ipc/tests/empty.html b/dom/file/ipc/tests/empty.html
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/dom/file/ipc/tests/empty.html
diff --git a/dom/file/ipc/tests/green.jpg b/dom/file/ipc/tests/green.jpg
new file mode 100644
index 0000000000..48c454d27c
--- /dev/null
+++ b/dom/file/ipc/tests/green.jpg
Binary files differ
diff --git a/dom/file/ipc/tests/mochitest.ini b/dom/file/ipc/tests/mochitest.ini
new file mode 100644
index 0000000000..99b885762a
--- /dev/null
+++ b/dom/file/ipc/tests/mochitest.ini
@@ -0,0 +1,12 @@
+[DEFAULT]
+support-files = script_file.js
+
+[test_ipcBlob_fileReaderSync.html]
+[test_ipcBlob_workers.html]
+[test_ipcBlob_createImageBitmap.html]
+support-files = green.jpg
+skip-if =
+ http3
+[test_ipcBlob_emptyMultiplex.html]
+[test_ipcBlob_mixedMultiplex.html]
+support-files = ok.sjs
diff --git a/dom/file/ipc/tests/ok.sjs b/dom/file/ipc/tests/ok.sjs
new file mode 100644
index 0000000000..42f65733d9
--- /dev/null
+++ b/dom/file/ipc/tests/ok.sjs
@@ -0,0 +1,11 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC(
+ "@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream"
+);
+
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/html", false);
+ response.write(request.getHeader("Content-Length"));
+}
diff --git a/dom/file/ipc/tests/script_file.js b/dom/file/ipc/tests/script_file.js
new file mode 100644
index 0000000000..b671d46f39
--- /dev/null
+++ b/dom/file/ipc/tests/script_file.js
@@ -0,0 +1,53 @@
+/* eslint-env mozilla/chrome-script */
+
+Cu.importGlobalProperties(["File"]);
+
+addMessageListener("file.open", function (e) {
+ var testFile = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIDirectoryService)
+ .QueryInterface(Ci.nsIProperties)
+ .get("ProfD", Ci.nsIFile);
+ testFile.append("ipc_fileReader_testing");
+ testFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
+
+ var outStream = Cc[
+ "@mozilla.org/network/file-output-stream;1"
+ ].createInstance(Ci.nsIFileOutputStream);
+ outStream.init(
+ testFile,
+ 0x02 | 0x08 | 0x20, // write, create, truncate
+ 0o666,
+ 0
+ );
+
+ var fileData = "Hello World!";
+ outStream.write(fileData, fileData.length);
+ outStream.close();
+
+ File.createFromNsIFile(testFile).then(function (file) {
+ sendAsyncMessage("file.opened", { file });
+ });
+});
+
+addMessageListener("emptyfile.open", function (e) {
+ var testFile = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIDirectoryService)
+ .QueryInterface(Ci.nsIProperties)
+ .get("ProfD", Ci.nsIFile);
+ testFile.append("ipc_fileReader_testing");
+ testFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
+
+ var outStream = Cc[
+ "@mozilla.org/network/file-output-stream;1"
+ ].createInstance(Ci.nsIFileOutputStream);
+ outStream.init(
+ testFile,
+ 0x02 | 0x08 | 0x20, // write, create, truncate
+ 0o666,
+ 0
+ );
+
+ File.createFromNsIFile(testFile).then(function (file) {
+ sendAsyncMessage("emptyfile.opened", { file });
+ });
+});
diff --git a/dom/file/ipc/tests/temporary.sjs b/dom/file/ipc/tests/temporary.sjs
new file mode 100644
index 0000000000..76db4e2f2e
--- /dev/null
+++ b/dom/file/ipc/tests/temporary.sjs
@@ -0,0 +1,6 @@
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/plain", false);
+
+ var data = new Array(1024 * 64).join("1234567890ABCDEF");
+ response.bodyOutputStream.write(data, data.length);
+}
diff --git a/dom/file/ipc/tests/test_ipcBlob_createImageBitmap.html b/dom/file/ipc/tests/test_ipcBlob_createImageBitmap.html
new file mode 100644
index 0000000000..868888c529
--- /dev/null
+++ b/dom/file/ipc/tests/test_ipcBlob_createImageBitmap.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test IPCBlob and CreateImageBitmap</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function test_mainThread() {
+ let bc = new BroadcastChannel('testMainThread');
+ bc.onmessage = e => {
+ createImageBitmap(e.data).then(image => {
+ ok(image.height, "this image has a valid size.");
+ }, () => {
+ ok(false, "error creating the image!");
+ }).then(next);
+ }
+
+ fetch('green.jpg').then(r => r.blob()).then(blob => {
+ let bc = new BroadcastChannel('testMainThread');
+ bc.postMessage(blob);
+ });
+}
+
+function test_worker() {
+ function workerScript() {
+ function ok(a, msg) { postMessage({ type: 'test', status: !!a, msg }); };
+ function finish() { postMessage({ type: 'finish' }); };
+
+ let bc = new BroadcastChannel('testWorker');
+ bc.onmessage = e => {
+ createImageBitmap(e.data).then(image => {
+ ok(image.height, "this image has a valid size.");
+ }, () => {
+ ok(false, "error creating the image!");
+ }).then(finish);
+ }
+
+ fetch('http://mochi.test:8888/tests/dom/file/ipc/tests/green.jpg').then(r => r.blob()).then(blob => {
+ let bc = new BroadcastChannel('testWorker');
+ bc.postMessage(blob);
+ });
+ }
+ let workerUrl = URL.createObjectURL(new Blob(["(", workerScript.toString(), ")()"]));
+ let worker = new Worker(workerUrl);
+
+ worker.onmessage = event => {
+ if (event.data.type == 'test') {
+ ok(event.data.status, event.data.msg);
+ return;
+ }
+
+ if (event.data.type == 'finish') {
+ next();
+ }
+ }
+}
+
+let tests = [
+ test_mainThread,
+ test_worker,
+];
+
+function next() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ let test = tests.shift();
+ test();
+}
+
+next();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/file/ipc/tests/test_ipcBlob_emptyMultiplex.html b/dom/file/ipc/tests/test_ipcBlob_emptyMultiplex.html
new file mode 100644
index 0000000000..0487069467
--- /dev/null
+++ b/dom/file/ipc/tests/test_ipcBlob_emptyMultiplex.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test an empty IPCBlob together with other parts</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script type="text/javascript">
+
+function checkContent(msg, content) {
+ return new Promise(resolve => {
+ let fr = new FileReader();
+ fr.readAsText(new Blob(content));
+ fr.onloadend = () => {
+ is(fr.result, "Hello world!", "The content matches: " + msg);
+ resolve();
+ };
+ });
+}
+
+SimpleTest.waitForExplicitFinish();
+
+let url = SimpleTest.getTestFileURL("script_file.js");
+
+let script = SpecialPowers.loadChromeScript(url);
+script.addMessageListener("emptyfile.opened", message => {
+ checkContent("middle", ["Hello ", message.file, "world!"]).
+ then(() => checkContent("begin", [message.file, "Hello world!"])).
+ then(() => checkContent("end", ["Hello world!", message.file])).
+ then(() => checkContent("random", [message.file, message.file, "Hello world!", message.file])).
+ then(() => checkContent("random 2", [message.file, message.file, "Hello ",
+ message.file, "world", message.file,
+ message.file, "!", message.file, "",
+ message.file, message.file])).
+ then(SimpleTest.finish);
+});
+
+script.sendAsyncMessage("emptyfile.open");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/file/ipc/tests/test_ipcBlob_fileReaderSync.html b/dom/file/ipc/tests/test_ipcBlob_fileReaderSync.html
new file mode 100644
index 0000000000..f37d4b79ed
--- /dev/null
+++ b/dom/file/ipc/tests/test_ipcBlob_fileReaderSync.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test IPCBlob and FileReaderSync</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script type="text/javascript">
+
+function workerScript() {
+ onmessage = function(event) {
+ let readerMemoryBlob = new FileReaderSync();
+ let status = readerMemoryBlob.readAsText(new Blob(['hello world'])) == 'hello world';
+ postMessage({ status, message: "FileReaderSync with memory blob still works" });
+
+ let readerIPCBlob1 = new FileReaderSync();
+ postMessage({ blob: event.data, method: 'readAsText',
+ data: readerIPCBlob1.readAsText(event.data)});
+
+ let readerIPCBlob2 = new FileReaderSync();
+ postMessage({ blob: event.data, method: 'readAsArrayBuffer',
+ data: readerIPCBlob2.readAsArrayBuffer(event.data)});
+
+ let readerIPCBlob3 = new FileReaderSync();
+ postMessage({ blob: event.data, method: 'readAsDataURL',
+ data: readerIPCBlob3.readAsDataURL(event.data)});
+
+ let multipartBlob = new Blob(['wow', event.data]);
+
+ let readerIPCBlobMultipart1 = new FileReaderSync();
+ postMessage({ blob: multipartBlob, method: 'readAsText',
+ data: readerIPCBlobMultipart1.readAsText(multipartBlob)});
+
+ let readerIPCBlobMultipart2 = new FileReaderSync();
+ postMessage({ blob: multipartBlob, method: 'readAsArrayBuffer',
+ data: readerIPCBlobMultipart2.readAsArrayBuffer(multipartBlob)});
+
+ let readerIPCBlobMultipart3 = new FileReaderSync();
+ postMessage({ blob: multipartBlob, method: 'readAsDataURL',
+ data: readerIPCBlobMultipart3.readAsDataURL(multipartBlob)});
+
+ postMessage({ finish: true });
+ }
+}
+
+let completed = false;
+let pendingTasks = 0;
+function maybeFinish() {
+ if (completed && !pendingTasks) {
+ SimpleTest.finish();
+ }
+}
+
+let workerUrl = URL.createObjectURL(new Blob(["(", workerScript.toString(), ")()"]));
+let worker = new Worker(workerUrl);
+worker.onmessage = event => {
+ if ("status" in event.data) {
+ ok(event.data.status, event.data.message);
+ return;
+ }
+
+ if ("blob" in event.data) {
+ let fr = new FileReader();
+ fr[event.data.method](event.data.blob);
+ ++pendingTasks;
+ fr.onload = () => {
+ if (event.data.method != 'readAsArrayBuffer') {
+ is(event.data.data, fr.result, "The file has been read");
+ } else {
+ is(event.data.data.byteLength, fr.result.byteLength, "The file has been read");
+ }
+ --pendingTasks;
+ maybeFinish();
+ }
+
+ return;
+ }
+
+ if ("finish" in event.data) {
+ completed = true;
+ maybeFinish();
+ }
+};
+
+let url = SimpleTest.getTestFileURL("script_file.js");
+let script = SpecialPowers.loadChromeScript(url);
+script.addMessageListener("file.opened", message => {
+ worker.postMessage(message.file);
+});
+
+script.sendAsyncMessage("file.open");
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/file/ipc/tests/test_ipcBlob_mixedMultiplex.html b/dom/file/ipc/tests/test_ipcBlob_mixedMultiplex.html
new file mode 100644
index 0000000000..c8e046fa88
--- /dev/null
+++ b/dom/file/ipc/tests/test_ipcBlob_mixedMultiplex.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test an empty IPCBlob together with other parts</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script type="text/javascript">
+
+let url = SimpleTest.getTestFileURL("script_file.js");
+let data = new Array(1024*1024).join('A');
+
+let script = SpecialPowers.loadChromeScript(url);
+script.addMessageListener("file.opened", message => {
+ let blob = new Blob([data]);
+
+ let form = new FormData();
+ form.append("blob1", blob);
+ form.append("blob2", message.file);
+ form.append("blob3", blob);
+
+ fetch("ok.sjs", {
+ method: "POST",
+ body: form,
+ })
+ .then(r => r.text())
+ .then(r => {
+ ok(parseInt(r, 10) > (data.length * 2), "We have data");
+ })
+ . then(SimpleTest.finish);
+});
+
+script.sendAsyncMessage("file.open");
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/file/ipc/tests/test_ipcBlob_workers.html b/dom/file/ipc/tests/test_ipcBlob_workers.html
new file mode 100644
index 0000000000..a473948f25
--- /dev/null
+++ b/dom/file/ipc/tests/test_ipcBlob_workers.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test IPCBlob and Workers</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script type="text/javascript">
+
+function test_workerOwner() {
+ info("test_workerOwner");
+
+ function workerScript() {
+ onmessage = e => {
+ e.ports[0].onmessage = event => {
+ let reader = new FileReader();
+ reader.readAsText(event.data);
+ reader.onloadend = () => {
+ let status = reader.result == 'hello world';
+ postMessage(status);
+ }
+ }
+ }
+ }
+
+ let mc = new MessageChannel();
+ mc.port1.postMessage(new Blob(['hello world']));
+
+ let workerUrl = URL.createObjectURL(new Blob(["(", workerScript.toString(), ")()"]));
+ let worker = new Worker(workerUrl);
+
+ worker.postMessage("", [mc.port2]);
+ worker.onmessage = event => {
+ ok(event.data, "All is done!");
+ next();
+ }
+}
+
+function test_workerToMainThread() {
+ info("test_workerToMainThread");
+ function workerScript() {
+ onmessage = e => {
+ e.ports[0].onmessage = event => {
+ postMessage(event.data);
+ }
+ }
+ }
+
+ let mc = new MessageChannel();
+ mc.port1.postMessage(new Blob(['hello world']));
+
+ let workerUrl = URL.createObjectURL(new Blob(["(", workerScript.toString(), ")()"]));
+ let worker = new Worker(workerUrl);
+
+ worker.postMessage("", [mc.port2]);
+ worker.onmessage = event => {
+ info("Blob received back, terminate the worker and force GC");
+ worker.terminate();
+ worker = null;
+ SpecialPowers.forceGC();
+
+ var fr = new FileReader();
+ fr.readAsText(event.data);
+ fr.onloadend = () => {
+ is(fr.result, "hello world", "Data matches");
+ next();
+ }
+ }
+}
+
+function test_workerOwnerPlusFileReaderSync() {
+ info("test_workerOwnerPlusFileReaderSync");
+
+ function workerScript() {
+ onmessage = e => {
+ e.ports[0].onmessage = event => {
+ let reader = new FileReaderSync();
+ let status = reader.readAsText(event.data) == 'hello world';
+ postMessage(status);
+ }
+ }
+ }
+
+ let mc = new MessageChannel();
+ mc.port1.postMessage(new Blob(['hello world']));
+
+ let workerUrl = URL.createObjectURL(new Blob(["(", workerScript.toString(), ")()"]));
+ let worker = new Worker(workerUrl);
+
+ worker.postMessage("", [mc.port2]);
+ worker.onmessage = event => {
+ ok(event.data, "All is done!");
+ next();
+ }
+}
+
+var tests = [
+ test_workerOwner,
+ test_workerToMainThread,
+ test_workerOwnerPlusFileReaderSync,
+];
+
+function next() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var test = tests.shift();
+ test();
+}
+
+SimpleTest.waitForExplicitFinish();
+next();
+
+</script>
+</pre>
+</body>
+</html>