summaryrefslogtreecommitdiffstats
path: root/toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingProtection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingProtection.cpp')
-rw-r--r--toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingProtection.cpp123
1 files changed, 95 insertions, 28 deletions
diff --git a/toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingProtection.cpp b/toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingProtection.cpp
index e5d9ccfea9..2b0577d5c6 100644
--- a/toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingProtection.cpp
+++ b/toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingProtection.cpp
@@ -12,6 +12,7 @@
#include "ErrorList.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/ContentBlockingAllowList.h"
#include "mozilla/Logging.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPrefs_privacy.h"
@@ -122,7 +123,7 @@ nsresult BounceTrackingProtection::RecordStatefulBounces(
aBounceTrackingState->Describe().get()));
// Assert: navigable’s bounce tracking record is not null.
- BounceTrackingRecord* record =
+ const Maybe<BounceTrackingRecord>& record =
aBounceTrackingState->GetBounceTrackingRecord();
NS_ENSURE_TRUE(record, NS_ERROR_FAILURE);
@@ -369,6 +370,11 @@ BounceTrackingProtection::TestRunPurgeBounceTrackers(
}
NS_IMETHODIMP
+BounceTrackingProtection::TestClearExpiredUserActivations() {
+ return ClearExpiredUserInteractions();
+}
+
+NS_IMETHODIMP
BounceTrackingProtection::TestAddBounceTrackerCandidate(
JS::Handle<JS::Value> aOriginAttributes, const nsACString& aHost,
const PRTime aBounceTime, JSContext* aCx) {
@@ -415,6 +421,22 @@ BounceTrackingProtection::TestAddUserActivation(
RefPtr<BounceTrackingProtection::PurgeBounceTrackersMozPromise>
BounceTrackingProtection::PurgeBounceTrackers() {
+ // Prevent multiple purge operations from running at the same time.
+ if (mPurgeInProgress) {
+ MOZ_LOG(gBounceTrackingProtectionLog, LogLevel::Debug,
+ ("%s: Skip: Purge already in progress.", __FUNCTION__));
+ return PurgeBounceTrackersMozPromise::CreateAndReject(
+ nsresult::NS_ERROR_NOT_AVAILABLE, __func__);
+ }
+ mPurgeInProgress = true;
+
+ // Obtain a cache of ContentBlockingAllowList permissions so we only need to
+ // fetch permissions once even when we do multiple base domain lookups.
+ ContentBlockingAllowListCache contentBlockingAllowListCache;
+
+ // Collect promises for all clearing operations to later await on.
+ nsTArray<RefPtr<ClearDataMozPromise>> clearPromises;
+
// Run the purging algorithm for all global state objects.
for (const auto& entry : mStorage->StateGlobalMapRef()) {
const OriginAttributes& originAttributes = entry.GetKey();
@@ -429,13 +451,17 @@ BounceTrackingProtection::PurgeBounceTrackers() {
oaSuffix.get()));
}
- PurgeBounceTrackersForStateGlobal(stateGlobal, originAttributes);
+ nsresult rv = PurgeBounceTrackersForStateGlobal(
+ stateGlobal, contentBlockingAllowListCache, clearPromises);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return PurgeBounceTrackersMozPromise::CreateAndReject(rv, __func__);
+ }
}
// Wait for all data clearing operations to complete. mClearPromises contains
// one promise per host / clear task.
return ClearDataMozPromise::AllSettled(GetCurrentSerialEventTarget(),
- mClearPromises)
+ clearPromises)
->Then(
GetCurrentSerialEventTarget(), __func__,
[&](ClearDataMozPromise::AllSettledPromiseType::ResolveOrRejectValue&&
@@ -450,7 +476,7 @@ BounceTrackingProtection::PurgeBounceTrackers() {
// If any clear call failed reject.
for (auto& result : aResults.ResolveValue()) {
if (result.IsReject()) {
- mClearPromises.Clear();
+ mPurgeInProgress = false;
return PurgeBounceTrackersMozPromise::CreateAndReject(
NS_ERROR_FAILURE, __func__);
}
@@ -458,7 +484,8 @@ BounceTrackingProtection::PurgeBounceTrackers() {
}
// No clearing errors, resolve.
- mClearPromises.Clear();
+
+ mPurgeInProgress = false;
return PurgeBounceTrackersMozPromise::CreateAndResolve(
std::move(purgedSiteHosts), __func__);
});
@@ -466,34 +493,17 @@ BounceTrackingProtection::PurgeBounceTrackers() {
nsresult BounceTrackingProtection::PurgeBounceTrackersForStateGlobal(
BounceTrackingStateGlobal* aStateGlobal,
- const OriginAttributes& aOriginAttributes) {
+ ContentBlockingAllowListCache& aContentBlockingAllowList,
+ nsTArray<RefPtr<ClearDataMozPromise>>& aClearPromises) {
MOZ_ASSERT(aStateGlobal);
MOZ_LOG(gBounceTrackingProtectionLog, LogLevel::Debug,
- ("%s: #mUserActivation: %d, #mBounceTrackers: %d", __FUNCTION__,
- aStateGlobal->UserActivationMapRef().Count(),
- aStateGlobal->BounceTrackersMapRef().Count()));
-
- // Purge already in progress.
- if (!mClearPromises.IsEmpty()) {
- MOZ_LOG(gBounceTrackingProtectionLog, LogLevel::Debug,
- ("%s: Skip: Purge already in progress.", __FUNCTION__));
- return NS_ERROR_NOT_AVAILABLE;
- }
+ ("%s: %s", __FUNCTION__, aStateGlobal->Describe().get()));
const PRTime now = PR_Now();
- // Convert the user activation lifetime into microseconds for calculation with
- // PRTime values. The pref is a 32-bit value. Cast into 64-bit before
- // multiplying so we get the correct result.
- int64_t activationLifetimeUsec =
- static_cast<int64_t>(
- StaticPrefs::
- privacy_bounceTrackingProtection_bounceTrackingActivationLifetimeSec()) *
- PR_USEC_PER_SEC;
// 1. Remove hosts from the user activation map whose user activation flag has
// expired.
- nsresult rv =
- aStateGlobal->ClearUserActivationBefore(now - activationLifetimeUsec);
+ nsresult rv = ClearExpiredUserInteractions(aStateGlobal);
NS_ENSURE_SUCCESS(rv, rv);
// 2. Go over bounce tracker candidate map and purge state.
@@ -502,7 +512,6 @@ nsresult BounceTrackingProtection::PurgeBounceTrackersForStateGlobal(
do_GetService("@mozilla.org/clear-data-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
- mClearPromises.Clear();
nsTArray<nsCString> purgedSiteHosts;
// Collect hosts to remove from the bounce trackers map. We can not remove
@@ -545,6 +554,27 @@ nsresult BounceTrackingProtection::PurgeBounceTrackersForStateGlobal(
continue;
}
+ // Gecko specific: If the host is on the content blocking allow-list,
+ // continue.
+ bool isAllowListed = false;
+ rv = aContentBlockingAllowList.CheckForBaseDomain(
+ host, aStateGlobal->OriginAttributesRef(), isAllowListed);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ continue;
+ }
+ if (isAllowListed) {
+ if (MOZ_LOG_TEST(gBounceTrackingProtectionLog, LogLevel::Debug)) {
+ nsAutoCString originAttributeSuffix;
+ aStateGlobal->OriginAttributesRef().CreateSuffix(originAttributeSuffix);
+ MOZ_LOG(gBounceTrackingProtectionLog, LogLevel::Debug,
+ ("%s: Skip host on the content blocking allow-list: host: %s, "
+ "originAttributes: %s",
+ __FUNCTION__, PromiseFlatCString(host).get(),
+ originAttributeSuffix.get()));
+ }
+ continue;
+ }
+
// No exception above applies, clear state for the given host.
RefPtr<ClearDataMozPromise::Private> clearPromise =
@@ -562,7 +592,7 @@ nsresult BounceTrackingProtection::PurgeBounceTrackersForStateGlobal(
clearPromise->Reject(0, __func__);
}
- mClearPromises.AppendElement(clearPromise);
+ aClearPromises.AppendElement(clearPromise);
// Remove it from the bounce trackers map, it's about to be purged. If the
// clear call fails still remove it. We want to avoid an ever growing list
@@ -575,6 +605,43 @@ nsresult BounceTrackingProtection::PurgeBounceTrackersForStateGlobal(
return aStateGlobal->RemoveBounceTrackers(bounceTrackerCandidatesToRemove);
}
+nsresult BounceTrackingProtection::ClearExpiredUserInteractions(
+ BounceTrackingStateGlobal* aStateGlobal) {
+ if (!aStateGlobal && mStorage->StateGlobalMapRef().IsEmpty()) {
+ // Nothing to clear.
+ return NS_OK;
+ }
+
+ const PRTime now = PR_Now();
+
+ // Convert the user activation lifetime into microseconds for calculation with
+ // PRTime values. The pref is a 32-bit value. Cast into 64-bit before
+ // multiplying so we get the correct result.
+ int64_t activationLifetimeUsec =
+ static_cast<int64_t>(
+ StaticPrefs::
+ privacy_bounceTrackingProtection_bounceTrackingActivationLifetimeSec()) *
+ PR_USEC_PER_SEC;
+
+ // Clear user activation for the given state global.
+ if (aStateGlobal) {
+ return aStateGlobal->ClearUserActivationBefore(now -
+ activationLifetimeUsec);
+ }
+
+ // aStateGlobal not passed, clear user activation for all state globals.
+ for (const auto& entry : mStorage->StateGlobalMapRef()) {
+ const RefPtr<BounceTrackingStateGlobal>& stateGlobal = entry.GetData();
+ MOZ_ASSERT(stateGlobal);
+
+ nsresult rv =
+ stateGlobal->ClearUserActivationBefore(now - activationLifetimeUsec);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+}
+
// ClearDataCallback
NS_IMPL_ISUPPORTS(BounceTrackingProtection::ClearDataCallback,