From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- caps/tests/gtest/TestBackgroundThreadPrincipal.cpp | 94 +++++ caps/tests/gtest/TestNullPrincipalPrecursor.cpp | 56 +++ caps/tests/gtest/TestOriginAttributes.cpp | 118 +++++++ caps/tests/gtest/TestPrincipalAttributes.cpp | 39 ++ caps/tests/gtest/TestPrincipalSerialization.cpp | 214 +++++++++++ .../tests/gtest/TestRedirectChainURITruncation.cpp | 231 ++++++++++++ caps/tests/gtest/moz.build | 18 + caps/tests/mochitest/browser.ini | 2 + caps/tests/mochitest/browser_aboutOrigin.js | 12 + caps/tests/mochitest/browser_checkloaduri.js | 393 +++++++++++++++++++++ caps/tests/mochitest/chrome.ini | 12 + caps/tests/mochitest/file_bug1367586-followon.html | 1 + caps/tests/mochitest/file_bug1367586-redirect.sjs | 8 + caps/tests/mochitest/file_bug1367586-target.html | 6 + caps/tests/mochitest/file_data.txt | 1 + caps/tests/mochitest/file_disableScript.html | 11 + caps/tests/mochitest/mochitest.ini | 18 + caps/tests/mochitest/resource_test_file.html | 2 + caps/tests/mochitest/test_addonMayLoad.html | 95 +++++ caps/tests/mochitest/test_bug1367586.html | 50 +++ caps/tests/mochitest/test_bug246699.html | 60 ++++ caps/tests/mochitest/test_bug292789.html | 121 +++++++ caps/tests/mochitest/test_bug423375.html | 43 +++ caps/tests/mochitest/test_bug470804.html | 41 +++ caps/tests/mochitest/test_bug995943.xhtml | 111 ++++++ caps/tests/mochitest/test_disableScript.xhtml | 330 +++++++++++++++++ .../mochitest/test_disallowInheritPrincipal.html | 58 +++ caps/tests/unit/test_ipv6_host_literal.js | 38 ++ caps/tests/unit/test_oa_partitionKey_pattern.js | 159 +++++++++ caps/tests/unit/test_origin.js | 323 +++++++++++++++++ caps/tests/unit/test_precursor_principal.js | 259 ++++++++++++++ caps/tests/unit/test_site_origin.js | 184 ++++++++++ caps/tests/unit/test_uri_escaping.js | 28 ++ caps/tests/unit/xpcshell.ini | 11 + 34 files changed, 3147 insertions(+) create mode 100644 caps/tests/gtest/TestBackgroundThreadPrincipal.cpp create mode 100644 caps/tests/gtest/TestNullPrincipalPrecursor.cpp create mode 100644 caps/tests/gtest/TestOriginAttributes.cpp create mode 100644 caps/tests/gtest/TestPrincipalAttributes.cpp create mode 100644 caps/tests/gtest/TestPrincipalSerialization.cpp create mode 100644 caps/tests/gtest/TestRedirectChainURITruncation.cpp create mode 100644 caps/tests/gtest/moz.build create mode 100644 caps/tests/mochitest/browser.ini create mode 100644 caps/tests/mochitest/browser_aboutOrigin.js create mode 100644 caps/tests/mochitest/browser_checkloaduri.js create mode 100644 caps/tests/mochitest/chrome.ini create mode 100644 caps/tests/mochitest/file_bug1367586-followon.html create mode 100644 caps/tests/mochitest/file_bug1367586-redirect.sjs create mode 100644 caps/tests/mochitest/file_bug1367586-target.html create mode 100644 caps/tests/mochitest/file_data.txt create mode 100644 caps/tests/mochitest/file_disableScript.html create mode 100644 caps/tests/mochitest/mochitest.ini create mode 100644 caps/tests/mochitest/resource_test_file.html create mode 100644 caps/tests/mochitest/test_addonMayLoad.html create mode 100644 caps/tests/mochitest/test_bug1367586.html create mode 100644 caps/tests/mochitest/test_bug246699.html create mode 100644 caps/tests/mochitest/test_bug292789.html create mode 100644 caps/tests/mochitest/test_bug423375.html create mode 100644 caps/tests/mochitest/test_bug470804.html create mode 100644 caps/tests/mochitest/test_bug995943.xhtml create mode 100644 caps/tests/mochitest/test_disableScript.xhtml create mode 100644 caps/tests/mochitest/test_disallowInheritPrincipal.html create mode 100644 caps/tests/unit/test_ipv6_host_literal.js create mode 100644 caps/tests/unit/test_oa_partitionKey_pattern.js create mode 100644 caps/tests/unit/test_origin.js create mode 100644 caps/tests/unit/test_precursor_principal.js create mode 100644 caps/tests/unit/test_site_origin.js create mode 100644 caps/tests/unit/test_uri_escaping.js create mode 100644 caps/tests/unit/xpcshell.ini (limited to 'caps/tests') diff --git a/caps/tests/gtest/TestBackgroundThreadPrincipal.cpp b/caps/tests/gtest/TestBackgroundThreadPrincipal.cpp new file mode 100644 index 0000000000..82c7b15757 --- /dev/null +++ b/caps/tests/gtest/TestBackgroundThreadPrincipal.cpp @@ -0,0 +1,94 @@ +/* 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/gtest/MozAssertions.h" +#include "mozilla/BasePrincipal.h" +#include "mozilla/ContentPrincipal.h" +#include "mozilla/NullPrincipal.h" +#include "mozilla/ipc/BackgroundUtils.h" +#include "mozilla/ipc/PBackgroundSharedTypes.h" +#include "nsIEventTarget.h" +#include "nsISerialEventTarget.h" +#include "nsIURIMutator.h" +#include "nsNetUtil.h" +#include "nsPrintfCString.h" +#include "nsThreadUtils.h" + +namespace mozilla { + +template +void RunOnBackgroundThread(F&& aFunction) { + nsCOMPtr backgroundQueue; + ASSERT_NS_SUCCEEDED(NS_CreateBackgroundTaskQueue( + "RunOnBackgroundThread", getter_AddRefs(backgroundQueue))); + ASSERT_NS_SUCCEEDED(NS_DispatchAndSpinEventLoopUntilComplete( + "RunOnBackgroundThread"_ns, backgroundQueue, + NS_NewRunnableFunction("RunOnBackgroundThread", + std::forward(aFunction)))); +} + +TEST(BackgroundThreadPrincipal, CreateContent) +{ + RunOnBackgroundThread([] { + nsCOMPtr contentURI; + ASSERT_NS_SUCCEEDED(NS_NewURI(getter_AddRefs(contentURI), + "http://subdomain.example.com:8000"_ns)); + RefPtr contentPrincipal = + BasePrincipal::CreateContentPrincipal(contentURI, OriginAttributes()); + EXPECT_TRUE(contentPrincipal->Is()); + + nsCString origin; + ASSERT_NS_SUCCEEDED(contentPrincipal->GetOrigin(origin)); + EXPECT_EQ(origin, "http://subdomain.example.com:8000"_ns); + + nsCString siteOrigin; + ASSERT_NS_SUCCEEDED(contentPrincipal->GetSiteOrigin(siteOrigin)); + EXPECT_EQ(siteOrigin, "http://example.com"_ns); + }); +} + +TEST(BackgroundThreadPrincipal, CreateNull) +{ + RunOnBackgroundThread([] { + nsCOMPtr contentURI; + ASSERT_NS_SUCCEEDED(NS_NewURI(getter_AddRefs(contentURI), + "data:text/plain,hello world"_ns)); + RefPtr principal = + BasePrincipal::CreateContentPrincipal(contentURI, OriginAttributes()); + EXPECT_TRUE(principal->Is()); + + nsCString origin; + ASSERT_NS_SUCCEEDED(principal->GetOrigin(origin)); + EXPECT_TRUE(StringBeginsWith(origin, "moz-nullprincipal:"_ns)); + }); +} + +TEST(BackgroundThreadPrincipal, PrincipalInfoConversions) +{ + RunOnBackgroundThread([] { + nsCOMPtr contentURI; + ASSERT_NS_SUCCEEDED(NS_NewURI(getter_AddRefs(contentURI), + "http://subdomain.example.com:8000"_ns)); + RefPtr contentPrincipal = + BasePrincipal::CreateContentPrincipal(contentURI, OriginAttributes()); + EXPECT_TRUE(contentPrincipal->Is()); + + ipc::PrincipalInfo info; + ASSERT_NS_SUCCEEDED(ipc::PrincipalToPrincipalInfo(contentPrincipal, &info)); + + EXPECT_TRUE(info.type() == ipc::PrincipalInfo::TContentPrincipalInfo); + EXPECT_EQ(info.get_ContentPrincipalInfo().spec(), + "http://subdomain.example.com:8000/"_ns); + EXPECT_EQ(info.get_ContentPrincipalInfo().baseDomain(), "example.com"_ns); + + auto result = PrincipalInfoToPrincipal(info); + ASSERT_TRUE(result.isOk()); + nsCOMPtr deserialized = result.unwrap(); + EXPECT_TRUE(deserialized->GetIsContentPrincipal()); + + EXPECT_TRUE(deserialized->Equals(contentPrincipal)); + }); +} + +} // namespace mozilla diff --git a/caps/tests/gtest/TestNullPrincipalPrecursor.cpp b/caps/tests/gtest/TestNullPrincipalPrecursor.cpp new file mode 100644 index 0000000000..96db5aeffd --- /dev/null +++ b/caps/tests/gtest/TestNullPrincipalPrecursor.cpp @@ -0,0 +1,56 @@ +/* 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/gtest/MozAssertions.h" +#include "mozilla/NullPrincipal.h" +#include "nsIURIMutator.h" +#include "nsPrintfCString.h" + +namespace mozilla { + +TEST(NullPrincipalPrecursor, EscapingRoundTrips) +{ + nsTArray inputs; + + inputs.AppendElements(mozilla::Span(std::array{ + "mailbox:///dev/shm/tmp5wkt9ff_.mozrunner/Mail/Local%20Folders/secure-mail?number=5"_ns, + })); + + // Add a string for every ASCII byte both escaped and unescaped. + for (uint8_t c = 0; c < 128; ++c) { + inputs.AppendElement(nsPrintfCString("%02X: %c", c, (char)c)); + inputs.AppendElement(nsPrintfCString("%02X: %%%02X", c, c)); + } + + nsID dummyID{0xddf15eaf, + 0x3837, + 0x4678, + {0x80, 0x3b, 0x86, 0x86, 0xe8, 0x17, 0x66, 0x71}}; + nsCOMPtr baseURI = NullPrincipal::CreateURI(nullptr, &dummyID); + ASSERT_TRUE(baseURI); + + for (auto& input : inputs) { + // First build an escaped version of the input string using + // `EscapePrecursorQuery`. + nsCString escaped(input); + NullPrincipal::EscapePrecursorQuery(escaped); + + // Make sure that this escaped URI round-trips through a `moz-nullprincipal` + // URI's query without any additional escapes. + nsCOMPtr clone; + EXPECT_NS_SUCCEEDED( + NS_MutateURI(baseURI).SetQuery(escaped).Finalize(clone)); + nsCString query; + EXPECT_NS_SUCCEEDED(clone->GetQuery(query)); + EXPECT_EQ(escaped, query); + + // Try to unescape our escaped URI and make sure we recover the input + // string. + nsCString unescaped(escaped); + NullPrincipal::UnescapePrecursorQuery(unescaped); + EXPECT_EQ(input, unescaped); + } +} + +} // namespace mozilla diff --git a/caps/tests/gtest/TestOriginAttributes.cpp b/caps/tests/gtest/TestOriginAttributes.cpp new file mode 100644 index 0000000000..fa759f80d5 --- /dev/null +++ b/caps/tests/gtest/TestOriginAttributes.cpp @@ -0,0 +1,118 @@ +/* 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" +#include "mozilla/NullPrincipal.h" +#include "mozilla/Preferences.h" +#include "nsNetUtil.h" + +using mozilla::OriginAttributes; +using mozilla::Preferences; + +#define FPI_PREF "privacy.firstparty.isolate" +#define SITE_PREF "privacy.firstparty.isolate.use_site" + +#define TEST_FPD(_spec, _expected) \ + TestFPD(nsLiteralString(_spec), nsLiteralString(_expected)) + +namespace mozilla { + +static void TestSuffix(const OriginAttributes& attrs) { + nsAutoCString suffix; + attrs.CreateSuffix(suffix); + + OriginAttributes attrsFromSuffix; + bool success = attrsFromSuffix.PopulateFromSuffix(suffix); + EXPECT_TRUE(success); + + EXPECT_EQ(attrs, attrsFromSuffix); +} + +static void TestFPD(const nsAString& spec, const nsAString& expected) { + OriginAttributes attrs; + nsCOMPtr url; + ASSERT_EQ(NS_NewURI(getter_AddRefs(url), spec), NS_OK); + attrs.SetFirstPartyDomain(true, url); + EXPECT_TRUE(attrs.mFirstPartyDomain.Equals(expected)); + + TestSuffix(attrs); +} + +TEST(OriginAttributes, Suffix_default) +{ + OriginAttributes attrs; + TestSuffix(attrs); +} + +TEST(OriginAttributes, Suffix_inIsolatedMozBrowser) +{ + OriginAttributes attrs(true); + TestSuffix(attrs); +} + +TEST(OriginAttributes, FirstPartyDomain_default) +{ + bool oldFpiPref = Preferences::GetBool(FPI_PREF); + Preferences::SetBool(FPI_PREF, true); + bool oldSitePref = Preferences::GetBool(SITE_PREF); + Preferences::SetBool(SITE_PREF, false); + + TEST_FPD(u"http://www.example.com", u"example.com"); + TEST_FPD(u"http://www.example.com:80", u"example.com"); + TEST_FPD(u"http://www.example.com:8080", u"example.com"); + TEST_FPD(u"http://s3.amazonaws.com", u"s3.amazonaws.com"); + TEST_FPD(u"http://com", u"com"); + TEST_FPD(u"http://com.", u"com."); + TEST_FPD(u"http://com:8080", u"com"); + TEST_FPD(u"http://.com", u""); + TEST_FPD(u"http://..com", u""); + TEST_FPD(u"http://127.0.0.1", u"127.0.0.1"); + TEST_FPD(u"http://[::1]", u"[::1]"); + TEST_FPD(u"about:config", + u"about.ef2a7dd5-93bc-417f-a698-142c3116864f.mozilla"); + TEST_FPD(u"moz-extension://f5b6ca10-5bd4-4ed6-9baf-820dc5152bc1", u""); + TEST_FPD(u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}", + u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla"); + TEST_FPD( + u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}" + u"?https://www.example.com", + u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla"); + + Preferences::SetBool(FPI_PREF, oldFpiPref); + Preferences::SetBool(SITE_PREF, oldSitePref); +} + +TEST(OriginAttributes, FirstPartyDomain_site) +{ + bool oldFpiPref = Preferences::GetBool(FPI_PREF); + Preferences::SetBool(FPI_PREF, true); + bool oldSitePref = Preferences::GetBool(SITE_PREF); + Preferences::SetBool(SITE_PREF, true); + + TEST_FPD(u"http://www.example.com", u"(http,example.com)"); + TEST_FPD(u"http://www.example.com:80", u"(http,example.com)"); + TEST_FPD(u"http://www.example.com:8080", u"(http,example.com)"); + TEST_FPD(u"http://s3.amazonaws.com", u"(http,s3.amazonaws.com)"); + TEST_FPD(u"http://com", u"(http,com)"); + TEST_FPD(u"http://com.", u"(http,com.)"); + TEST_FPD(u"http://com:8080", u"(http,com,8080)"); + TEST_FPD(u"http://.com", u"(http,.com)"); + TEST_FPD(u"http://..com", u"(http,..com)"); + TEST_FPD(u"http://127.0.0.1", u"(http,127.0.0.1)"); + TEST_FPD(u"http://[::1]", u"(http,[::1])"); + TEST_FPD(u"about:config", + u"(about,about.ef2a7dd5-93bc-417f-a698-142c3116864f.mozilla)"); + TEST_FPD(u"moz-extension://f5b6ca10-5bd4-4ed6-9baf-820dc5152bc1", u""); + TEST_FPD(u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}", + u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla"); + TEST_FPD( + u"moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42}" + u"?https://www.example.com", + u"9bebdabb-828a-4284-8b00-432a968c6e42.mozilla"); + + Preferences::SetBool(FPI_PREF, oldFpiPref); + Preferences::SetBool(SITE_PREF, oldSitePref); +} + +} // namespace mozilla diff --git a/caps/tests/gtest/TestPrincipalAttributes.cpp b/caps/tests/gtest/TestPrincipalAttributes.cpp new file mode 100644 index 0000000000..bc0bff90f6 --- /dev/null +++ b/caps/tests/gtest/TestPrincipalAttributes.cpp @@ -0,0 +1,39 @@ +/* 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" +#include "nsScriptSecurityManager.h" + +using namespace mozilla; + +class PrincipalAttributesParam { + public: + nsAutoCString spec; + bool expectIsIpAddress; +}; + +class PrincipalAttributesTest + : public ::testing::TestWithParam {}; + +TEST_P(PrincipalAttributesTest, PrincipalAttributesTest) { + nsCOMPtr ssm = + nsScriptSecurityManager::GetScriptSecurityManager(); + + nsAutoCString spec(GetParam().spec); + nsCOMPtr principal; + nsresult rv = + ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal)); + ASSERT_EQ(rv, NS_OK); + + ASSERT_EQ(principal->GetIsIpAddress(), GetParam().expectIsIpAddress); +} + +static const PrincipalAttributesParam kAttributes[] = { + {nsAutoCString("https://mozilla.com"), false}, + {nsAutoCString("https://127.0.0.1"), true}, + {nsAutoCString("https://[::1]"), true}, +}; + +INSTANTIATE_TEST_SUITE_P(TestPrincipalAttributes, PrincipalAttributesTest, + ::testing::ValuesIn(kAttributes)); diff --git a/caps/tests/gtest/TestPrincipalSerialization.cpp b/caps/tests/gtest/TestPrincipalSerialization.cpp new file mode 100644 index 0000000000..159cf1c269 --- /dev/null +++ b/caps/tests/gtest/TestPrincipalSerialization.cpp @@ -0,0 +1,214 @@ +/* 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/Base64.h" +#include "mozilla/BasePrincipal.h" +#include "mozilla/ContentPrincipal.h" +#include "mozilla/NullPrincipal.h" +#include "mozilla/SystemPrincipal.h" +#include "mozilla/ExpandedPrincipal.h" + +using mozilla::BasePrincipal; +using mozilla::ContentPrincipal; +using mozilla::NullPrincipal; +using mozilla::SystemPrincipal; + +// None of these tests work in debug due to assert guards +#ifndef MOZ_DEBUG + +// calling toJson() twice with the same string arg +// (ensure that we truncate correctly where needed) +TEST(PrincipalSerialization, ReusedJSONArgument) +{ + nsCOMPtr ssm = + nsScriptSecurityManager::GetScriptSecurityManager(); + + nsAutoCString spec("https://mozilla.com"); + nsCOMPtr principal; + nsresult rv = + ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal)); + ASSERT_EQ(rv, NS_OK); + + nsAutoCString JSON; + rv = BasePrincipal::Cast(principal)->ToJSON(JSON); + ASSERT_EQ(rv, NS_OK); + ASSERT_TRUE(JSON.EqualsLiteral("{\"1\":{\"0\":\"https://mozilla.com/\"}}")); + + nsAutoCString spec2("https://example.com"); + nsCOMPtr principal2; + rv = ssm->CreateContentPrincipalFromOrigin(spec2, getter_AddRefs(principal2)); + ASSERT_EQ(rv, NS_OK); + + // Reuse JSON without truncation to check the code is doing this + rv = BasePrincipal::Cast(principal2)->ToJSON(JSON); + ASSERT_EQ(rv, NS_OK); + ASSERT_TRUE(JSON.EqualsLiteral("{\"1\":{\"0\":\"https://example.com/\"}}")); +} + +// Assure that calling FromProperties() with an empty array list always returns +// a nullptr The exception here is SystemPrincipal which doesn't have fields but +// it also doesn't implement FromProperties These are overly cautious checks +// that we don't try to create a principal in reality FromProperties is only +// called with a populated array. +TEST(PrincipalSerialization, FromPropertiesEmpty) +{ + nsTArray resContent; + nsCOMPtr contentPrincipal = + ContentPrincipal::FromProperties(resContent); + ASSERT_EQ(nullptr, contentPrincipal); + + nsTArray resExpanded; + nsCOMPtr expandedPrincipal = + ExpandedPrincipal::FromProperties(resExpanded); + ASSERT_EQ(nullptr, expandedPrincipal); + + nsTArray resNull; + nsCOMPtr nullprincipal = NullPrincipal::FromProperties(resNull); + ASSERT_EQ(nullptr, nullprincipal); +} + +// Double check that if we have two valid principals in a serialized JSON that +// nullptr is returned +TEST(PrincipalSerialization, TwoKeys) +{ + // Sanity check that this returns a system principal + nsCOMPtr systemPrincipal = + BasePrincipal::FromJSON("{\"3\":{}}"_ns); + ASSERT_EQ(BasePrincipal::Cast(systemPrincipal)->Kind(), + BasePrincipal::eSystemPrincipal); + + // Sanity check that this returns a content principal + nsCOMPtr contentPrincipal = + BasePrincipal::FromJSON("{\"1\":{\"0\":\"https://mozilla.com\"}}"_ns); + ASSERT_EQ(BasePrincipal::Cast(contentPrincipal)->Kind(), + BasePrincipal::eContentPrincipal); + + // Check both combined don't return a principal + nsCOMPtr combinedPrincipal = BasePrincipal::FromJSON( + "{\"1\":{\"0\":\"https://mozilla.com\"},\"3\":{}}"_ns); + ASSERT_EQ(nullptr, combinedPrincipal); +} + +#endif // ifndef MOZ_DEBUG + +TEST(PrincipalSerialization, ExpandedPrincipal) +{ + // Check basic Expandedprincipal works without OA + nsCOMPtr ssm = + nsScriptSecurityManager::GetScriptSecurityManager(); + + uint32_t length = 2; + nsTArray > allowedDomains(length); + allowedDomains.SetLength(length); + + nsAutoCString spec("https://mozilla.com"); + nsCOMPtr principal; + nsresult rv = + ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principal)->Kind(), + BasePrincipal::eContentPrincipal); + allowedDomains[0] = principal; + + nsAutoCString spec2("https://mozilla.org"); + nsCOMPtr principal2; + rv = ssm->CreateContentPrincipalFromOrigin(spec2, getter_AddRefs(principal2)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principal2)->Kind(), + BasePrincipal::eContentPrincipal); + allowedDomains[1] = principal2; + + mozilla::OriginAttributes attrs; + RefPtr result = + ExpandedPrincipal::Create(allowedDomains, attrs); + ASSERT_EQ(BasePrincipal::Cast(result)->Kind(), + BasePrincipal::eExpandedPrincipal); + + nsAutoCString JSON; + rv = BasePrincipal::Cast(result)->ToJSON(JSON); + ASSERT_EQ(rv, NS_OK); + ASSERT_STREQ(JSON.get(), + "{\"2\":{\"0\":[{\"1\":{\"0\":\"https://mozilla.com/" + "\"}},{\"1\":{\"0\":\"https://mozilla.org/\"}}]}}"); + + nsCOMPtr returnedPrincipal = BasePrincipal::FromJSON(JSON); + auto outPrincipal = BasePrincipal::Cast(returnedPrincipal); + ASSERT_EQ(outPrincipal->Kind(), BasePrincipal::eExpandedPrincipal); + + ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal)); + ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal2)); + + nsAutoCString specDev("https://mozilla.dev"); + nsCOMPtr principalDev; + rv = ssm->CreateContentPrincipalFromOrigin(specDev, + getter_AddRefs(principalDev)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principalDev)->Kind(), + BasePrincipal::eContentPrincipal); + + ASSERT_FALSE(outPrincipal->FastSubsumesIgnoringFPD(principalDev)); +} + +TEST(PrincipalSerialization, ExpandedPrincipalOA) +{ + // Check Expandedprincipal works with top level OA + nsCOMPtr ssm = + nsScriptSecurityManager::GetScriptSecurityManager(); + + uint32_t length = 2; + nsTArray > allowedDomains(length); + allowedDomains.SetLength(length); + + nsAutoCString spec("https://mozilla.com"); + nsCOMPtr principal; + nsresult rv = + ssm->CreateContentPrincipalFromOrigin(spec, getter_AddRefs(principal)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principal)->Kind(), + BasePrincipal::eContentPrincipal); + allowedDomains[0] = principal; + + nsAutoCString spec2("https://mozilla.org"); + nsCOMPtr principal2; + rv = ssm->CreateContentPrincipalFromOrigin(spec2, getter_AddRefs(principal2)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principal2)->Kind(), + BasePrincipal::eContentPrincipal); + allowedDomains[1] = principal2; + + mozilla::OriginAttributes attrs; + nsAutoCString suffix("^userContextId=1"); + bool ok = attrs.PopulateFromSuffix(suffix); + ASSERT_TRUE(ok); + + RefPtr result = + ExpandedPrincipal::Create(allowedDomains, attrs); + ASSERT_EQ(BasePrincipal::Cast(result)->Kind(), + BasePrincipal::eExpandedPrincipal); + + nsAutoCString JSON; + rv = BasePrincipal::Cast(result)->ToJSON(JSON); + ASSERT_EQ(rv, NS_OK); + ASSERT_STREQ(JSON.get(), + "{\"2\":{\"0\":[{\"1\":{\"0\":\"https://mozilla.com/" + "\"}},{\"1\":{\"0\":\"https://mozilla.org/" + "\"}}],\"1\":\"^userContextId=1\"}}"); + + nsCOMPtr returnedPrincipal = BasePrincipal::FromJSON(JSON); + auto outPrincipal = BasePrincipal::Cast(returnedPrincipal); + ASSERT_EQ(outPrincipal->Kind(), BasePrincipal::eExpandedPrincipal); + + ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal)); + ASSERT_TRUE(outPrincipal->FastSubsumesIgnoringFPD(principal2)); + + nsAutoCString specDev("https://mozilla.dev"); + nsCOMPtr principalDev; + rv = ssm->CreateContentPrincipalFromOrigin(specDev, + getter_AddRefs(principalDev)); + ASSERT_EQ(rv, NS_OK); + ASSERT_EQ(BasePrincipal::Cast(principalDev)->Kind(), + BasePrincipal::eContentPrincipal); + + ASSERT_FALSE(outPrincipal->FastSubsumesIgnoringFPD(principalDev)); +} diff --git a/caps/tests/gtest/TestRedirectChainURITruncation.cpp b/caps/tests/gtest/TestRedirectChainURITruncation.cpp new file mode 100644 index 0000000000..34c633499c --- /dev/null +++ b/caps/tests/gtest/TestRedirectChainURITruncation.cpp @@ -0,0 +1,231 @@ +/* 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" +#include "mozilla/ContentPrincipal.h" +#include "mozilla/NullPrincipal.h" +#include "mozilla/SystemPrincipal.h" +#include "mozilla/ExpandedPrincipal.h" +#include "nsContentUtils.h" +#include "mozilla/LoadInfo.h" + +namespace mozilla { + +void checkPrincipalTruncation(nsIPrincipal* aPrincipal, + const nsACString& aExpectedSpec = ""_ns, + const nsTArray& aExpectedSpecs = {}) { + nsCOMPtr truncatedPrincipal = + net::CreateTruncatedPrincipal(aPrincipal); + ASSERT_TRUE(truncatedPrincipal); + + if (aPrincipal->IsSystemPrincipal()) { + ASSERT_TRUE(truncatedPrincipal->IsSystemPrincipal()); + return; + } + + if (aPrincipal->GetIsNullPrincipal()) { + nsCOMPtr precursorPrincipal = + aPrincipal->GetPrecursorPrincipal(); + + nsAutoCString principalSpecEnding("}"); + nsAutoCString expectedTestSpec(aExpectedSpec); + if (!aExpectedSpec.IsEmpty()) { + principalSpecEnding += "?"_ns; + expectedTestSpec += "/"_ns; + } + + if (precursorPrincipal) { + nsAutoCString precursorSpec; + precursorPrincipal->GetAsciiSpec(precursorSpec); + ASSERT_TRUE(precursorSpec.Equals(expectedTestSpec)); + } + + // NullPrincipals have UUIDs as part of their scheme i.e. + // moz-nullprincipal:{9bebdabb-828a-4284-8b00-432a968c6e42} + // To avoid having to know the UUID beforehand we check the principal's spec + // before and after the UUID + nsAutoCString principalSpec; + truncatedPrincipal->GetAsciiSpec(principalSpec); + ASSERT_TRUE(StringBeginsWith(principalSpec, "moz-nullprincipal:{"_ns)); + ASSERT_TRUE( + StringEndsWith(principalSpec, principalSpecEnding + aExpectedSpec)); + return; + } + + if (aPrincipal->GetIsExpandedPrincipal()) { + const nsTArray>& truncatedAllowList = + BasePrincipal::Cast(truncatedPrincipal) + ->As() + ->AllowList(); + + for (size_t i = 0; i < aExpectedSpecs.Length(); ++i) { + nsAutoCString principalSpec; + truncatedAllowList[i]->GetAsciiSpec(principalSpec); + ASSERT_TRUE(principalSpec.Equals(aExpectedSpecs[i])); + } + return; + } + + if (aPrincipal->GetIsContentPrincipal()) { + nsAutoCString principalSpec; + truncatedPrincipal->GetAsciiSpec(principalSpec); + ASSERT_TRUE(principalSpec.Equals(aExpectedSpec)); + return; + } + + // Tests should not reach this point + ADD_FAILURE(); +} + +void checkPrincipalTruncation(nsIPrincipal* aPrincipal, + const nsTArray& aExpectedSpecs = {}) { + checkPrincipalTruncation(aPrincipal, ""_ns, aExpectedSpecs); +} + +TEST(RedirectChainURITruncation, ContentPrincipal) +{ + // ======================= HTTP Scheme ======================= + nsAutoCString httpSpec( + "http://root:toor@www.example.com:200/foo/bar/baz.html?qux#thud"); + nsCOMPtr uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), httpSpec); + ASSERT_EQ(rv, NS_OK); + + nsCOMPtr principal; + OriginAttributes attrs; + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, + "http://www.example.com:200/foo/bar/baz.html"_ns); + + // ======================= HTTPS Scheme ======================= + nsAutoCString httpsSpec( + "https://root:toor@www.example.com:200/foo/bar/baz.html?qux#thud"); + rv = NS_NewURI(getter_AddRefs(uri), httpsSpec); + ASSERT_EQ(rv, NS_OK); + + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, + "https://www.example.com:200/foo/bar/baz.html"_ns); + + // ======================= View Source Scheme ======================= + nsAutoCString viewSourceSpec( + "view-source:https://root:toor@www.example.com:200/foo/bar/" + "baz.html?qux#thud"); + rv = NS_NewURI(getter_AddRefs(uri), viewSourceSpec); + ASSERT_EQ(rv, NS_OK); + + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation( + principal, "view-source:https://www.example.com:200/foo/bar/baz.html"_ns); + + // ======================= About Scheme ======================= + nsAutoCString aboutSpec("about:config"); + rv = NS_NewURI(getter_AddRefs(uri), aboutSpec); + ASSERT_EQ(rv, NS_OK); + + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, "about:config"_ns); + + // ======================= Resource Scheme ======================= + nsAutoCString resourceSpec("resource://testing/"); + rv = NS_NewURI(getter_AddRefs(uri), resourceSpec); + ASSERT_EQ(rv, NS_OK); + + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, "resource://testing/"_ns); + + // ======================= Chrome Scheme ======================= + nsAutoCString chromeSpec("chrome://foo/content/bar.xul"); + rv = NS_NewURI(getter_AddRefs(uri), chromeSpec); + ASSERT_EQ(rv, NS_OK); + + principal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, "chrome://foo/content/bar.xul"_ns); +} + +TEST(RedirectChainURITruncation, NullPrincipal) +{ + // ======================= NullPrincipal ======================= + nsCOMPtr principal = + NullPrincipal::CreateWithoutOriginAttributes(); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, ""_ns); + + // ======================= NullPrincipal & Precursor ======================= + nsAutoCString precursorSpec( + "https://root:toor@www.example.com:200/foo/bar/baz.html?qux#thud"); + + nsCOMPtr precursorURI; + nsresult rv = NS_NewURI(getter_AddRefs(precursorURI), precursorSpec); + ASSERT_EQ(rv, NS_OK); + + OriginAttributes attrs; + nsCOMPtr precursorPrincipal = + BasePrincipal::CreateContentPrincipal(precursorURI, attrs); + principal = NullPrincipal::CreateWithInheritedAttributes(precursorPrincipal); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, "https://www.example.com:200"_ns); +} + +TEST(RedirectChainURITruncation, SystemPrincipal) +{ + nsCOMPtr principal = nsContentUtils::GetSystemPrincipal(); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, ""_ns); +} + +TEST(RedirectChainURITruncation, ExtendedPrincipal) +{ + // ======================= HTTP Scheme ======================= + nsAutoCString httpSpec( + "http://root:toor@www.example.com:200/foo/bar/baz.html?qux#thud"); + nsCOMPtr uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), httpSpec); + ASSERT_EQ(rv, NS_OK); + + nsCOMPtr firstContentPrincipal; + OriginAttributes attrs; + firstContentPrincipal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(firstContentPrincipal); + + // ======================= HTTPS Scheme ======================= + nsCOMPtr secondContentPrincipal; + nsAutoCString httpsSpec( + "https://root:toor@www.example.com:200/foo/bar/baz.html?qux#thud"); + rv = NS_NewURI(getter_AddRefs(uri), httpsSpec); + ASSERT_EQ(rv, NS_OK); + + secondContentPrincipal = BasePrincipal::CreateContentPrincipal(uri, attrs); + ASSERT_TRUE(secondContentPrincipal); + + // ======================= ExpandedPrincipal ======================= + const nsTArray& expectedSpecs = { + "http://www.example.com:200/foo/bar/baz.html"_ns, + "https://www.example.com:200/foo/bar/baz.html"_ns, + }; + nsTArray> allowList = {firstContentPrincipal, + secondContentPrincipal}; + nsCOMPtr principal = + ExpandedPrincipal::Create(allowList, attrs); + ASSERT_TRUE(principal); + + checkPrincipalTruncation(principal, expectedSpecs); +} + +} // namespace mozilla diff --git a/caps/tests/gtest/moz.build b/caps/tests/gtest/moz.build new file mode 100644 index 0000000000..10b1a66f3b --- /dev/null +++ b/caps/tests/gtest/moz.build @@ -0,0 +1,18 @@ +# -*- 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 += [ + "TestBackgroundThreadPrincipal.cpp", + "TestNullPrincipalPrecursor.cpp", + "TestOriginAttributes.cpp", + "TestPrincipalAttributes.cpp", + "TestPrincipalSerialization.cpp", + "TestRedirectChainURITruncation.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..a1c76eb57b --- /dev/null +++ b/caps/tests/mochitest/browser.ini @@ -0,0 +1,2 @@ +[browser_checkloaduri.js] +[browser_aboutOrigin.js] diff --git a/caps/tests/mochitest/browser_aboutOrigin.js b/caps/tests/mochitest/browser_aboutOrigin.js new file mode 100644 index 0000000000..fc2e2d8f53 --- /dev/null +++ b/caps/tests/mochitest/browser_aboutOrigin.js @@ -0,0 +1,12 @@ +"use strict"; + +let tests = ["about:robots?foo", "about:robots#foo", "about:robots?foo#bar"]; +tests.forEach(async test => { + add_task(async () => { + await BrowserTestUtils.withNewTab(test, async browser => { + await SpecialPowers.spawn(browser, [], () => { + is(content.document.nodePrincipal.origin, "about:robots"); + }); + }); + }); +}); diff --git a/caps/tests/mochitest/browser_checkloaduri.js b/caps/tests/mochitest/browser_checkloaduri.js new file mode 100644 index 0000000000..11ff2d1a08 --- /dev/null +++ b/caps/tests/mochitest/browser_checkloaduri.js @@ -0,0 +1,393 @@ +"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], + ["https://www.example2.com", true, true, true], + ["moz-icon:file:///foo/bar/baz.exe", false, false, true], + ["moz-icon://.exe", false, false, true], + ["chrome://foo/content/bar.xul", false, false, true], + ["view-source:http://www.example2.com", false, false, true], + ["view-source:https://www.example2.com", false, false, true], + ["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], + ["https://www.example2.com", true, true, true], + ["moz-icon:file:///foo/bar/baz.exe", false, false, true], + ["moz-icon://.exe", false, false, true], + ["chrome://foo/content/bar.xul", false, false, true], + ["view-source:http://www.example2.com", true, true, true], + ["view-source:https://www.example2.com", true, true, true], + ["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], + ["moz-icon:file:///foo/bar/baz.exe", true, true, true], + ["moz-icon://.exe", 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.spec != "") { + return principal.spec; + } + if (principal.isSystemPrincipal) { + return "system principal"; + } + if (principal.isNullPrincipal) { + return "null principal"; + } + return "unknown principal"; + } + let threw = false; + let targetURI; + try { + targetURI = Services.io.newURI(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(async function () { + // In this test we want to verify both http and https load + // restrictions, hence we explicitly switch off the https-first + // upgrading mechanism. + await SpecialPowers.pushPrefEnv({ + set: [["dom.security.https_first", false]], + }); + + await 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.createContentPrincipal(Services.io.newURI(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. + await BrowserTestUtils.withNewTab( + "http://www.example.com/", + async function (browser) { + await SpecialPowers.spawn( + browser, + [testURL.toString()], + async function (testURLFn) { + // eslint-disable-next-line no-shadow , no-eval + let testURL = eval("(" + testURLFn + ")"); + // eslint-disable-next-line no-shadow + let ssm = Services.scriptSecurityManager; + // eslint-disable-next-line no-shadow + let baseFlags = ssm.STANDARD | ssm.DONT_REPORT_ERRORS; + // eslint-disable-next-line no-unused-vars + 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 + ); + } + ); + } + ); +}); diff --git a/caps/tests/mochitest/chrome.ini b/caps/tests/mochitest/chrome.ini new file mode 100644 index 0000000000..776afa34e4 --- /dev/null +++ b/caps/tests/mochitest/chrome.ini @@ -0,0 +1,12 @@ +[DEFAULT] +skip-if = os == 'android' +support-files = + file_data.txt + file_disableScript.html + !/caps/tests/mochitest/file_data.txt + !/caps/tests/mochitest/file_disableScript.html + +[test_bug995943.xhtml] +skip-if = (verify && debug && (os == 'mac')) +[test_addonMayLoad.html] +[test_disableScript.xhtml] diff --git a/caps/tests/mochitest/file_bug1367586-followon.html b/caps/tests/mochitest/file_bug1367586-followon.html new file mode 100644 index 0000000000..3b648ce746 --- /dev/null +++ b/caps/tests/mochitest/file_bug1367586-followon.html @@ -0,0 +1 @@ +Follow-on navigation content diff --git a/caps/tests/mochitest/file_bug1367586-redirect.sjs b/caps/tests/mochitest/file_bug1367586-redirect.sjs new file mode 100644 index 0000000000..12a980155f --- /dev/null +++ b/caps/tests/mochitest/file_bug1367586-redirect.sjs @@ -0,0 +1,8 @@ +function handleRequest(aRequest, aResponse) { + aResponse.setStatusLine(aRequest.httpVersion, 302, "Moved"); + aResponse.setHeader( + "Location", + "http://mochi.test:8888/tests/caps/tests/mochitest/file_bug1367586-target.html" + ); + aResponse.write("To be redirected to target"); +} diff --git a/caps/tests/mochitest/file_bug1367586-target.html b/caps/tests/mochitest/file_bug1367586-target.html new file mode 100644 index 0000000000..e2a2fde20d --- /dev/null +++ b/caps/tests/mochitest/file_bug1367586-target.html @@ -0,0 +1,6 @@ + +Redirect target content 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 @@ + + + + + + + + diff --git a/caps/tests/mochitest/mochitest.ini b/caps/tests/mochitest/mochitest.ini new file mode 100644 index 0000000000..9036a3ac23 --- /dev/null +++ b/caps/tests/mochitest/mochitest.ini @@ -0,0 +1,18 @@ +[DEFAULT] +support-files = + file_bug1367586-followon.html + file_bug1367586-redirect.sjs + file_bug1367586-target.html + file_data.txt + file_disableScript.html + !/js/xpconnect/tests/mochitest/file_empty.html + +[test_bug246699.html] +[test_bug292789.html] +skip-if = os == 'android' +[test_bug423375.html] +[test_bug470804.html] +[test_bug1367586.html] +skip-if = + http3 +[test_disallowInheritPrincipal.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 @@ + +resource test file diff --git a/caps/tests/mochitest/test_addonMayLoad.html b/caps/tests/mochitest/test_addonMayLoad.html new file mode 100644 index 0000000000..2d5e5e59f1 --- /dev/null +++ b/caps/tests/mochitest/test_addonMayLoad.html @@ -0,0 +1,95 @@ + + + + + + Test for Bug 1180921 + + + + + + +Mozilla Bug 1180921 +

+ +
+
+ + diff --git a/caps/tests/mochitest/test_bug1367586.html b/caps/tests/mochitest/test_bug1367586.html new file mode 100644 index 0000000000..d95693c94d --- /dev/null +++ b/caps/tests/mochitest/test_bug1367586.html @@ -0,0 +1,50 @@ + + + + + Test for Bug 1367586 + + + + + +
+
+
+ + diff --git a/caps/tests/mochitest/test_bug246699.html b/caps/tests/mochitest/test_bug246699.html new file mode 100644 index 0000000000..9ff25c110a --- /dev/null +++ b/caps/tests/mochitest/test_bug246699.html @@ -0,0 +1,60 @@ + + + + + Test for Bug 246699 + + + + +Mozilla Bug 246699 +

+ +
+
+
+ + diff --git a/caps/tests/mochitest/test_bug292789.html b/caps/tests/mochitest/test_bug292789.html new file mode 100644 index 0000000000..cd177dfd5b --- /dev/null +++ b/caps/tests/mochitest/test_bug292789.html @@ -0,0 +1,121 @@ + + + + + Test for Bug 292789 + + + + +Mozilla Bug 292789 +

+ +
+
+
+ + diff --git a/caps/tests/mochitest/test_bug423375.html b/caps/tests/mochitest/test_bug423375.html new file mode 100644 index 0000000000..2ae1dfb923 --- /dev/null +++ b/caps/tests/mochitest/test_bug423375.html @@ -0,0 +1,43 @@ + + + + + Test for Bug 423375 + + + + +Mozilla Bug 423375 +

+ +
+
+
+ + diff --git a/caps/tests/mochitest/test_bug470804.html b/caps/tests/mochitest/test_bug470804.html new file mode 100644 index 0000000000..26da479af6 --- /dev/null +++ b/caps/tests/mochitest/test_bug470804.html @@ -0,0 +1,41 @@ + + + + + Test for Bug 470804 + + + + +Mozilla Bug 470804 +

+ +
+
+
+ + diff --git a/caps/tests/mochitest/test_bug995943.xhtml b/caps/tests/mochitest/test_bug995943.xhtml new file mode 100644 index 0000000000..0ba95f548d --- /dev/null +++ b/caps/tests/mochitest/test_bug995943.xhtml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `); +}); + +server.registerPathHandler("/frame", (request, response) => { + response.setHeader("Content-Type", "text/html"); + response.write(`

HTTP Subframe

`); +}); + +server.registerPathHandler("/redirect", (request, response) => { + let redirect; + if (request.queryString == "com") { + redirect = "http://example.com/frame"; + } else if (request.queryString == "org") { + redirect = "http://example.org/frame"; + } else { + response.setStatusLine(request.httpVersion, 404, "Not found"); + return; + } + + response.setStatusLine(request.httpVersion, 302, "Found"); + response.setHeader("Location", redirect); +}); + +server.registerPathHandler("/client_replace", (request, response) => { + let redirect; + if (request.queryString == "blank") { + redirect = "about:blank"; + } else if (request.queryString == "data") { + redirect = "data:text/html,

Data Subframe

"; + } else { + response.setStatusLine(request.httpVersion, 404, "Not found"); + return; + } + + response.setHeader("Content-Type", "text/html"); + response.write(` + + `); +}); + +add_task(async function sandboxed_precursor() { + // Bug 1725345: Make XPCShellContentUtils.createHttpServer support https + Services.prefs.setBoolPref("dom.security.https_first", false); + + let extension = await ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["webRequest", "webRequestBlocking", ""], + }, + background() { + // eslint-disable-next-line no-undef + browser.webRequest.onBeforeRequest.addListener( + details => { + let url = new URL(details.url); + if (!url.pathname.includes("ext_redirect")) { + return {}; + } + + let redirectUrl; + if (url.search == "?com") { + redirectUrl = "http://example.com/frame"; + } else if (url.search == "?org") { + redirectUrl = "http://example.org/frame"; + } else if (url.search == "?data") { + redirectUrl = "data:text/html,

Data Subframe

"; + } + return { redirectUrl }; + }, + { urls: [""] }, + ["blocking"] + ); + }, + }); + await extension.startup(); + + registerCleanupFunction(async function () { + await extension.unload(); + }); + + for (let userContextId of [undefined, 1]) { + let comURI = Services.io.newURI("http://example.com"); + let comPrin = Services.scriptSecurityManager.createContentPrincipal( + comURI, + { userContextId } + ); + let orgURI = Services.io.newURI("http://example.org"); + let orgPrin = Services.scriptSecurityManager.createContentPrincipal( + orgURI, + { userContextId } + ); + + let page = await XPCShellContentUtils.loadContentPage( + "http://example.com/static_frames", + { + remote: true, + remoteSubframes: true, + userContextId, + } + ); + let bc = page.browsingContext; + + ok( + bc.currentWindowGlobal.documentPrincipal.equals(comPrin), + "toplevel principal matches" + ); + + // XXX: This is sketchy as heck, but it's also the easiest way to wait for + // the `window.location.replace` loads to finish. + await TestUtils.waitForCondition( + () => + bc.children.every( + child => + !child.currentWindowGlobal.documentURI.spec.includes( + "/client_replace" + ) + ), + "wait for every client_replace global to be replaced" + ); + + let principals = {}; + for (let child of bc.children) { + notEqual(child.name, "", "child frames must have names"); + ok(!(child.name in principals), "duplicate child frame name"); + principals[child.name] = child.currentWindowGlobal.documentPrincipal; + } + + function principal_is(name, expected) { + let principal = principals[name]; + info(`${name} = ${principal.origin}`); + ok(principal.equals(expected), `${name} is correct`); + } + function precursor_is(name, precursor) { + let principal = principals[name]; + info(`${name} = ${principal.origin}`); + ok(principal.isNullPrincipal, `${name} is null`); + ok( + principal.precursorPrincipal.equals(precursor), + `${name} has the correct precursor` + ); + } + + // Basic loads should have the principals or precursor principals for the + // document being loaded. + principal_is("same_origin", comPrin); + precursor_is("same_origin_sandbox", comPrin); + + principal_is("cross_origin", orgPrin); + precursor_is("cross_origin_sandbox", orgPrin); + + // Loads of a data: URI should complete with a sandboxed principal based on + // the principal which tried to perform the load. + precursor_is("data_uri", comPrin); + precursor_is("data_uri_sandbox", comPrin); + + // Loads which inherit principals, such as srcdoc an about:blank loads, + // should also inherit sandboxed precursor principals. + principal_is("srcdoc", comPrin); + precursor_is("srcdoc_sandbox", comPrin); + + principal_is("blank", comPrin); + precursor_is("blank_sandbox", comPrin); + + // Redirects shouldn't interfere with the final principal, and it should be + // based only on the final URI. + principal_is("redirect_com", comPrin); + precursor_is("redirect_com_sandbox", comPrin); + + principal_is("redirect_org", orgPrin); + precursor_is("redirect_org_sandbox", orgPrin); + + // Extension redirects should act like normal redirects, and still resolve + // with the principal or sandboxed principal of the final URI. + principal_is("ext_redirect_com_com", comPrin); + precursor_is("ext_redirect_com_com_sandbox", comPrin); + + principal_is("ext_redirect_com_org", orgPrin); + precursor_is("ext_redirect_com_org_sandbox", orgPrin); + + principal_is("ext_redirect_org_com", comPrin); + precursor_is("ext_redirect_org_com_sandbox", comPrin); + + principal_is("ext_redirect_org_org", orgPrin); + precursor_is("ext_redirect_org_org_sandbox", orgPrin); + + // When an extension redirects to a data: URI, we use the last non-data: URI + // in the chain as the precursor principal. + // FIXME: This should perhaps use the extension's principal instead? + precursor_is("ext_redirect_com_data", comPrin); + precursor_is("ext_redirect_com_data_sandbox", comPrin); + + precursor_is("ext_redirect_org_data", orgPrin); + precursor_is("ext_redirect_org_data_sandbox", orgPrin); + + // Check that navigations triggred by script within the frames will have the + // correct behaviour when navigating to blank and data URIs. + principal_is("client_replace_org_blank", orgPrin); + precursor_is("client_replace_org_blank_sandbox", orgPrin); + + precursor_is("client_replace_org_data", orgPrin); + precursor_is("client_replace_org_data_sandbox", orgPrin); + + await page.close(); + } + Services.prefs.clearUserPref("dom.security.https_first"); +}); diff --git a/caps/tests/unit/test_site_origin.js b/caps/tests/unit/test_site_origin.js new file mode 100644 index 0000000000..bbde787f00 --- /dev/null +++ b/caps/tests/unit/test_site_origin.js @@ -0,0 +1,184 @@ +const scriptSecMan = Services.scriptSecurityManager; + +// SystemPrincipal checks +let systemPrincipal = scriptSecMan.getSystemPrincipal(); +Assert.ok(systemPrincipal.isSystemPrincipal); +Assert.equal(systemPrincipal.origin, "[System Principal]"); +Assert.equal(systemPrincipal.originNoSuffix, "[System Principal]"); +Assert.equal(systemPrincipal.siteOrigin, "[System Principal]"); +Assert.equal(systemPrincipal.siteOriginNoSuffix, "[System Principal]"); + +// ContentPrincipal checks +let uri1 = Services.io.newURI("http://example.com"); +let prinicpal1 = scriptSecMan.createContentPrincipal(uri1, { + userContextId: 11, +}); +Assert.ok(prinicpal1.isContentPrincipal); +Assert.equal(prinicpal1.origin, "http://example.com^userContextId=11"); +Assert.equal(prinicpal1.originNoSuffix, "http://example.com"); +Assert.equal(prinicpal1.siteOrigin, "http://example.com^userContextId=11"); +Assert.equal(prinicpal1.siteOriginNoSuffix, "http://example.com"); + +let uri2 = Services.io.newURI("http://test1.example.com"); +let prinicpal2 = scriptSecMan.createContentPrincipal(uri2, { + userContextId: 22, +}); +Assert.ok(prinicpal2.isContentPrincipal); +Assert.equal(prinicpal2.origin, "http://test1.example.com^userContextId=22"); +Assert.equal(prinicpal2.originNoSuffix, "http://test1.example.com"); +Assert.equal(prinicpal2.siteOrigin, "http://example.com^userContextId=22"); +Assert.equal(prinicpal2.siteOriginNoSuffix, "http://example.com"); + +let uri3 = Services.io.newURI("https://test1.test2.example.com:5555"); +let prinicpal3 = scriptSecMan.createContentPrincipal(uri3, { + userContextId: 5555, +}); +Assert.ok(prinicpal3.isContentPrincipal); +Assert.equal( + prinicpal3.origin, + "https://test1.test2.example.com:5555^userContextId=5555" +); +Assert.equal(prinicpal3.originNoSuffix, "https://test1.test2.example.com:5555"); +Assert.equal(prinicpal3.siteOrigin, "https://example.com^userContextId=5555"); +Assert.equal(prinicpal3.siteOriginNoSuffix, "https://example.com"); + +let uri4 = Services.io.newURI("https://.example.com:6666"); +let prinicpal4 = scriptSecMan.createContentPrincipal(uri4, { + userContextId: 6666, +}); +Assert.ok(prinicpal4.isContentPrincipal); +Assert.equal(prinicpal4.origin, "https://.example.com:6666^userContextId=6666"); +Assert.equal(prinicpal4.originNoSuffix, "https://.example.com:6666"); +Assert.equal(prinicpal4.siteOrigin, "https://.example.com^userContextId=6666"); +Assert.equal(prinicpal4.siteOriginNoSuffix, "https://.example.com"); + +let aboutURI = Services.io.newURI("about:preferences"); +let aboutPrincipal = scriptSecMan.createContentPrincipal(aboutURI, { + userContextId: 66, +}); +Assert.ok(aboutPrincipal.isContentPrincipal); +Assert.equal(aboutPrincipal.origin, "about:preferences^userContextId=66"); +Assert.equal(aboutPrincipal.originNoSuffix, "about:preferences"); +Assert.equal(aboutPrincipal.siteOrigin, "about:preferences^userContextId=66"); +Assert.equal(aboutPrincipal.siteOriginNoSuffix, "about:preferences"); + +let viewSourceURI = Services.io.newURI( + "view-source:https://test1.test2.example.com" +); +let viewSourcePrincipal = scriptSecMan.createContentPrincipal(viewSourceURI, { + userContextId: 101, +}); +Assert.ok(viewSourcePrincipal.isContentPrincipal); +Assert.ok(viewSourcePrincipal.schemeIs("view-source")); +Assert.equal( + viewSourcePrincipal.origin, + "https://test1.test2.example.com^userContextId=101" +); +Assert.equal( + viewSourcePrincipal.originNoSuffix, + "https://test1.test2.example.com" +); +Assert.equal( + viewSourcePrincipal.siteOrigin, + "https://example.com^userContextId=101" +); +Assert.equal(viewSourcePrincipal.siteOriginNoSuffix, "https://example.com"); + +let mozExtensionURI = Services.io.newURI( + "moz-extension://924f966d-c93b-4fbf-968a-16608461663c/meh.txt" +); +let mozExtensionPrincipal = scriptSecMan.createContentPrincipal( + mozExtensionURI, + { + userContextId: 102, + } +); +Assert.ok(mozExtensionPrincipal.isContentPrincipal); +Assert.ok(mozExtensionPrincipal.schemeIs("moz-extension")); +Assert.equal( + mozExtensionPrincipal.origin, + "moz-extension://924f966d-c93b-4fbf-968a-16608461663c^userContextId=102" +); +Assert.equal( + mozExtensionPrincipal.originNoSuffix, + "moz-extension://924f966d-c93b-4fbf-968a-16608461663c" +); +Assert.equal( + mozExtensionPrincipal.siteOrigin, + "moz-extension://924f966d-c93b-4fbf-968a-16608461663c^userContextId=102" +); +Assert.equal( + mozExtensionPrincipal.siteOriginNoSuffix, + "moz-extension://924f966d-c93b-4fbf-968a-16608461663c" +); + +let localhostURI = Services.io.newURI(" http://localhost:44203"); +let localhostPrincipal = scriptSecMan.createContentPrincipal(localhostURI, { + userContextId: 144, +}); +Assert.ok(localhostPrincipal.isContentPrincipal); +Assert.ok(localhostPrincipal.schemeIs("http")); +Assert.equal( + localhostPrincipal.origin, + "http://localhost:44203^userContextId=144" +); +Assert.equal(localhostPrincipal.originNoSuffix, "http://localhost:44203"); +Assert.equal( + localhostPrincipal.siteOrigin, + "http://localhost^userContextId=144" +); +Assert.equal(localhostPrincipal.siteOriginNoSuffix, "http://localhost"); + +// NullPrincipal checks +let nullPrincipal = scriptSecMan.createNullPrincipal({ userContextId: 33 }); +Assert.ok(nullPrincipal.isNullPrincipal); +Assert.ok(nullPrincipal.origin.includes("moz-nullprincipal")); +Assert.ok(nullPrincipal.origin.includes("^userContextId=33")); +Assert.ok(nullPrincipal.originNoSuffix.includes("moz-nullprincipal")); +Assert.ok(!nullPrincipal.originNoSuffix.includes("^userContextId=33")); +Assert.ok(nullPrincipal.siteOrigin.includes("moz-nullprincipal")); +Assert.ok(nullPrincipal.siteOrigin.includes("^userContextId=33")); +Assert.ok(nullPrincipal.siteOriginNoSuffix.includes("moz-nullprincipal")); +Assert.ok(!nullPrincipal.siteOriginNoSuffix.includes("^userContextId=33")); + +// ExpandedPrincipal checks +let expandedPrincipal = Cu.getObjectPrincipal(Cu.Sandbox([prinicpal2])); +Assert.ok(expandedPrincipal.isExpandedPrincipal); +Assert.equal( + expandedPrincipal.origin, + "[Expanded Principal [http://test1.example.com^userContextId=22]]^userContextId=22" +); +Assert.equal( + expandedPrincipal.originNoSuffix, + "[Expanded Principal [http://test1.example.com^userContextId=22]]" +); +Assert.equal( + expandedPrincipal.siteOrigin, + "[Expanded Principal [http://test1.example.com^userContextId=22]]^userContextId=22" +); +Assert.equal( + expandedPrincipal.siteOriginNoSuffix, + "[Expanded Principal [http://test1.example.com^userContextId=22]]" +); + +let ipv6URI = Services.io.newURI("https://[2001:db8::ff00:42:8329]:123"); +let ipv6Principal = scriptSecMan.createContentPrincipal(ipv6URI, { + userContextId: 6, +}); +Assert.ok(ipv6Principal.isContentPrincipal); +Assert.equal( + ipv6Principal.origin, + "https://[2001:db8::ff00:42:8329]:123^userContextId=6" +); +Assert.equal( + ipv6Principal.originNoSuffix, + "https://[2001:db8::ff00:42:8329]:123" +); +Assert.equal( + ipv6Principal.siteOrigin, + "https://[2001:db8::ff00:42:8329]^userContextId=6" +); +Assert.equal( + ipv6Principal.siteOriginNoSuffix, + "https://[2001:db8::ff00:42:8329]" +); diff --git a/caps/tests/unit/test_uri_escaping.js b/caps/tests/unit/test_uri_escaping.js new file mode 100644 index 0000000000..7feb581295 --- /dev/null +++ b/caps/tests/unit/test_uri_escaping.js @@ -0,0 +1,28 @@ +var ssm = Services.scriptSecurityManager; + +function makeURI(uri) { + return Services.io.newURI(uri); +} + +function createPrincipal(aURI) { + try { + var uri = makeURI(aURI); + var principal = ssm.createContentPrincipal(uri, {}); + return principal; + } catch (e) { + return null; + } +} + +function run_test() { + Assert.equal(createPrincipal("http://test^test/foo^bar#x^y"), null); + + Assert.equal(createPrincipal("http://test^test/foo\\bar"), null); + + Assert.equal(createPrincipal("http://test:2^3/foo\\bar"), null); + + Assert.equal( + createPrincipal("http://test/foo^bar").exposableSpec, + "http://test/foo%5Ebar" + ); +} diff --git a/caps/tests/unit/xpcshell.ini b/caps/tests/unit/xpcshell.ini new file mode 100644 index 0000000000..9ff2b22617 --- /dev/null +++ b/caps/tests/unit/xpcshell.ini @@ -0,0 +1,11 @@ +[DEFAULT] +head = + +[test_origin.js] +[test_uri_escaping.js] +[test_ipv6_host_literal.js] +[test_oa_partitionKey_pattern.js] +[test_site_origin.js] +[test_precursor_principal.js] +firefox-appdir = browser +skip-if = toolkit == 'android' -- cgit v1.2.3