diff options
Diffstat (limited to 'toolkit/identity/tests/chrome/test_sandbox.xul')
-rw-r--r-- | toolkit/identity/tests/chrome/test_sandbox.xul | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/toolkit/identity/tests/chrome/test_sandbox.xul b/toolkit/identity/tests/chrome/test_sandbox.xul new file mode 100644 index 000000000..2b353c53b --- /dev/null +++ b/toolkit/identity/tests/chrome/test_sandbox.xul @@ -0,0 +1,324 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?> +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=762993 +--> +<window title="Mozilla Bug 762993" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + onload="run_next_test();"> + <script type="application/javascript" + src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=762993" + target="_blank">Mozilla Bug 762993</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript;version=1.8"> + <![CDATA[ + + /** Test for Bug 762993 **/ + +"use strict"; + +SimpleTest.expectAssertions(1); + +SimpleTest.waitForExplicitFinish(); + +var Cc = Components.classes; +var Ci = Components.interfaces; +var Cu = Components.utils; + +const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); + +const TEST_URL_1 = "https://example.com/"; +// No trailing slash plus port to test normalization +const TEST_URL_2 = "https://example.com:443"; + +const TEST_BASE = "http://mochi.test:8888/chrome/toolkit/identity/tests/chrome/" +const STATE_URL = TEST_BASE + "sandbox_content.sjs" + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +Services.prefs.setBoolPref("toolkit.identity.debug", true); + +XPCOMUtils.defineLazyModuleGetter(this, "Sandbox", + "resource://gre/modules/identity/Sandbox.jsm"); + +function check_sandbox(aSandbox, aURL) { + ok(aSandbox.id > 0, "valid ID"); + is(aSandbox._url, aURL, "matching URL (with normalization)"); + isnot(aSandbox._frame, null, "frame"); + isnot(aSandbox._container, null, "container"); + let docPrincipal = aSandbox._frame.contentDocument.nodePrincipal; + is(secMan.isSystemPrincipal(docPrincipal), false, + "principal must not be system"); +} + +/** + * Free the sandbox and make sure all properties that are not booleans, + * functions or numbers were freed. + */ +function free_and_check_sandbox(aSandbox) { + SimpleTest.executeSoon(function() { + aSandbox.free(); + + for(let prop in aSandbox) { + // Don't trigger the "id" getter when the frame is supposed to be freed already + if (prop == "id") + continue; + let propType = typeof(aSandbox[prop]); + if (propType == "boolean" || propType == "function" || propType == "number") + continue; + is(aSandbox[prop], null, "freed " + prop); + } + run_next_test(); + }); +} + +function reset_server_state() { + // Now reset the server state + let resetReq = new XMLHttpRequest(); + resetReq.open("GET", STATE_URL + "?reset", false); + resetReq.send(); +} + +function test_creation() { + new Sandbox(TEST_URL_1, function sandboxCB(aSandbox) { + check_sandbox(aSandbox, TEST_URL_1); + free_and_check_sandbox(aSandbox); + }); +} + +function test_reload() { + new Sandbox(TEST_URL_1, function sandboxCB(aSandbox) { + check_sandbox(aSandbox, TEST_URL_1); + let originalId = aSandbox.id; + + aSandbox.reload(function sandboxReloadCB(aSandbox) { + check_sandbox(aSandbox, TEST_URL_1); + is(aSandbox.id, originalId, "Sandbox ID should be the same after reload"); + free_and_check_sandbox(aSandbox); + }); + }); +} + +function test_url_normalization() { + new Sandbox(TEST_URL_2, function sandboxCB(aSandbox) { + // TEST_URL_2 should be normalized into the form of TEST_URL_1 + check_sandbox(aSandbox, TEST_URL_1); + free_and_check_sandbox(aSandbox); + }); +} + +/** + * Check with the server's state to see what content was loaded then reset it. + */ +function check_loaded_content(aSandbox, aNothingShouldLoad, aCallback) { + + let xhr = new XMLHttpRequest(); + xhr.open("GET", STATE_URL + "?get_loaded", true); + xhr.onload = function() { + let res = xhr.responseText; + is(xhr.status, 200, "Check successful response"); + + if (aNothingShouldLoad) { + is(res, "NOTHING", "Check that nothing was loaded on the server"); + } else { + let allowedTypes = [ "application/javascript", "text/html", "application/x-test" ]; + let loadedTypes = res == "NOTHING" ? [] : res.split(","); + + for (let loadedType of loadedTypes) { + isnot(allowedTypes.indexOf(loadedType), -1, "Check that " + loadedType + " was expected to load"); // TODO + } + + isnot(loadedTypes.indexOf("application/javascript"), -1, "Check JS was loaded"); + isnot(loadedTypes.indexOf("text/html"), -1, "Check iframe was loaded"); + is(loadedTypes.indexOf("video/webm"), -1, "Check webm was not loaded"); + is(loadedTypes.indexOf("audio/ogg"), -1, "Check ogg was not loaded"); + + // Check that no plugin tags have a type other than TYPE_NULL (failed load) + // -- + // Checking if a channel was opened is not sufficient for plugin tags -- + // An object tag may still be allowed to load a sub-document, but not a + // plugin, so it will open a channel but then abort when it gets a + // plugin-type. + let doc = aSandbox._frame.contentDocument; + let nullType = Components.interfaces.nsIObjectLoadingContent.TYPE_NULL; + for (let tag of doc.querySelectorAll("embed, object, applet")) { + tag instanceof Components.interfaces.nsIObjectLoadingContent; + is(tag.displayedType, nullType, "Check that plugin did not load content"); + } + } + + reset_server_state(); + + aCallback(); + }; + xhr.send(); +} + +/** + * Helper to check that only certain content is loaded on creation and during reload. + */ +function check_disabled_content(aSandboxURL, aNothingShouldLoad = false) { + new Sandbox(aSandboxURL, function sandboxCB(aSandbox) { + check_sandbox(aSandbox, aSandboxURL); + let originalId = aSandbox.id; + + setTimeout(function() { + check_loaded_content(aSandbox, aNothingShouldLoad, function checkFinished() { + + info("reload the sandbox content"); + aSandbox.reload(function sandboxReloadCB(aSandbox) { + check_sandbox(aSandbox, aSandboxURL); + is(aSandbox.id, originalId, "Sandbox ID should be the same after reload"); + + setTimeout(function() { + check_loaded_content(aSandbox, aNothingShouldLoad, function reloadCheckFinished() { + free_and_check_sandbox(aSandbox); + }); + }, 5000); + }); + }); + }, 5000); + }); +} + +function test_disabled_content() { + let url = TEST_BASE + "sandbox_content.html"; + check_disabled_content(url); +} + +// Same as test above but with content in an iframe. +function test_disabled_content_framed() { + let url = TEST_BASE + "sandbox_content_framed.html"; + check_disabled_content(url); +} + +function test_redirect() { + let url = TEST_BASE + "sandbox_content_redirect.html"; + check_disabled_content(url); +} + +function WindowObserver(aCallback) { + this.observe = function(aSubject, aTopic, aData) { + if (aTopic != "domwindowopened") { + return; + } + Services.ww.unregisterNotification(this); + + let domWin = aSubject.QueryInterface(Ci.nsIDOMWindow); + ok(!domWin, "No window should be opened"); + SimpleTest.executeSoon(function() { + info("Closing opened window"); + domWin.close(); + aCallback(); + }); + } +} + +// Can the sandbox call window.alert() or popup other UI? +function test_alert() { + let alertURL = TEST_BASE + "sandbox_content_alert.html"; + + new Sandbox(alertURL, function sandboxCB(aSandbox) { + check_sandbox(aSandbox, alertURL); + setTimeout(function() { + + let win = Services.wm.getMostRecentWindow(null); + isnot(win.document.documentElement.getAttribute("id"), "commonDialog", + "Make sure most recent window is not a dialog"); + if (win.document.documentElement.getAttribute("id") == "commonDialog") { + // If a dialog did open, close it so we don't interfere with future tests + win.close() + } + + free_and_check_sandbox(aSandbox); + }, 1000); + }); +} + +// Can the sandboxed page open a popup with window.open? +function test_popup() { + let alertURL = TEST_BASE + "sandbox_content_popup.html"; + let theSandbox; + function continueTest() { + // avoid double-free + if (!theSandbox) + return; + free_and_check_sandbox(theSandbox); + theSandbox = null; + } + let winObs = new WindowObserver(continueTest); + Services.ww.registerNotification(winObs); + new Sandbox(alertURL, function sandboxCB(aSandbox) { + theSandbox = aSandbox; + check_sandbox(aSandbox, alertURL); + // Wait 5 seconds to see if the window is going to open. + setTimeout(function() { + Services.ww.unregisterNotification(winObs); + continueTest(); + }, 5000); + }); +} + +// Loading a page with a bad cert +function test_bad_cert() { + let url = TEST_BASE + "sandbox_content.sjs?text/html"; + url = url.replace("http://mochi.test:8888", "https://untrusted.example.com"); + check_disabled_content(url, /*nothingShouldLoad=*/true); +} + +// Loading a page to check window.top and other permissions. +function test_frame_perms() { + let url = TEST_BASE + "sandbox_content_perms.html"; + new Sandbox(url, function sandboxCB(aSandbox) { + check_sandbox(aSandbox, url); + + // Give the content time to load + setTimeout(function() { + let xhr = new XMLHttpRequest(); + xhr.open("GET", STATE_URL + "?get_loaded", true); + xhr.responseType = "json"; + xhr.onload = function() { + is(xhr.status, 200, "Check successful response"); + is(typeof(xhr.response), "object", "Check response is object"); + is(Object.keys(xhr.response).length, 3, "Check the number of perm. tests"); + for (let test in xhr.response) { + ok(xhr.response[test], "Check result of " + test); + } + + reset_server_state(); + free_and_check_sandbox(aSandbox); + }; + xhr.send(); + }, 3000); + }); +} + +let TESTS = [test_creation, test_reload, test_url_normalization]; +TESTS.push(test_disabled_content, test_disabled_content_framed); +TESTS.push(test_alert, test_popup, test_bad_cert); +TESTS.push(test_redirect, test_frame_perms); + +function run_next_test() { + if (TESTS.length) { + let test = TESTS.shift(); + info(test.name); + test(); + } else { + Services.prefs.clearUserPref("toolkit.identity.debug"); + SimpleTest.finish(); + } +} + + ]]> + </script> +</window> |