diff --git a/caps/ContentPrincipal.cpp b/caps/ContentPrincipal.cpp index d17679e714fa..ed8151a4bc4f 100644 --- a/caps/ContentPrincipal.cpp +++ b/caps/ContentPrincipal.cpp @@ -441,16 +441,31 @@ ContentPrincipal::GetBaseDomain(nsACString& aBaseDomain) { NS_IMETHODIMP ContentPrincipal::GetSiteOriginNoSuffix(nsACString& aSiteOrigin) { + nsresult rv = GetOriginNoSuffix(aSiteOrigin); + NS_ENSURE_SUCCESS(rv, rv); + + // It is possible for two principals with the same origin to have different + // mURI values. In order to ensure that two principals with matching origins + // also have matching siteOrigins, we derive the siteOrigin entirely from the + // origin string and do not rely on mURI at all here. + nsCOMPtr origin; + rv = NS_NewURI(getter_AddRefs(origin), aSiteOrigin); + if (NS_FAILED(rv)) { + // We got an error parsing the origin as a URI? siteOrigin == origin + // aSiteOrigin was already filled with `OriginNoSuffix` + return rv; + } + // Handle some special URIs first. nsAutoCString baseDomain; bool handled; - nsresult rv = GetSpecialBaseDomain(mURI, &handled, baseDomain); + rv = GetSpecialBaseDomain(origin, &handled, baseDomain); NS_ENSURE_SUCCESS(rv, rv); if (handled) { // This is a special URI ("file:", "about:", "view-source:", etc). Just // return the origin. - return GetOriginNoSuffix(aSiteOrigin); + return NS_OK; } // For everything else, we ask the TLD service. Note that, unlike in @@ -465,7 +480,7 @@ ContentPrincipal::GetSiteOriginNoSuffix(nsACString& aSiteOrigin) { } bool gotBaseDomain = false; - rv = tldService->GetBaseDomain(mURI, 0, baseDomain); + rv = tldService->GetBaseDomain(origin, 0, baseDomain); if (NS_SUCCEEDED(rv)) { gotBaseDomain = true; } else { @@ -480,7 +495,7 @@ ContentPrincipal::GetSiteOriginNoSuffix(nsACString& aSiteOrigin) { // NOTE: Calling `SetHostPort` with a portless domain is insufficient to clear // the port, so an extra `SetPort` call has to be made. nsCOMPtr siteUri; - NS_MutateURI mutator(mURI); + NS_MutateURI mutator(origin); mutator.SetUserPass(""_ns).SetPort(-1); if (gotBaseDomain) { mutator.SetHost(baseDomain); @@ -489,6 +504,7 @@ ContentPrincipal::GetSiteOriginNoSuffix(nsACString& aSiteOrigin) { MOZ_ASSERT(NS_SUCCEEDED(rv), "failed to create siteUri"); NS_ENSURE_SUCCESS(rv, rv); + aSiteOrigin.Truncate(); rv = GenerateOriginNoSuffixFromURI(siteUri, aSiteOrigin); MOZ_ASSERT(NS_SUCCEEDED(rv), "failed to create siteOriginNoSuffix"); return rv; diff --git a/caps/tests/unit/test_site_origin.js b/caps/tests/unit/test_site_origin.js index 6ce2d0dfadb5..1cea7abe7108 100644 --- a/caps/tests/unit/test_site_origin.js +++ b/caps/tests/unit/test_site_origin.js @@ -57,6 +57,73 @@ 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);