UrlClassifierFeatureFingerprintingProtection.cpp (7603B)
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 "UrlClassifierFeatureFingerprintingProtection.h" 8 9 #include "mozilla/AntiTrackingUtils.h" 10 #include "mozilla/net/UrlClassifierCommon.h" 11 #include "ChannelClassifierService.h" 12 #include "mozilla/StaticPrefs_privacy.h" 13 #include "nsNetUtil.h" 14 #include "mozilla/StaticPtr.h" 15 #include "nsIWebProgressListener.h" 16 #include "nsIHttpChannelInternal.h" 17 #include "nsIChannel.h" 18 19 namespace mozilla { 20 namespace net { 21 22 namespace { 23 24 #define FINGERPRINTING_FEATURE_NAME "fingerprinting-protection" 25 26 #define URLCLASSIFIER_FINGERPRINTING_BLOCKLIST \ 27 "urlclassifier.features.fingerprinting.blacklistTables" 28 #define URLCLASSIFIER_FINGERPRINTING_BLOCKLIST_TEST_ENTRIES \ 29 "urlclassifier.features.fingerprinting.blacklistHosts" 30 #define URLCLASSIFIER_FINGERPRINTING_ENTITYLIST \ 31 "urlclassifier.features.fingerprinting.whitelistTables" 32 #define URLCLASSIFIER_FINGERPRINTING_ENTITYLIST_TEST_ENTRIES \ 33 "urlclassifier.features.fingerprinting.whitelistHosts" 34 #define URLCLASSIFIER_FINGERPRINTING_EXCEPTION_URLS \ 35 "urlclassifier.features.fingerprinting.skipURLs" 36 #define TABLE_FINGERPRINTING_BLOCKLIST_PREF "fingerprinting-blacklist-pref" 37 #define TABLE_FINGERPRINTING_ENTITYLIST_PREF "fingerprinting-whitelist-pref" 38 39 StaticRefPtr<UrlClassifierFeatureFingerprintingProtection> 40 gFeatureFingerprintingProtection; 41 42 } // namespace 43 44 UrlClassifierFeatureFingerprintingProtection:: 45 UrlClassifierFeatureFingerprintingProtection() 46 : UrlClassifierFeatureAntiTrackingBase( 47 nsLiteralCString(FINGERPRINTING_FEATURE_NAME), 48 nsLiteralCString(URLCLASSIFIER_FINGERPRINTING_BLOCKLIST), 49 nsLiteralCString(URLCLASSIFIER_FINGERPRINTING_ENTITYLIST), 50 nsLiteralCString(URLCLASSIFIER_FINGERPRINTING_BLOCKLIST_TEST_ENTRIES), 51 nsLiteralCString( 52 URLCLASSIFIER_FINGERPRINTING_ENTITYLIST_TEST_ENTRIES), 53 nsLiteralCString(TABLE_FINGERPRINTING_BLOCKLIST_PREF), 54 nsLiteralCString(TABLE_FINGERPRINTING_ENTITYLIST_PREF), 55 nsLiteralCString(URLCLASSIFIER_FINGERPRINTING_EXCEPTION_URLS)) {} 56 57 /* static */ const char* UrlClassifierFeatureFingerprintingProtection::Name() { 58 return FINGERPRINTING_FEATURE_NAME; 59 } 60 61 /* static */ 62 void UrlClassifierFeatureFingerprintingProtection::MaybeInitialize() { 63 UC_LOG_LEAK( 64 ("UrlClassifierFeatureFingerprintingProtection::MaybeInitialize")); 65 66 if (!gFeatureFingerprintingProtection) { 67 gFeatureFingerprintingProtection = 68 new UrlClassifierFeatureFingerprintingProtection(); 69 gFeatureFingerprintingProtection->InitializePreferences(); 70 } 71 } 72 73 /* static */ 74 void UrlClassifierFeatureFingerprintingProtection::MaybeShutdown() { 75 UC_LOG_LEAK(("UrlClassifierFeatureFingerprintingProtection::MaybeShutdown")); 76 77 if (gFeatureFingerprintingProtection) { 78 gFeatureFingerprintingProtection->ShutdownPreferences(); 79 gFeatureFingerprintingProtection = nullptr; 80 } 81 } 82 83 /* static */ 84 already_AddRefed<UrlClassifierFeatureFingerprintingProtection> 85 UrlClassifierFeatureFingerprintingProtection::MaybeCreate( 86 nsIChannel* aChannel) { 87 MOZ_ASSERT(aChannel); 88 89 UC_LOG_LEAK( 90 ("UrlClassifierFeatureFingerprintingProtection::MaybeCreate - channel %p", 91 aChannel)); 92 93 if (!StaticPrefs::privacy_trackingprotection_fingerprinting_enabled()) { 94 return nullptr; 95 } 96 97 RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); 98 bool isThirdParty = loadInfo->GetIsThirdPartyContextToTopWindow(); 99 if (!isThirdParty) { 100 UC_LOG( 101 ("UrlClassifierFeatureFingerprintingProtection::MaybeCreate - " 102 "skipping first party or top-level load for channel %p", 103 aChannel)); 104 return nullptr; 105 } 106 107 if (UrlClassifierCommon::IsPassiveContent(aChannel)) { 108 return nullptr; 109 } 110 111 if (!UrlClassifierCommon::ShouldEnableProtectionForChannel(aChannel)) { 112 return nullptr; 113 } 114 115 MaybeInitialize(); 116 MOZ_ASSERT(gFeatureFingerprintingProtection); 117 118 RefPtr<UrlClassifierFeatureFingerprintingProtection> self = 119 gFeatureFingerprintingProtection; 120 return self.forget(); 121 } 122 123 /* static */ 124 already_AddRefed<nsIUrlClassifierFeature> 125 UrlClassifierFeatureFingerprintingProtection::GetIfNameMatches( 126 const nsACString& aName) { 127 if (!aName.EqualsLiteral(FINGERPRINTING_FEATURE_NAME)) { 128 return nullptr; 129 } 130 131 MaybeInitialize(); 132 MOZ_ASSERT(gFeatureFingerprintingProtection); 133 134 RefPtr<UrlClassifierFeatureFingerprintingProtection> self = 135 gFeatureFingerprintingProtection; 136 return self.forget(); 137 } 138 139 NS_IMETHODIMP 140 UrlClassifierFeatureFingerprintingProtection::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_FINGERPRINTING_CONTENT 173 : nsIWebProgressListener::STATE_ALLOWED_FINGERPRINTING_CONTENT; 174 175 // Need to set aBlocked to True if we replace the Fingerprinter with a shim, 176 // since the shim is treated as a blocked event 177 if (event == 178 nsIWebProgressListener::STATE_REPLACED_FINGERPRINTING_CONTENT) { 179 ContentBlockingNotifier::OnEvent(aChannel, event, true); 180 } else { 181 ContentBlockingNotifier::OnEvent(aChannel, event, false); 182 } 183 184 *aShouldContinue = true; 185 return NS_OK; 186 } 187 188 UrlClassifierCommon::SetBlockedContent(aChannel, NS_ERROR_FINGERPRINTING_URI, 189 list, ""_ns, ""_ns); 190 191 UC_LOG( 192 ("UrlClassifierFeatureFingerprintingProtection::ProcessChannel - " 193 "cancelling channel %p", 194 aChannel)); 195 196 nsCOMPtr<nsIHttpChannelInternal> httpChannel = do_QueryInterface(aChannel); 197 if (httpChannel) { 198 (void)httpChannel->CancelByURLClassifier(NS_ERROR_FINGERPRINTING_URI); 199 } else { 200 (void)aChannel->Cancel(NS_ERROR_FINGERPRINTING_URI); 201 } 202 203 return NS_OK; 204 } 205 206 NS_IMETHODIMP 207 UrlClassifierFeatureFingerprintingProtection::GetURIByListType( 208 nsIChannel* aChannel, nsIUrlClassifierFeature::listType aListType, 209 nsIUrlClassifierFeature::URIType* aURIType, nsIURI** aURI) { 210 NS_ENSURE_ARG_POINTER(aChannel); 211 NS_ENSURE_ARG_POINTER(aURIType); 212 NS_ENSURE_ARG_POINTER(aURI); 213 214 if (aListType == nsIUrlClassifierFeature::blocklist) { 215 *aURIType = nsIUrlClassifierFeature::blocklistURI; 216 return aChannel->GetURI(aURI); 217 } 218 219 MOZ_ASSERT(aListType == nsIUrlClassifierFeature::entitylist); 220 221 *aURIType = nsIUrlClassifierFeature::pairwiseEntitylistURI; 222 return UrlClassifierCommon::CreatePairwiseEntityListURI(aChannel, aURI); 223 } 224 225 } // namespace net 226 } // namespace mozilla