diff options
Diffstat (limited to 'toolkit/identity/tests/chrome')
11 files changed, 542 insertions, 0 deletions
diff --git a/toolkit/identity/tests/chrome/.eslintrc.js b/toolkit/identity/tests/chrome/.eslintrc.js new file mode 100644 index 000000000..2c669d844 --- /dev/null +++ b/toolkit/identity/tests/chrome/.eslintrc.js @@ -0,0 +1,7 @@ +"use strict"; + +module.exports = { + "extends": [ + "../../../../testing/mochitest/chrome.eslintrc.js" + ] +}; diff --git a/toolkit/identity/tests/chrome/chrome.ini b/toolkit/identity/tests/chrome/chrome.ini new file mode 100644 index 000000000..ffaff0fb1 --- /dev/null +++ b/toolkit/identity/tests/chrome/chrome.ini @@ -0,0 +1,13 @@ +[DEFAULT] +skip-if = buildapp == 'b2g' || os == 'android' +support-files = + sandbox_content.html + sandbox_content.sjs + sandbox_content_alert.html + sandbox_content_framed.html + sandbox_content_perms.html + sandbox_content_popup.html + sandbox_content_redirect.html + sandbox_content_redirect.html^headers^ + +[test_sandbox.xul] diff --git a/toolkit/identity/tests/chrome/sandbox_content.html b/toolkit/identity/tests/chrome/sandbox_content.html new file mode 100644 index 000000000..9a9b63ac2 --- /dev/null +++ b/toolkit/identity/tests/chrome/sandbox_content.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<!-- Any copyright is dedicated to the Public Domain. + - http://creativecommons.org/publicdomain/zero/1.0/ --> +<head> +<meta charset="utf-8"> +<title>Page testing blocked content in the Sandbox</title> + +<link rel="stylesheet" src="sandbox_content.sjs?text/css"/> + +<script src="sandbox_content.sjs?application/javascript"></script> + +</head> + +<body> + +<img src="sandbox_content.sjs?image/jpeg"/> + +<!-- media --> +<video src="sandbox_content.sjs?video/webm" autoplay="true"></video> +<audio src="sandbox_content.sjs?audio/ogg" autoplay="true"></audio> + +<!-- plugins --> +<embed src="sandbox_content.sjs?application/x-test"/> +<object data="sandbox_content.sjs?application/x-test"></object> +<applet code="sandbox_content.sjs?application/x-java-applet"></applet> + +<iframe src="sandbox_content.sjs?text/html"></iframe> + +</body> + +</html> diff --git a/toolkit/identity/tests/chrome/sandbox_content.sjs b/toolkit/identity/tests/chrome/sandbox_content.sjs new file mode 100644 index 000000000..2f562f214 --- /dev/null +++ b/toolkit/identity/tests/chrome/sandbox_content.sjs @@ -0,0 +1,36 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * * License, v. 2.0. If a copy of the MPL was not distributed with this + * * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function handleRequest(request, response) { + response.setHeader("Cache-Control", "no-cache", false); + + let loadedStateKey = "sandbox_content_loaded"; + switch(request.queryString) { + case "reset": { + setState(loadedStateKey, ""); + response.write("reset"); + break; + } + case "get_loaded": { + response.setHeader("Content-Type", "text/plain", false); + let loaded = getState(loadedStateKey); + if (loaded) + response.write(loaded); + else + response.write("NOTHING"); + break; + } + default: { + let contentType = decodeURIComponent(request.queryString); + // set the Content-Type equal to the query string + response.setHeader("Content-Type", contentType, false); + // If any content is loaded, append it's content type in state + let loaded = getState(loadedStateKey); + if (loaded) + loaded += ","; + setState(loadedStateKey, loaded + contentType); + break; + } + } +} diff --git a/toolkit/identity/tests/chrome/sandbox_content_alert.html b/toolkit/identity/tests/chrome/sandbox_content_alert.html new file mode 100644 index 000000000..f07308e84 --- /dev/null +++ b/toolkit/identity/tests/chrome/sandbox_content_alert.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<head> +<meta charset="utf-8"> +<title>Page creating an alert inside the Sandbox</title> + +<script> + +alert("The user shouldn't see this"); + +</script> + +</head> + +<body> + +</body> +</html> diff --git a/toolkit/identity/tests/chrome/sandbox_content_framed.html b/toolkit/identity/tests/chrome/sandbox_content_framed.html new file mode 100644 index 000000000..72b0c49d0 --- /dev/null +++ b/toolkit/identity/tests/chrome/sandbox_content_framed.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> +<head> +<meta charset="utf-8"> +<title>Page testing blocked content in an iframe inside the Sandbox</title> + +</head> + +<body> + +<iframe src="sandbox_content.html"></iframe> + +</body> + +</html> diff --git a/toolkit/identity/tests/chrome/sandbox_content_perms.html b/toolkit/identity/tests/chrome/sandbox_content_perms.html new file mode 100644 index 000000000..d24c683f8 --- /dev/null +++ b/toolkit/identity/tests/chrome/sandbox_content_perms.html @@ -0,0 +1,64 @@ +<!DOCTYPE html> +<html> + <!-- Any copyright is dedicated to the Public Domain. + - http://creativecommons.org/publicdomain/zero/1.0/ --> + <head> + <meta charset="utf-8"> + <title>Page testing content in the Sandbox can't escape</title> + <script type="application/javascript;version=1.8"> + const TEST_BASE = "http://mochi.test:8888/chrome/toolkit/identity/tests/chrome/" + const Ci = SpecialPowers.Ci; + + function expectException(aFunc) { + try { + aFunc(); + } catch (ex) { + return true; + } + return false; + } + + function CcNotPresent() { + if (typeof Components === 'undefined') + return true; + // Components shim doesn't define Components.classes. + try { + return typeof Components.classes === 'undefined'; + } catch (e) { + return false; + } + } + + // Build an object with test results (true = pass) + let results = { + windowTop: window.top == window, + + qiWindow: expectException(function() { + let isForced = window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils) + .docCharsetIsForced; + }), + + ccAccess: !!CcNotPresent(), + }; + + let resultsJSON = JSON.stringify(results); + + // Send the results to the mochitest server so the test file can retrieve them. + let stateURL = TEST_BASE + "sandbox_content.sjs" + let xhr = new XMLHttpRequest(); + xhr.open("GET", stateURL + "?" + encodeURIComponent(resultsJSON), true); + xhr.onload = function() { + if (xhr.status != 200) { + dump("Failed sending results\n"); + } + }; + xhr.send(); + + </script> + </head> + + <body> + + </body> +</html> diff --git a/toolkit/identity/tests/chrome/sandbox_content_popup.html b/toolkit/identity/tests/chrome/sandbox_content_popup.html new file mode 100644 index 000000000..cb21f706f --- /dev/null +++ b/toolkit/identity/tests/chrome/sandbox_content_popup.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> +<!-- Any copyright is dedicated to the Public Domain. + - http://creativecommons.org/publicdomain/zero/1.0/ --> +<head> +<meta charset="utf-8"> +<title>Page creating an popup inside the Sandbox</title> + +<script> + +var strWindowFeatures = "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes"; + +var uri = "data:text/html,"; +uri += encodeURI("<body onload='setTimeout(window.close, 1000)'>"); + +var win = window.open(uri, "sandbox_popup", strWindowFeatures); + +</script> + +</head> + +<body> + +</body> +</html> diff --git a/toolkit/identity/tests/chrome/sandbox_content_redirect.html b/toolkit/identity/tests/chrome/sandbox_content_redirect.html new file mode 100644 index 000000000..7570ffad8 --- /dev/null +++ b/toolkit/identity/tests/chrome/sandbox_content_redirect.html @@ -0,0 +1,2 @@ +<!-- Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ --> diff --git a/toolkit/identity/tests/chrome/sandbox_content_redirect.html^headers^ b/toolkit/identity/tests/chrome/sandbox_content_redirect.html^headers^ new file mode 100644 index 000000000..7c06340b9 --- /dev/null +++ b/toolkit/identity/tests/chrome/sandbox_content_redirect.html^headers^ @@ -0,0 +1,2 @@ +HTTP 302 Found +Location: http://mochi.test:8888/chrome/toolkit/identity/tests/chrome/sandbox_content.html 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> |