diff options
Diffstat (limited to 'caps/tests/unit/test_origin.js')
-rw-r--r-- | caps/tests/unit/test_origin.js | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/caps/tests/unit/test_origin.js b/caps/tests/unit/test_origin.js new file mode 100644 index 0000000000..c0cbc2996a --- /dev/null +++ b/caps/tests/unit/test_origin.js @@ -0,0 +1,323 @@ +var ssm = Services.scriptSecurityManager; +function makeURI(uri) { + return Services.io.newURI(uri); +} + +function checkThrows(f) { + var threw = false; + try { + f(); + } catch (e) { + threw = true; + } + Assert.ok(threw); +} + +function checkCrossOrigin(a, b) { + Assert.ok(!a.equals(b)); + Assert.ok(!a.equalsConsideringDomain(b)); + Assert.ok(!a.subsumes(b)); + Assert.ok(!a.subsumesConsideringDomain(b)); + Assert.ok(!b.subsumes(a)); + Assert.ok(!b.subsumesConsideringDomain(a)); +} + +function checkOriginAttributes(prin, attrs, suffix) { + attrs = attrs || {}; + Assert.equal( + prin.originAttributes.inIsolatedMozBrowser, + attrs.inIsolatedMozBrowser || false + ); + Assert.equal(prin.originSuffix, suffix || ""); + Assert.equal(ChromeUtils.originAttributesToSuffix(attrs), suffix || ""); + Assert.ok( + ChromeUtils.originAttributesMatchPattern(prin.originAttributes, attrs) + ); + if (!prin.isNullPrincipal && !prin.origin.startsWith("[")) { + Assert.ok(ssm.createContentPrincipalFromOrigin(prin.origin).equals(prin)); + } else { + checkThrows(() => ssm.createContentPrincipalFromOrigin(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 +// eslint-disable-next-line no-unused-vars +function printAttrs(name, attrs) { + info( + name + + " {\n" + + "\tuserContextId: " + + attrs.userContextId + + ",\n" + + "\tinIsolatedMozBrowser: " + + attrs.inIsolatedMozBrowser + + ",\n" + + "\tprivateBrowsingId: '" + + attrs.privateBrowsingId + + "',\n" + + "\tfirstPartyDomain: '" + + attrs.firstPartyDomain + + "'\n}" + ); +} + +function checkValues(attrs, values) { + values = values || {}; + // printAttrs("attrs", attrs); + // printAttrs("values", values); + Assert.equal(attrs.userContextId, values.userContextId || 0); + Assert.equal( + attrs.inIsolatedMozBrowser, + values.inIsolatedMozBrowser || false + ); + Assert.equal(attrs.privateBrowsingId, values.privateBrowsingId || ""); + Assert.equal(attrs.firstPartyDomain, values.firstPartyDomain || ""); +} + +function run_test() { + // Attributeless origins. + Assert.equal(ssm.getSystemPrincipal().origin, "[System Principal]"); + checkOriginAttributes(ssm.getSystemPrincipal()); + var exampleOrg = ssm.createContentPrincipal( + makeURI("http://example.org"), + {} + ); + Assert.equal(exampleOrg.origin, "http://example.org"); + checkOriginAttributes(exampleOrg); + var exampleCom = ssm.createContentPrincipal( + makeURI("https://www.example.com:123"), + {} + ); + Assert.equal(exampleCom.origin, "https://www.example.com:123"); + checkOriginAttributes(exampleCom); + var nullPrin = Cu.getObjectPrincipal(new Cu.Sandbox(null)); + Assert.ok( + /^moz-nullprincipal:\{([0-9]|[a-z]|\-){36}\}$/.test(nullPrin.origin) + ); + checkOriginAttributes(nullPrin); + var ipv6Prin = ssm.createContentPrincipal( + makeURI("https://[2001:db8::ff00:42:8329]:123"), + {} + ); + Assert.equal(ipv6Prin.origin, "https://[2001:db8::ff00:42:8329]:123"); + checkOriginAttributes(ipv6Prin); + var ipv6NPPrin = ssm.createContentPrincipal( + makeURI("https://[2001:db8::ff00:42:8329]"), + {} + ); + Assert.equal(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. + Assert.equal( + ep.origin, + `[Expanded Principal [${exampleCom.origin}, ${nullPrin.origin}, ${exampleOrg.origin}]]` + ); + + // Make sure createContentPrincipal does what the rest of gecko does. + Assert.ok( + exampleOrg.equals( + Cu.getObjectPrincipal(new Cu.Sandbox("http://example.org")) + ) + ); + + // + // Test origin attributes. + // + + // Just browser. + var exampleOrg_browser = ssm.createContentPrincipal( + 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" + ); + Assert.equal(exampleOrg_browser.origin, "http://example.org^inBrowser=1"); + + // First party Uri + var exampleOrg_firstPartyDomain = ssm.createContentPrincipal( + makeURI("http://example.org"), + { firstPartyDomain: "example.org" } + ); + checkOriginAttributes( + exampleOrg_firstPartyDomain, + { firstPartyDomain: "example.org" }, + "^firstPartyDomain=example.org" + ); + Assert.equal( + exampleOrg_firstPartyDomain.origin, + "http://example.org^firstPartyDomain=example.org" + ); + + // Just userContext. + var exampleOrg_userContext = ssm.createContentPrincipal( + makeURI("http://example.org"), + { userContextId: 42 } + ); + checkOriginAttributes( + exampleOrg_userContext, + { userContextId: 42 }, + "^userContextId=42" + ); + Assert.equal( + exampleOrg_userContext.origin, + "http://example.org^userContextId=42" + ); + + checkSandboxOriginAttributes(null, {}); + checkSandboxOriginAttributes("http://example.org", {}); + checkSandboxOriginAttributes( + "http://example.org", + {}, + { originAttributes: {} } + ); + checkSandboxOriginAttributes(["http://example.org"], {}); + checkSandboxOriginAttributes( + ["http://example.org"], + {}, + { originAttributes: {} } + ); + + // Check that all of the above are cross-origin. + checkCrossOrigin(exampleOrg_browser, nullPrin_browser); + checkCrossOrigin(exampleOrg_firstPartyDomain, exampleOrg); + checkCrossOrigin(exampleOrg_userContext, exampleOrg); + + // Check Principal kinds. + function checkKind(prin, kind) { + Assert.equal(prin.isNullPrincipal, kind == "nullPrincipal"); + Assert.equal(prin.isContentPrincipal, kind == "contentPrincipal"); + Assert.equal(prin.isExpandedPrincipal, kind == "expandedPrincipal"); + Assert.equal(prin.isSystemPrincipal, kind == "systemPrincipal"); + } + checkKind(ssm.createNullPrincipal({}), "nullPrincipal"); + checkKind( + ssm.createContentPrincipal(makeURI("http://www.example.com"), {}), + "contentPrincipal" + ); + checkKind( + Cu.getObjectPrincipal( + Cu.Sandbox([ + ssm.createContentPrincipal(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 = [ + ["", {}], + ["^userContextId=3", { userContextId: 3 }], + ["^inBrowser=1", { inIsolatedMozBrowser: true }], + ["^firstPartyDomain=example.org", { firstPartyDomain: "example.org" }], + ]; + + // 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]); + Assert.equal(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]); + Assert.equal(ChromeUtils.originAttributesToSuffix(attrs), t[0]); + }); + + // 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 }, {}, ""], + ]; + + // 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]); + Assert.equal(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" }, {}, ""], + ]; + + // 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]); + Assert.equal(ChromeUtils.originAttributesToSuffix(mod), t[3]); + }); + + var fileURI = makeURI("file:///foo/bar").QueryInterface(Ci.nsIFileURL); + var fileTests = [ + [true, fileURI.spec], + [false, "file://UNIVERSAL_FILE_URI_ORIGIN"], + ]; + fileTests.forEach(t => { + Services.prefs.setBoolPref("security.fileuri.strict_origin_policy", t[0]); + var filePrin = ssm.createContentPrincipal(fileURI, {}); + Assert.equal(filePrin.origin, t[1]); + }); + Services.prefs.clearUserPref("security.fileuri.strict_origin_policy"); + + var aboutBlankURI = makeURI("about:blank"); + var aboutBlankPrin = ssm.createContentPrincipal(aboutBlankURI, {}); + Assert.ok( + /^moz-nullprincipal:\{([0-9]|[a-z]|\-){36}\}$/.test(aboutBlankPrin.origin) + ); +} |