diff --git a/caps/BasePrincipal.cpp b/caps/BasePrincipal.cpp index b02932820254..28492689303f 100644 --- a/caps/BasePrincipal.cpp +++ b/caps/BasePrincipal.cpp @@ -556,6 +556,11 @@ nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI, NS_IMETHODIMP BasePrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) { + if (AddonPolicy() && AddonAllowsLoad(aURI)) { + *aRes = false; + return NS_OK; + } + *aRes = true; // If we do not have a URI its always 3rd party. nsCOMPtr prinURI; diff --git a/caps/ExpandedPrincipal.cpp b/caps/ExpandedPrincipal.cpp index a8a2bd6c86af..5b599acc1c64 100644 --- a/caps/ExpandedPrincipal.cpp +++ b/caps/ExpandedPrincipal.cpp @@ -368,14 +368,21 @@ already_AddRefed ExpandedPrincipal::FromProperties( NS_IMETHODIMP ExpandedPrincipal::IsThirdPartyURI(nsIURI* aURI, bool* aRes) { - nsresult rv; + // ExpandedPrincipal for extension content scripts consist of two principals, + // the document's principal and the extension's principal. + // To make sure that the third-party check behaves like the web page on which + // the content script is running, ignore the extension's principal. + for (const auto& principal : mPrincipals) { - rv = Cast(principal)->IsThirdPartyURI(aURI, aRes); - if (NS_WARN_IF(NS_FAILED(rv)) || !*aRes) { - return rv; + if (!Cast(principal)->AddonPolicy()) { + return Cast(principal)->IsThirdPartyURI(aURI, aRes); } } - *aRes = true; - return NS_OK; + if (mPrincipals.IsEmpty()) { + *aRes = true; + return NS_OK; + } + + return Cast(mPrincipals[0])->IsThirdPartyURI(aURI, aRes); } diff --git a/dom/base/ThirdPartyUtil.cpp b/dom/base/ThirdPartyUtil.cpp index 23b997d10815..2d8f8cd8e32e 100644 --- a/dom/base/ThirdPartyUtil.cpp +++ b/dom/base/ThirdPartyUtil.cpp @@ -288,16 +288,12 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel, nsIURI* aURI, if (!doForce) { nsCOMPtr loadInfo = aChannel->LoadInfo(); parentIsThird = loadInfo->GetIsInThirdPartyContext(); - BasePrincipal* loadingPrincipal = - BasePrincipal::Cast(loadInfo->GetLoadingPrincipal()); - if (!parentIsThird && - loadInfo->GetExternalContentPolicyType() != - nsIContentPolicy::TYPE_DOCUMENT && - (!loadingPrincipal->AddonPolicy() || - !loadingPrincipal->AddonAllowsLoad(channelURI))) { + if (!parentIsThird && loadInfo->GetExternalContentPolicyType() != + nsIContentPolicy::TYPE_DOCUMENT) { // Check if the channel itself is third-party to its own requestor. // Unforunately, we have to go through the loading principal. - + BasePrincipal* loadingPrincipal = + BasePrincipal::Cast(loadInfo->GetLoadingPrincipal()); rv = loadingPrincipal->IsThirdPartyURI(channelURI, &parentIsThird); if (NS_FAILED(rv)) { return rv; diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_cookies_firstParty.js b/toolkit/components/extensions/test/xpcshell/test_ext_cookies_firstParty.js index c78d1d34d9be..700794b46c5b 100644 --- a/toolkit/components/extensions/test/xpcshell/test_ext_cookies_firstParty.js +++ b/toolkit/components/extensions/test/xpcshell/test_ext_cookies_firstParty.js @@ -46,6 +46,22 @@ function promiseLoadedCookies() { response.write(""); }); + server.registerPathHandler("/nestedfetch", (request, response) => { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + response.write( + "" + ); + }); + + server.registerPathHandler("/nestedfetch2", (request, response) => { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "text/html; charset=utf-8", false); + response.write( + "" + ); + }); + server.registerPathHandler("/ready", (request, response) => { response.setStatusLine(request.httpVersion, 200, "OK"); response.setHeader("Content-Type", "text/html; charset=utf-8", false); @@ -122,10 +138,34 @@ add_task(async function test_cookies_firstParty() { extension, }); + // Let's check the cookies received during the last loading. + Assert.equal(await cookiesPromise, "none=a; lax=b; strict=c"); + await contentPage.close(); + + // Let's run a fetch() from a nested iframe (extension -> example.net -> + // example.org -> fetch) + cookiesPromise = promiseLoadedCookies(); + contentPage = await ExtensionTestUtils.loadContentPage(url + "?nestedfetch", { + extension, + }); + // Let's check the cookies received during the last loading. Assert.equal(await cookiesPromise, "none=a"); await contentPage.close(); + // Let's run a fetch() from a nested iframe (extension -> example.org -> fetch) + cookiesPromise = promiseLoadedCookies(); + contentPage = await ExtensionTestUtils.loadContentPage( + url + "?nestedfetch2", + { + extension, + } + ); + + // Let's check the cookies received during the last loading. + Assert.equal(await cookiesPromise, "none=a; lax=b; strict=c"); + await contentPage.close(); + await extension.unload(); });