summaryrefslogtreecommitdiff
path: root/caps/tests
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /caps/tests
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloaduxp-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
Add m-esr52 at 52.6.0
Diffstat (limited to 'caps/tests')
-rw-r--r--caps/tests/gtest/TestOriginAttributes.cpp38
-rw-r--r--caps/tests/gtest/moz.build13
-rw-r--r--caps/tests/mochitest/browser.ini1
-rw-r--r--caps/tests/mochitest/browser_checkloaduri.js292
-rw-r--r--caps/tests/mochitest/chrome.ini9
-rw-r--r--caps/tests/mochitest/file_data.txt1
-rw-r--r--caps/tests/mochitest/file_disableScript.html11
-rw-r--r--caps/tests/mochitest/mochitest.ini13
-rw-r--r--caps/tests/mochitest/resource_test_file.html2
-rw-r--r--caps/tests/mochitest/test_addonMayLoad.html97
-rw-r--r--caps/tests/mochitest/test_app_principal_equality.html88
-rw-r--r--caps/tests/mochitest/test_bug246699.html65
-rw-r--r--caps/tests/mochitest/test_bug292789.html105
-rw-r--r--caps/tests/mochitest/test_bug423375.html44
-rw-r--r--caps/tests/mochitest/test_bug470804.html41
-rw-r--r--caps/tests/mochitest/test_bug995943.xul115
-rw-r--r--caps/tests/mochitest/test_disableScript.xul339
-rw-r--r--caps/tests/mochitest/test_disallowInheritPrincipal.html60
-rw-r--r--caps/tests/mochitest/test_extensionURL.html166
-rw-r--r--caps/tests/unit/test_origin.js307
-rw-r--r--caps/tests/unit/xpcshell.ini5
21 files changed, 1812 insertions, 0 deletions
diff --git a/caps/tests/gtest/TestOriginAttributes.cpp b/caps/tests/gtest/TestOriginAttributes.cpp
new file mode 100644
index 0000000000..e11bf28eb0
--- /dev/null
+++ b/caps/tests/gtest/TestOriginAttributes.cpp
@@ -0,0 +1,38 @@
+/* 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/. */
+#include "gtest/gtest.h"
+#include "mozilla/BasePrincipal.h"
+
+using mozilla::PrincipalOriginAttributes;
+
+static void
+TestSuffix(const PrincipalOriginAttributes& attrs)
+{
+ nsAutoCString suffix;
+ attrs.CreateSuffix(suffix);
+
+ PrincipalOriginAttributes attrsFromSuffix;
+ bool success = attrsFromSuffix.PopulateFromSuffix(suffix);
+ EXPECT_TRUE(success);
+
+ EXPECT_EQ(attrs, attrsFromSuffix);
+}
+
+TEST(PrincipalOriginAttributes, Suffix_default)
+{
+ PrincipalOriginAttributes attrs;
+ TestSuffix(attrs);
+}
+
+TEST(PrincipalOriginAttributes, Suffix_appId_inIsolatedMozBrowser)
+{
+ PrincipalOriginAttributes attrs(1, true);
+ TestSuffix(attrs);
+}
+
+TEST(PrincipalOriginAttributes, Suffix_maxAppId_inIsolatedMozBrowser)
+{
+ PrincipalOriginAttributes attrs(4294967295, true);
+ TestSuffix(attrs);
+}
diff --git a/caps/tests/gtest/moz.build b/caps/tests/gtest/moz.build
new file mode 100644
index 0000000000..26447f54c2
--- /dev/null
+++ b/caps/tests/gtest/moz.build
@@ -0,0 +1,13 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+UNIFIED_SOURCES += [
+ 'TestOriginAttributes.cpp'
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul-gtest'
diff --git a/caps/tests/mochitest/browser.ini b/caps/tests/mochitest/browser.ini
new file mode 100644
index 0000000000..d8a1278f9b
--- /dev/null
+++ b/caps/tests/mochitest/browser.ini
@@ -0,0 +1 @@
+[browser_checkloaduri.js]
diff --git a/caps/tests/mochitest/browser_checkloaduri.js b/caps/tests/mochitest/browser_checkloaduri.js
new file mode 100644
index 0000000000..24a97c1c45
--- /dev/null
+++ b/caps/tests/mochitest/browser_checkloaduri.js
@@ -0,0 +1,292 @@
+"use strict";
+
+let ssm = Services.scriptSecurityManager;
+// This will show a directory listing, but we never actually load these so that's OK.
+const kDummyPage = getRootDirectory(gTestPath);
+
+const kAboutPagesRegistered = Promise.all([
+ BrowserTestUtils.registerAboutPage(
+ registerCleanupFunction, "test-chrome-privs", kDummyPage,
+ Ci.nsIAboutModule.ALLOW_SCRIPT),
+ BrowserTestUtils.registerAboutPage(
+ registerCleanupFunction, "test-chrome-privs2", kDummyPage,
+ Ci.nsIAboutModule.ALLOW_SCRIPT),
+ BrowserTestUtils.registerAboutPage(
+ registerCleanupFunction, "test-unknown-linkable", kDummyPage,
+ Ci.nsIAboutModule.MAKE_LINKABLE | Ci.nsIAboutModule.ALLOW_SCRIPT),
+ BrowserTestUtils.registerAboutPage(
+ registerCleanupFunction, "test-unknown-linkable2", kDummyPage,
+ Ci.nsIAboutModule.MAKE_LINKABLE | Ci.nsIAboutModule.ALLOW_SCRIPT),
+ BrowserTestUtils.registerAboutPage(
+ registerCleanupFunction, "test-unknown-unlinkable", kDummyPage,
+ Ci.nsIAboutModule.ALLOW_SCRIPT),
+ BrowserTestUtils.registerAboutPage(
+ registerCleanupFunction, "test-unknown-unlinkable2", kDummyPage,
+ Ci.nsIAboutModule.ALLOW_SCRIPT),
+ BrowserTestUtils.registerAboutPage(
+ registerCleanupFunction, "test-content-unlinkable", kDummyPage,
+ Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT | Ci.nsIAboutModule.ALLOW_SCRIPT),
+ BrowserTestUtils.registerAboutPage(
+ registerCleanupFunction, "test-content-unlinkable2", kDummyPage,
+ Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT | Ci.nsIAboutModule.ALLOW_SCRIPT),
+ BrowserTestUtils.registerAboutPage(
+ registerCleanupFunction, "test-content-linkable", kDummyPage,
+ Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT | Ci.nsIAboutModule.MAKE_LINKABLE |
+ Ci.nsIAboutModule.ALLOW_SCRIPT),
+ BrowserTestUtils.registerAboutPage(
+ registerCleanupFunction, "test-content-linkable2", kDummyPage,
+ Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT | Ci.nsIAboutModule.MAKE_LINKABLE |
+ Ci.nsIAboutModule.ALLOW_SCRIPT),
+]);
+
+const URLs = new Map([
+ ["http://www.example.com", [
+ // For each of these entries, the booleans represent whether the parent URI can:
+ // - load them
+ // - load them without principal inheritance
+ // - whether the URI can be created at all (some protocol handlers will
+ // refuse to create certain variants)
+ ["http://www.example2.com", true, true, true],
+ ["feed:http://www.example2.com", false, false, true],
+ ["https://www.example2.com", true, true, true],
+ ["chrome://foo/content/bar.xul", false, false, true],
+ ["feed:chrome://foo/content/bar.xul", false, false, false],
+ ["view-source:http://www.example2.com", false, false, true],
+ ["view-source:https://www.example2.com", false, false, true],
+ ["view-source:feed:http://www.example2.com", false, false, true],
+ ["feed:view-source:http://www.example2.com", false, false, false],
+ ["data:text/html,Hi", true, false, true],
+ ["view-source:data:text/html,Hi", false, false, true],
+ ["javascript:alert('hi')", true, false, true],
+ ["moz://a", false, false, true],
+ ["about:test-chrome-privs", false, false, true],
+ ["about:test-unknown-unlinkable", false, false, true],
+ ["about:test-content-unlinkable", false, false, true],
+ ["about:test-content-linkable", true, true, true],
+ // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
+ ["about:test-unknown-linkable", false, false, true],
+ ]],
+ ["feed:http://www.example.com", [
+ ["http://www.example2.com", true, true, true],
+ ["feed:http://www.example2.com", true, true, true],
+ ["https://www.example2.com", true, true, true],
+ ["feed:https://www.example2.com", true, true, true],
+ ["chrome://foo/content/bar.xul", false, false, true],
+ ["feed:chrome://foo/content/bar.xul", false, false, false],
+ ["view-source:http://www.example2.com", false, false, true],
+ ["view-source:https://www.example2.com", false, false, true],
+ ["view-source:feed:http://www.example2.com", false, false, true],
+ ["feed:view-source:http://www.example2.com", false, false, false],
+ ["data:text/html,Hi", true, false, true],
+ ["view-source:data:text/html,Hi", false, false, true],
+ ["javascript:alert('hi')", true, false, true],
+ ["moz://a", false, false, true],
+ ["about:test-chrome-privs", false, false, true],
+ ["about:test-unknown-unlinkable", false, false, true],
+ ["about:test-content-unlinkable", false, false, true],
+ ["about:test-content-linkable", true, true, true],
+ // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
+ ["about:test-unknown-linkable", false, false, true],
+ ]],
+ ["view-source:http://www.example.com", [
+ ["http://www.example2.com", true, true, true],
+ ["feed:http://www.example2.com", false, false, true],
+ ["https://www.example2.com", true, true, true],
+ ["feed:https://www.example2.com", false, false, true],
+ ["chrome://foo/content/bar.xul", false, false, true],
+ ["feed:chrome://foo/content/bar.xul", false, false, false],
+ ["view-source:http://www.example2.com", true, true, true],
+ ["view-source:https://www.example2.com", true, true, true],
+ ["view-source:feed:http://www.example2.com", false, false, true],
+ ["feed:view-source:http://www.example2.com", false, false, false],
+ ["data:text/html,Hi", true, false, true],
+ ["view-source:data:text/html,Hi", true, false, true],
+ ["javascript:alert('hi')", true, false, true],
+ ["moz://a", false, false, true],
+ ["about:test-chrome-privs", false, false, true],
+ ["about:test-unknown-unlinkable", false, false, true],
+ ["about:test-content-unlinkable", false, false, true],
+ ["about:test-content-linkable", true, true, true],
+ // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
+ ["about:test-unknown-linkable", false, false, true],
+ ]],
+ // about: related tests.
+ ["about:test-chrome-privs", [
+ ["about:test-chrome-privs", true, true, true],
+ ["about:test-chrome-privs2", true, true, true],
+ ["about:test-chrome-privs2?foo#bar", true, true, true],
+ ["about:test-chrome-privs2?foo", true, true, true],
+ ["about:test-chrome-privs2#bar", true, true, true],
+
+ ["about:test-unknown-unlinkable", true, true, true],
+
+ ["about:test-content-unlinkable", true, true, true],
+ ["about:test-content-unlinkable?foo", true, true, true],
+ ["about:test-content-unlinkable?foo#bar", true, true, true],
+ ["about:test-content-unlinkable#bar", true, true, true],
+
+ ["about:test-content-linkable", true, true, true],
+
+ ["about:test-unknown-linkable", true, true, true],
+ ]],
+ ["about:test-unknown-unlinkable", [
+ ["about:test-chrome-privs", false, false, true],
+
+ // Can link to ourselves:
+ ["about:test-unknown-unlinkable", true, true, true],
+ // Can't link to unlinkable content if we're not sure it's privileged:
+ ["about:test-unknown-unlinkable2", false, false, true],
+
+ ["about:test-content-unlinkable", true, true, true],
+ ["about:test-content-unlinkable2", true, true, true],
+ ["about:test-content-unlinkable2?foo", true, true, true],
+ ["about:test-content-unlinkable2?foo#bar", true, true, true],
+ ["about:test-content-unlinkable2#bar", true, true, true],
+
+ ["about:test-content-linkable", true, true, true],
+
+ // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
+ ["about:test-unknown-linkable", false, false, true],
+ ]],
+ ["about:test-content-unlinkable", [
+ ["about:test-chrome-privs", false, false, true],
+
+ // Can't link to unlinkable content if we're not sure it's privileged:
+ ["about:test-unknown-unlinkable", false, false, true],
+
+ ["about:test-content-unlinkable", true, true, true],
+ ["about:test-content-unlinkable2", true, true, true],
+ ["about:test-content-unlinkable2?foo", true, true, true],
+ ["about:test-content-unlinkable2?foo#bar", true, true, true],
+ ["about:test-content-unlinkable2#bar", true, true, true],
+
+ ["about:test-content-linkable", true, true, true],
+ ["about:test-unknown-linkable", false, false, true],
+ ]],
+ ["about:test-unknown-linkable", [
+ ["about:test-chrome-privs", false, false, true],
+
+ // Linkable content can't link to unlinkable content.
+ ["about:test-unknown-unlinkable", false, false, true],
+
+ ["about:test-content-unlinkable", false, false, true],
+ ["about:test-content-unlinkable2", false, false, true],
+ ["about:test-content-unlinkable2?foo", false, false, true],
+ ["about:test-content-unlinkable2?foo#bar", false, false, true],
+ ["about:test-content-unlinkable2#bar", false, false, true],
+
+ // ... but it can link to other linkable content.
+ ["about:test-content-linkable", true, true, true],
+
+ // Can link to ourselves:
+ ["about:test-unknown-linkable", true, true, true],
+
+ // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
+ ["about:test-unknown-linkable2", false, false, true],
+ ]],
+ ["about:test-content-linkable", [
+ ["about:test-chrome-privs", false, false, true],
+
+ // Linkable content can't link to unlinkable content.
+ ["about:test-unknown-unlinkable", false, false, true],
+
+ ["about:test-content-unlinkable", false, false, true],
+
+ // ... but it can link to itself and other linkable content.
+ ["about:test-content-linkable", true, true, true],
+ ["about:test-content-linkable2", true, true, true],
+
+ // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
+ ["about:test-unknown-linkable", false, false, true],
+ ]],
+]);
+
+function testURL(source, target, canLoad, canLoadWithoutInherit, canCreate, flags) {
+ function getPrincipalDesc(principal) {
+ if (principal.URI) {
+ return principal.URI.spec;
+ }
+ if (principal.isSystemPrincipal) {
+ return "system principal";
+ }
+ if (principal.isNullPrincipal) {
+ return "null principal";
+ }
+ return "unknown principal";
+ }
+ let threw = false;
+ let targetURI;
+ try {
+ targetURI = makeURI(target);
+ } catch (ex) {
+ ok(!canCreate, "Shouldn't be passing URIs that we can't create. Failed to create: " + target);
+ return;
+ }
+ ok(canCreate, "Created a URI for " + target + " which should " +
+ (canCreate ? "" : "not ") + "be possible.");
+ try {
+ ssm.checkLoadURIWithPrincipal(source, targetURI, flags);
+ } catch (ex) {
+ info(ex.message);
+ threw = true;
+ }
+ let inheritDisallowed = flags & ssm.DISALLOW_INHERIT_PRINCIPAL;
+ let shouldThrow = inheritDisallowed ? !canLoadWithoutInherit : !canLoad;
+ ok(threw == shouldThrow,
+ "Should " + (shouldThrow ? "" : "not ") + "throw an error when loading " +
+ target + " from " + getPrincipalDesc(source) +
+ (inheritDisallowed ? " without" : " with") + " principal inheritance.");
+}
+
+add_task(function* () {
+ yield kAboutPagesRegistered;
+ let baseFlags = ssm.STANDARD | ssm.DONT_REPORT_ERRORS;
+ for (let [sourceString, targetsAndExpectations] of URLs) {
+ let source;
+ if (sourceString.startsWith("about:test-chrome-privs")) {
+ source = ssm.getSystemPrincipal();
+ } else {
+ source = ssm.createCodebasePrincipal(makeURI(sourceString), {});
+ }
+ for (let [target, canLoad, canLoadWithoutInherit, canCreate] of targetsAndExpectations) {
+ testURL(source, target, canLoad, canLoadWithoutInherit, canCreate, baseFlags);
+ testURL(source, target, canLoad, canLoadWithoutInherit, canCreate,
+ baseFlags | ssm.DISALLOW_INHERIT_PRINCIPAL);
+ }
+ }
+
+ // Now test blob URIs, which we need to do in-content.
+ yield BrowserTestUtils.withNewTab("http://www.example.com/", function* (browser) {
+ yield ContentTask.spawn(
+ browser,
+ testURL.toString(),
+ function* (testURLFn) {
+ let testURL = eval("(" + testURLFn + ")");
+ let ssm = Services.scriptSecurityManager;
+ let baseFlags = ssm.STANDARD | ssm.DONT_REPORT_ERRORS;
+ let makeURI = Cu.import("resource://gre/modules/BrowserUtils.jsm", {}).BrowserUtils.makeURI;
+ let b = new content.Blob(["I am a blob"]);
+ let contentBlobURI = content.URL.createObjectURL(b);
+ let contentPrincipal = content.document.nodePrincipal;
+ // Loading this blob URI from the content page should work:
+ testURL(contentPrincipal, contentBlobURI, true, true, true, baseFlags);
+ testURL(contentPrincipal, contentBlobURI, true, true, true,
+ baseFlags | ssm.DISALLOW_INHERIT_PRINCIPAL);
+
+ testURL(contentPrincipal, "view-source:" + contentBlobURI, false, false, true,
+ baseFlags);
+ testURL(contentPrincipal, "view-source:" + contentBlobURI, false, false, true,
+ baseFlags | ssm.DISALLOW_INHERIT_PRINCIPAL);
+
+ // Feed URIs for blobs can't be created, so need to pass false as the fourth param.
+ for (let prefix of ["feed:", "view-source:feed:", "feed:view-source:"]) {
+ testURL(contentPrincipal, prefix + contentBlobURI, false, false, false,
+ baseFlags);
+ testURL(contentPrincipal, prefix + contentBlobURI, false, false, false,
+ baseFlags | ssm.DISALLOW_INHERIT_PRINCIPAL);
+ }
+ }
+ );
+
+ });
+});
diff --git a/caps/tests/mochitest/chrome.ini b/caps/tests/mochitest/chrome.ini
new file mode 100644
index 0000000000..ee71ad30bb
--- /dev/null
+++ b/caps/tests/mochitest/chrome.ini
@@ -0,0 +1,9 @@
+[DEFAULT]
+skip-if = os == 'android'
+support-files =
+ file_disableScript.html
+ !/caps/tests/mochitest/file_disableScript.html
+
+[test_bug995943.xul]
+[test_addonMayLoad.html]
+[test_disableScript.xul]
diff --git a/caps/tests/mochitest/file_data.txt b/caps/tests/mochitest/file_data.txt
new file mode 100644
index 0000000000..26d7bd8488
--- /dev/null
+++ b/caps/tests/mochitest/file_data.txt
@@ -0,0 +1 @@
+server data fetched over XHR
diff --git a/caps/tests/mochitest/file_disableScript.html b/caps/tests/mochitest/file_disableScript.html
new file mode 100644
index 0000000000..f4888cd586
--- /dev/null
+++ b/caps/tests/mochitest/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/caps/tests/mochitest/mochitest.ini b/caps/tests/mochitest/mochitest.ini
new file mode 100644
index 0000000000..866553ea26
--- /dev/null
+++ b/caps/tests/mochitest/mochitest.ini
@@ -0,0 +1,13 @@
+[DEFAULT]
+support-files =
+ file_data.txt
+ file_disableScript.html
+ !/js/xpconnect/tests/mochitest/file_empty.html
+
+[test_app_principal_equality.html]
+[test_bug246699.html]
+[test_bug292789.html]
+[test_bug423375.html]
+[test_bug470804.html]
+[test_disallowInheritPrincipal.html]
+[test_extensionURL.html]
diff --git a/caps/tests/mochitest/resource_test_file.html b/caps/tests/mochitest/resource_test_file.html
new file mode 100644
index 0000000000..8201bd70e0
--- /dev/null
+++ b/caps/tests/mochitest/resource_test_file.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<html><head><title>resource test file</title></head><body></body></html>
diff --git a/caps/tests/mochitest/test_addonMayLoad.html b/caps/tests/mochitest/test_addonMayLoad.html
new file mode 100644
index 0000000000..286284bfe8
--- /dev/null
+++ b/caps/tests/mochitest/test_addonMayLoad.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1180921
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1180921</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <script type="application/javascript;version=1.8">
+
+ /** Test for Bug 1180921 **/
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+ const Cu = Components.utils;
+ Cu.import("resource://gre/modules/Services.jsm");
+ let ssm = Services.scriptSecurityManager;
+ let aps = Cc["@mozilla.org/addons/policy-service;1"].getService(Ci.nsIAddonPolicyService).wrappedJSObject;
+
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.registerCleanupFunction(function() {
+ aps.setAddonLoadURICallback('addonA', null);
+ aps.setAddonLoadURICallback('addonB', null);
+ });
+
+ function tryLoad(sb, uri) {
+ let p = new Promise(function(resolve, reject) {
+ Cu.exportFunction(resolve, sb, { defineAs: "finish" });
+ Cu.exportFunction(reject, sb, { defineAs: "error" });
+ sb.eval("try { (function () { " +
+ " var xhr = new XMLHttpRequest();" +
+ " xhr.onreadystatechange = function() { if (xhr.readyState == XMLHttpRequest.DONE) { finish(xhr.status == 200); } };" +
+ " xhr.open('GET', '" + uri + "', true);" +
+ " xhr.send();" +
+ "})() } catch (e) { error(e); }");
+ });
+ return p;
+ }
+
+ let exampleCom_addonA = new Cu.Sandbox(ssm.createCodebasePrincipal(Services.io.newURI('http://example.com', null, null), {addonId: 'addonA'}),
+ {wantGlobalProperties: ['XMLHttpRequest']});
+ let nullPrin_addonA = new Cu.Sandbox(ssm.createNullPrincipal({addonId: 'addonA'}),
+ {wantGlobalProperties: ['XMLHttpRequest']});
+ let exampleCom_addonB = new Cu.Sandbox(ssm.createCodebasePrincipal(Services.io.newURI('http://example.com', null, null), {addonId: 'addonB'}),
+ {wantGlobalProperties: ['XMLHttpRequest']});
+
+ function uriForDomain(d) { return d + '/tests/caps/tests/mochitest/file_data.txt' }
+
+ tryLoad(exampleCom_addonA, uriForDomain('http://example.com'))
+ .then(function(success) {
+ ok(success, "same-origin load should succeed for addon A");
+ return tryLoad(nullPrin_addonA, uriForDomain('http://example.com'));
+ }).then(function(success) {
+ ok(!success, "null-principal load should fail for addon A");
+ return tryLoad(exampleCom_addonB, uriForDomain('http://example.com'));
+ }).then(function(success) {
+ ok(success, "same-origin load should succeed for addon B");
+ return tryLoad(exampleCom_addonA, uriForDomain('http://test1.example.org'));
+ }).then(function(success) {
+ ok(!success, "cross-origin load should fail for addon A");
+ aps.setAddonLoadURICallback('addonA', function(uri) { return /test1/.test(uri.host); });
+ aps.setAddonLoadURICallback('addonB', function(uri) { return /test2/.test(uri.host); });
+ return tryLoad(exampleCom_addonA, uriForDomain('http://test1.example.org'));
+ }).then(function(success) {
+ ok(success, "whitelisted cross-origin load of test1 should succeed for addon A");
+ return tryLoad(nullPrin_addonA, uriForDomain('http://test1.example.org'));
+ }).then(function(success) {
+ ok(!success, "whitelisted null principal load of test1 should still fail for addon A");
+ return tryLoad(exampleCom_addonB, uriForDomain('http://test1.example.org'));
+ }).then(function(success) {
+ ok(!success, "non-whitelisted cross-origin load of test1 should fail for addon B");
+ return tryLoad(exampleCom_addonB, uriForDomain('http://test2.example.org'));
+ }).then(function(success) {
+ ok(success, "whitelisted cross-origin load of test2 should succeed for addon B");
+ return tryLoad(exampleCom_addonA, uriForDomain('http://test2.example.org'));
+ }).then(function(success) {
+ ok(!success, "non-whitelisted cross-origin load of test2 should fail for addon A");
+ SimpleTest.finish();
+ }, function(e) {
+ ok(false, "Rejected promise chain: " + e);
+ SimpleTest.finish();
+ });
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1180921">Mozilla Bug 1180921</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/caps/tests/mochitest/test_app_principal_equality.html b/caps/tests/mochitest/test_app_principal_equality.html
new file mode 100644
index 0000000000..f59f1f7893
--- /dev/null
+++ b/caps/tests/mochitest/test_app_principal_equality.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=777467
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test app principal's equality</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=777467">Mozilla Bug 777467</a>
+<p id="display"></p>
+<script>
+
+/** Test for app principal's equality **/
+
+SimpleTest.waitForExplicitFinish();
+
+var permissions = new Promise(resolve => {
+ SpecialPowers.pushPermissions(
+ [{ type: "browser", allow: true, context: document },
+ { type: "embed-apps", allow: true, context: document }],
+ resolve);
+});
+
+permissions.then(() => {
+ $('content').innerHTML =
+ '<iframe src="error404"></iframe>\n' +
+ '<iframe mozbrowser src="error404"></iframe>\n' +
+ '<iframe mozapp="http://example.org/manifest.webapp" mozbrowser src="error404"></iframe>';
+
+ var iframes = document.getElementsByTagName("iframe");
+ var promises = []
+ for (var i = 0; i < promises.length; ++i) {
+ promises.push(new Promise(resolve => {
+ iframes[i].addEventListener("load", resolve);
+ }));
+ }
+
+ return Promise.all(promises);
+});
+
+var prefs = new Promise(resolve => {
+ SpecialPowers.pushPrefEnv(
+ { set: [[ "dom.mozBrowserFramesEnabled", true ],
+ [ "dom.ipc.browser_frames.oop_by_default", false ]] },
+ resolve);
+});
+</script>
+<div id="content" style="display: none;">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+function canAccessDocument(win) {
+ var result = true;
+ try {
+ win.document;
+ } catch(e) {
+ result = false;
+ }
+ return result;
+}
+
+var loaded = new Promise(resolve => addLoadEvent(resolve));
+
+Promise.all([ permissions, prefs, loaded ]).then(runTest);
+
+function runTest() {
+ // Test the witness frame (we can access same-origin frame).
+ is(canAccessDocument(frames[0]), true,
+ "should be able to access the first frame");
+
+ // Test different app/browserElement frames.
+ for (var i=1; i<frames.length; ++i) {
+ is(canAccessDocument(frames[i]), false,
+ "should not be able to access the other frames");
+ }
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/caps/tests/mochitest/test_bug246699.html b/caps/tests/mochitest/test_bug246699.html
new file mode 100644
index 0000000000..bb733e5dfb
--- /dev/null
+++ b/caps/tests/mochitest/test_bug246699.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=246699
+-->
+<head>
+ <title>Test for Bug 246699</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=246699">Mozilla Bug 246699</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id="load-frame"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/**
+ ** Test for Bug 246699
+ ** (should produce stack information for caps errors)
+ **/
+function isError(e)
+{
+ return e.constructor.name === "Error" || e.constructor.name === "TypeError";
+}
+
+function hasStack(e)
+{
+ return isError(e) && /inciteCaps/.test(e.stack);
+}
+
+function inciteCaps(f)
+{
+ try {
+ f();
+ return "operation succeeded";
+ } catch (e if hasStack(e)) {
+ return "denied-stack";
+ } catch (e) {
+ return "unexpected: " + e;
+ }
+}
+
+function tryChromeLoad()
+{
+ window.frames[0].location = "chrome://global/content/mozilla.xhtml";
+}
+
+function tryComponentsClasses()
+{
+ return SpecialPowers.Components.classes["@mozilla.org/dummy;1"];
+}
+
+
+is(inciteCaps(tryChromeLoad), "denied-stack",
+ "should get stack for content-loading-chrome rejection");
+is(inciteCaps(tryComponentsClasses), "denied-stack",
+ "should get stack for SpecialPowers.Components.classes rejection");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/caps/tests/mochitest/test_bug292789.html b/caps/tests/mochitest/test_bug292789.html
new file mode 100644
index 0000000000..291ba00c10
--- /dev/null
+++ b/caps/tests/mochitest/test_bug292789.html
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=292789
+-->
+<head>
+ <title>Test for Bug 292789</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=292789">Mozilla Bug 292789</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <script src="chrome://global/content/treeUtils.js"></script>
+ <script type="application/javascript;version=1.8" src="chrome://mozapps/content/xpinstall/xpinstallConfirm.js"></script>
+ <script id="resjs" type="application/javascript;version=1.8"></script>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 292789
+ **
+ ** Selectively allow access to whitelisted chrome packages
+ ** even for ALLOW_CHROME mechanisms (<script>, <img> etc)
+ **/
+
+SimpleTest.waitForExplicitFinish();
+
+/** <script src=""> test **/
+function testScriptSrc(aCallback) {
+ is(typeof gTreeUtils.sort, "function",
+ "content can still load <script> from chrome://global");
+ is(typeof XPInstallConfirm, "undefined",
+ "content should not be able to load <script> from chrome://mozapps");
+
+ /** make sure the last one didn't pass because someone
+ ** moved the resource
+ **/
+ var resjs = document.getElementById("resjs");
+ resjs.onload = scriptOnload;
+ resjs.src = "resource://gre/chrome/toolkit/content/mozapps/xpinstall/xpinstallConfirm.js";
+ document.getElementById("content").appendChild(resjs);
+
+ function scriptOnload() {
+ is(typeof XPInstallConfirm, "object",
+ "xpinstallConfirm.js has not moved unexpectedly");
+
+ // trigger the callback
+ if (aCallback)
+ aCallback();
+ }
+}
+
+/** <img src=""> tests **/
+var img_global = "chrome://global/skin/icons/Error.png";
+var img_mozapps = "chrome://mozapps/skin/plugins/contentPluginClose.png";
+var res_mozapps = "resource://gre/chrome/toolkit/skin/classic/mozapps/plugins/contentPluginClose.png";
+
+var imgTests = [[img_global, "success"],
+ [img_mozapps, "fail"],
+ [res_mozapps, "success"]];
+
+var curImgTest = 0;
+
+function runImgTest() {
+ var test = imgTests[curImgTest++];
+ var callback = curImgTest == imgTests.length ? finishTest : runImgTest;
+ loadImage(test[0], test[1], callback);
+}
+
+function finishTest() {
+ SimpleTest.finish();
+}
+
+function fail(event) {
+ is("fail", event.target.expected,
+ "content should not be allowed to load "+event.target.src);
+ if (event.target.callback)
+ event.target.callback();
+}
+
+function success(event) {
+ is("success", event.target.expected,
+ "content should be able to load "+event.target.src);
+ if (event.target.callback)
+ event.target.callback();
+}
+
+function loadImage(uri, expect, callback) {
+ var img = document.createElement("img");
+ img.onerror = fail;
+ img.onload = success;
+ img.expected = expect;
+ img.callback = callback;
+ img.src = uri;
+ //document.getElementById("content").appendChild(img);
+}
+
+// Start off the script src test, and have it start the img tests when complete.
+testScriptSrc(runImgTest);
+</script>
+</pre>
+</body>
+</html>
diff --git a/caps/tests/mochitest/test_bug423375.html b/caps/tests/mochitest/test_bug423375.html
new file mode 100644
index 0000000000..1cd2a7a823
--- /dev/null
+++ b/caps/tests/mochitest/test_bug423375.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=423375
+-->
+<head>
+ <title>Test for Bug 423375</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=423375">Mozilla Bug 423375</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id="load-frame"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/**
+ ** Test for Bug 423375
+ ** (content shouldn't be able to load chrome: or resource:)
+ **/
+function tryLoad(url)
+{
+ try {
+ window.frames[0].location = url;
+ return "loaded";
+ } catch (e if /Access.*denied/.test(String(e))) {
+ return "denied";
+ } catch (e) {
+ return "unexpected: " + e;
+ }
+}
+
+is(tryLoad("chrome://global/content/mozilla.xhtml"), "denied",
+ "content should have been prevented from loading chrome: URL");
+is(tryLoad("resource://gre-resources/html.css"), "denied",
+ "content should have been prevented from loading resource: URL");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/caps/tests/mochitest/test_bug470804.html b/caps/tests/mochitest/test_bug470804.html
new file mode 100644
index 0000000000..9ac88c8d73
--- /dev/null
+++ b/caps/tests/mochitest/test_bug470804.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=470804
+-->
+<head>
+ <title>Test for Bug 470804</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=470804">Mozilla Bug 470804</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 470804
+ Passing a null targetURL to checkLoadURIWithPrincipal shouldn't crash
+ **/
+
+const nsIScriptSecurityManager = SpecialPowers.Ci.nsIScriptSecurityManager;
+var secMan = SpecialPowers.Services.scriptSecurityManager;
+var principal = SpecialPowers.wrap(document).nodePrincipal;
+isnot(principal, undefined, "Should have a principal");
+isnot(principal, null, "Should have a non-null principal");
+is(secMan.isSystemPrincipal(principal), false,
+ "Shouldn't have system principal here");
+try {
+ secMan.checkLoadURIWithPrincipal(principal, null,
+ nsIScriptSecurityManager.STANDARD);
+} catch (e) {
+ // throwing is fine, it's just crashing that's bad
+}
+ok(true, "Survival", "We should get here without crashing");
+</script>
+</pre>
+</body>
+</html>
diff --git a/caps/tests/mochitest/test_bug995943.xul b/caps/tests/mochitest/test_bug995943.xul
new file mode 100644
index 0000000000..e9eebb7369
--- /dev/null
+++ b/caps/tests/mochitest/test_bug995943.xul
@@ -0,0 +1,115 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=995943
+-->
+<window title="Mozilla Bug 995943"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <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=995943"
+ target="_blank">Mozilla Bug 995943</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ const Cu = Components.utils;
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+ Cu.import("resource://gre/modules/Services.jsm");
+ function debug(msg) { info(msg); }
+
+ /** Test for CAPS file:// URI prefs. **/
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestCompleteLog();
+ if (navigator.userAgent.indexOf("Mac OS X 10.10") != -1)
+ SimpleTest.expectAssertions(5, 11); // See bug 1067022, 1307988
+ else if (Services.appinfo.OS == "WINNT")
+ SimpleTest.expectAssertions(0, 1); // See bug 1067022
+ else
+ SimpleTest.expectAssertions(0, 2); // See bug 1305241
+
+ var rootdir = Services.appinfo.OS == "WINNT" ? "file:///C:" : "file:///";
+
+ function checkLoadFileURI(domain, shouldLoad) {
+ debug("Invoking checkLoadFileURI with domain: " + domain + ", shouldLoad: " + shouldLoad);
+ return new Promise(function(resolve, reject) {
+ $('ifr').addEventListener('load', function l1() {
+ debug("Invoked l1 for " + domain);
+ $('ifr').removeEventListener('load', l1);
+ function l2() {
+ debug("Invoked l2 for " + domain);
+ $('ifr').removeEventListener('load', l2);
+ ok(shouldLoad, "Successfully loaded file:// URI for domain: " + domain);
+ resolve();
+ }
+ $('ifr').addEventListener('load', l2);
+ try {
+ window[0].wrappedJSObject.location = rootdir;
+ debug("Successfully navigated for " + domain);
+ } catch (e) {
+ ok(!shouldLoad && /denied|insecure/.test(e),
+ "Prevented loading of file:// URI for domain: " + domain + " - " + e);
+ $('ifr').removeEventListener('load', l2);
+ resolve();
+ }
+ });
+ let targetURI = domain + '/tests/js/xpconnect/tests/mochitest/file_empty.html';
+ debug("Navigating iframe to " + targetURI);
+ $('ifr').contentWindow.location = targetURI;
+ });
+ }
+
+ function pushPrefs(prefs) {
+ return new Promise(function(resolve) { SpecialPowers.pushPrefEnv({ set: prefs }, resolve); });
+ }
+
+ function popPrefs() {
+ return new Promise(function(resolve) { SpecialPowers.popPrefEnv(resolve); });
+ }
+
+ var gGoCount = 0;
+ function go() {
+ debug("Invoking go for window with id: " + window.getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID);
+ is(++gGoCount, 1, "Should only call go once!");
+ checkLoadFileURI('http://example.com', false).then(
+ pushPrefs.bind(null, [['capability.policy.policynames', ' somepolicy '],
+ ['capability.policy.somepolicy.checkloaduri.enabled', 'AlLAcCeSs'],
+ ['capability.policy.somepolicy.sites', 'http://example.com']]))
+ .then(checkLoadFileURI.bind(null, 'http://example.com', true))
+ .then(popPrefs)
+ .then(checkLoadFileURI.bind(null, 'http://example.com', false))
+ .then(
+ pushPrefs.bind(null, [['capability.policy.policynames', ',somepolicy, someotherpolicy, '],
+ ['capability.policy.somepolicy.checkloaduri.enabled', 'allaccess'],
+ ['capability.policy.someotherpolicy.checkloaduri.enabled', 'nope'],
+ ['capability.policy.somepolicy.sites', ' http://example.org test1.example.com https://test2.example.com '],
+ ['capability.policy.someotherpolicy.sites', 'http://example.net ']]))
+ .then(checkLoadFileURI.bind(null, 'http://example.org', true))
+ .then(checkLoadFileURI.bind(null, 'http://test2.example.com', false))
+ .then(checkLoadFileURI.bind(null, 'https://test2.example.com', true))
+ .then(checkLoadFileURI.bind(null, 'http://sub1.test2.example.com', false))
+ .then(checkLoadFileURI.bind(null, 'https://sub1.test2.example.com', true))
+ .then(checkLoadFileURI.bind(null, 'http://example.net', false))
+ .then(checkLoadFileURI.bind(null, 'http://test1.example.com', true))
+ .then(checkLoadFileURI.bind(null, 'https://test1.example.com', true))
+ .then(checkLoadFileURI.bind(null, 'http://sub1.test1.example.com', true))
+ .then(checkLoadFileURI.bind(null, 'https://sub1.test1.example.com', true))
+ .then(pushPrefs.bind(null, [['capability.policy.someotherpolicy.checkloaduri.enabled', 'allAccess']]))
+ .then(checkLoadFileURI.bind(null, 'http://example.net', true))
+ .then(popPrefs)
+ .then(popPrefs)
+ .then(checkLoadFileURI.bind(null, 'http://example.net', false))
+ .then(SimpleTest.finish.bind(SimpleTest));
+
+ }
+ addLoadEvent(go);
+
+ ]]>
+ </script>
+ <iframe id="ifr" type="content" />
+</window>
diff --git a/caps/tests/mochitest/test_disableScript.xul b/caps/tests/mochitest/test_disableScript.xul
new file mode 100644
index 0000000000..cef5f401a2
--- /dev/null
+++ b/caps/tests/mochitest/test_disableScript.xul
@@ -0,0 +1,339 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=840488
+-->
+<window title="Mozilla Bug 840488"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <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=840488"
+ target="_blank">Mozilla Bug 840488</a>
+ </body>
+
+ <iframe id="root" name="root" type="content"/>
+ <iframe id="chromeFrame" name="chromeFrame" type="content"/>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for all the different ways that script can be disabled for a given global. **/
+
+ SimpleTest.waitForExplicitFinish();
+ const Cu = Components.utils;
+ const Ci = Components.interfaces;
+ Cu.import("resource://gre/modules/Promise.jsm");
+ Cu.import("resource://gre/modules/Services.jsm");
+ const ssm = Services.scriptSecurityManager;
+ function makeURI(uri) { return Services.io.newURI(uri, null, null); }
+ const path = "/tests/caps/tests/mochitest/file_disableScript.html";
+ const uri = "http://www.example.com" + path;
+ var rootFrame = document.getElementById('root');
+ var chromeFrame = document.getElementById('chromeFrame');
+ navigateFrame(rootFrame, uri + "?name=rootframe").then(function() {
+ navigateFrame(chromeFrame, "file_disableScript.html").then(go);
+ });
+
+ function navigateFrame(ifr, src) {
+ let deferred = Promise.defer();
+ function onload() {
+ ifr.removeEventListener('load', onload);
+ deferred.resolve();
+ }
+ ifr.addEventListener('load', onload, false);
+ ifr.setAttribute('src', src);
+ return deferred.promise;
+ }
+
+ function navigateBack(ifr) {
+ let deferred = Promise.defer();
+
+ // pageshow events don't fire on the iframe element, so we need to use the
+ // chrome event handler for the docshell.
+ var browser = ifr.contentWindow
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell)
+ .chromeEventHandler;
+ function onpageshow(evt) {
+ info("Navigated back. Persisted: " + evt.persisted);
+ browser.removeEventListener('pageshow', onpageshow);
+ deferred.resolve();
+ }
+ browser.addEventListener('pageshow', onpageshow, false);
+ ifr.contentWindow.history.back();
+ return deferred.promise;
+ }
+
+ function addFrame(parentWin, name, expectOnload) {
+ let ifr = parentWin.document.createElement('iframe');
+ parentWin.document.body.appendChild(ifr);
+ ifr.setAttribute('name', name);
+ let deferred = Promise.defer();
+ // We need to append 'name' to avoid running afoul of recursive frame detection.
+ let frameURI = uri + "?name=" + name;
+ navigateFrame(ifr, frameURI).then(function() {
+ is(String(ifr.contentWindow.location), frameURI, "Successful load");
+ is(!!ifr.contentWindow.wrappedJSObject.gFiredOnload, expectOnload,
+ "onload should only fire when scripts are enabled");
+ deferred.resolve();
+ });
+ return deferred.promise;
+ }
+
+ function checkScriptEnabled(win, expectEnabled) {
+ win.wrappedJSObject.gFiredOnclick = false;
+ win.document.body.dispatchEvent(new win.Event('click'));
+ is(win.wrappedJSObject.gFiredOnclick, expectEnabled, "Checking script-enabled for " + win.name + " (" + win.location + ")");
+ }
+
+ function setScriptEnabledForDocShell(win, enabled) {
+ win.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDocShell)
+ .allowJavascript = enabled;
+ }
+
+ function testList(expectEnabled, win, list, idx) {
+ idx = idx || 0;
+ let deferred = Promise.defer();
+ let target = list[idx] + path;
+ info("Testing scriptability for: " + target + ". expecting " + expectEnabled);
+ navigateFrame(win.frameElement, target).then(function() {
+ checkScriptEnabled(win, expectEnabled);
+ if (idx == list.length - 1)
+ deferred.resolve();
+ else
+ testList(expectEnabled, win, list, idx + 1).then(function() { deferred.resolve(); });
+ });
+ return deferred.promise;
+ }
+
+ function testDomainPolicy(defaultScriptability, exceptions, superExceptions,
+ exempt, notExempt, set, superSet, win) {
+ // Populate our sets.
+ for (var e of exceptions)
+ set.add(makeURI(e));
+ for (var e of superExceptions)
+ superSet.add(makeURI(e));
+
+ return testList(defaultScriptability, win, notExempt).then(function() {
+ return testList(!defaultScriptability, win, exempt);
+ });
+ }
+
+ function setScriptEnabledForBrowser(enabled) {
+ var prefname = "javascript.enabled";
+ Services.prefs.setBoolPref(prefname, enabled);
+ }
+
+ function reloadFrame(frame) {
+ let deferred = Promise.defer();
+ frame.addEventListener('load', function onload() {
+ deferred.resolve();
+ frame.removeEventListener('load', onload);
+ }, false);
+ frame.contentWindow.location.reload(true);
+ return deferred.promise;
+ }
+
+ function go() {
+ var rootWin = rootFrame.contentWindow;
+ var chromeWin = chromeFrame.contentWindow;
+
+ // Test simple docshell enable/disable.
+ checkScriptEnabled(rootWin, true);
+ setScriptEnabledForDocShell(rootWin, false);
+ checkScriptEnabled(rootWin, false);
+ setScriptEnabledForDocShell(rootWin, true);
+ checkScriptEnabled(rootWin, true);
+
+ // Privileged frames are immune to docshell flags.
+ ok(ssm.isSystemPrincipal(chromeWin.document.nodePrincipal), "Sanity check for System Principal");
+ setScriptEnabledForDocShell(chromeWin, false);
+ checkScriptEnabled(chromeWin, true);
+ setScriptEnabledForDocShell(chromeWin, true);
+
+ // Play around with the docshell tree and make sure everything works as
+ // we expect.
+ addFrame(rootWin, 'parent', true).then(function() {
+ checkScriptEnabled(rootWin[0], true);
+ return addFrame(rootWin[0], 'childA', true);
+ }).then(function() {
+ checkScriptEnabled(rootWin[0][0], true);
+ setScriptEnabledForDocShell(rootWin[0], false);
+ checkScriptEnabled(rootWin, true);
+ checkScriptEnabled(rootWin[0], false);
+ checkScriptEnabled(rootWin[0][0], false);
+ return addFrame(rootWin[0], 'childB', false);
+ }).then(function() {
+ checkScriptEnabled(rootWin[0][1], false);
+ setScriptEnabledForDocShell(rootWin[0][0], false);
+ setScriptEnabledForDocShell(rootWin[0], true);
+ checkScriptEnabled(rootWin[0], true);
+ checkScriptEnabled(rootWin[0][0], false);
+ setScriptEnabledForDocShell(rootWin[0][0], true);
+
+ // Flags are inherited from the parent docshell at attach time. Note that
+ // the flag itself is inherited, regardless of whether or not scripts are
+ // currently allowed on the parent (which could depend on the parent's
+ // parent). Check that.
+ checkScriptEnabled(rootWin[0][1], false);
+ setScriptEnabledForDocShell(rootWin[0], false);
+ setScriptEnabledForDocShell(rootWin[0][1], true);
+ return addFrame(rootWin[0][1], 'grandchild', false);
+ }).then(function() {
+ checkScriptEnabled(rootWin[0], false);
+ checkScriptEnabled(rootWin[0][1], false);
+ checkScriptEnabled(rootWin[0][1][0], false);
+ setScriptEnabledForDocShell(rootWin[0], true);
+ checkScriptEnabled(rootWin[0], true);
+ checkScriptEnabled(rootWin[0][1], true);
+ checkScriptEnabled(rootWin[0][1][0], true);
+
+ // Try navigating two frames, then munging docshell scriptability, then
+ // pulling the frames out of the bfcache to make sure that flags are
+ // properly propagated to inactive inner windows. We do this both for an
+ // 'own' docshell, as well as for an ancestor docshell.
+ return navigateFrame(rootWin[0][0].frameElement, rootWin[0][0].location + '-navigated');
+ }).then(function() { return navigateFrame(rootWin[0][1][0].frameElement, rootWin[0][1][0].location + '-navigated'); })
+ .then(function() {
+ checkScriptEnabled(rootWin[0][0], true);
+ checkScriptEnabled(rootWin[0][1][0], true);
+ setScriptEnabledForDocShell(rootWin[0][0], false);
+ setScriptEnabledForDocShell(rootWin[0][1], false);
+ checkScriptEnabled(rootWin[0][0], false);
+ checkScriptEnabled(rootWin[0][1][0], false);
+ return navigateBack(rootWin[0][0].frameElement);
+ }).then(function() { return navigateBack(rootWin[0][1][0].frameElement); })
+ .then(function() {
+ checkScriptEnabled(rootWin[0][0], false);
+ checkScriptEnabled(rootWin[0][1][0], false);
+
+ // Disable JS via the global pref pref. This is only guaranteed to have an effect
+ // for subsequent loads.
+ setScriptEnabledForBrowser(false);
+ return reloadFrame(rootFrame);
+ }).then(function() {
+ checkScriptEnabled(rootWin, false);
+ checkScriptEnabled(chromeWin, true);
+ setScriptEnabledForBrowser(true);
+ return reloadFrame(rootFrame);
+ }).then(function() {
+ checkScriptEnabled(rootWin, true);
+
+ // Play around with dynamically blocking script for a given global.
+ // This takes effect immediately.
+ Cu.blockScriptForGlobal(rootWin);
+ Cu.blockScriptForGlobal(rootWin);
+ Cu.unblockScriptForGlobal(rootWin);
+ checkScriptEnabled(rootWin, false);
+ Cu.unblockScriptForGlobal(rootWin);
+ checkScriptEnabled(rootWin, true);
+ Cu.blockScriptForGlobal(rootWin);
+ try {
+ Cu.blockScriptForGlobal(chromeWin);
+ ok(false, "Should have thrown");
+ } catch (e) {
+ ok(/may not be disabled/.test(e),
+ "Shouldn't be able to programmatically block script for system globals");
+ }
+ return reloadFrame(rootFrame);
+ }).then(function() {
+ checkScriptEnabled(rootWin, true);
+
+ // Test system-wide domain policy. This only takes effect for subsequently-
+ // loaded globals.
+
+ // Check the basic semantics of the sets.
+ is(ssm.domainPolicyActive, false, "not enabled");
+ window.policy = ssm.activateDomainPolicy();
+ ok(policy instanceof Ci.nsIDomainPolicy, "Got a policy");
+ try {
+ ssm.activateDomainPolicy();
+ ok(false, "Should have thrown");
+ } catch (e) {
+ ok(true, "can't have two live domain policies");
+ }
+ var sbRef = policy.superBlacklist;
+ isnot(sbRef, null, "superBlacklist non-null");
+ ok(!sbRef.contains(makeURI('http://www.example.com')));
+ sbRef.add(makeURI('http://www.example.com/foopy'));
+ ok(sbRef.contains(makeURI('http://www.example.com')));
+ sbRef.remove(makeURI('http://www.example.com'));
+ ok(!sbRef.contains(makeURI('http://www.example.com')));
+ sbRef.add(makeURI('http://www.example.com/foopy/this.that/'));
+ ok(sbRef.contains(makeURI('http://www.example.com/baz')));
+ ok(!sbRef.contains(makeURI('https://www.example.com')));
+ ok(!sbRef.contains(makeURI('https://www.example.com:88')));
+ ok(!sbRef.contains(makeURI('http://foo.www.example.com')));
+ ok(sbRef.containsSuperDomain(makeURI('http://foo.www.example.com')));
+ ok(sbRef.containsSuperDomain(makeURI('http://foo.bar.www.example.com')));
+ ok(!sbRef.containsSuperDomain(makeURI('http://foo.bar.www.exxample.com')));
+ ok(!sbRef.containsSuperDomain(makeURI('http://example.com')));
+ ok(!sbRef.containsSuperDomain(makeURI('http://com/this.that/')));
+ ok(!sbRef.containsSuperDomain(makeURI('https://foo.www.example.com')));
+ ok(sbRef.contains(makeURI('http://www.example.com')));
+ policy.deactivate();
+ is(ssm.domainPolicyActive, false, "back to inactive");
+ ok(!sbRef.contains(makeURI('http://www.example.com')),
+ "Disabling domain policy clears the set");
+ policy = ssm.activateDomainPolicy();
+ ok(policy.superBlacklist);
+ isnot(sbRef, policy.superBlacklist, "Mint new sets each time!");
+ policy.deactivate();
+ is(policy.blacklist, null, "blacklist nulled out");
+ policy = ssm.activateDomainPolicy();
+ isnot(policy.blacklist, null, "non-null again");
+ isnot(policy.blacklist, sbRef, "freshly minted");
+ policy.deactivate();
+
+ //
+ // Now, create and apply a mock-policy. We check the same policy both as
+ // a blacklist and as a whitelist.
+ //
+
+ window.testPolicy = {
+ // The policy.
+ exceptions: ['http://test1.example.com', 'http://example.com'],
+ superExceptions: ['http://test2.example.org', 'https://test1.example.com'],
+
+ // The testcases.
+ 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'],
+ };
+
+ policy = ssm.activateDomainPolicy();
+ info("Testing Blacklist-style Domain Policy");
+ return testDomainPolicy(true, testPolicy.exceptions,
+ testPolicy.superExceptions, testPolicy.exempt,
+ testPolicy.notExempt, policy.blacklist,
+ policy.superBlacklist, rootWin);
+ }).then(function() {
+ policy.deactivate();
+ policy = ssm.activateDomainPolicy();
+ info("Testing Whitelist-style Domain Policy");
+ setScriptEnabledForBrowser(false);
+ return testDomainPolicy(false, testPolicy.exceptions,
+ testPolicy.superExceptions, testPolicy.exempt,
+ testPolicy.notExempt, policy.whitelist,
+ policy.superWhitelist, rootWin);
+ }).then(function() {
+ setScriptEnabledForBrowser(true);
+ policy.deactivate();
+
+ SimpleTest.finish();
+ });
+ }
+
+ ]]>
+ </script>
+</window>
diff --git a/caps/tests/mochitest/test_disallowInheritPrincipal.html b/caps/tests/mochitest/test_disallowInheritPrincipal.html
new file mode 100644
index 0000000000..ec59bec3c1
--- /dev/null
+++ b/caps/tests/mochitest/test_disallowInheritPrincipal.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=732413
+-->
+<head>
+ <title>Test for Bug 732413</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=732413">Mozilla Bug 732413</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 732413
+ Passing DISALLOW_INHERIT_PRINCIPAL flag should be effective even if
+ aPrincipal is the system principal.
+ **/
+
+const nsIScriptSecurityManager = SpecialPowers.Ci.nsIScriptSecurityManager;
+var secMan = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
+ .getService(nsIScriptSecurityManager);
+var sysPrincipal = secMan.getSystemPrincipal();
+isnot(sysPrincipal, undefined, "Should have a principal");
+isnot(sysPrincipal, null, "Should have a non-null principal");
+is(secMan.isSystemPrincipal(sysPrincipal), true,
+ "Should have system principal here");
+
+
+var ioService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"].
+ getService(SpecialPowers.Ci.nsIIOService);
+var inheritingURI = ioService.newURI("javascript:1+1", null, null);
+
+// First try a normal call to checkLoadURIWithPrincipal
+try {
+ secMan.checkLoadURIWithPrincipal(sysPrincipal, inheritingURI,
+ nsIScriptSecurityManager.STANDARD);
+ ok(true, "checkLoadURI allowed the load");
+} catch (e) {
+ ok(false, "checkLoadURI failed unexpectedly: " + e);
+}
+
+// Now call checkLoadURIWithPrincipal with DISALLOW_INHERIT_PRINCIPAL
+try {
+ secMan.checkLoadURIWithPrincipal(sysPrincipal, inheritingURI,
+ nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
+ ok(false, "checkLoadURI allowed the load unexpectedly");
+} catch (e) {
+ ok(true, "checkLoadURI prevented load of principal-inheriting URI");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/caps/tests/mochitest/test_extensionURL.html b/caps/tests/mochitest/test_extensionURL.html
new file mode 100644
index 0000000000..315c473213
--- /dev/null
+++ b/caps/tests/mochitest/test_extensionURL.html
@@ -0,0 +1,166 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1161831</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1161831 **/
+ SimpleTest.waitForExplicitFinish();
+
+ var aps = SpecialPowers.Cc["@mozilla.org/addons/policy-service;1"]
+ .getService(SpecialPowers.Ci.nsIAddonPolicyService).wrappedJSObject;
+ var oldLoadCallback = aps.setExtensionURILoadCallback(null);
+ var oldMapCallback = aps.setExtensionURIToAddonIdCallback(null);
+ var resourceHandler = SpecialPowers.Services.io.getProtocolHandler("resource")
+ .QueryInterface(SpecialPowers.Ci.nsISubstitutingProtocolHandler);
+ var extensionHandler = SpecialPowers.Services.io.getProtocolHandler("moz-extension")
+ .QueryInterface(SpecialPowers.Ci.nsISubstitutingProtocolHandler);
+
+ SimpleTest.registerCleanupFunction(function() {
+ extensionHandler.setSubstitution('cherise', null);
+ extensionHandler.setSubstitution('liebchen', null);
+ aps.setExtensionURILoadCallback(oldLoadCallback);
+ aps.setExtensionURIToAddonIdCallback(oldMapCallback);
+ });
+
+ addLoadEvent(function() {
+
+ // First, get a file:// URI to something - open to suggestions on how to do
+ // this more easily.
+ var resURI = SpecialPowers.Services.io.newURI('resource://testing-common/resource_test_file.html', null, null);
+ var filePath = resourceHandler.resolveURI(resURI);
+ ok(filePath.startsWith('file://'), 'resource:// URI resolves where we expect: ' + filePath);
+ var fileURI = SpecialPowers.Services.io.newURI(filePath, null, null);
+
+ // Register a moz-extension:// URI.
+ extensionHandler.setSubstitution('cherise', fileURI);
+
+ // Alias the above.
+ extensionHandler.setSubstitution('liebchen', SpecialPowers.Services.io.newURI('moz-extension://cherise', null, null));
+
+ //
+ // Make sure that non-file:// URIs don't work.
+ //
+
+ // resource://
+ try {
+ extensionHandler.setSubstitution('interdit', resURI);
+ ok(false, "Should have thrown for mapping moz-extension to resource");
+ } catch (e) {
+ ok(true, "Threw correctly: " + e);
+ }
+
+ // chrome://
+ try {
+ var chromeURI = SpecialPowers.Services.io.newURI('chrome://global/content/mozilla.xhtml', null, null);
+ extensionHandler.setSubstitution('verboten', chromeURI);
+ ok(false, "Should have thrown for mapping moz-extension to chrome");
+ } catch (e) {
+ ok(true, "Threw correctly: " + e);
+ }
+
+ function navigateWithLocation(ifr, url) { ifr.contentWindow.location = url; }
+ function navigateWithSrc(ifr, url) { ifr.setAttribute('src', url); }
+ function navigateFromChromeWithLocation(ifr, url) { SpecialPowers.wrap(ifr).contentWindow.location = url; }
+ function navigateFromChromeWithWebNav(ifr, url) {
+ SpecialPowers.wrap(ifr).contentWindow
+ .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsIWebNavigation)
+ .loadURI(url, 0, null, null, null);
+ }
+
+
+ function setWhitelistCallback(rgxp) {
+ var cb = SpecialPowers.wrapCallback(function(uri) { return rgxp.test(uri.spec); });
+ aps.setExtensionURILoadCallback(cb);
+ }
+
+ aps.setExtensionURIToAddonIdCallback(SpecialPowers.wrapCallback(function (uri) { return 'imaginaryaddon-' + uri.host[0]; }));
+
+ function testLoad(url, navigate, shouldThrow) {
+ var ifr = document.createElement('iframe');
+ var p = new Promise(function(resolve, reject) {
+ ifr.onload = function() {
+ ok(true, 'Loaded ' + url);
+ var prin = SpecialPowers.wrap(ifr.contentWindow).document.nodePrincipal;
+ function stripTrailingSlash(s) { return s.replace(/\/$/, ''); };
+ is(stripTrailingSlash(prin.URI.spec), url, 'Principal uri is correct: ' + url);
+ function stripPath(s) { return s.replace(/(.*\/\/.+)\/.*/, '$1'); };
+ is(prin.originNoSuffix, stripPath(url), 'Principal origin is correct: ' + prin.originNoSuffix);
+ is(prin.originAttributes.addonId, 'imaginaryaddon-' + url[url.indexOf('/') + 2], 'addonId is correct');
+ if (/_blank/.test(url)) {
+ is(SpecialPowers.wrap(ifr.contentWindow).document.documentElement.innerHTML,
+ '<head></head><body></body>', 'blank document looks right');
+ } else {
+ is(SpecialPowers.wrap(ifr.contentWindow).document.title, 'resource test file',
+ 'document looks right');
+ }
+ ifr.remove();
+ resolve();
+ };
+ document.body.appendChild(ifr);
+
+ var threw = false;
+ try {
+ navigate(ifr, url);
+ } catch (e) {
+ ifr.remove();
+ threw = true;
+ ok(/denied|insecure/.test(e), "exception correct: " + e);
+ }
+ is(threw, !!shouldThrow, "Correct throwing behavior for: " + url);
+ !threw || resolve();
+ });
+
+ return p;
+ }
+
+ function testXHR(url, shouldError) {
+ return new Promise(function(resolve, reject) {
+ var xhr = new XMLHttpRequest();
+ xhr.addEventListener("load", () => { ok(!shouldError, `XHR to ${url} should succeed`); resolve(); });
+ xhr.addEventListener("error", () => { ok(shouldError, `XHR to ${url} should fail`); resolve(); });
+ xhr.open("GET", url, true);
+ xhr.send();
+ });
+ }
+
+ //
+ // Perform some loads and make sure they work correctly.
+ //
+ testLoad.bind(null, 'moz-extension://cherise', navigateFromChromeWithLocation)()
+ .then(testLoad.bind(null, 'moz-extension://cherise', navigateFromChromeWithWebNav))
+ .then(testLoad.bind(null, 'moz-extension://cherise', navigateWithLocation, /* shouldThrow = */ true))
+ .then(testXHR.bind(null, 'moz-extension://cherise', /* shouldError = */ true))
+ .then(setWhitelistCallback.bind(null, /cherise/))
+ .then(testLoad.bind(null, 'moz-extension://cherise', navigateWithLocation))
+ .then(testXHR.bind(null, 'moz-extension://cherise'))
+ .then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithLocation, /* shouldThrow = */ true))
+ .then(testXHR.bind(null, 'moz-extension://liebchen', /* shouldError = */ true))
+ .then(setWhitelistCallback.bind(null, /cherise|liebchen/))
+ .then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithLocation))
+ .then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithSrc))
+ .then(testLoad.bind(null, 'moz-extension://cherise', navigateWithSrc))
+ .then(testLoad.bind(null, 'moz-extension://cherise/_blank.html', navigateWithSrc))
+ .then(SimpleTest.finish.bind(SimpleTest),
+ function(e) { ok(false, "rejected promise: " + e); SimpleTest.finish() }
+ );
+ });
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1161831">Mozilla Bug 1161831</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/caps/tests/unit/test_origin.js b/caps/tests/unit/test_origin.js
new file mode 100644
index 0000000000..0fa125b617
--- /dev/null
+++ b/caps/tests/unit/test_origin.js
@@ -0,0 +1,307 @@
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+var ssm = Services.scriptSecurityManager;
+function makeURI(uri) { return Services.io.newURI(uri, null, null); }
+
+function checkThrows(f) {
+ var threw = false;
+ try { f(); } catch (e) { threw = true }
+ do_check_true(threw);
+}
+
+function checkCrossOrigin(a, b) {
+ do_check_false(a.equals(b));
+ do_check_false(a.equalsConsideringDomain(b));
+ do_check_false(a.subsumes(b));
+ do_check_false(a.subsumesConsideringDomain(b));
+ do_check_false(b.subsumes(a));
+ do_check_false(b.subsumesConsideringDomain(a));
+}
+
+function checkOriginAttributes(prin, attrs, suffix) {
+ attrs = attrs || {};
+ do_check_eq(prin.originAttributes.appId, attrs.appId || 0);
+ do_check_eq(prin.originAttributes.inIsolatedMozBrowser, attrs.inIsolatedMozBrowser || false);
+ do_check_eq(prin.originSuffix, suffix || '');
+ do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), suffix || '');
+ do_check_true(ChromeUtils.originAttributesMatchPattern(prin.originAttributes, attrs));
+ if (!prin.isNullPrincipal && !prin.origin.startsWith('[')) {
+ do_check_true(ssm.createCodebasePrincipalFromOrigin(prin.origin).equals(prin));
+ } else {
+ checkThrows(() => ssm.createCodebasePrincipalFromOrigin(prin.origin));
+ }
+}
+
+function checkSandboxOriginAttributes(arr, attrs, options) {
+ options = options || {};
+ var sandbox = Cu.Sandbox(arr, options);
+ checkOriginAttributes(Cu.getObjectPrincipal(sandbox), attrs,
+ ChromeUtils.originAttributesToSuffix(attrs));
+}
+
+// utility function useful for debugging
+function printAttrs(name, attrs) {
+ do_print(name + " {\n" +
+ "\tappId: " + attrs.appId + ",\n" +
+ "\tuserContextId: " + attrs.userContextId + ",\n" +
+ "\tinIsolatedMozBrowser: " + attrs.inIsolatedMozBrowser + ",\n" +
+ "\taddonId: '" + attrs.addonId + "',\n" +
+ "\tprivateBrowsingId: '" + attrs.privateBrowsingId + "',\n" +
+ "\tfirstPartyDomain: '" + attrs.firstPartyDomain + "'\n}");
+}
+
+
+function checkValues(attrs, values) {
+ values = values || {};
+ //printAttrs("attrs", attrs);
+ //printAttrs("values", values);
+ do_check_eq(attrs.appId, values.appId || 0);
+ do_check_eq(attrs.userContextId, values.userContextId || 0);
+ do_check_eq(attrs.inIsolatedMozBrowser, values.inIsolatedMozBrowser || false);
+ do_check_eq(attrs.addonId, values.addonId || '');
+ do_check_eq(attrs.privateBrowsingId, values.privateBrowsingId || '');
+ do_check_eq(attrs.firstPartyDomain, values.firstPartyDomain || '');
+}
+
+function run_test() {
+ // Attributeless origins.
+ do_check_eq(ssm.getSystemPrincipal().origin, '[System Principal]');
+ checkOriginAttributes(ssm.getSystemPrincipal());
+ var exampleOrg = ssm.createCodebasePrincipal(makeURI('http://example.org'), {});
+ do_check_eq(exampleOrg.origin, 'http://example.org');
+ checkOriginAttributes(exampleOrg);
+ var exampleCom = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {});
+ do_check_eq(exampleCom.origin, 'https://www.example.com:123');
+ checkOriginAttributes(exampleCom);
+ var nullPrin = Cu.getObjectPrincipal(new Cu.Sandbox(null));
+ do_check_true(/^moz-nullprincipal:\{([0-9]|[a-z]|\-){36}\}$/.test(nullPrin.origin));
+ checkOriginAttributes(nullPrin);
+ var ipv6Prin = ssm.createCodebasePrincipal(makeURI('https://[2001:db8::ff00:42:8329]:123'), {});
+ do_check_eq(ipv6Prin.origin, 'https://[2001:db8::ff00:42:8329]:123');
+ checkOriginAttributes(ipv6Prin);
+ var ipv6NPPrin = ssm.createCodebasePrincipal(makeURI('https://[2001:db8::ff00:42:8329]'), {});
+ do_check_eq(ipv6NPPrin.origin, 'https://[2001:db8::ff00:42:8329]');
+ checkOriginAttributes(ipv6NPPrin);
+ var ep = Cu.getObjectPrincipal(Cu.Sandbox([exampleCom, nullPrin, exampleOrg]));
+ checkOriginAttributes(ep);
+ checkCrossOrigin(exampleCom, exampleOrg);
+ checkCrossOrigin(exampleOrg, nullPrin);
+
+ // nsEP origins should be in lexical order.
+ do_check_eq(ep.origin, `[Expanded Principal [${exampleOrg.origin}, ${exampleCom.origin}, ${nullPrin.origin}]]`);
+
+ // Make sure createCodebasePrincipal does what the rest of gecko does.
+ do_check_true(exampleOrg.equals(Cu.getObjectPrincipal(new Cu.Sandbox('http://example.org'))));
+
+ //
+ // Test origin attributes.
+ //
+
+ // Just app.
+ var exampleOrg_app = ssm.createCodebasePrincipal(makeURI('http://example.org'), {appId: 42});
+ var nullPrin_app = ssm.createNullPrincipal({appId: 42});
+ checkOriginAttributes(exampleOrg_app, {appId: 42}, '^appId=42');
+ checkOriginAttributes(nullPrin_app, {appId: 42}, '^appId=42');
+ do_check_eq(exampleOrg_app.origin, 'http://example.org^appId=42');
+
+ // Just browser.
+ var exampleOrg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inIsolatedMozBrowser: true});
+ var nullPrin_browser = ssm.createNullPrincipal({inIsolatedMozBrowser: true});
+ checkOriginAttributes(exampleOrg_browser, {inIsolatedMozBrowser: true}, '^inBrowser=1');
+ checkOriginAttributes(nullPrin_browser, {inIsolatedMozBrowser: true}, '^inBrowser=1');
+ do_check_eq(exampleOrg_browser.origin, 'http://example.org^inBrowser=1');
+
+ // App and browser.
+ var exampleOrg_appBrowser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inIsolatedMozBrowser: true, appId: 42});
+ var nullPrin_appBrowser = ssm.createNullPrincipal({inIsolatedMozBrowser: true, appId: 42});
+ checkOriginAttributes(exampleOrg_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, '^appId=42&inBrowser=1');
+ checkOriginAttributes(nullPrin_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, '^appId=42&inBrowser=1');
+ do_check_eq(exampleOrg_appBrowser.origin, 'http://example.org^appId=42&inBrowser=1');
+
+ // App and browser, different domain.
+ var exampleCom_appBrowser = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {appId: 42, inIsolatedMozBrowser: true});
+ checkOriginAttributes(exampleCom_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, '^appId=42&inBrowser=1');
+ do_check_eq(exampleCom_appBrowser.origin, 'https://www.example.com:123^appId=42&inBrowser=1');
+
+ // Addon.
+ var exampleOrg_addon = ssm.createCodebasePrincipal(makeURI('http://example.org'), {addonId: 'dummy'});
+ checkOriginAttributes(exampleOrg_addon, { addonId: "dummy" }, '^addonId=dummy');
+ do_check_eq(exampleOrg_addon.origin, 'http://example.org^addonId=dummy');
+
+ // First party Uri
+ var exampleOrg_firstPartyDomain = ssm.createCodebasePrincipal(makeURI('http://example.org'), {firstPartyDomain: 'example.org'});
+ checkOriginAttributes(exampleOrg_firstPartyDomain, { firstPartyDomain: "example.org" }, '^firstPartyDomain=example.org');
+ do_check_eq(exampleOrg_firstPartyDomain.origin, 'http://example.org^firstPartyDomain=example.org');
+
+ // Make sure we don't crash when serializing principals with UNKNOWN_APP_ID.
+ try {
+ let binaryStream = Cc["@mozilla.org/binaryoutputstream;1"].
+ createInstance(Ci.nsIObjectOutputStream);
+ let pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
+ pipe.init(false, false, 0, 0xffffffff, null);
+ binaryStream.setOutputStream(pipe.outputStream);
+ binaryStream.writeCompoundObject(simplePrin, Ci.nsISupports, true);
+ binaryStream.close();
+ } catch (e) {
+ do_check_true(true);
+ }
+
+
+ // Just userContext.
+ var exampleOrg_userContext = ssm.createCodebasePrincipal(makeURI('http://example.org'), {userContextId: 42});
+ checkOriginAttributes(exampleOrg_userContext, { userContextId: 42 }, '^userContextId=42');
+ do_check_eq(exampleOrg_userContext.origin, 'http://example.org^userContextId=42');
+
+ // UserContext and Addon.
+ var exampleOrg_userContextAddon = ssm.createCodebasePrincipal(makeURI('http://example.org'), {addonId: 'dummy', userContextId: 42});
+ var nullPrin_userContextAddon = ssm.createNullPrincipal({addonId: 'dummy', userContextId: 42});
+ checkOriginAttributes(exampleOrg_userContextAddon, {addonId: 'dummy', userContextId: 42}, '^addonId=dummy&userContextId=42');
+ checkOriginAttributes(nullPrin_userContextAddon, {addonId: 'dummy', userContextId: 42}, '^addonId=dummy&userContextId=42');
+ do_check_eq(exampleOrg_userContextAddon.origin, 'http://example.org^addonId=dummy&userContextId=42');
+
+ // UserContext and App.
+ var exampleOrg_userContextApp = ssm.createCodebasePrincipal(makeURI('http://example.org'), {appId: 24, userContextId: 42});
+ var nullPrin_userContextApp = ssm.createNullPrincipal({appId: 24, userContextId: 42});
+ checkOriginAttributes(exampleOrg_userContextApp, {appId: 24, userContextId: 42}, '^appId=24&userContextId=42');
+ checkOriginAttributes(nullPrin_userContextApp, {appId: 24, userContextId: 42}, '^appId=24&userContextId=42');
+ do_check_eq(exampleOrg_userContextApp.origin, 'http://example.org^appId=24&userContextId=42');
+
+ checkSandboxOriginAttributes(null, {});
+ checkSandboxOriginAttributes('http://example.org', {});
+ checkSandboxOriginAttributes('http://example.org', {}, {originAttributes: {}});
+ checkSandboxOriginAttributes('http://example.org', {appId: 42}, {originAttributes: {appId: 42}});
+ checkSandboxOriginAttributes(['http://example.org'], {});
+ checkSandboxOriginAttributes(['http://example.org'], {}, {originAttributes: {}});
+ checkSandboxOriginAttributes(['http://example.org'], {appId: 42}, {originAttributes: {appId: 42}});
+
+ // Check that all of the above are cross-origin.
+ checkCrossOrigin(exampleOrg_app, exampleOrg);
+ checkCrossOrigin(exampleOrg_app, nullPrin_app);
+ checkCrossOrigin(exampleOrg_browser, exampleOrg_app);
+ checkCrossOrigin(exampleOrg_browser, nullPrin_browser);
+ checkCrossOrigin(exampleOrg_appBrowser, exampleOrg_app);
+ checkCrossOrigin(exampleOrg_appBrowser, nullPrin_appBrowser);
+ checkCrossOrigin(exampleOrg_appBrowser, exampleCom_appBrowser);
+ checkCrossOrigin(exampleOrg_addon, exampleOrg);
+ checkCrossOrigin(exampleOrg_firstPartyDomain, exampleOrg);
+ checkCrossOrigin(exampleOrg_userContext, exampleOrg);
+ checkCrossOrigin(exampleOrg_userContextAddon, exampleOrg);
+ checkCrossOrigin(exampleOrg_userContext, exampleOrg_userContextAddon);
+ checkCrossOrigin(exampleOrg_userContext, exampleOrg_userContextApp);
+
+ // Check Principal kinds.
+ function checkKind(prin, kind) {
+ do_check_eq(prin.isNullPrincipal, kind == 'nullPrincipal');
+ do_check_eq(prin.isCodebasePrincipal, kind == 'codebasePrincipal');
+ do_check_eq(prin.isExpandedPrincipal, kind == 'expandedPrincipal');
+ do_check_eq(prin.isSystemPrincipal, kind == 'systemPrincipal');
+ }
+ checkKind(ssm.createNullPrincipal({}), 'nullPrincipal');
+ checkKind(ssm.createCodebasePrincipal(makeURI('http://www.example.com'), {}), 'codebasePrincipal');
+ checkKind(Cu.getObjectPrincipal(Cu.Sandbox([ssm.createCodebasePrincipal(makeURI('http://www.example.com'), {})])), 'expandedPrincipal');
+ checkKind(ssm.getSystemPrincipal(), 'systemPrincipal');
+
+ //
+ // Test Origin Attribute Manipulation
+ //
+
+ // check that we can create an empty origin attributes dict with default
+ // members and values.
+ var emptyAttrs = ChromeUtils.fillNonDefaultOriginAttributes({});
+ checkValues(emptyAttrs);
+
+ var uri = "http://example.org";
+ var tests = [
+ [ "", {} ],
+ [ "^appId=5", {appId: 5} ],
+ [ "^userContextId=3", {userContextId: 3} ],
+ [ "^addonId=fooBar", {addonId: "fooBar"} ],
+ [ "^inBrowser=1", {inIsolatedMozBrowser: true} ],
+ [ "^firstPartyDomain=example.org", {firstPartyDomain: "example.org"} ],
+ [ "^appId=3&inBrowser=1&userContextId=6",
+ {appId: 3, userContextId: 6, inIsolatedMozBrowser: true} ] ];
+
+ // check that we can create an origin attributes from an origin properly
+ tests.forEach(t => {
+ let attrs = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
+ checkValues(attrs, t[1]);
+ do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), t[0]);
+ });
+
+ // check that we can create an origin attributes from a dict properly
+ tests.forEach(t => {
+ let attrs = ChromeUtils.fillNonDefaultOriginAttributes(t[1]);
+ checkValues(attrs, t[1]);
+ do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), t[0]);
+ });
+
+ // each row in the set_tests array has these values:
+ // [0] - the suffix used to create an origin attribute from
+ // [1] - the expected result of creating an origin attribute from [0]
+ // [2] - the pattern to set on the origin attributes
+ // [3] - the expected result of setting [2] values on [1]
+ // [4] - the expected result of creating a suffix from [3]
+ var set_tests = [
+ [ "", {}, {appId: 5}, {appId: 5}, "^appId=5" ],
+ [ "^appId=5", {appId: 5}, {appId: 3}, {appId: 3}, "^appId=3" ],
+ [ "^appId=5", {appId: 5}, {userContextId: 3}, {appId: 5, userContextId: 3}, "^appId=5&userContextId=3" ],
+ [ "^appId=5", {appId: 5}, {appId: 3, userContextId: 7}, {appId: 3, userContextId: 7}, "^appId=3&userContextId=7" ] ];
+
+ // check that we can set origin attributes values properly
+ set_tests.forEach(t => {
+ let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
+ checkValues(orig, t[1]);
+ let mod = orig;
+ for (var key in t[2]) {
+ mod[key] = t[2][key];
+ }
+ checkValues(mod, t[3]);
+ do_check_eq(ChromeUtils.originAttributesToSuffix(mod), t[4]);
+ });
+
+ // each row in the dflt_tests array has these values:
+ // [0] - the suffix used to create an origin attribute from
+ // [1] - the expected result of creating an origin attributes from [0]
+ // [2] - the expected result after setting userContextId to the default
+ // [3] - the expected result of creating a suffix from [2]
+ var dflt_tests = [
+ [ "", {}, {}, "" ],
+ [ "^userContextId=3", {userContextId: 3}, {}, "" ],
+ [ "^appId=5", {appId: 5}, {appId: 5}, "^appId=5" ],
+ [ "^appId=5&userContextId=3", {appId: 5, userContextId: 3}, {appId: 5}, "^appId=5" ] ];
+
+ // check that we can set the userContextId to default properly
+ dflt_tests.forEach(t => {
+ let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
+ checkValues(orig, t[1]);
+ let mod = orig;
+ mod['userContextId'] = 0;
+ checkValues(mod, t[2]);
+ do_check_eq(ChromeUtils.originAttributesToSuffix(mod), t[3]);
+ });
+
+ // each row in the dflt2_tests array has these values:
+ // [0] - the suffix used to create an origin attribute from
+ // [1] - the expected result of creating an origin attributes from [0]
+ // [2] - the expected result after setting firstPartyUri to the default
+ // [3] - the expected result of creating a suffix from [2]
+ var dflt2_tests = [
+ [ "", {}, {}, "" ],
+ [ "^firstPartyDomain=foo.com", {firstPartyDomain: "foo.com"}, {}, "" ],
+ [ "^appId=5", {appId: 5}, {appId: 5}, "^appId=5" ],
+ [ "^appId=5&firstPartyDomain=foo.com", {appId: 5, firstPartyDomain: "foo.com"}, {appId: 5}, "^appId=5" ] ];
+
+ // check that we can set the userContextId to default properly
+ dflt2_tests.forEach(t => {
+ let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
+ checkValues(orig, t[1]);
+ let mod = orig;
+ mod['firstPartyDomain'] = "";
+ checkValues(mod, t[2]);
+ do_check_eq(ChromeUtils.originAttributesToSuffix(mod), t[3]);
+ });
+
+}
diff --git a/caps/tests/unit/xpcshell.ini b/caps/tests/unit/xpcshell.ini
new file mode 100644
index 0000000000..c06a6b4e92
--- /dev/null
+++ b/caps/tests/unit/xpcshell.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+head =
+tail =
+
+[test_origin.js]