From 40a355a42d4a9444dc753c04c6608dade2f06a23 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:13:27 +0200 Subject: Adding upstream version 125.0.1. Signed-off-by: Daniel Baumann --- .../BounceTrackingProtection.cpp | 123 ++++++++++++++++----- 1 file changed, 95 insertions(+), 28 deletions(-) (limited to 'toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingProtection.cpp') 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& record = aBounceTrackingState->GetBounceTrackingRecord(); NS_ENSURE_TRUE(record, NS_ERROR_FAILURE); @@ -368,6 +369,11 @@ BounceTrackingProtection::TestRunPurgeBounceTrackers( return NS_OK; } +NS_IMETHODIMP +BounceTrackingProtection::TestClearExpiredUserActivations() { + return ClearExpiredUserInteractions(); +} + NS_IMETHODIMP BounceTrackingProtection::TestAddBounceTrackerCandidate( JS::Handle aOriginAttributes, const nsACString& aHost, @@ -415,6 +421,22 @@ BounceTrackingProtection::TestAddUserActivation( RefPtr 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> 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>& 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( - 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 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 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( + 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& 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, -- cgit v1.2.3