tor-browser

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

UrlClassifierCommon.cpp (25444B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/net/UrlClassifierCommon.h"
      8 
      9 #include "mozilla/AntiTrackingUtils.h"
     10 #include "mozilla/BasePrincipal.h"
     11 #include "mozilla/Components.h"
     12 #include "mozilla/ContentBlockingAllowList.h"
     13 #include "mozilla/ContentBlockingNotifier.h"
     14 #include "mozilla/dom/WindowGlobalParent.h"
     15 #include "mozilla/net/HttpBaseChannel.h"
     16 #include "mozilla/net/UrlClassifierFeatureFactory.h"
     17 #include "mozilla/StaticPrefs_network.h"
     18 #include "mozilla/StaticPrefs_privacy.h"
     19 #include "mozilla/StaticPrefs_channelclassifier.h"
     20 #include "mozilla/StaticPrefs_security.h"
     21 #include "mozIThirdPartyUtil.h"
     22 #include "nsContentUtils.h"
     23 #include "nsIChannel.h"
     24 #include "nsIClassifiedChannel.h"
     25 #include "mozilla/dom/Document.h"
     26 #include "nsIDocShell.h"
     27 #include "nsIHttpChannel.h"
     28 #include "nsIHttpChannelInternal.h"
     29 #include "nsIParentChannel.h"
     30 #include "nsIScriptError.h"
     31 #include "nsIWebProgressListener.h"
     32 #include "nsNetUtil.h"
     33 #include "nsQueryObject.h"
     34 #include "nsReadableUtils.h"
     35 
     36 namespace mozilla {
     37 namespace net {
     38 
     39 const nsCString::size_type UrlClassifierCommon::sMaxSpecLength = 128;
     40 
     41 // MOZ_LOG=nsChannelClassifier:5
     42 LazyLogModule UrlClassifierCommon::sLog("nsChannelClassifier");
     43 LazyLogModule UrlClassifierCommon::sLogLeak("nsChannelClassifierLeak");
     44 
     45 /* static */
     46 bool UrlClassifierCommon::AddonMayLoad(nsIChannel* aChannel, nsIURI* aURI) {
     47  nsCOMPtr<nsILoadInfo> channelLoadInfo = aChannel->LoadInfo();
     48  // loadingPrincipal is used here to ensure we are loading into an
     49  // addon principal.  This allows an addon, with explicit permission, to
     50  // call out to API endpoints that may otherwise get blocked.
     51  nsIPrincipal* loadingPrincipal = channelLoadInfo->GetLoadingPrincipal();
     52  if (!loadingPrincipal) {
     53    return false;
     54  }
     55 
     56  return BasePrincipal::Cast(loadingPrincipal)->AddonAllowsLoad(aURI, true);
     57 }
     58 
     59 /* static */
     60 bool UrlClassifierCommon::ShouldEnableProtectionForChannel(
     61    nsIChannel* aChannel) {
     62  MOZ_ASSERT(aChannel);
     63 
     64  nsCOMPtr<nsIURI> chanURI;
     65  nsresult rv = aChannel->GetURI(getter_AddRefs(chanURI));
     66  if (NS_WARN_IF(NS_FAILED(rv))) {
     67    return false;
     68  }
     69 
     70  if (UrlClassifierCommon::AddonMayLoad(aChannel, chanURI)) {
     71    return false;
     72  }
     73 
     74  nsCOMPtr<nsIURI> topWinURI;
     75  nsCOMPtr<nsIHttpChannelInternal> channel = do_QueryInterface(aChannel);
     76  if (NS_WARN_IF(!channel)) {
     77    return false;
     78  }
     79 
     80  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
     81  MOZ_ASSERT(loadInfo);
     82 
     83  auto policyType = loadInfo->GetExternalContentPolicyType();
     84  if (policyType == ExtContentPolicy::TYPE_DOCUMENT) {
     85    UC_LOG(
     86        ("UrlClassifierCommon::ShouldEnableProtectionForChannel - "
     87         "skipping top-level load for channel %p",
     88         aChannel));
     89    return false;
     90  }
     91 
     92  // Tracking protection will be enabled so return without updating
     93  // the security state. If any channels are subsequently cancelled
     94  // (page elements blocked) the state will be then updated.
     95 
     96  return true;
     97 }
     98 
     99 /* static */
    100 nsresult UrlClassifierCommon::SetTrackingInfo(
    101    nsIChannel* aChannel, const nsTArray<nsCString>& aLists,
    102    const nsTArray<nsCString>& aFullHashes) {
    103  NS_ENSURE_ARG(!aLists.IsEmpty());
    104 
    105  // Can be called in EITHER the parent or child process.
    106  nsresult rv;
    107  nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
    108      do_QueryInterface(aChannel, &rv);
    109  NS_ENSURE_SUCCESS(rv, rv);
    110 
    111  if (classifiedChannel) {
    112    classifiedChannel->SetMatchedTrackingInfo(aLists, aFullHashes);
    113  }
    114 
    115  nsCOMPtr<nsIParentChannel> parentChannel;
    116  NS_QueryNotificationCallbacks(aChannel, parentChannel);
    117  if (parentChannel) {
    118    // This channel is a parent-process proxy for a child process request.
    119    // Tell the child process channel to do this as well.
    120    // TODO: We can remove the code sending the IPC to content to update
    121    //       tracking info once we move the ContentBlockingLog into the parent.
    122    //       This would be done in Bug 1599046.
    123    nsAutoCString strLists, strHashes;
    124    TablesToString(aLists, strLists);
    125    TablesToString(aFullHashes, strHashes);
    126 
    127    parentChannel->SetClassifierMatchedTrackingInfo(strLists, strHashes);
    128  }
    129 
    130  return NS_OK;
    131 }
    132 
    133 /* static */
    134 nsresult UrlClassifierCommon::SetBlockedContent(nsIChannel* channel,
    135                                                nsresult aErrorCode,
    136                                                const nsACString& aList,
    137                                                const nsACString& aProvider,
    138                                                const nsACString& aFullHash) {
    139  NS_ENSURE_ARG(!aList.IsEmpty());
    140 
    141  switch (aErrorCode) {
    142    case NS_ERROR_HARMFULADDON_URI:
    143      NS_SetRequestBlockingReason(
    144          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_HARMFULADDON_URI);
    145      break;
    146    case NS_ERROR_MALWARE_URI:
    147      NS_SetRequestBlockingReason(
    148          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_MALWARE_URI);
    149      break;
    150    case NS_ERROR_PHISHING_URI:
    151      NS_SetRequestBlockingReason(
    152          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_PHISHING_URI);
    153      break;
    154    case NS_ERROR_UNWANTED_URI:
    155      NS_SetRequestBlockingReason(
    156          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_UNWANTED_URI);
    157      break;
    158    case NS_ERROR_TRACKING_URI:
    159      NS_SetRequestBlockingReason(
    160          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_TRACKING_URI);
    161      break;
    162    case NS_ERROR_BLOCKED_URI:
    163      NS_SetRequestBlockingReason(
    164          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_BLOCKED_URI);
    165      break;
    166    case NS_ERROR_HARMFUL_URI:
    167      NS_SetRequestBlockingReason(
    168          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_HARMFUL_URI);
    169      break;
    170    case NS_ERROR_CRYPTOMINING_URI:
    171      NS_SetRequestBlockingReason(
    172          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_CRYPTOMINING_URI);
    173      break;
    174    case NS_ERROR_FINGERPRINTING_URI:
    175      NS_SetRequestBlockingReason(
    176          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_FINGERPRINTING_URI);
    177      break;
    178    case NS_ERROR_SOCIALTRACKING_URI:
    179      NS_SetRequestBlockingReason(
    180          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_SOCIALTRACKING_URI);
    181      break;
    182    case NS_ERROR_EMAILTRACKING_URI:
    183      NS_SetRequestBlockingReason(
    184          channel, nsILoadInfo::BLOCKING_REASON_CLASSIFY_EMAILTRACKING_URI);
    185      break;
    186    default:
    187      MOZ_CRASH(
    188          "Missing nsILoadInfo::BLOCKING_REASON* for the classification error");
    189      break;
    190  }
    191 
    192  // Can be called in EITHER the parent or child process.
    193  nsresult rv;
    194  nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
    195      do_QueryInterface(channel, &rv);
    196  NS_ENSURE_SUCCESS(rv, rv);
    197 
    198  if (classifiedChannel) {
    199    classifiedChannel->SetMatchedInfo(aList, aProvider, aFullHash);
    200  }
    201 
    202  if (XRE_IsParentProcess()) {
    203    nsCOMPtr<nsIParentChannel> parentChannel;
    204    NS_QueryNotificationCallbacks(channel, parentChannel);
    205    if (parentChannel) {
    206      // This channel is a parent-process proxy for a child process request.
    207      // Tell the child process channel to do this as well.
    208      // TODO: We can remove the code sending the IPC to content to update
    209      //       matched info once we move the ContentBlockingLog into the parent.
    210      //       This would be done in Bug 1601063.
    211      parentChannel->SetClassifierMatchedInfo(aList, aProvider, aFullHash);
    212    }
    213 
    214    unsigned state =
    215        UrlClassifierFeatureFactory::GetClassifierBlockingEventCode(aErrorCode);
    216    if (!state) {
    217      state = nsIWebProgressListener::STATE_BLOCKED_UNSAFE_CONTENT;
    218    }
    219    ContentBlockingNotifier::OnEvent(channel, state);
    220 
    221    return NS_OK;
    222  }
    223 
    224  // TODO: ReportToConsole is called in the child process,
    225  // If nsContentUtils::ReportToConsole is not fission compatiable(cannot report
    226  // to correct top-level window), we need to do this in the parent process
    227  // instead (find the top-level window in the parent and send an IPC to child
    228  // processes to report console).
    229  nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil;
    230  thirdPartyUtil = mozilla::components::ThirdPartyUtil::Service();
    231  if (NS_WARN_IF(!thirdPartyUtil)) {
    232    return NS_OK;
    233  }
    234 
    235  nsCOMPtr<nsIURI> uriBeingLoaded =
    236      AntiTrackingUtils::MaybeGetDocumentURIBeingLoaded(channel);
    237  nsCOMPtr<mozIDOMWindowProxy> win;
    238  rv = thirdPartyUtil->GetTopWindowForChannel(channel, uriBeingLoaded,
    239                                              getter_AddRefs(win));
    240  NS_ENSURE_SUCCESS(rv, NS_OK);
    241  auto* pwin = nsPIDOMWindowOuter::From(win);
    242  nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
    243  if (!docShell) {
    244    return NS_OK;
    245  }
    246  RefPtr<dom::Document> doc = docShell->GetDocument();
    247  NS_ENSURE_TRUE(doc, NS_OK);
    248 
    249  // Log a warning to the web console.
    250  nsCOMPtr<nsIURI> uri;
    251  channel->GetURI(getter_AddRefs(uri));
    252  AutoTArray<nsString, 1> params;
    253  CopyUTF8toUTF16(uri->GetSpecOrDefault(), *params.AppendElement());
    254  const char* message;
    255  nsCString category;
    256 
    257  if (UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(aErrorCode)) {
    258    message = UrlClassifierFeatureFactory::
    259        ClassifierBlockingErrorCodeToConsoleMessage(aErrorCode, category);
    260  } else {
    261    message = "UnsafeUriBlocked";
    262    category = "Safe Browsing"_ns;
    263  }
    264 
    265  nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, category, doc,
    266                                  nsContentUtils::eNECKO_PROPERTIES, message,
    267                                  params);
    268 
    269  return NS_OK;
    270 }
    271 
    272 /* static */
    273 nsresult UrlClassifierCommon::GetTopWindowURI(nsIChannel* aChannel,
    274                                              nsIURI** aURI) {
    275  MOZ_ASSERT(XRE_IsParentProcess());
    276  MOZ_ASSERT(aChannel);
    277 
    278  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
    279  MOZ_ASSERT(loadInfo);
    280 
    281  RefPtr<dom::BrowsingContext> browsingContext;
    282  nsresult rv =
    283      loadInfo->GetTargetBrowsingContext(getter_AddRefs(browsingContext));
    284  if (NS_WARN_IF(NS_FAILED(rv)) || !browsingContext) {
    285    return NS_ERROR_FAILURE;
    286  }
    287 
    288  dom::CanonicalBrowsingContext* top = browsingContext->Canonical()->Top();
    289  dom::WindowGlobalParent* wgp = top->GetCurrentWindowGlobal();
    290  if (!wgp) {
    291    return NS_ERROR_FAILURE;
    292  }
    293 
    294  RefPtr<nsIURI> uri = wgp->GetDocumentURI();
    295  if (!uri) {
    296    return NS_ERROR_FAILURE;
    297  }
    298 
    299  uri.forget(aURI);
    300  return NS_OK;
    301 }
    302 
    303 /* static */
    304 nsresult UrlClassifierCommon::CreatePairwiseEntityListURI(nsIChannel* aChannel,
    305                                                          nsIURI** aURI) {
    306  MOZ_ASSERT(aChannel);
    307  MOZ_ASSERT(aURI);
    308 
    309  nsresult rv;
    310  nsCOMPtr<nsIHttpChannelInternal> chan = do_QueryInterface(aChannel, &rv);
    311  NS_ENSURE_SUCCESS(rv, rv);
    312  if (!chan) {
    313    return NS_ERROR_FAILURE;
    314  }
    315 
    316  nsCOMPtr<nsIURI> topWinURI;
    317  rv =
    318      UrlClassifierCommon::GetTopWindowURI(aChannel, getter_AddRefs(topWinURI));
    319  if (NS_FAILED(rv) || !topWinURI) {
    320    // SharedWorker and ServiceWorker don't have an associated window, use
    321    // client's URI instead.
    322    nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
    323    MOZ_ASSERT(loadInfo);
    324 
    325    Maybe<dom::ClientInfo> clientInfo = loadInfo->GetClientInfo();
    326    if (clientInfo.isSome()) {
    327      if ((clientInfo->Type() == dom::ClientType::Sharedworker) ||
    328          (clientInfo->Type() == dom::ClientType::Serviceworker)) {
    329        UC_LOG(
    330            ("UrlClassifierCommon::CreatePairwiseEntityListURI - "
    331             "channel %p initiated by worker, get uri from client",
    332             aChannel));
    333 
    334        auto clientPrincipalOrErr = clientInfo->GetPrincipal();
    335        if (clientPrincipalOrErr.isOk()) {
    336          nsCOMPtr<nsIPrincipal> principal = clientPrincipalOrErr.unwrap();
    337          if (principal) {
    338            auto* basePrin = BasePrincipal::Cast(principal);
    339            rv = basePrin->GetURI(getter_AddRefs(topWinURI));
    340            (void)NS_WARN_IF(NS_FAILED(rv));
    341          }
    342        }
    343      }
    344    }
    345 
    346    if (!topWinURI) {
    347      UC_LOG(
    348          ("UrlClassifierCommon::CreatePairwiseEntityListURI - "
    349           "no top-level window associated with channel %p, "
    350           "get uri from loading principal",
    351           aChannel));
    352 
    353      nsCOMPtr<nsIPrincipal> principal = loadInfo->GetLoadingPrincipal();
    354      if (principal) {
    355        auto* basePrin = BasePrincipal::Cast(principal);
    356        rv = basePrin->GetURI(getter_AddRefs(topWinURI));
    357        (void)NS_WARN_IF(NS_FAILED(rv));
    358      }
    359    }
    360  }
    361 
    362  if (!topWinURI) {
    363    UC_LOG(
    364        ("UrlClassifierCommon::CreatePairwiseEntityListURI - "
    365         "fail to get top-level window uri for channel %p",
    366         aChannel));
    367 
    368    // Return success because we want to continue to look up even without
    369    // whitelist.
    370    return NS_OK;
    371  }
    372 
    373  nsCOMPtr<nsIScriptSecurityManager> securityManager;
    374  securityManager = mozilla::components::ScriptSecurityManager::Service(&rv);
    375  NS_ENSURE_SUCCESS(rv, rv);
    376  nsCOMPtr<nsIPrincipal> chanPrincipal;
    377  rv = securityManager->GetChannelURIPrincipal(aChannel,
    378                                               getter_AddRefs(chanPrincipal));
    379  NS_ENSURE_SUCCESS(rv, rv);
    380 
    381  // Craft a entitylist URL like "toplevel.page/?resource=third.party.domain"
    382  nsAutoCString pageHostname, resourceDomain;
    383  rv = topWinURI->GetHost(pageHostname);
    384  if (NS_FAILED(rv)) {
    385    // When the top-level page doesn't support GetHost, for example, about:home,
    386    // we don't return an error here; instead, we return success to make sure
    387    // that the lookup process calling this API continues to run.
    388    if (UC_LOG_ENABLED()) {
    389      nsCString topWinSpec =
    390          topWinURI ? topWinURI->GetSpecOrDefault() : "(null)"_ns;
    391      topWinSpec.Truncate(
    392          std::min(topWinSpec.Length(), UrlClassifierCommon::sMaxSpecLength));
    393      UC_LOG(
    394          ("UrlClassifierCommon::CreatePairwiseEntityListURI - "
    395           "cannot get host from the top-level uri %s of channel %p",
    396           topWinSpec.get(), aChannel));
    397    }
    398    return NS_OK;
    399  }
    400 
    401  rv = chanPrincipal->GetBaseDomain(resourceDomain);
    402  NS_ENSURE_SUCCESS(rv, rv);
    403  nsAutoCString entitylistEntry =
    404      "http://"_ns + pageHostname + "/?resource="_ns + resourceDomain;
    405  UC_LOG(
    406      ("UrlClassifierCommon::CreatePairwiseEntityListURI - looking for %s in "
    407       "the entitylist on channel %p",
    408       entitylistEntry.get(), aChannel));
    409 
    410  nsCOMPtr<nsIURI> entitylistURI;
    411  rv = NS_NewURI(getter_AddRefs(entitylistURI), entitylistEntry);
    412  if (NS_FAILED(rv)) {
    413    return rv;
    414  }
    415 
    416  entitylistURI.forget(aURI);
    417  return NS_OK;
    418 }
    419 
    420 namespace {
    421 
    422 void LowerPriorityHelper(nsIChannel* aChannel) {
    423  MOZ_ASSERT(aChannel);
    424 
    425  bool isBlockingResource = false;
    426 
    427  nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(aChannel));
    428  if (cos) {
    429    if (StaticPrefs::network_http_tailing_enabled()) {
    430      uint32_t cosFlags = 0;
    431      cos->GetClassFlags(&cosFlags);
    432      isBlockingResource =
    433          cosFlags & (nsIClassOfService::UrgentStart |
    434                      nsIClassOfService::Leader | nsIClassOfService::Unblocked);
    435 
    436      // Requests not allowed to be tailed are usually those with higher
    437      // prioritization.  That overweights being a tracker: don't throttle
    438      // them when not in background.
    439      if (!(cosFlags & nsIClassOfService::TailForbidden)) {
    440        cos->AddClassFlags(nsIClassOfService::Throttleable);
    441      }
    442    } else {
    443      // Yes, we even don't want to evaluate the isBlockingResource when tailing
    444      // is off see bug 1395525.
    445 
    446      cos->AddClassFlags(nsIClassOfService::Throttleable);
    447    }
    448  }
    449 
    450  if (!isBlockingResource) {
    451    nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(aChannel);
    452    if (p) {
    453      UC_LOG(
    454          ("UrlClassifierCommon::LowerPriorityHelper - "
    455           "setting PRIORITY_LOWEST for channel %p",
    456           aChannel));
    457      p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
    458    }
    459  }
    460 }
    461 
    462 }  // namespace
    463 
    464 // static
    465 void UrlClassifierCommon::SetClassificationFlagsHelper(
    466    nsIChannel* aChannel, uint32_t aClassificationFlags, bool aIsThirdParty) {
    467  MOZ_ASSERT(aChannel);
    468 
    469  nsCOMPtr<nsIParentChannel> parentChannel;
    470  NS_QueryNotificationCallbacks(aChannel, parentChannel);
    471  if (parentChannel) {
    472    // This channel is a parent-process proxy for a child process
    473    // request. We should notify the child process as well.
    474    parentChannel->NotifyClassificationFlags(aClassificationFlags,
    475                                             aIsThirdParty);
    476  }
    477 
    478  RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(aChannel);
    479  if (httpChannel) {
    480    httpChannel->AddClassificationFlags(aClassificationFlags, aIsThirdParty);
    481  }
    482 }
    483 
    484 // static
    485 void UrlClassifierCommon::AnnotateChannel(nsIChannel* aChannel,
    486                                          uint32_t aClassificationFlags,
    487                                          uint32_t aLoadingState) {
    488  MOZ_ASSERT(XRE_IsParentProcess());
    489  MOZ_ASSERT(aChannel);
    490 
    491  nsCOMPtr<nsIURI> chanURI;
    492  nsresult rv = aChannel->GetURI(getter_AddRefs(chanURI));
    493  if (NS_WARN_IF(NS_FAILED(rv))) {
    494    return;
    495  }
    496 
    497  RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
    498  bool isThirdPartyWithTopLevelWinURI =
    499      loadInfo->GetIsThirdPartyContextToTopWindow();
    500 
    501  SetClassificationFlagsHelper(aChannel, aClassificationFlags,
    502                               isThirdPartyWithTopLevelWinURI);
    503 
    504  // We consider valid tracking flags (based on the current strict vs basic list
    505  // prefs) and cryptomining (which is not considered as tracking).
    506  bool validClassificationFlags =
    507      IsTrackingClassificationFlag(aClassificationFlags,
    508                                   NS_UsePrivateBrowsing(aChannel)) ||
    509      IsCryptominingClassificationFlag(aClassificationFlags,
    510                                       NS_UsePrivateBrowsing(aChannel));
    511 
    512  if (validClassificationFlags && isThirdPartyWithTopLevelWinURI) {
    513    ContentBlockingNotifier::OnEvent(aChannel, aLoadingState);
    514  }
    515 
    516  if (isThirdPartyWithTopLevelWinURI &&
    517      StaticPrefs::privacy_trackingprotection_lower_network_priority()) {
    518    LowerPriorityHelper(aChannel);
    519  }
    520 }
    521 
    522 // static
    523 void UrlClassifierCommon::AnnotateChannelWithoutNotifying(
    524    nsIChannel* aChannel, uint32_t aClassificationFlags) {
    525  MOZ_ASSERT(XRE_IsParentProcess());
    526  MOZ_ASSERT(aChannel);
    527 
    528  nsCOMPtr<nsIURI> chanURI;
    529  nsresult rv = aChannel->GetURI(getter_AddRefs(chanURI));
    530  if (NS_WARN_IF(NS_FAILED(rv))) {
    531    return;
    532  }
    533 
    534  RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
    535  bool isThirdPartyWithTopLevelWinURI =
    536      loadInfo->GetIsThirdPartyContextToTopWindow();
    537 
    538  SetClassificationFlagsHelper(aChannel, aClassificationFlags,
    539                               isThirdPartyWithTopLevelWinURI);
    540 
    541  if (isThirdPartyWithTopLevelWinURI &&
    542      StaticPrefs::privacy_trackingprotection_lower_network_priority()) {
    543    LowerPriorityHelper(aChannel);
    544  }
    545 }
    546 
    547 // static
    548 bool UrlClassifierCommon::IsAllowListed(nsIChannel* aChannel) {
    549  nsCOMPtr<nsIHttpChannelInternal> channel = do_QueryInterface(aChannel);
    550  if (NS_WARN_IF(!channel)) {
    551    return false;
    552  }
    553 
    554  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
    555 
    556  bool isAllowListed = false;
    557  if (StaticPrefs::channelclassifier_allowlist_example()) {
    558    UC_LOG(
    559        ("UrlClassifierCommon::IsAllowListed - "
    560         "check allowlisting test domain on channel %p",
    561         aChannel));
    562 
    563    nsCOMPtr<nsIIOService> ios = components::IO::Service();
    564    if (NS_WARN_IF(!ios)) {
    565      return false;
    566    }
    567 
    568    nsCOMPtr<nsIURI> uri;
    569    nsresult rv = ios->NewURI("http://allowlisted.example.com"_ns, nullptr,
    570                              nullptr, getter_AddRefs(uri));
    571    if (NS_WARN_IF(NS_FAILED(rv))) {
    572      return false;
    573    }
    574    nsCOMPtr<nsIPrincipal> cbAllowListPrincipal =
    575        BasePrincipal::CreateContentPrincipal(uri,
    576                                              loadInfo->GetOriginAttributes());
    577 
    578    rv = ContentBlockingAllowList::Check(
    579        cbAllowListPrincipal, NS_UsePrivateBrowsing(aChannel), isAllowListed);
    580    if (NS_WARN_IF(NS_FAILED(rv))) {
    581      return false;
    582    }
    583  } else {
    584    nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
    585    MOZ_ALWAYS_SUCCEEDS(
    586        loadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings)));
    587    isAllowListed = cookieJarSettings->GetIsOnContentBlockingAllowList();
    588  }
    589 
    590  if (isAllowListed) {
    591    UC_LOG(("UrlClassifierCommon::IsAllowListed - user override on channel %p",
    592            aChannel));
    593  }
    594 
    595  return isAllowListed;
    596 }
    597 
    598 // static
    599 bool UrlClassifierCommon::IsTrackingClassificationFlag(uint32_t aFlag,
    600                                                       bool aIsPrivate) {
    601  bool isLevel2ListEnabled =
    602      aIsPrivate
    603          ? StaticPrefs::privacy_annotate_channels_strict_list_pbmode_enabled()
    604          : StaticPrefs::privacy_annotate_channels_strict_list_enabled();
    605 
    606  if (isLevel2ListEnabled &&
    607      (aFlag & nsIClassifiedChannel::ClassificationFlags::
    608                   CLASSIFIED_ANY_STRICT_TRACKING)) {
    609    return true;
    610  }
    611 
    612  if (StaticPrefs::privacy_socialtracking_block_cookies_enabled() &&
    613      IsSocialTrackingClassificationFlag(aFlag)) {
    614    return true;
    615  }
    616 
    617  return (
    618      aFlag &
    619      nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_ANY_BASIC_TRACKING);
    620 }
    621 
    622 // static
    623 bool UrlClassifierCommon::IsSocialTrackingClassificationFlag(uint32_t aFlag) {
    624  return (aFlag & nsIClassifiedChannel::ClassificationFlags::
    625                      CLASSIFIED_ANY_SOCIAL_TRACKING) != 0;
    626 }
    627 
    628 // static
    629 bool UrlClassifierCommon::IsCryptominingClassificationFlag(uint32_t aFlag,
    630                                                           bool aIsPrivate) {
    631  if (aFlag &
    632      nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_CRYPTOMINING) {
    633    return true;
    634  }
    635 
    636  bool isLevel2ListEnabled =
    637      aIsPrivate
    638          ? StaticPrefs::privacy_annotate_channels_strict_list_pbmode_enabled()
    639          : StaticPrefs::privacy_annotate_channels_strict_list_enabled();
    640 
    641  if (isLevel2ListEnabled &&
    642      (aFlag & nsIClassifiedChannel::ClassificationFlags::
    643                   CLASSIFIED_CRYPTOMINING_CONTENT)) {
    644    return true;
    645  }
    646 
    647  return false;
    648 }
    649 
    650 void UrlClassifierCommon::TablesToString(const nsTArray<nsCString>& aList,
    651                                         nsACString& aString) {
    652  // Truncate and append rather than assigning because that's more efficient if
    653  // aString is an nsAutoCString.
    654  aString.Truncate();
    655  StringJoinAppend(aString, ","_ns, aList);
    656 }
    657 
    658 uint32_t UrlClassifierCommon::TablesToClassificationFlags(
    659    const nsTArray<nsCString>& aList,
    660    const std::vector<ClassificationData>& aData, uint32_t aDefaultFlag) {
    661  uint32_t flags = 0;
    662  for (const nsCString& table : aList) {
    663    flags |= TableToClassificationFlag(table, aData);
    664  }
    665 
    666  if (flags == 0) {
    667    flags |= aDefaultFlag;
    668  }
    669 
    670  return flags;
    671 }
    672 
    673 uint32_t UrlClassifierCommon::TableToClassificationFlag(
    674    const nsACString& aTable, const std::vector<ClassificationData>& aData) {
    675  for (const ClassificationData& data : aData) {
    676    if (StringBeginsWith(aTable, data.mPrefix)) {
    677      return data.mFlag;
    678    }
    679  }
    680 
    681  return 0;
    682 }
    683 
    684 /* static */
    685 bool UrlClassifierCommon::IsPassiveContent(nsIChannel* aChannel) {
    686  MOZ_ASSERT(aChannel);
    687 
    688  nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
    689  ExtContentPolicyType contentType = loadInfo->GetExternalContentPolicyType();
    690 
    691  // Return true if aChannel is loading passive display content, as
    692  // defined by the mixed content blocker.
    693  // https://searchfox.org/mozilla-central/rev/c80fa7258c935223fe319c5345b58eae85d4c6ae/dom/security/nsMixedContentBlocker.cpp#532
    694  return contentType == ExtContentPolicy::TYPE_IMAGE ||
    695         contentType == ExtContentPolicy::TYPE_MEDIA;
    696 }
    697 
    698 /* static */
    699 bool UrlClassifierCommon::ShouldProcessWithProtectionFeature(
    700    nsIChannel* aChannel) {
    701  MOZ_ASSERT(aChannel);
    702 
    703  bool shouldProcess = true;
    704  bool isPrivateMode = NS_UsePrivateBrowsing(aChannel);
    705 
    706  nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
    707      do_QueryInterface(aChannel);
    708 
    709  if (classifiedChannel) {
    710    if (classifiedChannel->GetClassificationFlags() &
    711        nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_CONSENTMANAGER) {
    712      // Channel is classified as consent manager
    713      if (StaticPrefs::
    714              privacy_trackingprotection_consentmanager_skip_enabled() ||
    715          (StaticPrefs::
    716               privacy_trackingprotection_consentmanager_skip_pbmode_enabled() &&
    717           isPrivateMode)) {
    718        // Don't process channel
    719        shouldProcess = false;
    720 
    721        UC_LOG(
    722            ("UrlClassifierCommon::ShouldProcessWithProtectionFeature - "
    723             "Skipping channel %p because annotated as a consent manager",
    724             aChannel));
    725      }
    726    }
    727 
    728    if (classifiedChannel->GetClassificationFlags() &
    729        nsIClassifiedChannel::ClassificationFlags::CLASSIFIED_ANTIFRAUD) {
    730      // Channel is classified as anti-fraud
    731      if (StaticPrefs::privacy_trackingprotection_antifraud_skip_enabled() ||
    732          (StaticPrefs::
    733               privacy_trackingprotection_antifraud_skip_pbmode_enabled() &&
    734           isPrivateMode)) {
    735        // Don't process channel
    736        shouldProcess = false;
    737 
    738        UC_LOG(
    739            ("UrlClassifierCommon::ShouldProcessWithProtectionFeature - "
    740             "Skipping channel %p because it is annotated as anti-fraud",
    741             aChannel));
    742      }
    743    }
    744  }
    745 
    746  return shouldProcess;
    747 }
    748 
    749 }  // namespace net
    750 }  // namespace mozilla