1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "ThirdPartyCookieBlockingExceptions.h"
7 #include "mozilla/Components.h"
8 #include "mozilla/dom/BrowsingContext.h"
9 #include "mozilla/dom/CanonicalBrowsingContext.h"
10 #include "mozilla/dom/Promise.h"
11 #include "mozilla/dom/Promise-inl.h"
12 #include "mozilla/dom/WindowGlobalParent.h"
13 #include "mozilla/ErrorNames.h"
14 #include "mozilla/Logging.h"
16 #include "nsIEffectiveTLDService.h"
17 #include "nsIChannel.h"
22 LazyLogModule
g3PCBExceptionLog("3pcbexception");
24 void ThirdPartyCookieBlockingExceptions::Initialize() {
29 // Get the remote third-party cookie blocking exception list service instance.
31 m3PCBExceptionService
= do_GetService(
32 NS_NSITHIRDPARTYCOOKIEBLOCKINGEXCEPTIONLISTSERVICE_CONTRACTID
, &rv
);
33 NS_ENSURE_SUCCESS_VOID(rv
);
35 RefPtr
<mozilla::dom::Promise
> initPromise
;
36 rv
= m3PCBExceptionService
->Init(getter_AddRefs(initPromise
));
37 NS_ENSURE_SUCCESS_VOID(rv
);
39 // Bail out earlier if we don't have a init promise.
41 MOZ_LOG(g3PCBExceptionLog
, LogLevel::Error
,
42 ("Failed to initialize 3PCB exception service: no init promise"));
46 initPromise
->AddCallbacksWithCycleCollectedArgs(
47 [&self
= *this](JSContext
*, JS::Handle
<JS::Value
>,
48 mozilla::ErrorResult
&) { self
.mIsInitialized
= true; },
49 [](JSContext
*, JS::Handle
<JS::Value
>, mozilla::ErrorResult
& error
) {
50 nsresult rv
= error
.StealNSResult();
53 GetErrorName(rv
, name
);
56 g3PCBExceptionLog
, LogLevel::Error
,
57 ("Failed to initialize 3PCB exception service: %s", name
.get()));
61 void ThirdPartyCookieBlockingExceptions::Shutdown() {
62 if (m3PCBExceptionService
) {
63 Unused
<< m3PCBExceptionService
->Shutdown();
64 m3PCBExceptionService
= nullptr;
67 mIsInitialized
= false;
70 void ThirdPartyCookieBlockingExceptions::Insert(const nsACString
& aException
) {
71 m3PCBExceptionsSet
.Insert(aException
);
74 void ThirdPartyCookieBlockingExceptions::Remove(const nsACString
& aException
) {
75 m3PCBExceptionsSet
.Remove(aException
);
78 bool ThirdPartyCookieBlockingExceptions::CheckWildcardException(
79 const nsACString
& aThirdPartySite
) {
81 Create3PCBExceptionKey("*"_ns
, aThirdPartySite
, key
);
83 return m3PCBExceptionsSet
.Contains(key
);
86 bool ThirdPartyCookieBlockingExceptions::CheckException(
87 const nsACString
& aFirstPartySite
, const nsACString
& aThirdPartySite
) {
89 Create3PCBExceptionKey(aFirstPartySite
, aThirdPartySite
, key
);
91 return m3PCBExceptionsSet
.Contains(key
);
94 bool ThirdPartyCookieBlockingExceptions::CheckExceptionForURIs(
95 nsIURI
* aFirstPartyURI
, nsIURI
* aThirdPartyURI
) {
96 MOZ_ASSERT(XRE_IsParentProcess());
97 NS_ENSURE_TRUE(aFirstPartyURI
, false);
98 NS_ENSURE_TRUE(aThirdPartyURI
, false);
100 if (!mIsInitialized
) {
104 nsCOMPtr
<nsIEffectiveTLDService
> eTLDService
=
105 mozilla::components::EffectiveTLD::Service();
106 NS_ENSURE_TRUE(eTLDService
, false);
108 nsAutoCString thirdPartySite
;
109 nsresult rv
= eTLDService
->GetSite(aThirdPartyURI
, thirdPartySite
);
110 NS_ENSURE_SUCCESS(rv
, false);
112 bool isInExceptionList
= CheckWildcardException(thirdPartySite
);
114 if (isInExceptionList
) {
118 nsAutoCString firstPartySite
;
119 rv
= eTLDService
->GetSite(aFirstPartyURI
, firstPartySite
);
120 NS_ENSURE_SUCCESS(rv
, false);
122 return CheckException(firstPartySite
, thirdPartySite
);
125 bool ThirdPartyCookieBlockingExceptions::CheckExceptionForChannel(
126 nsIChannel
* aChannel
) {
127 MOZ_ASSERT(XRE_IsParentProcess());
128 NS_ENSURE_TRUE(aChannel
, false);
130 if (!mIsInitialized
) {
134 nsCOMPtr
<nsIEffectiveTLDService
> eTLDService
=
135 mozilla::components::EffectiveTLD::Service();
136 NS_ENSURE_TRUE(eTLDService
, false);
138 nsCOMPtr
<nsIURI
> uri
;
139 nsresult rv
= aChannel
->GetURI(getter_AddRefs(uri
));
140 NS_ENSURE_SUCCESS(rv
, false);
142 nsAutoCString thirdPartySite
;
143 rv
= eTLDService
->GetSite(uri
, thirdPartySite
);
144 NS_ENSURE_SUCCESS(rv
, false);
146 bool isInExceptionList
= CheckWildcardException(thirdPartySite
);
148 if (isInExceptionList
) {
152 nsCOMPtr
<nsILoadInfo
> loadInfo
= aChannel
->LoadInfo();
154 RefPtr
<dom::BrowsingContext
> bc
;
155 loadInfo
->GetBrowsingContext(getter_AddRefs(bc
));
157 bc
= loadInfo
->GetWorkerAssociatedBrowsingContext();
160 nsAutoCString firstPartySite
;
162 // If the channel is not associated with a browsing context, we will try to
163 // get the first party site from the partition key.
165 nsCOMPtr
<nsICookieJarSettings
> cjs
;
166 nsresult rv
= loadInfo
->GetCookieJarSettings(getter_AddRefs(cjs
));
167 NS_ENSURE_SUCCESS(rv
, false);
169 nsAutoString partitionKey
;
170 rv
= cjs
->GetPartitionKey(partitionKey
);
171 NS_ENSURE_SUCCESS(rv
, false);
174 if (!OriginAttributes::ExtractSiteFromPartitionKey(partitionKey
, site
)) {
178 firstPartySite
.Assign(NS_ConvertUTF16toUTF8(site
));
180 RefPtr
<dom::WindowGlobalParent
> topWGP
=
181 bc
->Top()->Canonical()->GetCurrentWindowGlobal();
186 nsCOMPtr
<nsIPrincipal
> topPrincipal
= topWGP
->DocumentPrincipal();
188 // If the top window is an about page, we don't need to do anything. This
189 // could happen when fetching system resources, such as pocket's images
190 if (topPrincipal
->SchemeIs("about")) {
194 nsCOMPtr
<nsIURI
> topURI
= topPrincipal
->GetURI();
197 nsresult rv
= eTLDService
->GetSite(topURI
, firstPartySite
);
198 NS_ENSURE_SUCCESS(rv
, false);
201 return CheckException(firstPartySite
, thirdPartySite
);
204 void ThirdPartyCookieBlockingExceptions::GetExceptions(
205 nsTArray
<nsCString
>& aExceptions
) {
208 for (const auto& host
: m3PCBExceptionsSet
) {
209 aExceptions
.AppendElement(host
);
214 } // namespace mozilla