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