Bug 1461515 - Split tracking annotations from tracking protection. r=dimi

This makes it possible to use different lists for tracking protection
and for the features that rely on tracking annotations.

Differential Revision: https://phabricator.services.mozilla.com/D2484
This commit is contained in:
Francois Marier
2018-08-01 20:45:41 +00:00
parent 1fe5e9b6b6
commit 6d9c2d145e
9 changed files with 333 additions and 65 deletions

View File

@@ -5383,6 +5383,8 @@ pref("urlclassifier.downloadBlockTable", "goog-badbinurl-proto");
pref("urlclassifier.passwordAllowTable", "goog-passwordwhite-proto");
// Tables for tracking protection
pref("urlclassifier.trackingAnnotationTable", "test-track-simple,base-track-digest256");
pref("urlclassifier.trackingAnnotationWhitelistTable", "test-trackwhite-simple,mozstd-trackwhite-digest256");
pref("urlclassifier.trackingTable", "test-track-simple,base-track-digest256");
pref("urlclassifier.trackingWhitelistTable", "test-trackwhite-simple,mozstd-trackwhite-digest256");

View File

@@ -53,6 +53,7 @@ namespace net {
//
static LazyLogModule gChannelClassifierLog("nsChannelClassifier");
#undef LOG
#define LOG(args) MOZ_LOG(gChannelClassifierLog, LogLevel::Info, args)
#define LOG_DEBUG(args) MOZ_LOG(gChannelClassifierLog, LogLevel::Debug, args)
@@ -60,8 +61,10 @@ static LazyLogModule gChannelClassifierLog("nsChannelClassifier");
#define LOG_ENABLED() MOZ_LOG_TEST(gChannelClassifierLog, LogLevel::Info)
#define URLCLASSIFIER_SKIP_HOSTNAMES "urlclassifier.skipHostnames"
#define URLCLASSIFIER_TRACKING_WHITELIST "urlclassifier.trackingWhitelistTable"
#define URLCLASSIFIER_ANNOTATION_TABLE "urlclassifier.trackingAnnotationTable"
#define URLCLASSIFIER_ANNOTATION_WHITELIST "urlclassifier.trackingAnnotationWhitelistTable"
#define URLCLASSIFIER_TRACKING_TABLE "urlclassifier.trackingTable"
#define URLCLASSIFIER_TRACKING_WHITELIST "urlclassifier.trackingWhitelistTable"
static const nsCString::size_type sMaxSpecLength = 128;
@@ -83,12 +86,18 @@ public:
bool IsAllowListExample() { return sAllowListExample;}
bool IsLowerNetworkPriority() { return sLowerNetworkPriority;}
bool IsAnnotateChannelEnabled() { return sAnnotateChannelEnabled;}
nsCString GetTrackingWhiteList() { return mTrackingWhitelist; }
void SetTrackingWhiteList(const nsACString& aList) { mTrackingWhitelist = aList; }
nsCString GetSkipHostnames() { return mSkipHostnames; }
nsCString GetSkipHostnames() const { return mSkipHostnames; }
nsCString GetAnnotationBlackList() const { return mAnnotationBlacklist; }
nsCString GetAnnotationWhiteList() const { return mAnnotationWhitelist; }
nsCString GetTrackingBlackList() const { return mTrackingBlacklist; }
nsCString GetTrackingWhiteList() const { return mTrackingWhitelist; }
void SetSkipHostnames(const nsACString& aHostnames) { mSkipHostnames = aHostnames; }
void SetAnnotationBlackList(const nsACString& aList) { mAnnotationBlacklist = aList; }
void SetAnnotationWhiteList(const nsACString& aList) { mAnnotationWhitelist = aList; }
void SetTrackingBlackList(const nsACString& aList) { mTrackingBlacklist = aList; }
nsCString GetTrackingBlackList() { return mTrackingBlacklist; }
void SetTrackingWhiteList(const nsACString& aList) { mTrackingWhitelist = aList; }
private:
friend class StaticAutoPtr<CachedPrefs>;
@@ -105,9 +114,11 @@ private:
static bool sLowerNetworkPriority;
static bool sAllowListExample;
nsCString mTrackingWhitelist;
nsCString mSkipHostnames;
nsCString mAnnotationBlacklist;
nsCString mAnnotationWhitelist;
nsCString mTrackingBlacklist;
nsCString mTrackingWhitelist;
static StaticAutoPtr<CachedPrefs> sInstance;
};
@@ -127,6 +138,16 @@ CachedPrefs::OnPrefsChange(const char* aPref, CachedPrefs* aPrefs)
Preferences::GetCString(URLCLASSIFIER_SKIP_HOSTNAMES, skipHostnames);
ToLowerCase(skipHostnames);
aPrefs->SetSkipHostnames(skipHostnames);
} else if (!strcmp(aPref, URLCLASSIFIER_ANNOTATION_TABLE)) {
nsAutoCString annotationBlacklist;
Preferences::GetCString(URLCLASSIFIER_ANNOTATION_TABLE,
annotationBlacklist);
aPrefs->SetAnnotationBlackList(annotationBlacklist);
} else if (!strcmp(aPref, URLCLASSIFIER_ANNOTATION_WHITELIST)) {
nsAutoCString annotationWhitelist;
Preferences::GetCString(URLCLASSIFIER_ANNOTATION_WHITELIST,
annotationWhitelist);
aPrefs->SetAnnotationWhiteList(annotationWhitelist);
} else if (!strcmp(aPref, URLCLASSIFIER_TRACKING_WHITELIST)) {
nsCString trackingWhitelist;
Preferences::GetCString(URLCLASSIFIER_TRACKING_WHITELIST,
@@ -150,11 +171,14 @@ CachedPrefs::Init()
"channelclassifier.allowlist_example");
Preferences::RegisterCallbackAndCall(CachedPrefs::OnPrefsChange,
URLCLASSIFIER_SKIP_HOSTNAMES, this);
Preferences::RegisterCallbackAndCall(CachedPrefs::OnPrefsChange,
URLCLASSIFIER_ANNOTATION_TABLE, this);
Preferences::RegisterCallbackAndCall(CachedPrefs::OnPrefsChange,
URLCLASSIFIER_ANNOTATION_WHITELIST, this);
Preferences::RegisterCallbackAndCall(CachedPrefs::OnPrefsChange,
URLCLASSIFIER_TRACKING_WHITELIST, this);
Preferences::RegisterCallbackAndCall(CachedPrefs::OnPrefsChange,
URLCLASSIFIER_TRACKING_TABLE, this);
}
// static
@@ -180,6 +204,8 @@ CachedPrefs::~CachedPrefs()
MOZ_COUNT_DTOR(CachedPrefs);
Preferences::UnregisterCallback(CachedPrefs::OnPrefsChange, URLCLASSIFIER_SKIP_HOSTNAMES, this);
Preferences::UnregisterCallback(CachedPrefs::OnPrefsChange, URLCLASSIFIER_ANNOTATION_TABLE, this);
Preferences::UnregisterCallback(CachedPrefs::OnPrefsChange, URLCLASSIFIER_ANNOTATION_WHITELIST, this);
Preferences::UnregisterCallback(CachedPrefs::OnPrefsChange, URLCLASSIFIER_TRACKING_WHITELIST, this);
Preferences::UnregisterCallback(CachedPrefs::OnPrefsChange, URLCLASSIFIER_TRACKING_TABLE, this);
}
@@ -867,7 +893,7 @@ nsChannelClassifier::SetBlockedContent(nsIChannel *channel,
namespace {
// This class is designed to get the results of checking blacklist and whitelist.
// |mExpectWhitelistResult| is used to indicate that |OnClassifyComplete| is called
// |mExpect*WhitelistResult| are used to indicate that |OnClassifyComplete| is called
// for the result of blacklist or whitelist check.
class TrackingURICallback final : public nsIURIClassifierCallback {
public:
@@ -878,22 +904,24 @@ public:
std::function<void()>&& aCallback)
: mChannelClassifier(aChannelClassifier)
, mChannelCallback(std::move(aCallback))
, mExpectWhitelistResult(false)
, mExpectAnnotationWhitelistResult(false)
, mExpectTrackingWhitelistResult(false)
{
MOZ_ASSERT(mChannelClassifier);
}
private:
~TrackingURICallback() = default;
nsresult OnBlacklistResult(nsresult aErrorCode);
nsresult OnBlacklistResult(nsresult aErrorCode, bool aInTrackingTable,
bool aInAnnotationTable);
nsresult OnWhitelistResult(nsresult aErrorCode);
void OnTrackerFound(nsresult aErrorCode);
RefPtr<nsChannelClassifier> mChannelClassifier;
std::function<void()> mChannelCallback;
bool mExpectWhitelistResult;
bool mExpectAnnotationWhitelistResult;
bool mExpectTrackingWhitelistResult;
// Only need to save the result of blacklist check.
nsCString mList;
nsCString mProvider;
nsCString mFullHash;
@@ -901,26 +929,129 @@ private:
NS_IMPL_ISUPPORTS(TrackingURICallback, nsIURIClassifierCallback)
// This function gets called whenever we receive the results (match or
// no match) from an asynchronous list (blacklist or whitelist) lookup.
/*virtual*/ nsresult
TrackingURICallback::OnClassifyComplete(nsresult aErrorCode,
const nsACString& aLists,
const nsACString& aProvider,
const nsACString& aFullHash)
{
if (!mExpectWhitelistResult) {
nsresult status = aLists.IsEmpty() ? NS_OK : NS_ERROR_TRACKING_URI;
MOZ_ASSERT(aErrorCode == NS_OK);
const bool shouldEnableTrackingProtection =
mChannelClassifier->ShouldEnableTrackingProtection();
const bool shouldEnableTrackingAnnotation =
mChannelClassifier->ShouldEnableTrackingAnnotation() ||
StaticPrefs::privacy_restrict3rdpartystorage_enabled();
MOZ_ASSERT(shouldEnableTrackingProtection || shouldEnableTrackingAnnotation);
LOG(("TrackingURICallback[%p]:OnClassifyComplete "
"shouldEnableTrackingProtection=%d, shouldEnableTrackingAnnnotation=%d",
mChannelClassifier.get(), shouldEnableTrackingProtection,
shouldEnableTrackingAnnotation));
// Figure out whether we are receiving the results of a blacklist or
// a whitelist lookup
if (!mExpectAnnotationWhitelistResult && !mExpectTrackingWhitelistResult) {
// Blacklist lookup results
mList = aLists;
mProvider = aProvider;
mFullHash = aFullHash;
return OnBlacklistResult(status);
if (aLists.IsEmpty()) {
return OnBlacklistResult(NS_OK, false, false); // not a tracker
}
// Figure out which of the blacklist(s) matched
const nsCString annotationTable =
CachedPrefs::GetInstance()->GetAnnotationBlackList();
const nsCString trackingTable =
CachedPrefs::GetInstance()->GetTrackingBlackList();
bool inTrackingTable = false;
bool inAnnotationTable = false;
nsCCharSeparatedTokenizer tokenizer(aLists, ',');
while (tokenizer.hasMoreTokens()) {
const nsACString& list = tokenizer.nextToken();
if (shouldEnableTrackingProtection && !inTrackingTable &&
FindInReadable(list, trackingTable)) {
inTrackingTable = true;
}
if (shouldEnableTrackingAnnotation && !inAnnotationTable &&
FindInReadable(list, annotationTable)) {
inAnnotationTable = true;
}
}
MOZ_ASSERT(shouldEnableTrackingProtection || !inTrackingTable);
MOZ_ASSERT(shouldEnableTrackingAnnotation || !inAnnotationTable);
if ((shouldEnableTrackingProtection && inTrackingTable) ||
(shouldEnableTrackingAnnotation && inAnnotationTable)) {
// Valid blacklist result, need to check the whitelist(s) next
return OnBlacklistResult(NS_ERROR_MAYBE_TRACKING_URI, inTrackingTable,
inAnnotationTable);
}
if (NS_WARN_IF(!inTrackingTable && !inAnnotationTable)) {
MOZ_ASSERT(false, "The matching lists should be tracking-related.");
}
// Nothing to annotate or block
return OnBlacklistResult(NS_OK, inTrackingTable, inAnnotationTable);
}
nsresult status = aLists.IsEmpty() ? NS_ERROR_TRACKING_URI : NS_OK;
return OnWhitelistResult(status);
// Whitelist lookup results
MOZ_ASSERT(shouldEnableTrackingProtection || !mExpectTrackingWhitelistResult);
MOZ_ASSERT(shouldEnableTrackingAnnotation || !mExpectAnnotationWhitelistResult);
bool isTracker = mExpectTrackingWhitelistResult;
bool isAnnotation = mExpectAnnotationWhitelistResult;
MOZ_ASSERT(isTracker || isAnnotation);
if (!aLists.IsEmpty()) {
// Figure out which of the whitelist(s) matched
const nsCString annotationWhitelistTable =
CachedPrefs::GetInstance()->GetAnnotationWhiteList();
const nsCString trackingWhitelistTable =
CachedPrefs::GetInstance()->GetTrackingWhiteList();
nsCCharSeparatedTokenizer tokenizer(aLists, ',');
while (tokenizer.hasMoreTokens() && (isTracker || isAnnotation)) {
const nsACString& list = tokenizer.nextToken();
if (isTracker && FindInReadable(list, trackingWhitelistTable)) {
isTracker = false;
}
if (isAnnotation && FindInReadable(list, annotationWhitelistTable)) {
isAnnotation = false;
}
}
}
MOZ_ASSERT(shouldEnableTrackingProtection || !isTracker);
MOZ_ASSERT(shouldEnableTrackingAnnotation || !isAnnotation);
if (!isTracker && !isAnnotation) {
return OnWhitelistResult(NS_OK); // fully whitelisted
}
// The lookup failed to match at least one of the active whitelists
// (tracking protection takes precedence over tracking annotations)
return OnWhitelistResult(isTracker ? NS_ERROR_TRACKING_URI :
NS_ERROR_TRACKING_ANNOTATION_URI);
}
nsresult
TrackingURICallback::OnBlacklistResult(nsresult aErrorCode)
TrackingURICallback::OnBlacklistResult(nsresult aErrorCode,
bool aInTrackingTable,
bool aInAnnotationTable)
{
LOG_DEBUG(("TrackingURICallback[%p]::OnBlacklistResult aErrorCode=0x%" PRIx32,
mChannelClassifier.get(), static_cast<uint32_t>(aErrorCode)));
@@ -938,6 +1069,7 @@ TrackingURICallback::OnBlacklistResult(nsresult aErrorCode)
mChannelCallback();
return NS_OK;
}
MOZ_ASSERT(aErrorCode == NS_ERROR_MAYBE_TRACKING_URI);
if (LOG_ENABLED()) {
nsCOMPtr<nsIChannel> channel = mChannelClassifier->GetChannel();
@@ -950,20 +1082,61 @@ TrackingURICallback::OnBlacklistResult(nsresult aErrorCode)
mChannelClassifier.get(), channel.get(), spec.get()));
}
nsCOMPtr<nsIURI> whitelistURI = mChannelClassifier->CreateWhiteListURI();
// If IsTrackerWhitelisted has failed, it means the uri is not in whitelist.
if (NS_FAILED(mChannelClassifier->IsTrackerWhitelisted(whitelistURI, this))) {
LOG(("TrackingURICallback[%p]:OnBlacklistResult "
"IsTrackerWhitelisted has failed.",
mChannelClassifier.get()));
OnTrackerFound(aErrorCode);
nsCOMPtr<nsIURI> whitelistURI;
nsresult rv = mChannelClassifier->CreateWhiteListURI(getter_AddRefs(whitelistURI));
if (NS_FAILED(rv)) {
nsAutoCString errorName;
GetErrorName(rv, errorName);
NS_WARNING(nsPrintfCString("TrackingURICallback[%p]:OnBlacklistResult got "
"an unexpected error (rv=%s) while trying to "
"create a whitelist URI. Allowing tracker.",
mChannelClassifier.get(), errorName.get()).get());
mChannelCallback();
} else {
mExpectWhitelistResult = true;
return NS_OK; // let the tracker through
}
if (!whitelistURI) {
LOG(("TrackingURICallback[%p]:OnBlacklistResult could not create a "
"whitelist URI. Ignoring whitelist.", mChannelClassifier.get()));
OnTrackerFound(aInTrackingTable ? NS_ERROR_TRACKING_URI :
NS_ERROR_TRACKING_ANNOTATION_URI);
mChannelCallback();
return NS_OK;
}
rv = mChannelClassifier->IsTrackerWhitelisted(whitelistURI,
aInTrackingTable,
aInAnnotationTable,
this);
if (NS_FAILED(rv)) {
if (LOG_ENABLED()) {
nsAutoCString errorName;
GetErrorName(rv, errorName);
LOG(("TrackingURICallback[%p]:OnBlacklistResult "
"IsTrackerWhitelisted has failed with rv=%s.",
mChannelClassifier.get(), errorName.get()));
}
if (rv == NS_ERROR_TRACKING_URI ||
rv == NS_ERROR_TRACKING_ANNOTATION_URI) {
// whitelist disabled, blocking tracker
OnTrackerFound(rv);
} else {
// ignore other failures and let the tracker through
nsAutoCString errorName;
GetErrorName(rv, errorName);
NS_WARNING(nsPrintfCString("Unexpected error (%s) received from "
"TrackingURICallback::IsTrackerWhitelisted()",
errorName.get()).get());
}
mChannelCallback();
return NS_OK;
}
// We'll have to wait for OnWhitelistResult() to get called.
MOZ_ASSERT(aInTrackingTable || aInAnnotationTable);
mExpectTrackingWhitelistResult = aInTrackingTable;
mExpectAnnotationWhitelistResult = aInAnnotationTable;
return NS_OK;
}
@@ -1008,16 +1181,21 @@ void
TrackingURICallback::OnTrackerFound(nsresult aErrorCode)
{
nsCOMPtr<nsIChannel> channel = mChannelClassifier->GetChannel();
if (mChannelClassifier->ShouldEnableTrackingProtection()) {
if (aErrorCode == NS_ERROR_TRACKING_URI &&
mChannelClassifier->ShouldEnableTrackingProtection()) {
mChannelClassifier->SetBlockedContent(channel, aErrorCode,
mList, mProvider, mFullHash);
LOG(("TrackingURICallback[%p]::OnTrackerFound, cancelling channel[%p]",
mChannelClassifier.get(), channel.get()));
channel->Cancel(aErrorCode);
} else {
MOZ_ASSERT(aErrorCode == NS_ERROR_TRACKING_ANNOTATION_URI);
MOZ_ASSERT(mChannelClassifier->ShouldEnableTrackingAnnotation() ||
StaticPrefs::privacy_restrict3rdpartystorage_enabled());
LOG(("TrackingURICallback[%p]::OnTrackerFound, annotating channel[%p]",
mChannelClassifier.get(), channel.get()));
// 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
@@ -1033,39 +1211,48 @@ TrackingURICallback::OnTrackerFound(nsresult aErrorCode)
} // end of unnamed namespace/
already_AddRefed<nsIURI>
nsChannelClassifier::CreateWhiteListURI() const
nsresult
nsChannelClassifier::CreateWhiteListURI(nsIURI** aURI) const
{
nsresult rv;
nsCOMPtr<nsIHttpChannelInternal> chan = do_QueryInterface(mChannel, &rv);
NS_ENSURE_SUCCESS(rv, rv);
if (!chan) {
return nullptr;
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIURI> topWinURI;
rv = chan->GetTopWindowURI(getter_AddRefs(topWinURI));
NS_ENSURE_SUCCESS(rv, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
if (!topWinURI) {
LOG(("nsChannelClassifier[%p]: No window URI", this));
return nullptr;
if (LOG_ENABLED()) {
nsresult rv;
nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(mChannel, &rv);
nsCOMPtr<nsIURI> uri;
rv = httpChan->GetURI(getter_AddRefs(uri));
nsAutoCString spec;
uri->GetAsciiSpec(spec);
spec.Truncate(std::min(spec.Length(), sMaxSpecLength));
LOG(("nsChannelClassifier[%p]: No window URI associated with %s",
this, spec.get()));
}
return NS_OK;
}
nsCOMPtr<nsIScriptSecurityManager> securityManager =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> chanPrincipal;
rv = securityManager->GetChannelURIPrincipal(mChannel,
getter_AddRefs(chanPrincipal));
if (NS_FAILED(rv)) {
return nullptr;
}
NS_ENSURE_SUCCESS(rv, rv);
// Craft a whitelist URL like "toplevel.page/?resource=third.party.domain"
nsAutoCString pageHostname, resourceDomain;
rv = topWinURI->GetHost(pageHostname);
NS_ENSURE_SUCCESS(rv, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
rv = chanPrincipal->GetBaseDomain(resourceDomain);
NS_ENSURE_SUCCESS(rv, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString whitelistEntry = NS_LITERAL_CSTRING("http://") +
pageHostname + NS_LITERAL_CSTRING("/?resource=") + resourceDomain;
LOG(("nsChannelClassifier[%p]: Looking for %s in the whitelist (channel=%p)",
@@ -1073,15 +1260,21 @@ nsChannelClassifier::CreateWhiteListURI() const
nsCOMPtr<nsIURI> whitelistURI;
rv = NS_NewURI(getter_AddRefs(whitelistURI), whitelistEntry);
NS_ENSURE_SUCCESS(rv, rv);
return NS_SUCCEEDED(rv) ? whitelistURI.forget() : nullptr;
whitelistURI.forget(aURI);
return NS_OK;
}
nsresult
nsChannelClassifier::IsTrackerWhitelisted(nsIURI* aWhiteListURI,
bool aUseTrackingTable,
bool aUseAnnotationTable,
nsIURIClassifierCallback *aCallback)
{
if (!aCallback || !aWhiteListURI) {
MOZ_ASSERT(aUseTrackingTable || aUseAnnotationTable);
MOZ_ASSERT(aWhiteListURI);
if (!aCallback) {
return NS_ERROR_INVALID_ARG;
}
@@ -1090,14 +1283,24 @@ nsChannelClassifier::IsTrackerWhitelisted(nsIURI* aWhiteListURI,
do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCString trackingWhitelist = CachedPrefs::GetInstance()->GetTrackingWhiteList();
if (trackingWhitelist.IsEmpty()) {
LOG(("nsChannelClassifier[%p]:IsTrackerWhitelisted whitelist disabled",
this));
return NS_ERROR_TRACKING_URI;
nsAutoCString whitelist;
if (aUseAnnotationTable) {
whitelist += CachedPrefs::GetInstance()->GetAnnotationWhiteList();
whitelist += NS_LITERAL_CSTRING(",");
}
if (aUseTrackingTable) {
whitelist += CachedPrefs::GetInstance()->GetTrackingWhiteList();
}
return uriClassifier->AsyncClassifyLocalWithTables(aWhiteListURI, trackingWhitelist, aCallback);
if (whitelist.IsEmpty()) {
LOG(("nsChannelClassifier[%p]:IsTrackerWhitelisted whitelist disabled",
this));
return aUseTrackingTable ? NS_ERROR_TRACKING_URI :
NS_ERROR_TRACKING_ANNOTATION_URI;
}
return uriClassifier->AsyncClassifyLocalWithTables(aWhiteListURI, whitelist,
aCallback);
}
/* static */
@@ -1201,8 +1404,9 @@ nsChannelClassifier::CheckIsTrackerWithLocalTable(std::function<void()>&& aCallb
return rv;
}
if (!ShouldEnableTrackingProtection() && !ShouldEnableTrackingAnnotation() &&
!StaticPrefs::privacy_restrict3rdpartystorage_enabled()) {
const bool shouldEnableTrackingProtection = ShouldEnableTrackingProtection();
const bool shouldEnableTrackingAnnotation = ShouldEnableTrackingAnnotation() || StaticPrefs::privacy_restrict3rdpartystorage_enabled();
if (!shouldEnableTrackingProtection && !shouldEnableTrackingAnnotation) {
return NS_ERROR_FAILURE;
}
@@ -1212,13 +1416,20 @@ nsChannelClassifier::CheckIsTrackerWithLocalTable(std::function<void()>&& aCallb
return rv;
}
nsCString trackingBlacklist =
CachedPrefs::GetInstance()->GetTrackingBlackList();
if (trackingBlacklist.IsEmpty()) {
LOG_WARN(("nsChannelClassifier[%p]: CheckIsTrackerWithLocalTable blacklist is empty",
this));
nsAutoCString blacklist;
if (shouldEnableTrackingAnnotation) {
blacklist += CachedPrefs::GetInstance()->GetAnnotationBlackList();
blacklist += NS_LITERAL_CSTRING(",");
}
if (shouldEnableTrackingProtection) {
blacklist += CachedPrefs::GetInstance()->GetTrackingBlackList();
}
if (blacklist.IsEmpty()) {
LOG_WARN(("nsChannelClassifier[%p]:CheckIsTrackerWithLocalTable blacklist is empty",
this));
return NS_ERROR_FAILURE;
}
// Note: duplicate lists will be removed in Classifier::SplitTables().
nsCOMPtr<nsIURIClassifierCallback> callback =
new TrackingURICallback(this, std::move(aCallback));
@@ -1229,9 +1440,7 @@ nsChannelClassifier::CheckIsTrackerWithLocalTable(std::function<void()>&& aCallb
LOG(("nsChannelClassifier[%p]: Checking blacklist for uri=%s\n",
this, spec.get()));
}
return uriClassifier->AsyncClassifyLocalWithTables(uri,
trackingBlacklist,
callback);
return uriClassifier->AsyncClassifyLocalWithTables(uri, blacklist, callback);
}
already_AddRefed<nsIChannel>

View File

@@ -40,6 +40,8 @@ public:
// Helper function to check a tracking URI against the whitelist
nsresult IsTrackerWhitelisted(nsIURI* aWhiteListURI,
bool aUseTrackingTable,
bool aUseAnnotationTable,
nsIURIClassifierCallback* aCallback);
// Called once we actually classified an URI. (An additional whitelist
@@ -55,7 +57,7 @@ public:
nsresult CheckIsTrackerWithLocalTable(std::function<void()>&& aCallback);
// Helper function to create a whitelist URL.
already_AddRefed<nsIURI> CreateWhiteListURI() const;
nsresult CreateWhiteListURI(nsIURI** aURI) const;
already_AddRefed<nsIChannel> GetChannel();

View File

@@ -61,6 +61,11 @@ Classifier::SplitTables(const nsACString& str, nsTArray<nsCString>& tables)
begin++;
}
}
// Remove duplicates
tables.Sort();
const auto newEnd = std::unique(tables.begin(), tables.end());
tables.TruncateLength(std::distance(tables.begin(), newEnd));
}
nsresult

View File

@@ -38,6 +38,8 @@ const tablePreferences = [
"urlclassifier.downloadBlockTable",
"urlclassifier.downloadAllowTable",
"urlclassifier.passwordAllowTable",
"urlclassifier.trackingAnnotationTable",
"urlclassifier.trackingAnnotationWhitelistTable",
"urlclassifier.trackingTable",
"urlclassifier.trackingWhitelistTable",
"urlclassifier.blockedTable",
@@ -110,6 +112,12 @@ var SafeBrowsing = {
for (let i = 0; i < this.passwordAllowLists.length; ++i) {
this.registerTableWithURLs(this.passwordAllowLists[i]);
}
for (let i = 0; i < this.trackingAnnotationLists.length; ++i) {
this.registerTableWithURLs(this.trackingAnnotationLists[i]);
}
for (let i = 0; i < this.trackingAnnotationWhitelists.length; ++i) {
this.registerTableWithURLs(this.trackingAnnotationWhitelists[i]);
}
for (let i = 0; i < this.trackingProtectionLists.length; ++i) {
this.registerTableWithURLs(this.trackingProtectionLists[i]);
}
@@ -155,6 +163,8 @@ var SafeBrowsing = {
downloadBlockLists: [],
downloadAllowLists: [],
passwordAllowLists: [],
trackingAnnotationLists: [],
trackingAnnotationWhiteLists: [],
trackingProtectionLists: [],
trackingProtectionWhitelists: [],
blockedLists: [],
@@ -242,6 +252,8 @@ var SafeBrowsing = {
this.downloadBlockLists,
this.downloadAllowLists,
this.passwordAllowLists,
this.trackingAnnotationLists,
this.trackingAnnotationWhitelists,
this.trackingProtectionLists,
this.trackingProtectionWhitelists,
this.blockedLists,
@@ -254,6 +266,8 @@ var SafeBrowsing = {
this.downloadBlockLists,
this.downloadAllowLists,
this.passwordAllowLists,
this.trackingAnnotationLists,
this.trackingAnnotationWhitelists,
this.trackingProtectionLists,
this.trackingProtectionWhitelists,
this.blockedLists,
@@ -277,6 +291,8 @@ var SafeBrowsing = {
this.downloadBlockLists,
this.downloadAllowLists,
this.passwordAllowLists,
this.trackingAnnotationLists,
this.trackingAnnotationWhitelists,
this.trackingProtectionLists,
this.trackingProtectionWhitelists,
this.blockedLists,
@@ -426,15 +442,29 @@ var SafeBrowsing = {
listManager.disableUpdate(this.passwordAllowLists[i]);
}
}
for (let i = 0; i < this.trackingAnnotationLists.length; ++i) {
if (this.trackingAnnotations) {
listManager.enableUpdate(this.trackingAnnotationLists[i]);
} else {
listManager.disableUpdate(this.trackingAnnotationLists[i]);
}
}
for (let i = 0; i < this.trackingAnnotationWhitelists.length; ++i) {
if (this.trackingAnnotations) {
listManager.enableUpdate(this.trackingAnnotationWhitelists[i]);
} else {
listManager.disableUpdate(this.trackingAnnotationWhitelists[i]);
}
}
for (let i = 0; i < this.trackingProtectionLists.length; ++i) {
if (this.trackingEnabled || this.trackingAnnotations) {
if (this.trackingEnabled) {
listManager.enableUpdate(this.trackingProtectionLists[i]);
} else {
listManager.disableUpdate(this.trackingProtectionLists[i]);
}
}
for (let i = 0; i < this.trackingProtectionWhitelists.length; ++i) {
if (this.trackingEnabled || this.trackingAnnotations) {
if (this.trackingEnabled) {
listManager.enableUpdate(this.trackingProtectionWhitelists[i]);
} else {
listManager.disableUpdate(this.trackingProtectionWhitelists[i]);

View File

@@ -199,7 +199,7 @@ nsUrlClassifierDBServiceWorker::DoLocalLookup(const nsACString& spec,
static nsresult
ProcessLookupResults(const LookupResultArray& aResults, nsTArray<nsCString>& aTables)
{
// Build the result array.
// Build the result array, eliminating any duplicate tables.
for (const RefPtr<const LookupResult> result : aResults) {
MOZ_ASSERT(!result->mNoise, "Lookup results should not have noise added");
LOG(("Found result from table %s", result->mTableName.get()));

View File

@@ -2,6 +2,11 @@
var EXPORTED_SYMBOLS = ["UrlClassifierTestUtils"];
const ANNOTATION_TABLE_NAME = "mochitest-track-simple";
const ANNOTATION_TABLE_PREF = "urlclassifier.trackingAnnotationTable";
const ANNOTATION_WHITELIST_TABLE_NAME = "mochitest-trackwhite-simple";
const ANNOTATION_WHITELIST_TABLE_PREF = "urlclassifier.trackingAnnotationWhitelistTable";
const TRACKING_TABLE_NAME = "mochitest-track-simple";
const TRACKING_TABLE_PREF = "urlclassifier.trackingTable";
const WHITELIST_TABLE_NAME = "mochitest-trackwhite-simple";
@@ -20,6 +25,7 @@ var UrlClassifierTestUtils = {
let trackingURL3 = "trackertest.org/";
let whitelistedURL = "itisatrap.org/?resource=itisatracker.org";
// TODO: use different lists for annotations and TP
let trackingUpdate =
"n:1000\ni:" + TRACKING_TABLE_NAME + "\nad:3\n" +
"a:1:32:" + trackingURL1.length + "\n" +
@@ -34,6 +40,16 @@ var UrlClassifierTestUtils = {
whitelistedURL + "\n";
var tables = [
{
pref: ANNOTATION_TABLE_PREF,
name: ANNOTATION_TABLE_NAME,
update: trackingUpdate
},
{
pref: ANNOTATION_WHITELIST_TABLE_PREF,
name: ANNOTATION_WHITELIST_TABLE_NAME,
update: whitelistUpdate
},
{
pref: TRACKING_TABLE_PREF,
name: TRACKING_TABLE_NAME,
@@ -68,6 +84,8 @@ var UrlClassifierTestUtils = {
},
cleanupTestTrackers() {
Services.prefs.clearUserPref(ANNOTATION_TABLE_PREF);
Services.prefs.clearUserPref(ANNOTATION_WHITELIST_TABLE_PREF);
Services.prefs.clearUserPref(TRACKING_TABLE_PREF);
Services.prefs.clearUserPref(WHITELIST_TABLE_PREF);
},

View File

@@ -88,7 +88,7 @@ function endTest() {
}
SpecialPowers.pushPrefEnv(
{"set": [["urlclassifier.trackingTable", "test-track-simple"],
{"set": [["privacy.trackingprotection.enabled", false],
["privacy.trackingprotection.annotate_channels", true],
["privacy.trackingprotection.lower_network_priority", true],
["channelclassifier.allowlist_example", true]]},

View File

@@ -825,6 +825,8 @@ with modules["URILOADER"]:
errors["NS_ERROR_UNWANTED_URI"] = FAILURE(35)
errors["NS_ERROR_BLOCKED_URI"] = FAILURE(37)
errors["NS_ERROR_HARMFUL_URI"] = FAILURE(38)
errors["NS_ERROR_MAYBE_TRACKING_URI"] = FAILURE(39)
errors["NS_ERROR_TRACKING_ANNOTATION_URI"] = FAILURE(40)
# Used when "Save Link As..." doesn't see the headers quickly enough to
# choose a filename. See nsContextMenu.js.
errors["NS_ERROR_SAVE_LINK_AS_TIMEOUT"] = FAILURE(32)