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