From 69926deea650e8148cbd62a402c06406aa49abb5 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 14 Dec 2018 12:40:16 +0100 Subject: [PATCH] Bug 1511436 - Cleanup URL-Classifier code - part 1 - nsIUrlClassifierFeature, r=dimi --HG-- rename : netwerk/base/nsChannelClassifier.cpp => netwerk/url-classifier/nsChannelClassifier.cpp rename : netwerk/base/nsChannelClassifier.h => netwerk/url-classifier/nsChannelClassifier.h rename : netwerk/base/nsIURIClassifier.idl => netwerk/url-classifier/nsIURIClassifier.idl --- layout/build/nsLayoutStatics.cpp | 5 + netwerk/base/moz.build | 2 - netwerk/moz.build | 1 + netwerk/protocol/http/HttpChannelChild.cpp | 9 +- .../url-classifier/UrlClassifierCommon.cpp | 177 ++++++++++++++++++ netwerk/url-classifier/UrlClassifierCommon.h | 44 +++++ .../UrlClassifierFeatureBase.cpp | 163 ++++++++++++++++ .../url-classifier/UrlClassifierFeatureBase.h | 56 ++++++ .../UrlClassifierFeatureFactory.cpp | 65 +++++++ .../UrlClassifierFeatureFactory.h | 33 ++++ .../UrlClassifierFeatureResult.cpp | 41 ++++ .../UrlClassifierFeatureResult.h | 40 ++++ ...UrlClassifierFeatureTrackingAnnotation.cpp | 85 +++++++++ .../UrlClassifierFeatureTrackingAnnotation.h | 34 ++++ ...UrlClassifierFeatureTrackingProtection.cpp | 107 +++++++++++ .../UrlClassifierFeatureTrackingProtection.h | 34 ++++ netwerk/url-classifier/moz.build | 42 +++++ .../nsChannelClassifier.cpp | 104 +++------- .../nsChannelClassifier.h | 5 - .../nsIURIClassifier.idl | 13 ++ .../nsIUrlClassifierFeature.idl | 84 +++++++++ .../nsUrlClassifierDBService.cpp | 9 + .../url-classifier/nsUrlClassifierProxies.cpp | 1 + .../url-classifier/nsUrlClassifierUtils.cpp | 21 ++- .../url-classifier/nsUrlClassifierUtils.h | 2 + toolkit/content/aboutUrlClassifier.js | 1 + 26 files changed, 1091 insertions(+), 87 deletions(-) create mode 100644 netwerk/url-classifier/UrlClassifierCommon.cpp create mode 100644 netwerk/url-classifier/UrlClassifierCommon.h create mode 100644 netwerk/url-classifier/UrlClassifierFeatureBase.cpp create mode 100644 netwerk/url-classifier/UrlClassifierFeatureBase.h create mode 100644 netwerk/url-classifier/UrlClassifierFeatureFactory.cpp create mode 100644 netwerk/url-classifier/UrlClassifierFeatureFactory.h create mode 100644 netwerk/url-classifier/UrlClassifierFeatureResult.cpp create mode 100644 netwerk/url-classifier/UrlClassifierFeatureResult.h create mode 100644 netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.cpp create mode 100644 netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.h create mode 100644 netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.cpp create mode 100644 netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.h create mode 100644 netwerk/url-classifier/moz.build rename netwerk/{base => url-classifier}/nsChannelClassifier.cpp (94%) rename netwerk/{base => url-classifier}/nsChannelClassifier.h (94%) rename netwerk/{base => url-classifier}/nsIURIClassifier.idl (89%) create mode 100644 netwerk/url-classifier/nsIUrlClassifierFeature.idl diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index e9f61ec433d7..0b803c85e2a1 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -115,6 +115,7 @@ #include "mozilla/dom/RemoteWorkerService.h" #include "mozilla/dom/BlobURLProtocolHandler.h" #include "mozilla/dom/ReportingHeader.h" +#include "mozilla/net/UrlClassifierFeatureFactory.h" #include "nsThreadManager.h" #include "mozilla/css/ImageLoader.h" @@ -292,6 +293,8 @@ nsresult nsLayoutStatics::Initialize() { // Reporting API. ReportingHeader::Initialize(); + mozilla::net::UrlClassifierFeatureFactory::Initialize(); + return NS_OK; } @@ -397,4 +400,6 @@ void nsLayoutStatics::Shutdown() { BlobURLProtocolHandler::RemoveDataEntries(); css::ImageLoader::Shutdown(); + + mozilla::net::UrlClassifierFeatureFactory::Shutdown(); } diff --git a/netwerk/base/moz.build b/netwerk/base/moz.build index ac62afc706ed..54f79a8053f4 100644 --- a/netwerk/base/moz.build +++ b/netwerk/base/moz.build @@ -123,7 +123,6 @@ XPIDL_SOURCES += [ 'nsIUploadChannel.idl', 'nsIUploadChannel2.idl', 'nsIURI.idl', - 'nsIURIClassifier.idl', 'nsIURIMutator.idl', 'nsIURIWithSpecialOrigin.idl', 'nsIURL.idl', @@ -203,7 +202,6 @@ UNIFIED_SOURCES += [ 'nsBaseChannel.cpp', 'nsBaseContentStream.cpp', 'nsBufferedStreams.cpp', - 'nsChannelClassifier.cpp', 'nsDirectoryIndexStream.cpp', 'nsDNSPrefetch.cpp', 'nsDownloader.cpp', diff --git a/netwerk/moz.build b/netwerk/moz.build index 5505a4ccd030..c0e762088959 100644 --- a/netwerk/moz.build +++ b/netwerk/moz.build @@ -19,6 +19,7 @@ DIRS += [ 'protocol', 'system', 'ipc', + 'url-classifier' ] if CONFIG['MOZ_SRTP']: diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp index be555e09fd4c..9b4821442214 100644 --- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -22,6 +22,7 @@ #include "mozilla/ipc/IPCStreamUtils.h" #include "mozilla/net/NeckoChild.h" #include "mozilla/net/HttpChannelChild.h" +#include "mozilla/net/UrlClassifierCommon.h" #include "AltDataOutputStreamChild.h" #include "CookieServiceChild.h" @@ -1809,9 +1810,9 @@ void HttpChannelChild::ProcessNotifyTrackingProtectionDisabled() { nsCOMPtr neckoTarget = GetNeckoTarget(); neckoTarget->Dispatch( NS_NewRunnableFunction( - "nsChannelClassifier::NotifyTrackingProtectionDisabled", + "UrlClassifierCommon::NotifyTrackingProtectionDisabled", [self]() { - nsChannelClassifier::NotifyTrackingProtectionDisabled(self); + UrlClassifierCommon::NotifyTrackingProtectionDisabled(self); }), NS_DISPATCH_NORMAL); } @@ -1824,7 +1825,7 @@ void HttpChannelChild::ProcessNotifyCookieAllowed() { nsCOMPtr neckoTarget = GetNeckoTarget(); neckoTarget->Dispatch( NS_NewRunnableFunction( - "nsChannelClassifier::NotifyBlockingDecision", + "UrlClassifierCommon::NotifyBlockingDecision", [self]() { AntiTrackingCommon::NotifyBlockingDecision( self, AntiTrackingCommon::BlockingDecision::eAllow, 0); @@ -1841,7 +1842,7 @@ void HttpChannelChild::ProcessNotifyTrackingCookieBlocked( RefPtr self = this; nsCOMPtr neckoTarget = GetNeckoTarget(); neckoTarget->Dispatch( - NS_NewRunnableFunction("nsChannelClassifier::NotifyTrackingCookieBlocked", + NS_NewRunnableFunction("AntiTrackingCommon::NotifyBlockingDecision", [self, aRejectedReason]() { AntiTrackingCommon::NotifyBlockingDecision( self, diff --git a/netwerk/url-classifier/UrlClassifierCommon.cpp b/netwerk/url-classifier/UrlClassifierCommon.cpp new file mode 100644 index 000000000000..2d999011726f --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierCommon.cpp @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/net/UrlClassifierCommon.h" + +#include "mozilla/BasePrincipal.h" +#include "mozilla/StaticPrefs.h" +#include "mozIThirdPartyUtil.h" +#include "nsIChannel.h" +#include "nsIDocument.h" +#include "nsIDocShell.h" +#include "nsIHttpChannel.h" +#include "nsIHttpChannelInternal.h" +#include "nsIParentChannel.h" +#include "nsIWebProgressListener.h" +#include "nsNetUtil.h" + +namespace mozilla { +namespace net { + +const nsCString::size_type UrlClassifierCommon::sMaxSpecLength = 128; + +// MOZ_LOG=nsChannelClassifier:5 +LazyLogModule UrlClassifierCommon::sLog("nsChannelClassifier"); + +/* static */ bool UrlClassifierCommon::AddonMayLoad(nsIChannel* aChannel, + nsIURI* aURI) { + nsCOMPtr channelLoadInfo = aChannel->GetLoadInfo(); + if (!channelLoadInfo) { + return false; + } + + // loadingPrincipal is used here to ensure we are loading into an + // addon principal. This allows an addon, with explicit permission, to + // call out to API endpoints that may otherwise get blocked. + nsIPrincipal* loadingPrincipal = channelLoadInfo->LoadingPrincipal(); + if (!loadingPrincipal) { + return false; + } + + return BasePrincipal::Cast(loadingPrincipal)->AddonAllowsLoad(aURI, true); +} + +/* static */ void UrlClassifierCommon::NotifyTrackingProtectionDisabled( + nsIChannel* aChannel) { + // Can be called in EITHER the parent or child process. + nsCOMPtr parentChannel; + NS_QueryNotificationCallbacks(aChannel, parentChannel); + if (parentChannel) { + // This channel is a parent-process proxy for a child process request. + // Tell the child process channel to do this instead. + parentChannel->NotifyTrackingProtectionDisabled(); + return; + } + + NotifyChannelBlocked(aChannel, + nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT); +} + +/* static */ void UrlClassifierCommon::NotifyChannelBlocked( + nsIChannel* aChannel, unsigned aBlockedReason) { + nsCOMPtr thirdPartyUtil = services::GetThirdPartyUtil(); + if (NS_WARN_IF(!thirdPartyUtil)) { + return; + } + + nsCOMPtr win; + nsresult rv = + thirdPartyUtil->GetTopWindowForChannel(aChannel, getter_AddRefs(win)); + NS_ENSURE_SUCCESS_VOID(rv); + auto* pwin = nsPIDOMWindowOuter::From(win); + nsCOMPtr docShell = pwin->GetDocShell(); + if (!docShell) { + return; + } + nsCOMPtr doc = docShell->GetDocument(); + NS_ENSURE_TRUE_VOID(doc); + + nsCOMPtr uri; + aChannel->GetURI(getter_AddRefs(uri)); + pwin->NotifyContentBlockingState(aBlockedReason, aChannel, true, uri); +} + +/* static */ bool +UrlClassifierCommon::ShouldEnableTrackingProtectionOrAnnotation( + nsIChannel* aChannel, + AntiTrackingCommon::ContentBlockingAllowListPurpose aBlockingPurpose) { + MOZ_ASSERT(aChannel); + MOZ_ASSERT(aBlockingPurpose == AntiTrackingCommon::eTrackingProtection || + aBlockingPurpose == AntiTrackingCommon::eTrackingAnnotations); + + 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)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + + if (UrlClassifierCommon::AddonMayLoad(aChannel, chanURI)) { + 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())); + } + + // Tracking 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. + UrlClassifierCommon::NotifyTrackingProtectionDisabled(aChannel); + + 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()) { + nsCString chanSpec = chanURI->GetSpecOrDefault(); + chanSpec.Truncate( + std::min(chanSpec.Length(), UrlClassifierCommon::sMaxSpecLength)); + nsCString topWinSpec = topWinURI->GetSpecOrDefault(); + topWinSpec.Truncate( + std::min(topWinSpec.Length(), UrlClassifierCommon::sMaxSpecLength)); + UC_LOG( + ("nsChannelClassifier: Enabling tracking protection checks on " + "channel[%p] with uri %s for toplevel window uri %s", + aChannel, chanSpec.get(), topWinSpec.get())); + } + + return true; +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/url-classifier/UrlClassifierCommon.h b/netwerk/url-classifier/UrlClassifierCommon.h new file mode 100644 index 000000000000..1cfd99d0aadd --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierCommon.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_net_UrlClassifierCommon_h +#define mozilla_net_UrlClassifierCommon_h + +#include "nsString.h" +#include "mozilla/AntiTrackingCommon.h" + +class nsIChannel; +class nsIURI; + +#define UC_LOG(args) MOZ_LOG(UrlClassifierCommon::sLog, LogLevel::Info, args) +#define UC_LOG_ENABLED() MOZ_LOG_TEST(UrlClassifierCommon::sLog, LogLevel::Info) + +namespace mozilla { +namespace net { + +class UrlClassifierCommon final { + public: + static const nsCString::size_type sMaxSpecLength; + + static LazyLogModule sLog; + + static bool AddonMayLoad(nsIChannel* aChannel, nsIURI* aURI); + + static void NotifyTrackingProtectionDisabled(nsIChannel* aChannel); + + // aBlockedReason must be one of the nsIWebProgressListener state. + static void NotifyChannelBlocked(nsIChannel* aChannel, + unsigned aBlockedReason); + + static bool ShouldEnableTrackingProtectionOrAnnotation( + nsIChannel* aChannel, + AntiTrackingCommon::ContentBlockingAllowListPurpose aBlockingPurpose); +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_UrlClassifierCommon_h diff --git a/netwerk/url-classifier/UrlClassifierFeatureBase.cpp b/netwerk/url-classifier/UrlClassifierFeatureBase.cpp new file mode 100644 index 000000000000..914f3753fcaf --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureBase.cpp @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "UrlClassifierFeatureBase.h" +#include "Classifier.h" +#include "mozilla/Preferences.h" + +namespace mozilla { + +using namespace safebrowsing; + +namespace net { + +namespace { + +void OnPrefsChange(const char* aPrefName, nsTArray* aArray) { + MOZ_ASSERT(aArray); + + nsAutoCString value; + Preferences::GetCString(aPrefName, value); + Classifier::SplitTables(value, *aArray); +} + +void OnPrefSkipChange(const char* aPrefName, nsCString* aValue) { + MOZ_ASSERT(aValue); + + Preferences::GetCString(aPrefName, *aValue); +} + +} // namespace + +NS_INTERFACE_MAP_BEGIN(UrlClassifierFeatureBase) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIUrlClassifierFeature) + NS_INTERFACE_MAP_ENTRY(nsIUrlClassifierFeature) +NS_INTERFACE_MAP_END + +NS_IMPL_ADDREF(UrlClassifierFeatureBase) +NS_IMPL_RELEASE(UrlClassifierFeatureBase) + +UrlClassifierFeatureBase::UrlClassifierFeatureBase( + const nsACString& aName, const nsACString& aPrefBlacklistTables, + const nsACString& aPrefWhitelistTables, + const nsACString& aPrefBlacklistHosts, + const nsACString& aPrefWhitelistHosts, + const nsACString& aPrefBlacklistTableName, + const nsACString& aPrefWhitelistTableName, const nsACString& aPrefSkipHosts) + : mName(aName), mPrefSkipHosts(aPrefSkipHosts) { + static_assert(nsIUrlClassifierFeature::blacklist == 0, + "nsIUrlClassifierFeature::blacklist must be 0"); + static_assert(nsIUrlClassifierFeature::whitelist == 1, + "nsIUrlClassifierFeature::whitelist must be 1"); + + mPrefTables[nsIUrlClassifierFeature::blacklist] = aPrefBlacklistTables; + mPrefTables[nsIUrlClassifierFeature::whitelist] = aPrefWhitelistTables; + + mPrefHosts[nsIUrlClassifierFeature::blacklist] = aPrefBlacklistHosts; + mPrefHosts[nsIUrlClassifierFeature::whitelist] = aPrefWhitelistHosts; + + mPrefTableNames[nsIUrlClassifierFeature::blacklist] = aPrefBlacklistTableName; + mPrefTableNames[nsIUrlClassifierFeature::whitelist] = aPrefWhitelistTableName; +} + +UrlClassifierFeatureBase::~UrlClassifierFeatureBase() = default; + +void UrlClassifierFeatureBase::InitializePreferences() { + for (uint32_t i = 0; i < 2; ++i) { + if (!mPrefTables[i].IsEmpty()) { + Preferences::RegisterCallbackAndCall(OnPrefsChange, mPrefTables[i], + &mTables[i]); + } + + if (!mPrefHosts[i].IsEmpty()) { + Preferences::RegisterCallbackAndCall(OnPrefsChange, mPrefHosts[i], + &mHosts[i]); + } + } + + if (!mPrefSkipHosts.IsEmpty()) { + Preferences::RegisterCallbackAndCall(OnPrefSkipChange, mPrefSkipHosts, + &mSkipHosts); + } +} + +void UrlClassifierFeatureBase::ShutdownPreferences() { + for (uint32_t i = 0; i < 2; ++i) { + if (!mPrefTables[i].IsEmpty()) { + Preferences::UnregisterCallback(OnPrefsChange, mPrefTables[i], + &mTables[i]); + } + + if (!mPrefHosts[i].IsEmpty()) { + Preferences::UnregisterCallback(OnPrefsChange, mPrefHosts[i], &mHosts[i]); + } + } + + if (!mPrefSkipHosts.IsEmpty()) { + Preferences::UnregisterCallback(OnPrefSkipChange, mPrefSkipHosts, + &mSkipHosts); + } +} + +NS_IMETHODIMP +UrlClassifierFeatureBase::GetName(nsACString& aName) { + aName = mName; + return NS_OK; +} + +NS_IMETHODIMP +UrlClassifierFeatureBase::GetTables(nsIUrlClassifierFeature::listType aListType, + nsTArray& aTables) { + if (aListType != nsIUrlClassifierFeature::blacklist && + aListType != nsIUrlClassifierFeature::whitelist) { + return NS_ERROR_INVALID_ARG; + } + + aTables = mTables[aListType]; + return NS_OK; +} + +NS_IMETHODIMP +UrlClassifierFeatureBase::HasTable(const nsACString& aTable, + nsIUrlClassifierFeature::listType aListType, + bool* aResult) { + NS_ENSURE_ARG_POINTER(aResult); + + if (aListType != nsIUrlClassifierFeature::blacklist && + aListType != nsIUrlClassifierFeature::whitelist) { + return NS_ERROR_INVALID_ARG; + } + + *aResult = mTables[aListType].Contains(aTable); + return NS_OK; +} + +NS_IMETHODIMP +UrlClassifierFeatureBase::HasHostInPreferences( + const nsACString& aHost, nsIUrlClassifierFeature::listType aListType, + nsACString& aPrefTableName, bool* aResult) { + NS_ENSURE_ARG_POINTER(aResult); + + if (aListType != nsIUrlClassifierFeature::blacklist && + aListType != nsIUrlClassifierFeature::whitelist) { + return NS_ERROR_INVALID_ARG; + } + + *aResult = mHosts[aListType].Contains(aHost); + if (*aResult) { + aPrefTableName = mPrefTableNames[aListType]; + } + return NS_OK; +} + +NS_IMETHODIMP +UrlClassifierFeatureBase::GetSkipHostList(nsACString& aList) { + aList = mSkipHosts; + return NS_OK; +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/url-classifier/UrlClassifierFeatureBase.h b/netwerk/url-classifier/UrlClassifierFeatureBase.h new file mode 100644 index 000000000000..1aa4c25bea38 --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureBase.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_net_UrlClassifierFeatureBase_h +#define mozilla_net_UrlClassifierFeatureBase_h + +#include "nsIUrlClassifierFeature.h" +#include "nsTArray.h" +#include "nsString.h" + +namespace mozilla { +namespace net { + +class UrlClassifierFeatureBase : public nsIUrlClassifierFeature { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIURLCLASSIFIERFEATURE + + protected: + UrlClassifierFeatureBase(const nsACString& aName, + const nsACString& aPrefBlacklistTables, + const nsACString& aPrefWhitelistTables, + const nsACString& aPrefBlacklistHosts, + const nsACString& aPrefWhitelistHosts, + const nsACString& aPrefBlacklistTableName, + const nsACString& aPrefWhitelistTableName, + const nsACString& aPrefSkipHosts); + + virtual ~UrlClassifierFeatureBase(); + + void InitializePreferences(); + void ShutdownPreferences(); + + private: + nsCString mName; + + nsCString mPrefSkipHosts; + + // 2: blacklist and whitelist. + nsCString mPrefTables[2]; + nsTArray mTables[2]; + + nsCString mPrefHosts[2]; + nsCString mPrefTableNames[2]; + nsTArray mHosts[2]; + + nsCString mSkipHosts; +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_UrlClassifierFeatureBase_h diff --git a/netwerk/url-classifier/UrlClassifierFeatureFactory.cpp b/netwerk/url-classifier/UrlClassifierFeatureFactory.cpp new file mode 100644 index 000000000000..edba62919fad --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureFactory.cpp @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/net/UrlClassifierFeatureFactory.h" + +// List of Features +#include "UrlClassifierFeatureTrackingProtection.h" +#include "UrlClassifierFeatureTrackingAnnotation.h" + +#include "nsAppRunner.h" + +namespace mozilla { +namespace net { + +/* static */ void UrlClassifierFeatureFactory::Initialize() { + // We want to expose Features only in the parent process. + if (!XRE_IsParentProcess()) { + return; + } + + UrlClassifierFeatureTrackingAnnotation::Initialize(); + UrlClassifierFeatureTrackingProtection::Initialize(); +} + +/* static */ void UrlClassifierFeatureFactory::Shutdown() { + // We want to expose Features only in the parent process. + if (!XRE_IsParentProcess()) { + return; + } + + UrlClassifierFeatureTrackingAnnotation::Shutdown(); + UrlClassifierFeatureTrackingProtection::Shutdown(); +} + +/* static */ void UrlClassifierFeatureFactory::GetFeaturesFromChannel( + nsIChannel* aChannel, + nsTArray>& aFeatures) { + MOZ_ASSERT(XRE_IsParentProcess()); + MOZ_ASSERT(aChannel); + + nsCOMPtr feature; + + // Note that the order of the features is extremely important! When more than + // 1 feature classifies the channel, we call ::ProcessChannel() following this + // feature order, and this could produce different results with a different + // feature ordering. + + // Tracking Protection + feature = UrlClassifierFeatureTrackingProtection::MaybeCreate(aChannel); + if (feature) { + aFeatures.AppendElement(feature); + } + + // Tracking Annotation + feature = UrlClassifierFeatureTrackingAnnotation::MaybeCreate(aChannel); + if (feature) { + aFeatures.AppendElement(feature); + } +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/url-classifier/UrlClassifierFeatureFactory.h b/netwerk/url-classifier/UrlClassifierFeatureFactory.h new file mode 100644 index 000000000000..59c95373fd11 --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureFactory.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_net_UrlClassifierFeatureFactory_h +#define mozilla_net_UrlClassifierFeatureFactory_h + +#include "nsCOMPtr.h" +#include "nsTArray.h" + +class nsIChannel; +class nsIUrlClassifierFeature; + +namespace mozilla { +namespace net { + +class UrlClassifierFeatureFactory final { + public: + static void Initialize(); + + static void Shutdown(); + + static void GetFeaturesFromChannel( + nsIChannel* aChannel, + nsTArray>& aFeatures); +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_UrlClassifierFeatureFactory_h diff --git a/netwerk/url-classifier/UrlClassifierFeatureResult.cpp b/netwerk/url-classifier/UrlClassifierFeatureResult.cpp new file mode 100644 index 000000000000..258d860c91fd --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureResult.cpp @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/net/UrlClassifierFeatureResult.h" + +namespace mozilla { +namespace net { + +UrlClassifierFeatureResult::UrlClassifierFeatureResult( + nsIUrlClassifierFeature* aFeature, const nsACString& aList) + : mFeature(aFeature), mList(aList) {} + +UrlClassifierFeatureResult::~UrlClassifierFeatureResult() = default; + +NS_IMETHODIMP +UrlClassifierFeatureResult::GetFeature(nsIUrlClassifierFeature** aFeature) { + NS_ENSURE_ARG_POINTER(aFeature); + nsCOMPtr feature = mFeature; + feature.forget(aFeature); + return NS_OK; +} + +NS_IMETHODIMP +UrlClassifierFeatureResult::GetList(nsACString& aList) { + aList = mList; + return NS_OK; +} + +NS_INTERFACE_MAP_BEGIN(UrlClassifierFeatureResult) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIUrlClassifierFeatureResult) + NS_INTERFACE_MAP_ENTRY(nsIUrlClassifierFeatureResult) +NS_INTERFACE_MAP_END + +NS_IMPL_ADDREF(UrlClassifierFeatureResult) +NS_IMPL_RELEASE(UrlClassifierFeatureResult) + +} // namespace net +} // namespace mozilla diff --git a/netwerk/url-classifier/UrlClassifierFeatureResult.h b/netwerk/url-classifier/UrlClassifierFeatureResult.h new file mode 100644 index 000000000000..b6cf942c56ad --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureResult.h @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_net_UrlClassifierFeatureResult_h +#define mozilla_net_UrlClassifierFeatureResult_h + +#include "nsIUrlClassifierFeature.h" +#include "nsString.h" + +namespace mozilla { +namespace net { + +class UrlClassifierFeatureResult final : public nsIUrlClassifierFeatureResult { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIURLCLASSIFIERFEATURERESULT + + UrlClassifierFeatureResult(nsIUrlClassifierFeature* aFeature, + const nsACString& aList); + + nsIUrlClassifierFeature* Feature() const { return mFeature; } + + // Comma separated list of tables. + const nsCString& List() const { return mList; } + + protected: + ~UrlClassifierFeatureResult(); + + private: + nsCOMPtr mFeature; + const nsCString mList; +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_UrlClassifierFeatureResult_h diff --git a/netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.cpp b/netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.cpp new file mode 100644 index 000000000000..025ba6c1ef17 --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.cpp @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "UrlClassifierFeatureTrackingAnnotation.h" + +#include "mozilla/AntiTrackingCommon.h" +#include "mozilla/Logging.h" +#include "mozilla/StaticPrefs.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/net/UrlClassifierCommon.h" + +namespace mozilla { +namespace net { + +namespace { + +#define URLCLASSIFIER_ANNOTATION_BLACKLIST \ + "urlclassifier.trackingAnnotationTable" +#define URLCLASSIFIER_ANNOTATION_BLACKLIST_TEST_ENTRIES \ + "urlclassifier.trackingAnnotationTable.testEntries" +#define URLCLASSIFIER_ANNOTATION_WHITELIST \ + "urlclassifier.trackingAnnotationWhitelistTable" +#define URLCLASSIFIER_ANNOTATION_WHITELIST_TEST_ENTRIES \ + "urlclassifier.trackingAnnotationWhitelistTable.testEntries" +#define TABLE_ANNOTATION_BLACKLIST_PREF "annotation-blacklist-pref" +#define TABLE_ANNOTATION_WHITELIST_PREF "annotation-whitelist-pref" + +StaticRefPtr gFeatureTrackingAnnotation; + +} // namespace + +UrlClassifierFeatureTrackingAnnotation::UrlClassifierFeatureTrackingAnnotation() + : UrlClassifierFeatureBase( + NS_LITERAL_CSTRING("tracking-annotation"), + NS_LITERAL_CSTRING(URLCLASSIFIER_ANNOTATION_BLACKLIST), + NS_LITERAL_CSTRING(URLCLASSIFIER_ANNOTATION_WHITELIST), + NS_LITERAL_CSTRING(URLCLASSIFIER_ANNOTATION_BLACKLIST_TEST_ENTRIES), + NS_LITERAL_CSTRING(URLCLASSIFIER_ANNOTATION_WHITELIST_TEST_ENTRIES), + NS_LITERAL_CSTRING(TABLE_ANNOTATION_BLACKLIST_PREF), + NS_LITERAL_CSTRING(TABLE_ANNOTATION_WHITELIST_PREF), EmptyCString()) { +} + +/* static */ void UrlClassifierFeatureTrackingAnnotation::Initialize() { + UC_LOG(("UrlClassifierFeatureTrackingAnnotation: Initializing")); + MOZ_ASSERT(!gFeatureTrackingAnnotation); + + gFeatureTrackingAnnotation = new UrlClassifierFeatureTrackingAnnotation(); + gFeatureTrackingAnnotation->InitializePreferences(); +} + +/* static */ void UrlClassifierFeatureTrackingAnnotation::Shutdown() { + UC_LOG(("UrlClassifierFeatureTrackingAnnotation: Shutdown")); + MOZ_ASSERT(gFeatureTrackingAnnotation); + + gFeatureTrackingAnnotation->ShutdownPreferences(); + gFeatureTrackingAnnotation = nullptr; +} + +/* static */ already_AddRefed +UrlClassifierFeatureTrackingAnnotation::MaybeCreate(nsIChannel* aChannel) { + MOZ_ASSERT(gFeatureTrackingAnnotation); + MOZ_ASSERT(aChannel); + + UC_LOG(("UrlClassifierFeatureTrackingAnnotation: MaybeCreate for channel %p", + aChannel)); + + if (!StaticPrefs::privacy_trackingprotection_annotate_channels()) { + return nullptr; + } + + if (!UrlClassifierCommon::ShouldEnableTrackingProtectionOrAnnotation( + aChannel, AntiTrackingCommon::eTrackingAnnotations)) { + return nullptr; + } + + RefPtr self = + gFeatureTrackingAnnotation; + return self.forget(); +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.h b/netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.h new file mode 100644 index 000000000000..d49de7f0675a --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureTrackingAnnotation.h @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_net_UrlClassifierFeatureTrackingAnnotation_h +#define mozilla_net_UrlClassifierFeatureTrackingAnnotation_h + +#include "UrlClassifierFeatureBase.h" + +class nsIChannel; + +namespace mozilla { +namespace net { + +class UrlClassifierFeatureTrackingAnnotation final + : public UrlClassifierFeatureBase { + public: + static void Initialize(); + + static void Shutdown(); + + static already_AddRefed MaybeCreate( + nsIChannel* aChannel); + + private: + UrlClassifierFeatureTrackingAnnotation(); +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_UrlClassifierFeatureTrackingAnnotation_h diff --git a/netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.cpp b/netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.cpp new file mode 100644 index 000000000000..a91acfc21957 --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.cpp @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "UrlClassifierFeatureTrackingProtection.h" + +#include "mozilla/AntiTrackingCommon.h" +#include "mozilla/net/UrlClassifierCommon.h" +#include "nsContentUtils.h" +#include "nsILoadContext.h" +#include "nsNetUtil.h" + +namespace mozilla { +namespace net { + +namespace { + +#define URLCLASSIFIER_TRACKING_BLACKLIST "urlclassifier.trackingTable" +#define URLCLASSIFIER_TRACKING_BLACKLIST_TEST_ENTRIES \ + "urlclassifier.trackingTable.testEntries" +#define URLCLASSIFIER_TRACKING_WHITELIST "urlclassifier.trackingWhitelistTable" +#define URLCLASSIFIER_TRACKING_WHITELIST_TEST_ENTRIES \ + "urlclassifier.trackingWhitelistTable.testEntries" +#define TABLE_TRACKING_BLACKLIST_PREF "tracking-blacklist-pref" +#define TABLE_TRACKING_WHITELIST_PREF "tracking-whitelist-pref" + +StaticRefPtr gFeatureTrackingProtection; + +} // namespace + +UrlClassifierFeatureTrackingProtection::UrlClassifierFeatureTrackingProtection() + : UrlClassifierFeatureBase( + NS_LITERAL_CSTRING("tracking-protection"), + NS_LITERAL_CSTRING(URLCLASSIFIER_TRACKING_BLACKLIST), + NS_LITERAL_CSTRING(URLCLASSIFIER_TRACKING_WHITELIST), + NS_LITERAL_CSTRING(URLCLASSIFIER_TRACKING_BLACKLIST_TEST_ENTRIES), + NS_LITERAL_CSTRING(URLCLASSIFIER_TRACKING_WHITELIST_TEST_ENTRIES), + NS_LITERAL_CSTRING(TABLE_TRACKING_BLACKLIST_PREF), + NS_LITERAL_CSTRING(TABLE_TRACKING_WHITELIST_PREF), EmptyCString()) {} + +/* static */ void UrlClassifierFeatureTrackingProtection::Initialize() { + UC_LOG(("UrlClassifierFeatureTrackingProtection: Initializing")); + MOZ_ASSERT(!gFeatureTrackingProtection); + + gFeatureTrackingProtection = new UrlClassifierFeatureTrackingProtection(); + gFeatureTrackingProtection->InitializePreferences(); +} + +/* static */ void UrlClassifierFeatureTrackingProtection::Shutdown() { + UC_LOG(("UrlClassifierFeatureTrackingProtection: Shutdown")); + MOZ_ASSERT(gFeatureTrackingProtection); + + gFeatureTrackingProtection->ShutdownPreferences(); + gFeatureTrackingProtection = nullptr; +} + +/* static */ already_AddRefed +UrlClassifierFeatureTrackingProtection::MaybeCreate(nsIChannel* aChannel) { + MOZ_ASSERT(gFeatureTrackingProtection); + MOZ_ASSERT(aChannel); + + UC_LOG(("UrlClassifierFeatureTrackingProtection: MaybeCreate for channel %p", + aChannel)); + + nsCOMPtr loadContext; + NS_QueryNotificationCallbacks(aChannel, loadContext); + if (!loadContext || !loadContext->UseTrackingProtection()) { + return nullptr; + } + + nsCOMPtr chanURI; + nsresult rv = aChannel->GetURI(getter_AddRefs(chanURI)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return nullptr; + } + + bool isThirdParty = + nsContentUtils::IsThirdPartyWindowOrChannel(nullptr, aChannel, chanURI); + if (!isThirdParty) { + if (UC_LOG_ENABLED()) { + nsCString spec = chanURI->GetSpecOrDefault(); + spec.Truncate( + std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); + UC_LOG( + ("UrlClassifierFeatureTrackingProtection: Skipping tracking " + "protection checks for first party or top-level load channel[%p] " + "with uri %s", + aChannel, spec.get())); + } + + return nullptr; + } + + if (!UrlClassifierCommon::ShouldEnableTrackingProtectionOrAnnotation( + aChannel, AntiTrackingCommon::eTrackingProtection)) { + return nullptr; + } + + RefPtr self = + gFeatureTrackingProtection; + return self.forget(); +} + +} // namespace net +} // namespace mozilla diff --git a/netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.h b/netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.h new file mode 100644 index 000000000000..7bc7ef961e68 --- /dev/null +++ b/netwerk/url-classifier/UrlClassifierFeatureTrackingProtection.h @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_net_UrlClassifierFeatureTrackingProtection_h +#define mozilla_net_UrlClassifierFeatureTrackingProtection_h + +#include "UrlClassifierFeatureBase.h" + +class nsIChannel; + +namespace mozilla { +namespace net { + +class UrlClassifierFeatureTrackingProtection final + : public UrlClassifierFeatureBase { + public: + static void Initialize(); + + static void Shutdown(); + + static already_AddRefed MaybeCreate( + nsIChannel* aChannel); + + private: + UrlClassifierFeatureTrackingProtection(); +}; + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_UrlClassifierFeatureTrackingProtection_h diff --git a/netwerk/url-classifier/moz.build b/netwerk/url-classifier/moz.build new file mode 100644 index 000000000000..2c0883d2f2ab --- /dev/null +++ b/netwerk/url-classifier/moz.build @@ -0,0 +1,42 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +with Files('**'): + BUG_COMPONENT = ('Toolkit', 'Safe Browsing') + +XPIDL_SOURCES += [ + 'nsIURIClassifier.idl', + 'nsIUrlClassifierFeature.idl', +] + +XPIDL_MODULE = 'url-classifier' + +DEFINES['GOOGLE_PROTOBUF_NO_RTTI'] = True +DEFINES['GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER'] = True + +UNIFIED_SOURCES += [ + 'nsChannelClassifier.cpp', + 'UrlClassifierCommon.cpp', + 'UrlClassifierFeatureBase.cpp', + 'UrlClassifierFeatureFactory.cpp', + 'UrlClassifierFeatureTrackingAnnotation.cpp', + 'UrlClassifierFeatureTrackingProtection.cpp', +] + +EXPORTS.mozilla.net += [ + 'UrlClassifierCommon.h', + 'UrlClassifierFeatureFactory.h', +] + +LOCAL_INCLUDES += [ + '/netwerk/base', + '/netwerk/protocol/http', + '/toolkit/components/url-classifier', +] + +FINAL_LIBRARY = 'xul' + +include('/ipc/chromium/chromium-config.mozbuild') diff --git a/netwerk/base/nsChannelClassifier.cpp b/netwerk/url-classifier/nsChannelClassifier.cpp similarity index 94% rename from netwerk/base/nsChannelClassifier.cpp rename to netwerk/url-classifier/nsChannelClassifier.cpp index 36980e6e8e10..532bbef1f813 100644 --- a/netwerk/base/nsChannelClassifier.cpp +++ b/netwerk/url-classifier/nsChannelClassifier.cpp @@ -43,6 +43,7 @@ #include "mozilla/Preferences.h" #include "mozilla/net/HttpBaseChannel.h" #include "mozilla/net/TrackingDummyChannel.h" +#include "mozilla/net/UrlClassifierCommon.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/Services.h" #include "mozilla/StaticPrefs.h" @@ -84,8 +85,6 @@ static LazyLogModule gChannelClassifierLog("nsChannelClassifier"); #define TABLE_ANNOTATION_BLACKLIST_PREF "annotation-blacklist-pref" #define TABLE_ANNOTATION_WHITELIST_PREF "annotation-whitelist-pref" -static const nsCString::size_type sMaxSpecLength = 128; - // Put CachedPrefs in anonymous namespace to avoid any collision from outside of // this file. namespace { @@ -362,7 +361,8 @@ static void LowerPriorityHelper(nsIChannel* aChannel) { aChannel->GetURI(getter_AddRefs(uri)); nsAutoCString spec; uri->GetAsciiSpec(spec); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate( + std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG(("Setting PRIORITY_LOWEST for channel[%p] (%s)", aChannel, spec.get())); } @@ -448,7 +448,8 @@ nsresult nsChannelClassifier::ShouldEnableTrackingProtectionInternal( *result = false; if (LOG_ENABLED()) { nsCString spec = chanURI->GetSpecOrDefault(); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate( + std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG( ("nsChannelClassifier[%p]: Skipping tracking protection checks " "for first party or top-level load channel[%p] with uri %s", @@ -458,7 +459,7 @@ nsresult nsChannelClassifier::ShouldEnableTrackingProtectionInternal( } } - if (AddonMayLoad(aChannel, chanURI)) { + if (UrlClassifierCommon::AddonMayLoad(aChannel, chanURI)) { return NS_OK; } @@ -491,7 +492,8 @@ nsresult nsChannelClassifier::ShouldEnableTrackingProtectionInternal( *result = false; if (LOG_ENABLED()) { nsCString chanSpec = chanURI->GetSpecOrDefault(); - chanSpec.Truncate(std::min(chanSpec.Length(), sMaxSpecLength)); + chanSpec.Truncate( + std::min(chanSpec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG(("nsChannelClassifier[%p]: User override on channel[%p] (%s)", this, aChannel, chanSpec.get())); } @@ -505,9 +507,11 @@ nsresult nsChannelClassifier::ShouldEnableTrackingProtectionInternal( if (*result) { if (LOG_ENABLED()) { nsCString chanSpec = chanURI->GetSpecOrDefault(); - chanSpec.Truncate(std::min(chanSpec.Length(), sMaxSpecLength)); + chanSpec.Truncate( + std::min(chanSpec.Length(), UrlClassifierCommon::sMaxSpecLength)); nsCString topWinSpec = topWinURI->GetSpecOrDefault(); - topWinSpec.Truncate(std::min(topWinSpec.Length(), sMaxSpecLength)); + topWinSpec.Truncate( + std::min(topWinSpec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG( ("nsChannelClassifier[%p]: Enabling tracking protection checks on " "channel[%p] with uri %s for toplevel window uri %s", @@ -520,38 +524,8 @@ nsresult nsChannelClassifier::ShouldEnableTrackingProtectionInternal( // 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. - return NotifyTrackingProtectionDisabled(aChannel); -} - -bool nsChannelClassifier::AddonMayLoad(nsIChannel* aChannel, nsIURI* aUri) { - nsCOMPtr channelLoadInfo = aChannel->GetLoadInfo(); - if (!channelLoadInfo) return false; - - // loadingPrincipal is used here to ensure we are loading into an - // addon principal. This allows an addon, with explicit permission, to - // call out to API endpoints that may otherwise get blocked. - nsIPrincipal* loadingPrincipal = channelLoadInfo->LoadingPrincipal(); - if (!loadingPrincipal) return false; - - return BasePrincipal::Cast(loadingPrincipal)->AddonAllowsLoad(aUri, true); -} - -// static -nsresult nsChannelClassifier::NotifyTrackingProtectionDisabled( - nsIChannel* aChannel) { - // Can be called in EITHER the parent or child process. - nsCOMPtr parentChannel; - NS_QueryNotificationCallbacks(aChannel, parentChannel); - if (parentChannel) { - // This channel is a parent-process proxy for a child process request. - // Tell the child process channel to do this instead. - parentChannel->NotifyTrackingProtectionDisabled(); - return NS_OK; - } - - NotifyChannelBlocked(aChannel, - nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT); + UrlClassifierCommon::NotifyTrackingProtectionDisabled(aChannel); return NS_OK; } @@ -643,7 +617,7 @@ nsresult nsChannelClassifier::StartInternal() { nsCOMPtr principalURI; principal->GetURI(getter_AddRefs(principalURI)); nsCString spec = principalURI->GetSpecOrDefault(); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate(std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG(("nsChannelClassifier[%p]: Classifying principal %s on channel[%p]", this, spec.get(), mChannel.get())); } @@ -725,7 +699,7 @@ void nsChannelClassifier::MarkEntryClassified(nsresult status) { mChannel->GetURI(getter_AddRefs(uri)); nsAutoCString spec; uri->GetAsciiSpec(spec); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate(std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG(("nsChannelClassifier::MarkEntryClassified[%s] %s", errorName.get(), spec.get())); } @@ -831,7 +805,8 @@ nsresult nsChannelClassifier::SetBlockedContent(nsIChannel* channel, } else { state = nsIWebProgressListener::STATE_BLOCKED_UNSAFE_CONTENT; } - NotifyChannelBlocked(channel, state); + + UrlClassifierCommon::NotifyChannelBlocked(channel, state); // Log a warning to the web console. nsCOMPtr uri; @@ -852,31 +827,6 @@ nsresult nsChannelClassifier::SetBlockedContent(nsIChannel* channel, return NS_OK; } -// static -void nsChannelClassifier::NotifyChannelBlocked(nsIChannel* aChannel, - unsigned aBlockedReason) { - nsCOMPtr thirdPartyUtil = services::GetThirdPartyUtil(); - if (NS_WARN_IF(!thirdPartyUtil)) { - return; - } - - nsCOMPtr win; - nsresult rv = - thirdPartyUtil->GetTopWindowForChannel(aChannel, getter_AddRefs(win)); - NS_ENSURE_SUCCESS_VOID(rv); - auto* pwin = nsPIDOMWindowOuter::From(win); - nsCOMPtr docShell = pwin->GetDocShell(); - if (!docShell) { - return; - } - nsCOMPtr doc = docShell->GetDocument(); - NS_ENSURE_TRUE_VOID(doc); - - nsCOMPtr uri; - aChannel->GetURI(getter_AddRefs(uri)); - pwin->NotifyContentBlockingState(aBlockedReason, aChannel, true, uri); -} - namespace { // This class is designed to get the results of checking blacklist and @@ -1049,7 +999,8 @@ nsresult TrackingURICallback::OnBlacklistResult(nsresult aErrorCode, nsCOMPtr uri; channel->GetURI(getter_AddRefs(uri)); nsCString spec = uri->GetSpecOrDefault(); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate( + std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG( ("TrackingURICallback[%p]::OnBlacklistResult uri %s not found " "in blacklist", @@ -1065,7 +1016,7 @@ nsresult TrackingURICallback::OnBlacklistResult(nsresult aErrorCode, nsCOMPtr uri; channel->GetURI(getter_AddRefs(uri)); nsCString spec = uri->GetSpecOrDefault(); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate(std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG( ("TrackingURICallback[%p]::OnBlacklistResult channel[%p] " "uri=%s, is in blacklist. Start checking whitelist.", @@ -1154,7 +1105,8 @@ nsresult TrackingURICallback::OnWhitelistResult(nsresult aErrorCode) { if (NS_SUCCEEDED(aErrorCode)) { if (LOG_ENABLED()) { nsCString spec = uri->GetSpecOrDefault(); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate( + std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG( ("TrackingURICallback[%p]::OnWhitelistResult uri %s found " "in %s whitelist so we won't block it", @@ -1167,7 +1119,7 @@ nsresult TrackingURICallback::OnWhitelistResult(nsresult aErrorCode) { if (LOG_ENABLED()) { nsCString spec = uri->GetSpecOrDefault(); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate(std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG( ("TrackingURICallback[%p]::OnWhitelistResult " "channel[%p] uri=%s, should not be whitelisted", @@ -1220,7 +1172,7 @@ void TrackingURICallback::OnTrackerFound(nsresult aErrorCode) { // 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. - mChannelClassifier->NotifyTrackingProtectionDisabled(channel); + UrlClassifierCommon::NotifyTrackingProtectionDisabled(channel); if (StaticPrefs::privacy_trackingprotection_lower_network_priority()) { LowerPriorityHelper(channel); @@ -1250,7 +1202,8 @@ nsresult nsChannelClassifier::CreateWhiteListURI(nsIURI** aURI) const { rv = httpChan->GetURI(getter_AddRefs(uri)); nsAutoCString spec; uri->GetAsciiSpec(spec); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate( + std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG(("nsChannelClassifier[%p]: No window URI associated with %s", this, spec.get())); } @@ -1381,7 +1334,8 @@ nsChannelClassifier::OnClassifyComplete(nsresult aErrorCode, nsCOMPtr uri; mChannel->GetURI(getter_AddRefs(uri)); nsCString spec = uri->GetSpecOrDefault(); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate( + std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG( ("nsChannelClassifier[%p]: cancelling channel %p for %s " "with error code %s", @@ -1471,7 +1425,7 @@ nsresult nsChannelClassifier::CheckIsTrackerWithLocalTable( if (LOG_ENABLED()) { nsCString spec = uri->GetSpecOrDefault(); - spec.Truncate(std::min(spec.Length(), sMaxSpecLength)); + spec.Truncate(std::min(spec.Length(), UrlClassifierCommon::sMaxSpecLength)); LOG(("nsChannelClassifier[%p]: Checking blacklist for uri=%s\n", this, spec.get())); } diff --git a/netwerk/base/nsChannelClassifier.h b/netwerk/url-classifier/nsChannelClassifier.h similarity index 94% rename from netwerk/base/nsChannelClassifier.h rename to netwerk/url-classifier/nsChannelClassifier.h index 563deff17af7..f9966efee7a4 100644 --- a/netwerk/base/nsChannelClassifier.h +++ b/netwerk/url-classifier/nsChannelClassifier.h @@ -89,7 +89,6 @@ class nsChannelClassifier final : public nsIURIClassifierCallback, bool aAnnotationsOnly, bool* result); - bool AddonMayLoad(nsIChannel* aChannel, nsIURI* aUri); void AddShutdownObserver(); void RemoveShutdownObserver(); static nsresult SendThreatHitReport(nsIChannel* aChannel, @@ -97,9 +96,6 @@ class nsChannelClassifier final : public nsIURIClassifierCallback, const nsACString& aList, const nsACString& aFullHash); - static void NotifyChannelBlocked(nsIChannel* aChannel, - unsigned aBlockedReason); - public: // If we are blocking content, update the corresponding flag in the respective // docshell and call nsISecurityEventSink::onSecurityChange. @@ -107,7 +103,6 @@ class nsChannelClassifier final : public nsIURIClassifierCallback, const nsACString& aList, const nsACString& aProvider, const nsACString& aFullHash); - static nsresult NotifyTrackingProtectionDisabled(nsIChannel* aChannel); }; } // namespace net diff --git a/netwerk/base/nsIURIClassifier.idl b/netwerk/url-classifier/nsIURIClassifier.idl similarity index 89% rename from netwerk/base/nsIURIClassifier.idl rename to netwerk/url-classifier/nsIURIClassifier.idl index 9af86acca354..16bb4bb1b6bc 100644 --- a/netwerk/base/nsIURIClassifier.idl +++ b/netwerk/url-classifier/nsIURIClassifier.idl @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" +#include "nsIUrlClassifierFeature.idl" %{C++ #include "nsStringFwd.h" @@ -14,6 +15,7 @@ interface nsIChannel; interface nsIEventTarget; interface nsIPrincipal; interface nsIURI; +interface nsIUrlClassifierFeatureCallback; /** * Callback function for nsIURIClassifier lookups. @@ -85,6 +87,7 @@ interface nsIURIClassifier : nsISupports * The result is an array of table names that match. */ [noscript] StringArrayRef classifyLocalWithTables(in nsIURI aURI, in ACString aTables); + /** * Asynchronously classify a URI with a comma-separated string * containing the given tables. This does not make network requests. @@ -98,6 +101,16 @@ interface nsIURIClassifier : nsISupports in Array aExtraTablesByPrefs, in Array aExtraEntriesByPrefs, in nsIURIClassifierCallback aCallback); + + /** + * Asynchronously classify a URI with list of features. This does not make + * network requests. + */ + void asyncClassifyLocalWithFeatures(in nsIURI aURI, + in Array aFeatures, + in nsIUrlClassifierFeature_listType aListType, + in nsIUrlClassifierFeatureCallback aCallback); + /** * Same as above, but returns a comma separated list of table names. * This is an internal interface used only for testing purposes. diff --git a/netwerk/url-classifier/nsIUrlClassifierFeature.idl b/netwerk/url-classifier/nsIUrlClassifierFeature.idl new file mode 100644 index 000000000000..c85e536047a1 --- /dev/null +++ b/netwerk/url-classifier/nsIUrlClassifierFeature.idl @@ -0,0 +1,84 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +%{C++ +#include "nsStringFwd.h" +#include "nsTArrayForwardDeclare.h" +%} +[ref] native StringArrayRef(nsTArray); + +/** + * A single URLClassifier feature. + */ +[builtinclass, scriptable, uuid(a6c9b24e-b4f1-426e-af58-2c976c3943a8)] +interface nsIUrlClassifierFeature : nsISupports +{ + cenum listType: 8 { + blacklist = 0, + whitelist = 1, + }; + + /** + * The feature name + */ + readonly attribute ACString name; + + /** + * Returns the tables for one of the possible lists. + */ + [noscript] StringArrayRef getTables(in nsIUrlClassifierFeature_listType aListType); + + /** + * Returns true if |aTable| is part of the tables of |aListType| type. + */ + [noscript] boolean hasTable(in ACString aTable, + in nsIUrlClassifierFeature_listType aListType); + + /** + * Returns true if |aHost| is contained in the preference of |aListType| type. + * |aPrefTableName| will be set to the table name to use. + */ + [noscript] boolean hasHostInPreferences(in ACString aHost, + in nsIUrlClassifierFeature_listType aListType, + out ACString aPrefTableName); + + /** + * Returns true if this host has to be ignored also if blacklisted. + */ + readonly attribute ACString skipHostList; +}; + +/** + * The result of the classifier operation is this interface. + * See asyncClassifyLocalWithFeatures() in nsIURIClassifier.idl. + */ +[builtinclass, scriptable, uuid(ccb88140-5d66-4873-9815-a1b98d6cdc92)] +interface nsIUrlClassifierFeatureResult : nsISupports +{ + readonly attribute nsIUrlClassifierFeature feature; + + // Comma separate tables or preferences. + readonly attribute ACString list; +}; + +/** + * Callback function for nsIURIClassifier lookups. + * See asyncClassifyLocalWithFeatures() in nsIURIClassifier.idl. + */ +[scriptable, function, uuid(2ea83c26-dfc9-44ed-9cfc-171d4753d78e)] +interface nsIUrlClassifierFeatureCallback : nsISupports +{ + /** + * Called by the URI classifier service when it is done checking a URI. + * + * Clients are responsible for associating callback objects with classify() + * calls. + * + * @param aResults + * List of nsIUrlClassifierFeatureResult objects. + */ + void onClassifyComplete(in Array aResults); +}; diff --git a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp index 5bc3a9e185d7..5f97c5f296e7 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp @@ -2558,3 +2558,12 @@ nsIThread* nsUrlClassifierDBService::BackgroundThread() { bool nsUrlClassifierDBService::ShutdownHasStarted() { return gShuttingDownThread; } + +NS_IMETHODIMP +nsUrlClassifierDBService::AsyncClassifyLocalWithFeatures( + nsIURI* aURI, const nsTArray>& aFeatures, + nsIUrlClassifierFeature::listType aListType, + nsIUrlClassifierFeatureCallback* aCallback) { + // TODO + return NS_OK; +} diff --git a/toolkit/components/url-classifier/nsUrlClassifierProxies.cpp b/toolkit/components/url-classifier/nsUrlClassifierProxies.cpp index 74c49d59eb12..742f3667d7e3 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierProxies.cpp +++ b/toolkit/components/url-classifier/nsUrlClassifierProxies.cpp @@ -8,6 +8,7 @@ #include "mozilla/SyncRunnable.h" +using namespace mozilla; using namespace mozilla::safebrowsing; using mozilla::NewRunnableMethod; diff --git a/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp b/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp index 824f0716e8e7..0c901b97cc32 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp +++ b/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp @@ -20,9 +20,28 @@ #include "mozIThirdPartyUtil.h" #include "nsIDocShell.h" #include "mozilla/TextUtils.h" +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" +#include "mozilla/Telemetry.h" +#include "nsNetUtil.h" +#include "nsIHttpChannel.h" +#include "nsIObserverService.h" +#include "nsIPrefBranch.h" +#include "nsIPrefService.h" +#include "nsMemory.h" +#include "nsPIDOMWindow.h" +#include "nsServiceManagerUtils.h" +#include "nsThreadManager.h" +#include "Classifier.h" +#include "Entries.h" +#include "prprf.h" +#include "prtime.h" #define DEFAULT_PROTOCOL_VERSION "2.2" +using namespace mozilla; +using namespace mozilla::safebrowsing; + static char int_to_hex_digit(int32_t i) { NS_ASSERTION((i >= 0) && (i <= 15), "int too big in int_to_hex_digit"); return static_cast(((i < 10) ? (i + '0') : ((i - 10) + 'A'))); @@ -184,7 +203,7 @@ nsresult nsUrlClassifierUtils::Init() { if (!observerService) return NS_ERROR_FAILURE; observerService->AddObserver(this, "xpcom-shutdown-threads", false); - Preferences::AddStrongObserver(this, "browser.safebrowsing"); + mozilla::Preferences::AddStrongObserver(this, "browser.safebrowsing"); return NS_OK; } diff --git a/toolkit/components/url-classifier/nsUrlClassifierUtils.h b/toolkit/components/url-classifier/nsUrlClassifierUtils.h index dd4a6167a9f8..f397e17d4cf0 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierUtils.h +++ b/toolkit/components/url-classifier/nsUrlClassifierUtils.h @@ -5,6 +5,8 @@ #ifndef nsUrlClassifierUtils_h_ #define nsUrlClassifierUtils_h_ +#include "mozilla/Mutex.h" +#include "mozilla/Base64.h" #include "nsIUrlClassifierUtils.h" #include "nsClassHashtable.h" #include "nsIObserver.h" diff --git a/toolkit/content/aboutUrlClassifier.js b/toolkit/content/aboutUrlClassifier.js index 6d35c5d20608..6d16133770a8 100644 --- a/toolkit/content/aboutUrlClassifier.js +++ b/toolkit/content/aboutUrlClassifier.js @@ -339,6 +339,7 @@ var Debug = { // url-classifier NSPR Log modules. modules: ["UrlClassifierDbService", "nsChannelClassifier", + "UrlClassifier", "UrlClassifierProtocolParser", "UrlClassifierStreamUpdater", "UrlClassifierPrefixSet",