<?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>