ThirdPartyCookieBlockingExceptions.cpp (6231B)
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/. */ 4 5 #include "ThirdPartyCookieBlockingExceptions.h" 6 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" 15 16 #include "nsIEffectiveTLDService.h" 17 #include "nsIChannel.h" 18 19 namespace mozilla { 20 namespace net { 21 22 LazyLogModule g3PCBExceptionLog("3pcbexception"); 23 24 void ThirdPartyCookieBlockingExceptions::Initialize() { 25 if (mIsInitialized) { 26 return; 27 } 28 29 // Get the remote third-party cookie blocking exception list service instance. 30 nsresult rv; 31 m3PCBExceptionService = do_GetService( 32 NS_NSITHIRDPARTYCOOKIEBLOCKINGEXCEPTIONLISTSERVICE_CONTRACTID, &rv); 33 NS_ENSURE_SUCCESS_VOID(rv); 34 35 RefPtr<mozilla::dom::Promise> initPromise; 36 rv = m3PCBExceptionService->Init(getter_AddRefs(initPromise)); 37 NS_ENSURE_SUCCESS_VOID(rv); 38 39 // Bail out earlier if we don't have a init promise. 40 if (!initPromise) { 41 MOZ_LOG(g3PCBExceptionLog, LogLevel::Error, 42 ("Failed to initialize 3PCB exception service: no init promise")); 43 return; 44 } 45 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(); 51 52 nsAutoCString name; 53 GetErrorName(rv, name); 54 55 MOZ_LOG( 56 g3PCBExceptionLog, LogLevel::Error, 57 ("Failed to initialize 3PCB exception service: %s", name.get())); 58 }); 59 } 60 61 void ThirdPartyCookieBlockingExceptions::Shutdown() { 62 if (m3PCBExceptionService) { 63 (void)m3PCBExceptionService->Shutdown(); 64 m3PCBExceptionService = nullptr; 65 } 66 67 mIsInitialized = false; 68 } 69 70 void ThirdPartyCookieBlockingExceptions::Insert(const nsACString& aException) { 71 m3PCBExceptionsSet.Insert(aException); 72 } 73 74 void ThirdPartyCookieBlockingExceptions::Remove(const nsACString& aException) { 75 m3PCBExceptionsSet.Remove(aException); 76 } 77 78 bool ThirdPartyCookieBlockingExceptions::CheckWildcardException( 79 const nsACString& aThirdPartySite) { 80 nsAutoCString key; 81 Create3PCBExceptionKey("*"_ns, aThirdPartySite, key); 82 83 return m3PCBExceptionsSet.Contains(key); 84 } 85 86 bool ThirdPartyCookieBlockingExceptions::CheckException( 87 const nsACString& aFirstPartySite, const nsACString& aThirdPartySite) { 88 nsAutoCString key; 89 Create3PCBExceptionKey(aFirstPartySite, aThirdPartySite, key); 90 91 return m3PCBExceptionsSet.Contains(key); 92 } 93 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); 99 100 if (!mIsInitialized) { 101 return false; 102 } 103 104 nsCOMPtr<nsIEffectiveTLDService> eTLDService = 105 mozilla::components::EffectiveTLD::Service(); 106 NS_ENSURE_TRUE(eTLDService, false); 107 108 nsAutoCString thirdPartySite; 109 nsresult rv = eTLDService->GetSite(aThirdPartyURI, thirdPartySite); 110 NS_ENSURE_SUCCESS(rv, false); 111 112 bool isInExceptionList = CheckWildcardException(thirdPartySite); 113 114 if (isInExceptionList) { 115 return true; 116 } 117 118 nsAutoCString firstPartySite; 119 rv = eTLDService->GetSite(aFirstPartyURI, firstPartySite); 120 NS_ENSURE_SUCCESS(rv, false); 121 122 return CheckException(firstPartySite, thirdPartySite); 123 } 124 125 bool ThirdPartyCookieBlockingExceptions::CheckExceptionForChannel( 126 nsIChannel* aChannel) { 127 MOZ_ASSERT(XRE_IsParentProcess()); 128 NS_ENSURE_TRUE(aChannel, false); 129 130 if (!mIsInitialized) { 131 return false; 132 } 133 134 nsCOMPtr<nsIEffectiveTLDService> eTLDService = 135 mozilla::components::EffectiveTLD::Service(); 136 NS_ENSURE_TRUE(eTLDService, false); 137 138 nsCOMPtr<nsIURI> uri; 139 nsresult rv = aChannel->GetURI(getter_AddRefs(uri)); 140 NS_ENSURE_SUCCESS(rv, false); 141 142 nsAutoCString thirdPartySite; 143 rv = eTLDService->GetSite(uri, thirdPartySite); 144 NS_ENSURE_SUCCESS(rv, false); 145 146 bool isInExceptionList = CheckWildcardException(thirdPartySite); 147 148 if (isInExceptionList) { 149 return true; 150 } 151 152 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); 153 154 RefPtr<dom::BrowsingContext> bc; 155 loadInfo->GetBrowsingContext(getter_AddRefs(bc)); 156 if (!bc) { 157 bc = loadInfo->GetWorkerAssociatedBrowsingContext(); 158 } 159 160 nsAutoCString firstPartySite; 161 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. 164 if (!bc) { 165 nsCOMPtr<nsICookieJarSettings> cjs; 166 nsresult rv = loadInfo->GetCookieJarSettings(getter_AddRefs(cjs)); 167 NS_ENSURE_SUCCESS(rv, false); 168 169 nsAutoString partitionKey; 170 rv = cjs->GetPartitionKey(partitionKey); 171 NS_ENSURE_SUCCESS(rv, false); 172 173 nsAutoString site; 174 if (!OriginAttributes::ExtractSiteFromPartitionKey(partitionKey, site)) { 175 return false; 176 } 177 178 firstPartySite.Assign(NS_ConvertUTF16toUTF8(site)); 179 } else { 180 RefPtr<dom::WindowGlobalParent> topWGP = 181 bc->Top()->Canonical()->GetCurrentWindowGlobal(); 182 if (!topWGP) { 183 return false; 184 } 185 186 nsCOMPtr<nsIPrincipal> topPrincipal = topWGP->DocumentPrincipal(); 187 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")) { 191 return false; 192 } 193 194 nsCOMPtr<nsIURI> topURI = topPrincipal->GetURI(); 195 196 nsAutoCString site; 197 nsresult rv = eTLDService->GetSite(topURI, firstPartySite); 198 NS_ENSURE_SUCCESS(rv, false); 199 } 200 201 return CheckException(firstPartySite, thirdPartySite); 202 } 203 204 void ThirdPartyCookieBlockingExceptions::GetExceptions( 205 nsTArray<nsCString>& aExceptions) { 206 aExceptions.Clear(); 207 208 for (const auto& host : m3PCBExceptionsSet) { 209 aExceptions.AppendElement(host); 210 } 211 } 212 213 } // namespace net 214 } // namespace mozilla