diff options
Diffstat (limited to 'dom/ipc/tests')
-rw-r--r-- | dom/ipc/tests/blob_verify.sjs | 20 | ||||
-rw-r--r-- | dom/ipc/tests/browser.ini | 6 | ||||
-rw-r--r-- | dom/ipc/tests/browser_domainPolicy.js | 240 | ||||
-rw-r--r-- | dom/ipc/tests/chrome.ini | 8 | ||||
-rw-r--r-- | dom/ipc/tests/file_bug1086684.html | 16 | ||||
-rw-r--r-- | dom/ipc/tests/file_disableScript.html | 11 | ||||
-rw-r--r-- | dom/ipc/tests/file_domainPolicy_base.html | 8 | ||||
-rw-r--r-- | dom/ipc/tests/mochitest.ini | 22 | ||||
-rw-r--r-- | dom/ipc/tests/process_error.xul | 58 | ||||
-rw-r--r-- | dom/ipc/tests/process_error_contentscript.js | 7 | ||||
-rw-r--r-- | dom/ipc/tests/test_CrashService_crash.html | 95 | ||||
-rw-r--r-- | dom/ipc/tests/test_blob_sliced_from_child_process.html | 185 | ||||
-rw-r--r-- | dom/ipc/tests/test_blob_sliced_from_parent_process.html | 213 | ||||
-rw-r--r-- | dom/ipc/tests/test_bug1086684.html | 107 | ||||
-rw-r--r-- | dom/ipc/tests/test_child_docshell.html | 86 | ||||
-rw-r--r-- | dom/ipc/tests/test_cpow_cookies.html | 90 | ||||
-rw-r--r-- | dom/ipc/tests/test_process_error.xul | 22 | ||||
-rw-r--r-- | dom/ipc/tests/test_temporaryfile_stream.html | 80 |
18 files changed, 1274 insertions, 0 deletions
diff --git a/dom/ipc/tests/blob_verify.sjs b/dom/ipc/tests/blob_verify.sjs new file mode 100644 index 000000000..62b82359e --- /dev/null +++ b/dom/ipc/tests/blob_verify.sjs @@ -0,0 +1,20 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream"); +const BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1", + "nsIBinaryOutputStream", + "setOutputStream"); + +function handleRequest(request, response) { + var bodyStream = new BinaryInputStream(request.bodyInputStream); + var bodyBytes = []; + while ((bodyAvail = bodyStream.available()) > 0) + Array.prototype.push.apply(bodyBytes, bodyStream.readByteArray(bodyAvail)); + + var bos = new BinaryOutputStream(response.bodyOutputStream); + + response.processAsync(); + bos.writeByteArray(bodyBytes, bodyBytes.length); + response.finish(); +} diff --git a/dom/ipc/tests/browser.ini b/dom/ipc/tests/browser.ini new file mode 100644 index 000000000..f3d8ce140 --- /dev/null +++ b/dom/ipc/tests/browser.ini @@ -0,0 +1,6 @@ +[DEFAULT] +support-files = + file_disableScript.html + file_domainPolicy_base.html + +[browser_domainPolicy.js] diff --git a/dom/ipc/tests/browser_domainPolicy.js b/dom/ipc/tests/browser_domainPolicy.js new file mode 100644 index 000000000..df06b8bc0 --- /dev/null +++ b/dom/ipc/tests/browser_domainPolicy.js @@ -0,0 +1,240 @@ +var policy; // To make sure we never leave up an activated domain policy after a failed test, let's make this global. +function activateDomainPolicy() { + const ssm = Services.scriptSecurityManager; + policy = ssm.activateDomainPolicy(); +} + +function deactivateDomainPolicy() { + if (policy) { + policy.deactivate(); + policy = null; + } +} + +function* test_domainPolicy() { + + XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); + let deferred = Promise.defer(); + let currentTask = deferred.promise; + SpecialPowers.pushPrefEnv( + {set: [["dom.ipc.browser_frames.oop_by_default", false], + ["browser.pagethumbnails.capturing_disabled", false], + ["dom.mozBrowserFramesEnabled", false]]}, + () => { return deferred.resolve()}); + yield currentTask; + + // Create tab + let tab; + + // Init test + function initProcess() { + tab = gBrowser.addTab(); + gBrowser.selectedTab = tab; + + let initPromise = ContentTask.spawn(tab.linkedBrowser, null, function() { + Cu.import("resource://gre/modules/PromiseUtils.jsm"); + function loadBase() { + let deferred = PromiseUtils.defer(); + let listener = (event) => { + removeEventListener("DOMDocElementInserted", listener, true); + let listener2 = (event) => { + content.removeEventListener('load', listener2); + deferred.resolve(); + } + content.addEventListener('load', listener2); + }; + addEventListener("DOMDocElementInserted", listener, true); + return deferred.promise; + } + + return loadBase(); + }); + tab.linkedBrowser.loadURI("http://mochi.test:8888/browser/dom/ipc/tests/file_domainPolicy_base.html"); + return initPromise; + } + + // We use ContentTask for the tests, but we also want to pass some data and some helper functions too. + // To do that, we serialize an input object via JSON |ipcArgs| and some shared helper functions |initUtils| + // and eval them in the content process. + var ipcArgs = {}; + function initUtils(obj) { + obj.checkScriptEnabled = function(win, expectEnabled) { + win.wrappedJSObject.gFiredOnclick = false; + win.document.body.dispatchEvent(new win.Event('click')); + return { passed: win.wrappedJSObject.gFiredOnclick == expectEnabled, + msg: `Checking script-enabled for ${win.name} (${win.location})`}; + } + + obj.navigateFrame = function(ifr, src) { + let deferred = PromiseUtils.defer(); + function onload() { + ifr.removeEventListener('load', onload); + deferred.resolve(); + } + ifr.addEventListener('load', onload, false); + ifr.setAttribute('src', src); + return deferred.promise; + } + }; + + function runTest(test) { + return ContentTask.spawn(tab.linkedBrowser, + 'ipcArgs = ' + JSON.stringify(ipcArgs) + '; (' + initUtils.toSource() + ')(utils)', test); + } + + function checkAndCleanup(result) { + result = [].concat(result); + for (var i in result) + ok(result[i].passed, result[i].msg); + gBrowser.removeTab(tab); + deactivateDomainPolicy(); + ipcArgs = {}; + } + + function testDomain(domain) { + ipcArgs.domain = domain; + return (aUtils) => { + Cu.import("resource://gre/modules/PromiseUtils.jsm"); + var ipcArgs; + var utils = {}; + eval(aUtils); + + let path = '/browser/dom/ipc/tests/file_disableScript.html'; + let deferred = PromiseUtils.defer(); + var rootFrame = content.document.getElementById('root'); + utils.navigateFrame(rootFrame, ipcArgs.domain + path).then(() => { + deferred.resolve(utils.checkScriptEnabled(rootFrame.contentWindow, false)); + }); + return deferred.promise; + } + } + + info("Testing simple blacklist policy"); + + info("Creating child process first, activating domainPolicy after"); + currentTask = initProcess(); + yield currentTask; + activateDomainPolicy(); + var bl = policy.blacklist; + bl.add(Services.io.newURI('http://example.com', null, null)); + currentTask = runTest(testDomain("http://example.com")); + checkAndCleanup(yield currentTask); + + info("Activating domainPolicy first, creating child process after"); + activateDomainPolicy(); + var bl = policy.blacklist; + bl.add(Services.io.newURI('http://example.com', null, null)); + currentTask = initProcess(); + yield currentTask; + currentTask = runTest(testDomain("http://example.com")); + checkAndCleanup(yield currentTask); + + function testList(expectEnabled, list) { + ipcArgs.expectEnabled = expectEnabled; + ipcArgs.list = list; + return (aUtils) => { + Cu.import("resource://gre/modules/PromiseUtils.jsm"); + var ipcArgs; + var utils = {}; + eval(aUtils); + + var results = []; + var testListInternal = function(expectEnabled, list, idx) { + idx = idx || 0; + let deferred = PromiseUtils.defer(); + let path = '/browser/dom/ipc/tests/file_disableScript.html'; + let target = list[idx] + path; + var rootFrame = content.document.getElementById('root'); + utils.navigateFrame(rootFrame, target).then(function() { + results.push(utils.checkScriptEnabled(rootFrame.contentWindow, expectEnabled)); + if (idx == list.length - 1) + deferred.resolve(results); + else + testListInternal(expectEnabled, list, idx + 1).then(function(retArg) { deferred.resolve(retArg); }); + }); + return deferred.promise; + } + return testListInternal(ipcArgs.expectEnabled, ipcArgs.list); + } + } + + let testPolicy = { + exceptions: ['http://test1.example.com', 'http://example.com'], + superExceptions: ['http://test2.example.org', 'https://test1.example.com'], + exempt: ['http://test1.example.com', 'http://example.com', + 'http://test2.example.org', 'http://sub1.test2.example.org', + 'https://sub1.test1.example.com'], + notExempt: ['http://test2.example.com', 'http://sub1.test1.example.com', + 'http://www.example.com', 'https://test2.example.com', + 'https://example.com', 'http://test1.example.org'], + }; + + function activate(isBlack, exceptions, superExceptions) { + activateDomainPolicy(); + let set = isBlack ? policy.blacklist : policy.whitelist; + let superSet = isBlack ? policy.superBlacklist : policy.superWhitelist; + for (var e of exceptions) + set.add(makeURI(e)); + for (var e of superExceptions) + superSet.add(makeURI(e)); + }; + + info("Testing Blacklist-style Domain Policy"); + info("Activating domainPolicy first, creating child process after"); + activate(true, testPolicy.exceptions, testPolicy.superExceptions); + currentTask = initProcess(); + yield currentTask; + let results = []; + currentTask = runTest(testList(true, testPolicy.notExempt)); + results = results.concat(yield currentTask); + currentTask = runTest(testList(false, testPolicy.exempt)); + results = results.concat(yield currentTask); + checkAndCleanup(results); + + info("Creating child process first, activating domainPolicy after"); + currentTask = initProcess(); + yield currentTask; + activate(true, testPolicy.exceptions, testPolicy.superExceptions); + results = []; + currentTask = runTest(testList(true, testPolicy.notExempt)); + results = results.concat(yield currentTask); + currentTask = runTest(testList(false, testPolicy.exempt)); + results = results.concat(yield currentTask); + checkAndCleanup(results); + + info("Testing Whitelist-style Domain Policy"); + deferred = Promise.defer(); + currentTask = deferred.promise; + SpecialPowers.pushPrefEnv({set:[["javascript.enabled", false]]}, () => { return deferred.resolve()}); + yield currentTask; + + info("Activating domainPolicy first, creating child process after"); + activate(false, testPolicy.exceptions, testPolicy.superExceptions); + currentTask = initProcess(); + yield currentTask; + results = []; + currentTask = runTest(testList(false, testPolicy.notExempt)); + results = results.concat(yield currentTask); + currentTask = runTest(testList(true, testPolicy.exempt)); + results = results.concat(yield currentTask); + checkAndCleanup(results); + + info("Creating child process first, activating domainPolicy after"); + currentTask = initProcess(); + yield currentTask; + activate(false, testPolicy.exceptions, testPolicy.superExceptions); + results = []; + currentTask = runTest(testList(false, testPolicy.notExempt)); + results = results.concat(yield currentTask); + currentTask = runTest(testList(true, testPolicy.exempt)); + results = results.concat(yield currentTask); + checkAndCleanup(results); + finish(); +} + + +add_task(test_domainPolicy); + +registerCleanupFunction(()=>{ + deactivateDomainPolicy(); +})
\ No newline at end of file diff --git a/dom/ipc/tests/chrome.ini b/dom/ipc/tests/chrome.ini new file mode 100644 index 000000000..b6e3d4801 --- /dev/null +++ b/dom/ipc/tests/chrome.ini @@ -0,0 +1,8 @@ +[DEFAULT] +skip-if = os == 'android' +support-files = + process_error.xul + process_error_contentscript.js + +[test_process_error.xul] +skip-if = !crashreporter diff --git a/dom/ipc/tests/file_bug1086684.html b/dom/ipc/tests/file_bug1086684.html new file mode 100644 index 000000000..95db6f387 --- /dev/null +++ b/dom/ipc/tests/file_bug1086684.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1086684 +--> +<head> + <title>Test for Bug 1086684</title> + <meta charset="UTF-8"> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1086684">Mozilla Bug 1086684</a> +<div id="content"> + <input type="file" id="f"> +</div> +</body> +</html> diff --git a/dom/ipc/tests/file_disableScript.html b/dom/ipc/tests/file_disableScript.html new file mode 100644 index 000000000..f4888cd58 --- /dev/null +++ b/dom/ipc/tests/file_disableScript.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> +<script> +var gFiredOnload = false; +var gFiredOnclick = false; +</script> +</head> +<body onload="gFiredOnload = true;" onclick="gFiredOnclick = true;"> +</body> +</html> diff --git a/dom/ipc/tests/file_domainPolicy_base.html b/dom/ipc/tests/file_domainPolicy_base.html new file mode 100644 index 000000000..6e3ec7aec --- /dev/null +++ b/dom/ipc/tests/file_domainPolicy_base.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> +<head> +</head> +<body> +<iframe id="root" name="root"/> +</body> +</html> diff --git a/dom/ipc/tests/mochitest.ini b/dom/ipc/tests/mochitest.ini new file mode 100644 index 000000000..cf2a20d5b --- /dev/null +++ b/dom/ipc/tests/mochitest.ini @@ -0,0 +1,22 @@ +[DEFAULT] +support-files = + file_bug1086684.html + +[test_blob_sliced_from_child_process.html] +# This test is only supposed to run in the main process. +skip-if = e10s +[test_blob_sliced_from_parent_process.html] +# This test is only supposed to run in the main process. +skip-if = e10s +[test_bug1086684.html] +# This test is only supposed to run in the main process +skip-if = e10s || toolkit == 'android' +[test_cpow_cookies.html] +[test_child_docshell.html] +skip-if = toolkit == 'cocoa' # disabled due to hangs, see changeset 6852e7c47edf +[test_CrashService_crash.html] +skip-if = !(crashreporter && !e10s && (toolkit == 'gtk2' || toolkit == 'gtk3' || toolkit == 'cocoa' || toolkit == 'windows')) +[test_temporaryfile_stream.html] +support-files = + blob_verify.sjs + !/dom/canvas/test/captureStream_common.js diff --git a/dom/ipc/tests/process_error.xul b/dom/ipc/tests/process_error.xul new file mode 100644 index 000000000..62d3d9724 --- /dev/null +++ b/dom/ipc/tests/process_error.xul @@ -0,0 +1,58 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> + +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + orient="vertical"> + + <browser id="thebrowser" type="content" remote="true" /> + <script type="application/javascript"><![CDATA[ + Components.utils.import("resource://gre/modules/Services.jsm"); + + const ok = window.opener.wrappedJSObject.ok; + const is = window.opener.wrappedJSObject.is; + const done = window.opener.wrappedJSObject.done; + const SimpleTest = window.opener.wrappedJSObject.SimpleTest; + + function getMinidumpDirectory() { + var dir = Services.dirsvc.get('ProfD', Components.interfaces.nsIFile); + dir.append("minidumps"); + return dir; + } + + function removeFile(directory, filename) { + var file = directory.clone(); + file.append(filename); + if (file.exists()) { + file.remove(false); + } + } + + function crashObserver(subject, topic, data) { + is(topic, 'ipc:content-shutdown', 'Received correct observer topic.'); + ok(subject instanceof Components.interfaces.nsIPropertyBag2, + 'Subject implements nsIPropertyBag2.'); + + var dumpID; + if ('nsICrashReporter' in Components.interfaces) { + dumpID = subject.getPropertyAsAString('dumpID'); + ok(dumpID, "dumpID is present and not an empty string"); + } + + if (dumpID) { + var minidumpDirectory = getMinidumpDirectory(); + removeFile(minidumpDirectory, dumpID + '.dmp'); + removeFile(minidumpDirectory, dumpID + '.extra'); + } + + Services.obs.removeObserver(crashObserver, 'ipc:content-shutdown'); + done(); + } + Services.obs.addObserver(crashObserver, 'ipc:content-shutdown', false); + + document.getElementById('thebrowser') + .QueryInterface(Components.interfaces.nsIFrameLoaderOwner) + .frameLoader.messageManager + .loadFrameScript('chrome://mochitests/content/chrome/dom/ipc/tests/process_error_contentscript.js', true); + ]]></script> + +</window> diff --git a/dom/ipc/tests/process_error_contentscript.js b/dom/ipc/tests/process_error_contentscript.js new file mode 100644 index 000000000..789b8a37f --- /dev/null +++ b/dom/ipc/tests/process_error_contentscript.js @@ -0,0 +1,7 @@ +Components.utils.import("resource://gre/modules/ctypes.jsm"); + +privateNoteIntentionalCrash(); + +var zero = new ctypes.intptr_t(8); +var badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t)); +var crash = badptr.contents; diff --git a/dom/ipc/tests/test_CrashService_crash.html b/dom/ipc/tests/test_CrashService_crash.html new file mode 100644 index 000000000..a1d9b938d --- /dev/null +++ b/dom/ipc/tests/test_CrashService_crash.html @@ -0,0 +1,95 @@ +<!DOCTYPE HTML> +<html> +<!-- +Ensures that content crashes are reported to the crash service +(nsICrashService and CrashManager.jsm). +--> +<head> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestFlakyTimeout("untriaged"); +SpecialPowers.addPermission("browser", true, document); +SpecialPowers.pushPrefEnv({'set':[ + ["dom.mozBrowserFramesEnabled", true], + ["network.disable.ipc.security", true], + ["dom.ipc.tabs.disabled", false] +]}, function () { + + var iframe = document.createElementNS('http://www.w3.org/1999/xhtml', 'iframe'); + iframe.setAttribute("remote", "true"); + SpecialPowers.wrap(iframe).mozbrowser = true; + document.documentElement.appendChild(iframe); + + SimpleTest.expectChildProcessCrash(); + + var crashMan = + SpecialPowers.Cu.import("resource://gre/modules/Services.jsm"). + Services.crashmanager; + + // First, clear the crash record store. + info("Waiting for pruneOldCrashes"); + var future = new Date(Date.now() + 1000 * 60 * 60 * 24); + crashMan.pruneOldCrashes(future).then(function () { + + var crashDateMS = Date.now(); + + // Inject a frame script that crashes the content process. + var mm = SpecialPowers.getBrowserFrameMessageManager(iframe); + mm.loadFrameScript('data:,new ' + function ContentScriptScope() { + let Cu = Components.utils; + Cu.import("resource://gre/modules/ctypes.jsm"); + let crash = function() { + let zero = new ctypes.intptr_t(8); + let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t)); + badptr.contents; + }; + privateNoteIntentionalCrash(); + crash(); + }, false); + + // Finally, poll for the new crash record. + function tryGetCrash() { + info("Waiting for getCrashes"); + crashMan.getCrashes().then(SpecialPowers.wrapCallback(function (crashes) { + if (crashes.length) { + is(crashes.length, 1, "There should be only one record"); + var crash = crashes[0]; + ok(crash.isOfType(crashMan.PROCESS_TYPE_CONTENT, + crashMan.CRASH_TYPE_CRASH), + "Record should be a content crash"); + ok(!!crash.id, "Record should have an ID"); + ok(!!crash.crashDate, "Record should have a crash date"); + var dateMS = crash.crashDate.valueOf(); + var twoMin = 1000 * 60 * 2; + ok(crashDateMS - twoMin <= dateMS && + dateMS <= crashDateMS + twoMin, + "Record's crash date should be nowish: " + + "now=" + crashDateMS + " recordDate=" + dateMS); + SimpleTest.finish(); + } + else { + setTimeout(tryGetCrash, 1000); + } + }), function (err) { + ok(false, "Error getting crashes: " + err); + SimpleTest.finish(); + }); + } + setTimeout(tryGetCrash, 1000); + + }, function () { + ok(false, "pruneOldCrashes error"); + SimpleTest.finish(); + }); +}); + +</script> +</body> +</html> diff --git a/dom/ipc/tests/test_blob_sliced_from_child_process.html b/dom/ipc/tests/test_blob_sliced_from_child_process.html new file mode 100644 index 000000000..0dec1d84c --- /dev/null +++ b/dom/ipc/tests/test_blob_sliced_from_child_process.html @@ -0,0 +1,185 @@ +<!DOCTYPE html> +<html> + <head> + <title>Test for slicing blobs that originated in a child process</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + </head> + <body onload="setup();"> + <script type="application/javascript;version=1.7"> +"use strict"; + +function childFrameScript() { + "use strict"; + + Components.utils.importGlobalProperties(["Blob"]); + + const messageName = "test:blob-slice-test"; + const blobData = ["So", " ", "many", " ", "blobs!"]; + const blobText = blobData.join(""); + const blobType = "text/plain"; + + let blob = new Blob(blobData, { type: blobType }); + + let sliceText = blobData[2][1] + blobData[2][2]; + let sliceIndex = blobText.indexOf(sliceText); + + let firstSliceStart = blobData[0].length + blobData[1].length; + let firstSliceEnd = firstSliceStart + blobData[2].length; + + let slice = blob.slice(firstSliceStart, firstSliceEnd, blobType); + + let secondSliceStart = blobData[2].indexOf("a"); + let secondSliceEnd = secondSliceStart + 2; + + slice = slice.slice(secondSliceStart, secondSliceEnd, blobType); + + sendAsyncMessage(messageName, { blob: blob }); + sendAsyncMessage(messageName, { slice: slice }); +} + +function parentFrameScript(mm) { + const messageName = "test:blob-slice-test"; + const blobData = ["So", " ", "many", " ", "blobs!"]; + const blobText = blobData.join(""); + const blobType = "text/plain"; + + const sliceText = "an"; + + let receivedBlob = false; + let receivedSlice = false; + + let finishedTestingBlob = false; + let finishedTestingSlice = false; + + mm.addMessageListener(messageName, function(message) { + if ("blob" in message.data) { + is(receivedBlob, false, "Have not yet received Blob"); + is(receivedSlice, false, "Have not yet received Slice"); + is(finishedTestingBlob, false, "Have not yet finished testing Blob"); + is(finishedTestingSlice, false, "Have not yet finished testing Slice"); + + receivedBlob = true; + + let blob = message.data.blob; + + ok(blob instanceof Blob, "Received a Blob"); + is(blob.size, blobText.length, "Blob has correct size"); + is(blob.type, blobType, "Blob has correct type"); + + let slice = blob.slice(blobText.length - + blobData[blobData.length - 1].length, + blob.size, + blobType); + + ok(slice instanceof Blob, "Slice returned a Blob"); + is(slice.size, + blobData[blobData.length - 1].length, + "Slice has correct size"); + is(slice.type, blobType, "Slice has correct type"); + + let reader = new FileReader(); + reader.onload = function() { + is(reader.result, + blobData[blobData.length - 1], + "Slice has correct data"); + + finishedTestingBlob = true; + + if (finishedTestingSlice) { + SimpleTest.finish(); + } + }; + reader.readAsText(slice); + + return; + } + + if ("slice" in message.data) { + is(receivedBlob, true, "Already received Blob"); + is(receivedSlice, false, "Have not yet received Slice"); + is(finishedTestingSlice, false, "Have not yet finished testing Slice"); + + receivedSlice = true; + + let slice = message.data.slice; + + ok(slice instanceof Blob, "Received a Blob for slice"); + is(slice.size, sliceText.length, "Slice has correct size"); + is(slice.type, blobType, "Slice has correct type"); + + let reader = new FileReader(); + reader.onload = function() { + is(reader.result, sliceText, "Slice has correct data"); + + let slice2 = slice.slice(1, 2, blobType); + + ok(slice2 instanceof Blob, "Slice returned a Blob"); + is(slice2.size, 1, "Slice has correct size"); + is(slice2.type, blobType, "Slice has correct type"); + + let reader2 = new FileReader(); + reader2.onload = function() { + is(reader2.result, sliceText[1], "Slice has correct data"); + + finishedTestingSlice = true; + + if (finishedTestingBlob) { + SimpleTest.finish(); + } + }; + reader2.readAsText(slice2); + }; + reader.readAsText(slice); + + return; + } + + ok(false, "Received a bad message: " + JSON.stringify(message.data)); + }); + + mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();", + false); +} + +function setup() { + info("Got load event"); + + SpecialPowers.pushPrefEnv( + { set: [ ["dom.ipc.browser_frames.oop_by_default", true], + ["dom.mozBrowserFramesEnabled", true], + ["network.disable.ipc.security", true], + ["browser.pagethumbnails.capturing_disabled", true] ] }, + function() { + info("Prefs set"); + + SpecialPowers.pushPermissions( + [ { type: "browser", allow: true, context: document } ], + function() { + info("Permissions set"); + + let iframe = document.createElement("iframe"); + SpecialPowers.wrap(iframe).mozbrowser = true; + iframe.id = "iframe"; + iframe.src = + "data:text/html,<!DOCTYPE HTML><html><body></body></html>"; + + iframe.addEventListener("mozbrowserloadend", function() { + info("Starting tests"); + + let mm = SpecialPowers.getBrowserFrameMessageManager(iframe) + parentFrameScript(mm); + }); + + document.body.appendChild(iframe); + } + ); + } + ); +} + +SimpleTest.waitForExplicitFinish(); + </script> + </body> +</html> diff --git a/dom/ipc/tests/test_blob_sliced_from_parent_process.html b/dom/ipc/tests/test_blob_sliced_from_parent_process.html new file mode 100644 index 000000000..7d8a1665f --- /dev/null +++ b/dom/ipc/tests/test_blob_sliced_from_parent_process.html @@ -0,0 +1,213 @@ +<!DOCTYPE html> +<html> + <head> + <title>Test for slicing blobs that originated in a parent process</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"> + </script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + </head> + <body onload="setup();"> + <script type="application/javascript;version=1.7"> +"use strict"; + +function childFrameScript() { + "use strict"; + + const { classes: Cc, interfaces: Ci } = Components; + + const messageName = "test:blob-slice-test"; + const blobData = ["So", " ", "many", " ", "blobs!"]; + const blobText = blobData.join(""); + const blobType = "text/plain"; + + const sliceText = "an"; + + function info(msg) { + sendAsyncMessage(messageName, { op: "info", msg: msg }); + } + + function ok(condition, name, diag) { + sendAsyncMessage(messageName, + { op: "ok", + condition: condition, + name: name, + diag: diag }); + } + + function is(a, b, name) { + let pass = a == b; + let diag = pass ? "" : "got " + a + ", expected " + b; + ok(pass, name, diag); + } + + function finish(result) { + sendAsyncMessage(messageName, { op: "done", result: result }); + } + + function grabAndContinue(arg) { + testGenerator.send(arg); + } + + function testSteps() { + addMessageListener(messageName, grabAndContinue); + let message = yield undefined; + + let blob = message.data; + + ok(blob instanceof Ci.nsIDOMBlob, "Received a Blob"); + is(blob.size, blobText.length, "Blob has correct length"); + is(blob.type, blobType, "Blob has correct type"); + + info("Reading blob"); + + let reader = new FileReader(); + reader.addEventListener("load", grabAndContinue); + reader.readAsText(blob); + + yield undefined; + + is(reader.result, blobText, "Blob has correct data"); + + let firstSliceStart = blobData[0].length + blobData[1].length; + let firstSliceEnd = firstSliceStart + blobData[2].length; + + let slice = blob.slice(firstSliceStart, firstSliceEnd, blobType); + + ok(slice instanceof Ci.nsIDOMBlob, "Slice returned a Blob"); + is(slice.size, blobData[2].length, "Slice has correct length"); + is(slice.type, blobType, "Slice has correct type"); + + info("Reading slice"); + + reader = new FileReader(); + reader.addEventListener("load", grabAndContinue); + reader.readAsText(slice); + + yield undefined; + + is(reader.result, blobData[2], "Slice has correct data"); + + let secondSliceStart = blobData[2].indexOf("a"); + let secondSliceEnd = secondSliceStart + sliceText.length; + + slice = slice.slice(secondSliceStart, secondSliceEnd, blobType); + + ok(slice instanceof Ci.nsIDOMBlob, "Second slice returned a Blob"); + is(slice.size, sliceText.length, "Second slice has correct length"); + is(slice.type, blobType, "Second slice has correct type"); + + info("Sending second slice"); + finish(slice); + + yield undefined; + } + + let testGenerator = testSteps(); + testGenerator.next(); +} + +function parentFrameScript(mm) { + const messageName = "test:blob-slice-test"; + const blobData = ["So", " ", "many", " ", "blobs!"]; + const blobText = blobData.join(""); + const blobType = "text/plain"; + + const sliceText = "an"; + + function grabAndContinue(arg) { + testGenerator.send(arg); + } + + function testSteps() { + let slice = yield undefined; + + ok(slice instanceof Blob, "Received a Blob"); + is(slice.size, sliceText.length, "Slice has correct size"); + is(slice.type, blobType, "Slice has correct type"); + + let reader = new FileReader(); + reader.onload = grabAndContinue; + reader.readAsText(slice); + yield undefined; + + is(reader.result, sliceText, "Slice has correct data"); + SimpleTest.finish(); + + yield undefined; + } + + let testGenerator = testSteps(); + testGenerator.next(); + + mm.addMessageListener(messageName, function(message) { + let data = message.data; + switch (data.op) { + case "info": { + info(data.msg); + break; + } + + case "ok": { + ok(data.condition, data.name, data.diag); + break; + } + + case "done": { + testGenerator.send(data.result); + break; + } + + default: { + ok(false, "Unknown op: " + data.op); + SimpleTest.finish(); + } + } + }); + + mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();", + false); + + let blob = new Blob(blobData, { type: blobType }); + mm.sendAsyncMessage(messageName, blob); +} + +function setup() { + info("Got load event"); + + SpecialPowers.pushPrefEnv( + { set: [ ["dom.ipc.browser_frames.oop_by_default", true], + ["dom.mozBrowserFramesEnabled", true], + ["network.disable.ipc.security", true], + ["browser.pagethumbnails.capturing_disabled", true] ] }, + function() { + info("Prefs set"); + + SpecialPowers.pushPermissions( + [ { type: "browser", allow: true, context: document } ], + function() { + info("Permissions set"); + + let iframe = document.createElement("iframe"); + SpecialPowers.wrap(iframe).mozbrowser = true; + iframe.id = "iframe"; + iframe.src = + "data:text/html,<!DOCTYPE HTML><html><body></body></html>"; + + iframe.addEventListener("mozbrowserloadend", function() { + info("Starting tests"); + + let mm = SpecialPowers.getBrowserFrameMessageManager(iframe) + parentFrameScript(mm); + }); + + document.body.appendChild(iframe); + } + ); + } + ); +} + +SimpleTest.waitForExplicitFinish(); + </script> + </body> +</html> diff --git a/dom/ipc/tests/test_bug1086684.html b/dom/ipc/tests/test_bug1086684.html new file mode 100644 index 000000000..962826ec6 --- /dev/null +++ b/dom/ipc/tests/test_bug1086684.html @@ -0,0 +1,107 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for recursive CPOW-getting-cookie bug</title> + <script type="application/javascript" + src="/tests/SimpleTest/SimpleTest.js"> + </script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + + <script type="application/javascript;version=1.8"> + "use strict"; + + SimpleTest.waitForExplicitFinish(); + + const childFrameURL = + "http://mochi.test:8888/tests/dom/ipc/tests/file_bug1086684.html"; + + function childFrameScript() { + "use strict"; + + let { MockFilePicker } = + Components.utils.import("chrome://specialpowers/content/MockFilePicker.jsm", {}); + + function parentReady(message) { + MockFilePicker.init(content); + MockFilePicker.returnFiles = [message.data.file]; + MockFilePicker.returnValue = MockFilePicker.returnOK; + + let input = content.document.getElementById("f"); + input.addEventListener("change", () => { + MockFilePicker.cleanup(); + let value = input.value; + message.target.sendAsyncMessage("testBug1086684:childDone", { value }); + }); + + input.focus(); + input.click(); + } + + addMessageListener("testBug1086684:parentReady", function(message) { + parentReady(message); + }); + } + + let test; + function* testStructure(mm) { + let value; + + function testDone(msg) { + test.next(msg.data.value); + } + + mm.addMessageListener("testBug1086684:childDone", testDone); + + let blob = new Blob([]); + let file = new File([blob], "helloworld.txt", { type: "text/plain" }); + + mm.sendAsyncMessage("testBug1086684:parentReady", { file }); + value = yield; + + // Note that the "helloworld.txt" passed in above doesn't affect the + // 'value' getter. Because we're mocking a file using a blob, we ask the + // blob for its path, which is the empty string. + is(value, "", "got the right answer and didn't crash"); + + SimpleTest.finish(); + } + + function runTests() { + info("Browser prefs set."); + + let iframe = document.createElement("iframe"); + SpecialPowers.wrap(iframe).mozbrowser = true; + iframe.id = "iframe"; + iframe.src = childFrameURL; + + iframe.addEventListener("mozbrowserloadend", function() { + info("Got iframe load event."); + let mm = SpecialPowers.getBrowserFrameMessageManager(iframe); + mm.loadFrameScript("data:,(" + encodeURI(childFrameScript.toString()) + ")();", + false); + + test = testStructure(mm); + test.next(); + }); + + document.body.appendChild(iframe); + } + + addEventListener("load", function() { + info("Got load event."); + + SpecialPowers.addPermission("browser", true, document); + SpecialPowers.pushPrefEnv({ + "set": [ + ["dom.ipc.browser_frames.oop_by_default", true], + ["dom.mozBrowserFramesEnabled", true], + ["network.disable.ipc.security", true], + ["browser.pagethumbnails.capturing_disabled", true] + ] + }, runTests); + }); + </script> +</body> +</html> diff --git a/dom/ipc/tests/test_child_docshell.html b/dom/ipc/tests/test_child_docshell.html new file mode 100644 index 000000000..5855569e8 --- /dev/null +++ b/dom/ipc/tests/test_child_docshell.html @@ -0,0 +1,86 @@ +<!DOCTYPE HTML> +<html> +<!-- +--> +<head> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript;version=1.7"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.addPermission("browser", true, document); +SpecialPowers.pushPrefEnv({'set':[ + ["dom.mozBrowserFramesEnabled", true], + ["network.disable.ipc.security", true], + ["dom.ipc.tabs.disabled", false] +]}, function () { + + var iframe = document.createElementNS('http://www.w3.org/1999/xhtml', 'iframe'); + iframe.setAttribute("remote", "true"); + SpecialPowers.wrap(iframe).mozbrowser = true; + document.documentElement.appendChild(iframe); + + var mm = SpecialPowers.getBrowserFrameMessageManager(iframe); + mm.addMessageListener("chromeEventHandler", function (msg) { + msg = SpecialPowers.wrap(msg); + var result = msg.json; + is(result.processType, SpecialPowers.Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT, + "The frame script is running in a real distinct child process"); + ok(result.hasCorrectInterface, + "docshell.chromeEventHandler has nsIDOMEventTarget interface"); + }); + + + mm.addMessageListener("DOMWindowCreatedReceived", function (msg) { + msg = SpecialPowers.wrap(msg); + ok(true, "the chrome event handler looks functional"); + var result = msg.json; + ok(result.stableChromeEventHandler, "docShell.chromeEventHandler is stable"); + ok(result.iframeHasNewDocShell, "iframe spawns a new docShell"); + ok(result.iframeHasSameChromeEventHandler, "but iframe has the same chrome event handler"); + SimpleTest.finish(); + }); + // Inject a frame script in the child process: + mm.loadFrameScript('data:,new ' + function ContentScriptScope() { + var processType = Components.classes["@mozilla.org/xre/runtime;1"] + .getService(Components.interfaces.nsIXULRuntime) + .processType; + var chromeEventHandler = docShell.chromeEventHandler; + sendAsyncMessage("chromeEventHandler", { + processType: Services.appinfo.processType, + hasCorrectInterface: chromeEventHandler instanceof Components.interfaces.nsIDOMEventTarget + }); + + /* + Ensure that this chromeEventHandler actually works, + by creating a new window and listening for its DOMWindowCreated event + */ + chromeEventHandler.addEventListener("DOMWindowCreated", function listener(evt) { + if (evt.target == content.document) { + return; + } + chromeEventHandler.removeEventListener("DOMWindowCreated", listener); + let new_win = evt.target.defaultView; + let new_docShell = new_win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); + sendAsyncMessage("DOMWindowCreatedReceived", { + stableChromeEventHandler: chromeEventHandler === docShell.chromeEventHandler, + iframeHasNewDocShell: new_docShell !== docShell, + iframeHasSameChromeEventHandler: new_docShell.chromeEventHandler === chromeEventHandler + }); + }); + + let i = content.document.createElement("iframe"); + i.setAttribute("src", "data:text/html,foo"); + content.document.documentElement.appendChild(i); + }, false); +}); + +</script> +</body> +</html> diff --git a/dom/ipc/tests/test_cpow_cookies.html b/dom/ipc/tests/test_cpow_cookies.html new file mode 100644 index 000000000..1e55d3878 --- /dev/null +++ b/dom/ipc/tests/test_cpow_cookies.html @@ -0,0 +1,90 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for recursive CPOW-getting-cookie bug</title> + <script type="application/javascript" + src="/tests/SimpleTest/SimpleTest.js"> + </script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + + <script type="application/javascript;version=1.8"> + "use strict"; + + SimpleTest.waitForExplicitFinish(); + + const childFrameURL = + "data:text/html,<!DOCTYPE HTML><html><body></body></html>"; + + function childFrameScript() { + "use strict"; + + const Ci = Components.interfaces; + + function test1(message) { + // NB: This is a no-op because we're a data: document with a null + // principal. + content.document.cookie = "a=b"; + message.target.sendAsyncMessage("testCPOWCookies:test1Finished", { pass: true }); + } + + addMessageListener("testCPOWCookies:test1", function(message) { + test1(message); + }); + } + + let test; + function* testStructure(mm) { + let lastResult; + + function testDone(msg) { + test.next(msg.data); + } + + mm.addMessageListener("testCPOWCookies:test1Finished", testDone); + + mm.sendAsyncMessage("testCPOWCookies:test1", {}); + lastResult = yield; + ok(lastResult.pass, "got the right answer and didn't crash"); + + SimpleTest.finish(); + } + + function runTests() { + info("Browser prefs set."); + + let iframe = document.createElement("iframe"); + SpecialPowers.wrap(iframe).mozbrowser = true; + iframe.id = "iframe"; + iframe.src = childFrameURL; + + iframe.addEventListener("mozbrowserloadend", function() { + info("Got iframe load event."); + let mm = SpecialPowers.getBrowserFrameMessageManager(iframe); + mm.loadFrameScript("data:,(" + encodeURI(childFrameScript.toString()) + ")();", + false); + + test = testStructure(mm); + test.next(); + }); + + document.body.appendChild(iframe); + } + + addEventListener("load", function() { + info("Got load event."); + + SpecialPowers.addPermission("browser", true, document); + SpecialPowers.pushPrefEnv({ + "set": [ + ["dom.ipc.browser_frames.oop_by_default", true], + ["dom.mozBrowserFramesEnabled", true], + ["network.disable.ipc.security", true], + ["browser.pagethumbnails.capturing_disabled", true] + ] + }, runTests); + }); + </script> +</body> +</html> diff --git a/dom/ipc/tests/test_process_error.xul b/dom/ipc/tests/test_process_error.xul new file mode 100644 index 000000000..72352fc88 --- /dev/null +++ b/dom/ipc/tests/test_process_error.xul @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?> + +<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script type="application/javascript" + src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> + + <script> + SimpleTest.waitForExplicitFinish(); + + var w = window.open('process_error.xul', '_blank', 'chrome,resizable=yes,width=400,height=600'); + + function done() + { + w.close(); + SimpleTest.finish(); + } + </script> + + <body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;" /> +</window> diff --git a/dom/ipc/tests/test_temporaryfile_stream.html b/dom/ipc/tests/test_temporaryfile_stream.html new file mode 100644 index 000000000..e05accbdf --- /dev/null +++ b/dom/ipc/tests/test_temporaryfile_stream.html @@ -0,0 +1,80 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Send an nsTemporaryFileInputStream cross-process</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/dom/canvas/test/captureStream_common.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<pre id="test"> +<div id="content"> +</div> +<script class="testbody" type="text/javascript"> +function startTest() { + var canvas = document.createElement("canvas"); + canvas.width = canvas.height = 100; + document.getElementById("content").appendChild(canvas); + + var helper = new CaptureStreamTestHelper2D(100, 100); + helper.drawColor(canvas, helper.red); + + var stream = canvas.captureStream(0); + + var blob; + + mediaRecorder = new MediaRecorder(stream); + is(mediaRecorder.stream, stream, + "Media recorder stream = canvas stream at the start of recording"); + + mediaRecorder.onwarning = () => ok(false, "warning unexpectedly fired"); + + mediaRecorder.onerror = () => ok(false, "Recording failed"); + + mediaRecorder.ondataavailable = ev => { + is(blob, undefined, "Should only get one dataavailable event"); + blob = ev.data; + }; + + mediaRecorder.onstart = () => { + info("Got 'start' event"); + // We just want one frame encoded, to see that the recorder produces something readable. + mediaRecorder.stop(); + }; + + mediaRecorder.onstop = () => { + info("Got 'stop' event"); + ok(blob, "Should have gotten a data blob"); + var xhr = new XMLHttpRequest(); + xhr.open('POST', 'blob_verify.sjs', true); + xhr.onload = () => { + var video = document.createElement("video"); + video.id = "recorded-video"; + video.src = URL.createObjectURL(xhr.response); + video.play(); + video.onerror = err => { + ok(false, "Should be able to play the recording. Got error. code=" + video.error.code); + SimpleTest.finish(); + }; + document.getElementById("content").appendChild(video); + helper.waitForPixelColor(video, helper.red, 128, "Should become red") + .then(SimpleTest.finish); + }; + xhr.onerror = () => { + ok(false, "XHR error"); + SimpleTest.finish(); + } + xhr.responseType = "blob"; + xhr.send(blob); + }; + + mediaRecorder.start(); + is(mediaRecorder.state, "recording", "Media recorder should be recording"); +} + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({set:[["media.recorder.max_memory", 1]]}, startTest); +</script> +</pre> +</body> +</html> |