tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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