tor-browser

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

UrlClassifierFeatureEmailTrackingProtection.cpp (7899B)


      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 "UrlClassifierFeatureEmailTrackingProtection.h"
      8 
      9 #include "ChannelClassifierService.h"
     10 #include "mozilla/AntiTrackingUtils.h"
     11 #include "mozilla/net/UrlClassifierCommon.h"
     12 #include "mozilla/StaticPrefs_privacy.h"
     13 #include "mozilla/StaticPtr.h"
     14 #include "nsIChannel.h"
     15 #include "nsILoadContext.h"
     16 #include "nsIHttpChannelInternal.h"
     17 #include "nsIWebProgressListener.h"
     18 #include "nsNetUtil.h"
     19 
     20 namespace mozilla::net {
     21 
     22 namespace {
     23 
     24 #define EMAIL_TRACKING_PROTECTION_FEATURE_NAME "emailtracking-protection"
     25 
     26 #define URLCLASSIFIER_EMAIL_TRACKING_BLOCKLIST \
     27  "urlclassifier.features.emailtracking.blocklistTables"
     28 #define URLCLASSIFIER_EMAIL_TRACKING_BLOCKLIST_TEST_ENTRIES \
     29  "urlclassifier.features.emailtracking.blocklistHosts"
     30 #define URLCLASSIFIER_EMAIL_TRACKING_ENTITYLIST \
     31  "urlclassifier.features.emailtracking.allowlistTables"
     32 #define URLCLASSIFIER_EMAIL_TRACKING_ENTITYLIST_TEST_ENTRIES \
     33  "urlclassifier.features.emailtracking.allowlistHosts"
     34 #define URLCLASSIFIER_EMAIL_TRACKING_PROTECTION_EXCEPTION_URLS \
     35  "urlclassifier.features.emailtracking.skipURLs"
     36 #define TABLE_EMAIL_TRACKING_BLOCKLIST_PREF "emailtracking-blocklist-pref"
     37 #define TABLE_EMAIL_TRACKING_ENTITYLIST_PREF "emailtracking-allowlist-pref"
     38 
     39 StaticRefPtr<UrlClassifierFeatureEmailTrackingProtection>
     40    gFeatureEmailTrackingProtection;
     41 
     42 }  // namespace
     43 
     44 UrlClassifierFeatureEmailTrackingProtection::
     45    UrlClassifierFeatureEmailTrackingProtection()
     46    : UrlClassifierFeatureAntiTrackingBase(
     47          nsLiteralCString(EMAIL_TRACKING_PROTECTION_FEATURE_NAME),
     48          nsLiteralCString(URLCLASSIFIER_EMAIL_TRACKING_BLOCKLIST),
     49          nsLiteralCString(URLCLASSIFIER_EMAIL_TRACKING_ENTITYLIST),
     50          nsLiteralCString(URLCLASSIFIER_EMAIL_TRACKING_BLOCKLIST_TEST_ENTRIES),
     51          nsLiteralCString(
     52              URLCLASSIFIER_EMAIL_TRACKING_ENTITYLIST_TEST_ENTRIES),
     53          nsLiteralCString(TABLE_EMAIL_TRACKING_BLOCKLIST_PREF),
     54          nsLiteralCString(TABLE_EMAIL_TRACKING_ENTITYLIST_PREF),
     55          nsLiteralCString(
     56              URLCLASSIFIER_EMAIL_TRACKING_PROTECTION_EXCEPTION_URLS)) {}
     57 
     58 /* static */
     59 const char* UrlClassifierFeatureEmailTrackingProtection::Name() {
     60  return EMAIL_TRACKING_PROTECTION_FEATURE_NAME;
     61 }
     62 
     63 /* static */
     64 void UrlClassifierFeatureEmailTrackingProtection::MaybeInitialize() {
     65  MOZ_ASSERT(XRE_IsParentProcess());
     66  UC_LOG_LEAK(("UrlClassifierFeatureEmailTrackingProtection::MaybeInitialize"));
     67 
     68  if (!gFeatureEmailTrackingProtection) {
     69    gFeatureEmailTrackingProtection =
     70        new UrlClassifierFeatureEmailTrackingProtection();
     71    gFeatureEmailTrackingProtection->InitializePreferences();
     72  }
     73 }
     74 
     75 /* static */
     76 void UrlClassifierFeatureEmailTrackingProtection::MaybeShutdown() {
     77  UC_LOG_LEAK(("UrlClassifierFeatureEmailTrackingProtection::MaybeShutdown"));
     78 
     79  if (gFeatureEmailTrackingProtection) {
     80    gFeatureEmailTrackingProtection->ShutdownPreferences();
     81    gFeatureEmailTrackingProtection = nullptr;
     82  }
     83 }
     84 
     85 /* static */
     86 already_AddRefed<UrlClassifierFeatureEmailTrackingProtection>
     87 UrlClassifierFeatureEmailTrackingProtection::MaybeCreate(nsIChannel* aChannel) {
     88  MOZ_ASSERT(aChannel);
     89 
     90  UC_LOG_LEAK(
     91      ("UrlClassifierFeatureEmailTrackingProtection::MaybeCreate - channel %p",
     92       aChannel));
     93 
     94  // Check if the email tracking protection is enabled.
     95  if (!StaticPrefs::privacy_trackingprotection_emailtracking_enabled() &&
     96      !(NS_UsePrivateBrowsing(aChannel) &&
     97        StaticPrefs::
     98            privacy_trackingprotection_emailtracking_pbmode_enabled())) {
     99    return nullptr;
    100  }
    101 
    102  RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
    103  bool isThirdParty = loadInfo->GetIsThirdPartyContextToTopWindow();
    104  if (!isThirdParty) {
    105    UC_LOG(
    106        ("UrlClassifierFeatureEmailTrackingProtection::MaybeCreate - "
    107         "skipping first party or top-level load for channel %p",
    108         aChannel));
    109    return nullptr;
    110  }
    111 
    112  if (!UrlClassifierCommon::ShouldEnableProtectionForChannel(aChannel)) {
    113    return nullptr;
    114  }
    115 
    116  MaybeInitialize();
    117  MOZ_ASSERT(gFeatureEmailTrackingProtection);
    118 
    119  RefPtr<UrlClassifierFeatureEmailTrackingProtection> self =
    120      gFeatureEmailTrackingProtection;
    121  return self.forget();
    122 }
    123 
    124 /* static */
    125 already_AddRefed<nsIUrlClassifierFeature>
    126 UrlClassifierFeatureEmailTrackingProtection::GetIfNameMatches(
    127    const nsACString& aName) {
    128  if (!aName.EqualsLiteral(EMAIL_TRACKING_PROTECTION_FEATURE_NAME)) {
    129    return nullptr;
    130  }
    131 
    132  MaybeInitialize();
    133  MOZ_ASSERT(gFeatureEmailTrackingProtection);
    134 
    135  RefPtr<UrlClassifierFeatureEmailTrackingProtection> self =
    136      gFeatureEmailTrackingProtection;
    137  return self.forget();
    138 }
    139 
    140 NS_IMETHODIMP
    141 UrlClassifierFeatureEmailTrackingProtection::ProcessChannel(
    142    nsIChannel* aChannel, const nsTArray<nsCString>& aList,
    143    const nsTArray<nsCString>& aHashes, bool* aShouldContinue) {
    144  NS_ENSURE_ARG_POINTER(aChannel);
    145  NS_ENSURE_ARG_POINTER(aShouldContinue);
    146 
    147  bool isAllowListed = UrlClassifierCommon::IsAllowListed(aChannel);
    148 
    149  // This is a blocking feature.
    150  *aShouldContinue = isAllowListed;
    151 
    152  if (isAllowListed) {
    153    return NS_OK;
    154  }
    155 
    156  bool ShouldProcessByProtectionFeature =
    157      UrlClassifierCommon::ShouldProcessWithProtectionFeature(aChannel);
    158 
    159  *aShouldContinue = !ShouldProcessByProtectionFeature;
    160 
    161  if (!ShouldProcessByProtectionFeature) {
    162    return NS_OK;
    163  }
    164 
    165  nsAutoCString list;
    166  UrlClassifierCommon::TablesToString(aList, list);
    167 
    168  ChannelBlockDecision decision =
    169      ChannelClassifierService::OnBeforeBlockChannel(aChannel, mName, list);
    170  if (decision != ChannelBlockDecision::Blocked) {
    171    uint32_t event =
    172        decision == ChannelBlockDecision::Replaced
    173            ? nsIWebProgressListener::STATE_REPLACED_TRACKING_CONTENT
    174            : nsIWebProgressListener::STATE_ALLOWED_TRACKING_CONTENT;
    175 
    176    // Need to set aBlocked to True if we replace the Email Tracker with a shim,
    177    //  since the shim is treated as a blocked event
    178    // Note: If we need to account for which kind of tracker was replaced,
    179    //  we need to create a new event type in nsIWebProgressListener
    180    if (event == nsIWebProgressListener::STATE_REPLACED_TRACKING_CONTENT) {
    181      ContentBlockingNotifier::OnEvent(aChannel, event, true);
    182    } else {
    183      ContentBlockingNotifier::OnEvent(aChannel, event, false);
    184    }
    185 
    186    *aShouldContinue = true;
    187    return NS_OK;
    188  }
    189 
    190  UrlClassifierCommon::SetBlockedContent(aChannel, NS_ERROR_EMAILTRACKING_URI,
    191                                         list, ""_ns, ""_ns);
    192 
    193  UC_LOG(
    194      ("UrlClassifierFeatureEmailTrackingProtection::ProcessChannel - "
    195       "cancelling channel %p",
    196       aChannel));
    197 
    198  nsCOMPtr<nsIHttpChannelInternal> httpChannel = do_QueryInterface(aChannel);
    199  if (httpChannel) {
    200    (void)httpChannel->CancelByURLClassifier(NS_ERROR_EMAILTRACKING_URI);
    201  } else {
    202    (void)aChannel->Cancel(NS_ERROR_EMAILTRACKING_URI);
    203  }
    204 
    205  return NS_OK;
    206 }
    207 
    208 NS_IMETHODIMP
    209 UrlClassifierFeatureEmailTrackingProtection::GetURIByListType(
    210    nsIChannel* aChannel, nsIUrlClassifierFeature::listType aListType,
    211    nsIUrlClassifierFeature::URIType* aURIType, nsIURI** aURI) {
    212  NS_ENSURE_ARG_POINTER(aChannel);
    213  NS_ENSURE_ARG_POINTER(aURIType);
    214  NS_ENSURE_ARG_POINTER(aURI);
    215 
    216  if (aListType == nsIUrlClassifierFeature::blocklist) {
    217    *aURIType = nsIUrlClassifierFeature::blocklistURI;
    218    return aChannel->GetURI(aURI);
    219  }
    220 
    221  MOZ_ASSERT(aListType == nsIUrlClassifierFeature::entitylist);
    222 
    223  *aURIType = nsIUrlClassifierFeature::pairwiseEntitylistURI;
    224  return UrlClassifierCommon::CreatePairwiseEntityListURI(aChannel, aURI);
    225 }
    226 
    227 }  // namespace mozilla::net