Files
tubestation/netwerk/cookie/ThirdPartyCookieBlockingExceptions.cpp
Tim Huang 3b3c28d6ae Bug 1915355 - Part 4: Implement the third-party cookie blocking excpetion in CookieService. r=cookie-reviewers,baku,valentin
The patch integrates the third-party cookie blocking excpetion in
CookieService.

Depends on D223381

Differential Revision: https://phabricator.services.mozilla.com/D223383
2025-01-10 08:24:29 +00:00

209 lines
6.1 KiB
C++

/* 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 "ThirdPartyCookieBlockingExceptions.h"
#include "mozilla/Components.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/Promise-inl.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "nsIChannel.h"
namespace mozilla {
namespace net {
RefPtr<GenericNonExclusivePromise>
ThirdPartyCookieBlockingExceptions::EnsureInitialized() {
if (mInitPromise) {
return mInitPromise;
}
// Get the remote third-party cookie blocking exception list service instance.
nsresult rv;
m3PCBExceptionService = do_GetService(
NS_NSITHIRDPARTYCOOKIEBLOCKINGEXCEPTIONLISTSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv,
GenericNonExclusivePromise::CreateAndReject(rv, __func__));
RefPtr<mozilla::dom::Promise> initPromise;
rv = m3PCBExceptionService->Init(getter_AddRefs(initPromise));
NS_ENSURE_SUCCESS(rv,
GenericNonExclusivePromise::CreateAndReject(rv, __func__));
// Bail out earlier if we don't have a init promise.
if (!initPromise) {
return GenericNonExclusivePromise::CreateAndReject(rv, __func__);
}
mInitPromise = new GenericNonExclusivePromise::Private(__func__);
initPromise->AddCallbacksWithCycleCollectedArgs(
[&self = *this](JSContext*, JS::Handle<JS::Value>,
mozilla::ErrorResult&) {
self.mInitPromise->Resolve(true, __func__);
},
[&self = *this](JSContext*, JS::Handle<JS::Value>,
mozilla::ErrorResult& error) {
nsresult rv = error.StealNSResult();
self.mInitPromise->Reject(rv, __func__);
return;
});
return mInitPromise;
}
void ThirdPartyCookieBlockingExceptions::Shutdown() {
if (m3PCBExceptionService) {
Unused << m3PCBExceptionService->Shutdown();
m3PCBExceptionService = nullptr;
}
// Reject the init promise during the shutdown.
if (mInitPromise) {
mInitPromise->Reject(NS_ERROR_ABORT, __func__);
mInitPromise = nullptr;
}
}
void ThirdPartyCookieBlockingExceptions::Insert(const nsACString& aException) {
m3PCBExceptionsSet.Insert(aException);
}
void ThirdPartyCookieBlockingExceptions::Remove(const nsACString& aException) {
m3PCBExceptionsSet.Remove(aException);
}
bool ThirdPartyCookieBlockingExceptions::CheckWildcardException(
const nsACString& aThirdPartySite) {
nsAutoCString key;
Create3PCBExceptionKey("*"_ns, aThirdPartySite, key);
return m3PCBExceptionsSet.Contains(key);
}
bool ThirdPartyCookieBlockingExceptions::CheckException(
const nsACString& aFirstPartySite, const nsACString& aThirdPartySite) {
nsAutoCString key;
Create3PCBExceptionKey(aFirstPartySite, aThirdPartySite, key);
return m3PCBExceptionsSet.Contains(key);
}
bool ThirdPartyCookieBlockingExceptions::CheckExceptionForURIs(
nsIURI* aFirstPartyURI, nsIURI* aThirdPartyURI) {
MOZ_ASSERT(XRE_IsParentProcess());
NS_ENSURE_TRUE(aFirstPartyURI, false);
NS_ENSURE_TRUE(aThirdPartyURI, false);
RefPtr<nsEffectiveTLDService> eTLDService =
nsEffectiveTLDService::GetInstance();
NS_ENSURE_TRUE(eTLDService, false);
nsAutoCString thirdPartySite;
nsresult rv = eTLDService->GetSite(aThirdPartyURI, thirdPartySite);
NS_ENSURE_SUCCESS(rv, false);
bool isInExceptionList = CheckWildcardException(thirdPartySite);
if (isInExceptionList) {
return true;
}
nsAutoCString firstPartySite;
rv = eTLDService->GetSite(aFirstPartyURI, firstPartySite);
NS_ENSURE_SUCCESS(rv, false);
return CheckException(firstPartySite, thirdPartySite);
}
bool ThirdPartyCookieBlockingExceptions::CheckExceptionForChannel(
nsIChannel* aChannel) {
MOZ_ASSERT(XRE_IsParentProcess());
NS_ENSURE_TRUE(aChannel, false);
RefPtr<nsEffectiveTLDService> eTLDService =
nsEffectiveTLDService::GetInstance();
NS_ENSURE_TRUE(eTLDService, false);
nsCOMPtr<nsIURI> uri;
nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, false);
nsAutoCString thirdPartySite;
rv = eTLDService->GetSite(uri, thirdPartySite);
NS_ENSURE_SUCCESS(rv, false);
bool isInExceptionList = CheckWildcardException(thirdPartySite);
if (isInExceptionList) {
return true;
}
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
RefPtr<dom::BrowsingContext> bc;
loadInfo->GetBrowsingContext(getter_AddRefs(bc));
if (!bc) {
bc = loadInfo->GetWorkerAssociatedBrowsingContext();
}
nsAutoCString firstPartySite;
// If the channel is not associated with a browsing context, we will try to
// get the first party site from the partition key.
if (!bc) {
nsCOMPtr<nsICookieJarSettings> cjs;
nsresult rv = loadInfo->GetCookieJarSettings(getter_AddRefs(cjs));
NS_ENSURE_SUCCESS(rv, false);
nsAutoString partitionKey;
rv = cjs->GetPartitionKey(partitionKey);
NS_ENSURE_SUCCESS(rv, false);
nsAutoString site;
if (!OriginAttributes::ExtractSiteFromPartitionKey(partitionKey, site)) {
return false;
}
firstPartySite.Assign(NS_ConvertUTF16toUTF8(site));
} else {
RefPtr<dom::WindowGlobalParent> topWGP =
bc->Top()->Canonical()->GetCurrentWindowGlobal();
if (!topWGP) {
return false;
}
nsCOMPtr<nsIPrincipal> topPrincipal = topWGP->DocumentPrincipal();
// If the top window is an about page, we don't need to do anything. This
// could happen when fetching system resources, such as pocket's images
if (topPrincipal->SchemeIs("about")) {
return false;
}
nsCOMPtr<nsIURI> topURI = topPrincipal->GetURI();
nsAutoCString site;
nsresult rv = eTLDService->GetSite(topURI, firstPartySite);
NS_ENSURE_SUCCESS(rv, false);
}
return CheckException(firstPartySite, thirdPartySite);
}
void ThirdPartyCookieBlockingExceptions::GetExceptions(
nsTArray<nsCString>& aExceptions) {
aExceptions.Clear();
for (const auto& host : m3PCBExceptionsSet) {
aExceptions.AppendElement(host);
}
}
} // namespace net
} // namespace mozilla