From 8a0d0f80e01a21da7446e2ea25fbe7a481e2f4d8 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 26 Feb 2019 18:51:14 -0500 Subject: [PATCH] Bug 1525458 - Part 1: Only emit the loaded events for various content blocking categories in the presence of an allow-list entry for the top-level document when content would have been blocked otherwise; r=baku,dimi Previously the code here used to emit the loaded events for every resource examined by the URL Classifier Features (in other words, every third party resource). But we only need to emit the events in cases where without the presence of the allow-list we would have blocked the content. Differential Revision: https://phabricator.services.mozilla.com/D20874 --- .../url-classifier/UrlClassifierCommon.cpp | 98 +++---------------- netwerk/url-classifier/UrlClassifierCommon.h | 4 +- .../UrlClassifierFeatureBase.cpp | 60 ++++++++++++ .../url-classifier/UrlClassifierFeatureBase.h | 5 + .../UrlClassifierFeatureCryptomining.cpp | 44 ++++++--- .../UrlClassifierFeatureFingerprinting.cpp | 45 ++++++--- ...UrlClassifierFeatureTrackingAnnotation.cpp | 15 +-- ...UrlClassifierFeatureTrackingProtection.cpp | 32 +++--- 8 files changed, 167 insertions(+), 136 deletions(-) diff --git a/netwerk/url-classifier/UrlClassifierCommon.cpp b/netwerk/url-classifier/UrlClassifierCommon.cpp index 3a67e5380dd6..dae8e92c4716 100644 --- a/netwerk/url-classifier/UrlClassifierCommon.cpp +++ b/netwerk/url-classifier/UrlClassifierCommon.cpp @@ -88,19 +88,8 @@ UrlClassifierCommon::NotifyChannelClassifierProtectionDisabled( } /* static */ bool UrlClassifierCommon::ShouldEnableClassifier( - nsIChannel* aChannel, - AntiTrackingCommon::ContentBlockingAllowListPurpose aBlockingPurpose) { + nsIChannel* aChannel) { MOZ_ASSERT(aChannel); - MOZ_ASSERT(aBlockingPurpose == AntiTrackingCommon::eTrackingProtection || - aBlockingPurpose == AntiTrackingCommon::eTrackingAnnotations || - aBlockingPurpose == AntiTrackingCommon::eFingerprinting || - aBlockingPurpose == AntiTrackingCommon::eCryptomining); - - nsCOMPtr channel = do_QueryInterface(aChannel); - if (!channel) { - UC_LOG(("nsChannelClassifier: Not an HTTP channel")); - return false; - } nsCOMPtr chanURI; nsresult rv = aChannel->GetURI(getter_AddRefs(chanURI)); @@ -112,86 +101,31 @@ UrlClassifierCommon::NotifyChannelClassifierProtectionDisabled( return false; } - nsCOMPtr ios = services::GetIOService(); - if (NS_WARN_IF(!ios)) { - return false; - } - - nsCOMPtr topWinURI; - rv = channel->GetTopWindowURI(getter_AddRefs(topWinURI)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return false; - } - - if (!topWinURI && StaticPrefs::channelclassifier_allowlist_example()) { - UC_LOG(("nsChannelClassifier: Allowlisting test domain")); - rv = ios->NewURI(NS_LITERAL_CSTRING("http://allowlisted.example.com"), - nullptr, nullptr, getter_AddRefs(topWinURI)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return false; - } - } - - bool isAllowListed; - rv = AntiTrackingCommon::IsOnContentBlockingAllowList( - topWinURI, NS_UsePrivateBrowsing(aChannel), aBlockingPurpose, - isAllowListed); - if (NS_FAILED(rv)) { // normal for some loads, no need to print a warning - return false; - } - - if (isAllowListed) { - if (UC_LOG_ENABLED()) { - nsCString chanSpec = chanURI->GetSpecOrDefault(); - chanSpec.Truncate( - std::min(chanSpec.Length(), UrlClassifierCommon::sMaxSpecLength)); - UC_LOG(("nsChannelClassifier: User override on channel[%p] (%s)", - aChannel, chanSpec.get())); - } - - // Channel classifier protection will be disabled so update the security - // state of the document and fire a secure change event. If we can't get the - // window for the channel, then the shield won't show up so we can't send an - // event to the securityUI anyway. - - uint32_t event = 0; - switch (aBlockingPurpose) { - case AntiTrackingCommon::eTrackingProtection: - MOZ_FALLTHROUGH; - case AntiTrackingCommon::eTrackingAnnotations: - event = nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT; - break; - - case AntiTrackingCommon::eFingerprinting: - event = nsIWebProgressListener::STATE_LOADED_FINGERPRINTING_CONTENT; - break; - - case AntiTrackingCommon::eCryptomining: - event = nsIWebProgressListener::STATE_LOADED_CRYPTOMINING_CONTENT; - break; - - default: - MOZ_CRASH("Invalidate blocking purpose."); - } - - UrlClassifierCommon::NotifyChannelClassifierProtectionDisabled(aChannel, - event); - - return false; - } - // Tracking protection will be enabled so return without updating // the security state. If any channels are subsequently cancelled // (page elements blocked) the state will be then updated. if (UC_LOG_ENABLED()) { + nsCOMPtr topWinURI; + nsCOMPtr channel = do_QueryInterface(aChannel); + if (!channel) { + UC_LOG(("nsChannelClassifier: Not an HTTP channel")); + return false; + } + + nsresult rv = channel->GetTopWindowURI(getter_AddRefs(topWinURI)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + nsCString chanSpec = chanURI->GetSpecOrDefault(); chanSpec.Truncate( std::min(chanSpec.Length(), UrlClassifierCommon::sMaxSpecLength)); - nsCString topWinSpec = topWinURI->GetSpecOrDefault(); + nsCString topWinSpec = topWinURI ? topWinURI->GetSpecOrDefault() + : NS_LITERAL_CSTRING("(null)"); topWinSpec.Truncate( std::min(topWinSpec.Length(), UrlClassifierCommon::sMaxSpecLength)); UC_LOG( - ("nsChannelClassifier: Enabling tracking protection checks on " + ("nsChannelClassifier: Enabling url classifier checks on " "channel[%p] with uri %s for toplevel window uri %s", aChannel, chanSpec.get(), topWinSpec.get())); } diff --git a/netwerk/url-classifier/UrlClassifierCommon.h b/netwerk/url-classifier/UrlClassifierCommon.h index 74188156043f..bcd4b3b74883 100644 --- a/netwerk/url-classifier/UrlClassifierCommon.h +++ b/netwerk/url-classifier/UrlClassifierCommon.h @@ -30,9 +30,7 @@ class UrlClassifierCommon final { static void NotifyChannelClassifierProtectionDisabled( nsIChannel* aChannel, uint32_t aAcceptedReason); - static bool ShouldEnableClassifier( - nsIChannel* aChannel, - AntiTrackingCommon::ContentBlockingAllowListPurpose aBlockingPurpose); + static bool ShouldEnableClassifier(nsIChannel* aChannel); static nsresult SetBlockedContent(nsIChannel* channel, nsresult aErrorCode, const nsACString& aList, diff --git a/netwerk/url-classifier/UrlClassifierFeatureBase.cpp b/netwerk/url-classifier/UrlClassifierFeatureBase.cpp index 914f3753fcaf..ec83f437caee 100644 --- a/netwerk/url-classifier/UrlClassifierFeatureBase.cpp +++ b/netwerk/url-classifier/UrlClassifierFeatureBase.cpp @@ -159,5 +159,65 @@ UrlClassifierFeatureBase::GetSkipHostList(nsACString& aList) { return NS_OK; } +bool UrlClassifierFeatureBase::IsAllowListed( + nsIChannel* aChannel, + AntiTrackingCommon::ContentBlockingAllowListPurpose aPurpose) { + MOZ_ASSERT(aPurpose == AntiTrackingCommon::eTrackingProtection || + aPurpose == AntiTrackingCommon::eTrackingAnnotations || + aPurpose == AntiTrackingCommon::eFingerprinting || + aPurpose == AntiTrackingCommon::eCryptomining); + + nsCOMPtr channel = do_QueryInterface(aChannel); + if (!channel) { + UC_LOG(("nsChannelClassifier: Not an HTTP channel")); + return false; + } + + nsCOMPtr topWinURI; + nsresult rv = channel->GetTopWindowURI(getter_AddRefs(topWinURI)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + + if (!topWinURI && StaticPrefs::channelclassifier_allowlist_example()) { + UC_LOG(("nsChannelClassifier: Allowlisting test domain")); + nsCOMPtr ios = services::GetIOService(); + if (NS_WARN_IF(!ios)) { + return false; + } + + rv = ios->NewURI(NS_LITERAL_CSTRING("http://allowlisted.example.com"), + nullptr, nullptr, getter_AddRefs(topWinURI)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + } + + bool isAllowListed = false; + rv = AntiTrackingCommon::IsOnContentBlockingAllowList( + topWinURI, NS_UsePrivateBrowsing(aChannel), aPurpose, isAllowListed); + if (NS_FAILED(rv)) { // normal for some loads, no need to print a warning + return false; + } + + if (isAllowListed) { + if (UC_LOG_ENABLED()) { + nsCOMPtr chanURI; + nsresult rv = aChannel->GetURI(getter_AddRefs(chanURI)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return isAllowListed; + } + + nsCString chanSpec = chanURI->GetSpecOrDefault(); + chanSpec.Truncate( + std::min(chanSpec.Length(), UrlClassifierCommon::sMaxSpecLength)); + UC_LOG(("nsChannelClassifier: User override on channel[%p] (%s)", + aChannel, chanSpec.get())); + } + } + + return isAllowListed; +} + } // namespace net } // namespace mozilla diff --git a/netwerk/url-classifier/UrlClassifierFeatureBase.h b/netwerk/url-classifier/UrlClassifierFeatureBase.h index 79b35bf6daf0..176c6ca9d285 100644 --- a/netwerk/url-classifier/UrlClassifierFeatureBase.h +++ b/netwerk/url-classifier/UrlClassifierFeatureBase.h @@ -10,6 +10,7 @@ #include "nsIUrlClassifierFeature.h" #include "nsTArray.h" #include "nsString.h" +#include "mozilla/AntiTrackingCommon.h" namespace mozilla { namespace net { @@ -52,6 +53,10 @@ class UrlClassifierFeatureBase : public nsIUrlClassifierFeature { void InitializePreferences(); void ShutdownPreferences(); + bool IsAllowListed( + nsIChannel* aChannel, + AntiTrackingCommon::ContentBlockingAllowListPurpose aPurpose); + private: nsCString mName; diff --git a/netwerk/url-classifier/UrlClassifierFeatureCryptomining.cpp b/netwerk/url-classifier/UrlClassifierFeatureCryptomining.cpp index dbe4d5d73939..b4fbbe881986 100644 --- a/netwerk/url-classifier/UrlClassifierFeatureCryptomining.cpp +++ b/netwerk/url-classifier/UrlClassifierFeatureCryptomining.cpp @@ -101,8 +101,7 @@ UrlClassifierFeatureCryptomining::MaybeCreate(nsIChannel* aChannel) { return nullptr; } - if (!UrlClassifierCommon::ShouldEnableClassifier( - aChannel, AntiTrackingCommon::eCryptomining)) { + if (!UrlClassifierCommon::ShouldEnableClassifier(aChannel)) { return nullptr; } @@ -133,22 +132,37 @@ UrlClassifierFeatureCryptomining::ProcessChannel(nsIChannel* aChannel, NS_ENSURE_ARG_POINTER(aChannel); NS_ENSURE_ARG_POINTER(aShouldContinue); + bool isAllowListed = + IsAllowListed(aChannel, AntiTrackingCommon::eCryptomining); + // This is a blocking feature. - *aShouldContinue = false; + *aShouldContinue = isAllowListed; - UrlClassifierCommon::SetBlockedContent(aChannel, NS_ERROR_CRYPTOMINING_URI, - aList, EmptyCString(), EmptyCString()); - - UC_LOG( - ("UrlClassifierFeatureCryptomining::ProcessChannel, cancelling " - "channel[%p]", - aChannel)); - nsCOMPtr httpChannel = do_QueryInterface(aChannel); - - if (httpChannel) { - Unused << httpChannel->CancelByChannelClassifier(NS_ERROR_CRYPTOMINING_URI); + if (isAllowListed) { + // Even with cryptomining blocking disabled, we still want to show the user + // that there are unblocked cryptominers on the site, so notify the UI that + // we loaded cryptomining content. UI code can treat this notification + // differently depending on whether cryptomining blocking is enabled or + // disabled. + UrlClassifierCommon::NotifyChannelClassifierProtectionDisabled( + aChannel, nsIWebProgressListener::STATE_LOADED_CRYPTOMINING_CONTENT); } else { - Unused << aChannel->Cancel(NS_ERROR_CRYPTOMINING_URI); + UrlClassifierCommon::SetBlockedContent(aChannel, NS_ERROR_CRYPTOMINING_URI, + aList, EmptyCString(), + EmptyCString()); + + UC_LOG( + ("UrlClassifierFeatureCryptomining::ProcessChannel, cancelling " + "channel[%p]", + aChannel)); + nsCOMPtr httpChannel = do_QueryInterface(aChannel); + + if (httpChannel) { + Unused << httpChannel->CancelByChannelClassifier( + NS_ERROR_CRYPTOMINING_URI); + } else { + Unused << aChannel->Cancel(NS_ERROR_CRYPTOMINING_URI); + } } return NS_OK; diff --git a/netwerk/url-classifier/UrlClassifierFeatureFingerprinting.cpp b/netwerk/url-classifier/UrlClassifierFeatureFingerprinting.cpp index 490d71df0347..e90ff036db3e 100644 --- a/netwerk/url-classifier/UrlClassifierFeatureFingerprinting.cpp +++ b/netwerk/url-classifier/UrlClassifierFeatureFingerprinting.cpp @@ -103,8 +103,7 @@ UrlClassifierFeatureFingerprinting::MaybeCreate(nsIChannel* aChannel) { return nullptr; } - if (!UrlClassifierCommon::ShouldEnableClassifier( - aChannel, AntiTrackingCommon::eFingerprinting)) { + if (!UrlClassifierCommon::ShouldEnableClassifier(aChannel)) { return nullptr; } @@ -135,23 +134,37 @@ UrlClassifierFeatureFingerprinting::ProcessChannel(nsIChannel* aChannel, NS_ENSURE_ARG_POINTER(aChannel); NS_ENSURE_ARG_POINTER(aShouldContinue); + bool isAllowListed = + IsAllowListed(aChannel, AntiTrackingCommon::eFingerprinting); + // This is a blocking feature. - *aShouldContinue = false; + *aShouldContinue = isAllowListed; - UrlClassifierCommon::SetBlockedContent(aChannel, NS_ERROR_FINGERPRINTING_URI, - aList, EmptyCString(), EmptyCString()); - - UC_LOG( - ("UrlClassifierFeatureFingerprinting::ProcessChannel, cancelling " - "channel[%p]", - aChannel)); - nsCOMPtr httpChannel = do_QueryInterface(aChannel); - - if (httpChannel) { - Unused << httpChannel->CancelByChannelClassifier( - NS_ERROR_FINGERPRINTING_URI); + if (isAllowListed) { + // Even with fingerprinting blocking disabled, we still want to show the + // user that there are unblocked trackers on the site, so notify the UI that + // we loaded tracking content. UI code can treat this notification + // differently depending on whether fingerprinting blocking is enabled or + // not. + UrlClassifierCommon::NotifyChannelClassifierProtectionDisabled( + aChannel, nsIWebProgressListener::STATE_LOADED_FINGERPRINTING_CONTENT); } else { - Unused << aChannel->Cancel(NS_ERROR_FINGERPRINTING_URI); + UrlClassifierCommon::SetBlockedContent(aChannel, + NS_ERROR_FINGERPRINTING_URI, aList, + EmptyCString(), EmptyCString()); + + UC_LOG( + ("UrlClassifierFeatureFingerprinting::ProcessChannel, cancelling " + "channel[%p]", + aChannel)); + nsCOMPtr httpChannel = do_QueryInterface(aChannel); + + if (httpChannel) { + Unused << httpChannel->CancelByChannelClassifier( + NS_ERROR_FINGERPRINTING_URI); + } else { + Unused << aChannel->Cancel(NS_ERROR_FINGERPRINTING_URI); + } } return NS_OK; diff --git a/netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.cpp b/netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.cpp index 8d84f6ea8f3d..5a981da81954 100644 --- a/netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.cpp +++ b/netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.cpp @@ -154,8 +154,7 @@ UrlClassifierFeatureTrackingAnnotation::MaybeCreate(nsIChannel* aChannel) { return nullptr; } - if (!UrlClassifierCommon::ShouldEnableClassifier( - aChannel, AntiTrackingCommon::eTrackingAnnotations)) { + if (!UrlClassifierCommon::ShouldEnableClassifier(aChannel)) { return nullptr; } @@ -205,6 +204,9 @@ UrlClassifierFeatureTrackingAnnotation::ProcessChannel(nsIChannel* aChannel, bool isThirdPartyWithTopLevelWinURI = nsContentUtils::IsThirdPartyWindowOrChannel(nullptr, aChannel, chanURI); + bool isAllowListed = + IsAllowListed(aChannel, AntiTrackingCommon::eTrackingAnnotations); + UC_LOG( ("UrlClassifierFeatureTrackingAnnotation::ProcessChannel, annotating " "channel[%p]", @@ -212,17 +214,18 @@ UrlClassifierFeatureTrackingAnnotation::ProcessChannel(nsIChannel* aChannel, SetIsTrackingResourceHelper(aChannel, isThirdPartyWithTopLevelWinURI); - if (isThirdPartyWithTopLevelWinURI) { + if (isThirdPartyWithTopLevelWinURI || isAllowListed) { // Even with TP disabled, we still want to show the user that there // are unblocked trackers on the site, so notify the UI that we loaded // tracking content. UI code can treat this notification differently // depending on whether TP is enabled or disabled. UrlClassifierCommon::NotifyChannelClassifierProtectionDisabled( aChannel, nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT); + } - if (StaticPrefs::privacy_trackingprotection_lower_network_priority()) { - LowerPriorityHelper(aChannel); - } + if (isThirdPartyWithTopLevelWinURI && + StaticPrefs::privacy_trackingprotection_lower_network_priority()) { + LowerPriorityHelper(aChannel); } return NS_OK; diff --git a/netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.cpp b/netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.cpp index 4bf9b6f06d16..5c0f6bda982a 100644 --- a/netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.cpp +++ b/netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.cpp @@ -101,8 +101,7 @@ UrlClassifierFeatureTrackingProtection::MaybeCreate(nsIChannel* aChannel) { return nullptr; } - if (!UrlClassifierCommon::ShouldEnableClassifier( - aChannel, AntiTrackingCommon::eTrackingProtection)) { + if (!UrlClassifierCommon::ShouldEnableClassifier(aChannel)) { return nullptr; } @@ -136,21 +135,26 @@ UrlClassifierFeatureTrackingProtection::ProcessChannel(nsIChannel* aChannel, NS_ENSURE_ARG_POINTER(aChannel); NS_ENSURE_ARG_POINTER(aShouldContinue); + bool isAllowListed = + IsAllowListed(aChannel, AntiTrackingCommon::eTrackingProtection); + // This is a blocking feature. - *aShouldContinue = false; + *aShouldContinue = isAllowListed; - UrlClassifierCommon::SetBlockedContent(aChannel, NS_ERROR_TRACKING_URI, aList, - EmptyCString(), EmptyCString()); + if (!isAllowListed) { + UrlClassifierCommon::SetBlockedContent( + aChannel, NS_ERROR_TRACKING_URI, aList, EmptyCString(), EmptyCString()); - UC_LOG( - ("UrlClassifierFeatureTrackingProtection::ProcessChannel, cancelling " - "channel[%p]", - aChannel)); - nsCOMPtr httpChannel = do_QueryInterface(aChannel); - if (httpChannel) { - Unused << httpChannel->CancelByChannelClassifier(NS_ERROR_TRACKING_URI); - } else { - Unused << aChannel->Cancel(NS_ERROR_TRACKING_URI); + UC_LOG( + ("UrlClassifierFeatureTrackingProtection::ProcessChannel, cancelling " + "channel[%p]", + aChannel)); + nsCOMPtr httpChannel = do_QueryInterface(aChannel); + if (httpChannel) { + Unused << httpChannel->CancelByChannelClassifier(NS_ERROR_TRACKING_URI); + } else { + Unused << aChannel->Cancel(NS_ERROR_TRACKING_URI); + } } return NS_OK;