summaryrefslogtreecommitdiffstats
path: root/toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingStateGlobal.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingStateGlobal.cpp')
-rw-r--r--toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingStateGlobal.cpp190
1 files changed, 190 insertions, 0 deletions
diff --git a/toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingStateGlobal.cpp b/toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingStateGlobal.cpp
new file mode 100644
index 0000000000..3481753431
--- /dev/null
+++ b/toolkit/components/antitracking/bouncetrackingprotection/BounceTrackingStateGlobal.cpp
@@ -0,0 +1,190 @@
+/* -*- 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 "BounceTrackingStateGlobal.h"
+#include "BounceTrackingProtectionStorage.h"
+#include "ErrorList.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/Logging.h"
+#include "nsIPrincipal.h"
+
+namespace mozilla {
+
+NS_IMPL_CYCLE_COLLECTION(BounceTrackingStateGlobal);
+
+extern LazyLogModule gBounceTrackingProtectionLog;
+
+BounceTrackingStateGlobal::BounceTrackingStateGlobal(
+ BounceTrackingProtectionStorage* aStorage, const OriginAttributes& aAttrs)
+ : mStorage(aStorage), mOriginAttributes(aAttrs) {
+ MOZ_ASSERT(aStorage);
+}
+
+bool BounceTrackingStateGlobal::HasUserActivation(
+ const nsACString& aSiteHost) const {
+ return mUserActivation.Contains(aSiteHost);
+}
+
+nsresult BounceTrackingStateGlobal::RecordUserActivation(
+ const nsACString& aSiteHost, PRTime aTime, bool aSkipStorage) {
+ NS_ENSURE_TRUE(aSiteHost.Length(), NS_ERROR_INVALID_ARG);
+ NS_ENSURE_TRUE(aTime > 0, NS_ERROR_INVALID_ARG);
+
+ // A site must only be in one of the maps at a time.
+ bool hasRemoved = mBounceTrackers.Remove(aSiteHost);
+
+ if (hasRemoved) {
+ MOZ_LOG(gBounceTrackingProtectionLog, LogLevel::Debug,
+ ("%s: Removed bounce tracking candidate due to user activation: %s",
+ __FUNCTION__, PromiseFlatCString(aSiteHost).get()));
+ }
+
+ mUserActivation.InsertOrUpdate(aSiteHost, aTime);
+
+ if (aSkipStorage || !ShouldPersistToDisk()) {
+ return NS_OK;
+ }
+
+ // Write the change to storage.
+ NS_ENSURE_TRUE(mStorage, NS_ERROR_FAILURE);
+ return mStorage->UpdateDBEntry(
+ mOriginAttributes, aSiteHost,
+ BounceTrackingProtectionStorage::EntryType::UserActivation, aTime);
+}
+
+nsresult BounceTrackingStateGlobal::TestRemoveUserActivation(
+ const nsACString& aSiteHost) {
+ bool hasRemoved = mUserActivation.Remove(aSiteHost);
+
+ // Avoid potentially removing a bounce tracking entry if there is no user
+ // activation entry.
+ if (!hasRemoved) {
+ return NS_OK;
+ }
+
+ if (!ShouldPersistToDisk()) {
+ return NS_OK;
+ }
+
+ // Write the change to storage.
+ NS_ENSURE_TRUE(mStorage, NS_ERROR_FAILURE);
+ return mStorage->DeleteDBEntries(&mOriginAttributes, aSiteHost);
+}
+
+nsresult BounceTrackingStateGlobal::ClearUserActivationBefore(PRTime aTime) {
+ return ClearByTimeRange(
+ 0, Some(aTime),
+ Some(BounceTrackingProtectionStorage::EntryType::UserActivation));
+}
+
+nsresult BounceTrackingStateGlobal::ClearSiteHost(const nsACString& aSiteHost,
+ bool aSkipStorage) {
+ NS_ENSURE_TRUE(aSiteHost.Length(), NS_ERROR_INVALID_ARG);
+
+ bool removedUserActivation = mUserActivation.Remove(aSiteHost);
+ bool removedBounceTracker = mBounceTrackers.Remove(aSiteHost);
+ if (removedUserActivation || removedBounceTracker) {
+ MOZ_ASSERT(removedUserActivation != removedBounceTracker,
+ "A site must only be in one of the maps at a time.");
+ }
+
+ if (aSkipStorage || !ShouldPersistToDisk()) {
+ return NS_OK;
+ }
+
+ NS_ENSURE_TRUE(mStorage, NS_ERROR_FAILURE);
+ return mStorage->DeleteDBEntries(&mOriginAttributes, aSiteHost);
+}
+
+nsresult BounceTrackingStateGlobal::ClearByTimeRange(
+ PRTime aFrom, Maybe<PRTime> aTo,
+ Maybe<BounceTrackingProtectionStorage::EntryType> aEntryType,
+ bool aSkipStorage) {
+ NS_ENSURE_ARG_MIN(aFrom, 0);
+ NS_ENSURE_TRUE(!aTo || aTo.value() > aFrom, NS_ERROR_INVALID_ARG);
+
+ // Clear in memory user activation data.
+ if (aEntryType.isNothing() ||
+ aEntryType.value() ==
+ BounceTrackingProtectionStorage::EntryType::UserActivation) {
+ for (auto iter = mUserActivation.Iter(); !iter.Done(); iter.Next()) {
+ if (iter.Data() >= aFrom &&
+ (aTo.isNothing() || iter.Data() <= aTo.value())) {
+ iter.Remove();
+ MOZ_LOG(gBounceTrackingProtectionLog, LogLevel::Debug,
+ ("%s: Remove user activation for %s", __FUNCTION__,
+ PromiseFlatCString(iter.Key()).get()));
+ }
+ }
+ }
+
+ // Clear in memory bounce tracker data.
+ if (aEntryType.isNothing() ||
+ aEntryType.value() ==
+ BounceTrackingProtectionStorage::EntryType::BounceTracker) {
+ for (auto iter = mBounceTrackers.Iter(); !iter.Done(); iter.Next()) {
+ if (iter.Data() >= aFrom &&
+ (aTo.isNothing() || iter.Data() <= aTo.value())) {
+ iter.Remove();
+ MOZ_LOG(gBounceTrackingProtectionLog, LogLevel::Debug,
+ ("%s: Remove bouncer tracker for %s", __FUNCTION__,
+ PromiseFlatCString(iter.Key()).get()));
+ }
+ }
+ }
+
+ if (aSkipStorage || !ShouldPersistToDisk()) {
+ return NS_OK;
+ }
+
+ // Write the change to storage.
+ NS_ENSURE_TRUE(mStorage, NS_ERROR_FAILURE);
+ return mStorage->DeleteDBEntriesInTimeRange(&mOriginAttributes, aFrom, aTo,
+ aEntryType);
+}
+
+bool BounceTrackingStateGlobal::HasBounceTracker(
+ const nsACString& aSiteHost) const {
+ return mBounceTrackers.Contains(aSiteHost);
+}
+
+nsresult BounceTrackingStateGlobal::RecordBounceTracker(
+ const nsACString& aSiteHost, PRTime aTime, bool aSkipStorage) {
+ NS_ENSURE_TRUE(aSiteHost.Length(), NS_ERROR_INVALID_ARG);
+ NS_ENSURE_TRUE(aTime > 0, NS_ERROR_INVALID_ARG);
+
+ // Can not record a bounce tracker if the site has a user activation.
+ NS_ENSURE_TRUE(!mUserActivation.Contains(aSiteHost), NS_ERROR_FAILURE);
+ mBounceTrackers.InsertOrUpdate(aSiteHost, aTime);
+
+ if (aSkipStorage || !ShouldPersistToDisk()) {
+ return NS_OK;
+ }
+
+ // Write the change to storage.
+ NS_ENSURE_TRUE(mStorage, NS_ERROR_FAILURE);
+ return mStorage->UpdateDBEntry(
+ mOriginAttributes, aSiteHost,
+ BounceTrackingProtectionStorage::EntryType::BounceTracker, aTime);
+}
+
+nsresult BounceTrackingStateGlobal::RemoveBounceTrackers(
+ const nsTArray<nsCString>& aSiteHosts) {
+ for (const nsCString& siteHost : aSiteHosts) {
+ mBounceTrackers.Remove(siteHost);
+
+ // TODO: Create a bulk delete query.
+ if (ShouldPersistToDisk()) {
+ NS_ENSURE_TRUE(mStorage, NS_ERROR_FAILURE);
+ nsresult rv = mStorage->DeleteDBEntries(&mOriginAttributes, siteHost);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ }
+
+ return NS_OK;
+}
+
+} // namespace mozilla