From a95fb737fdf99e3a895f4fecd28a4047c45b7a79 Mon Sep 17 00:00:00 2001
From: Ehsan Akhgari <ehsan@mozilla.com>
Date: Mon, 9 Mar 2020 18:12:35 +0000
Subject: [PATCH] Bug 1620322 - Part 6: Refactor the code related to user
 interactions out of AntiTrackingCommon.cpp; r=baku

Differential Revision: https://phabricator.services.mozilla.com/D65819

--HG--
extra : moz-landing-system : lando
---
 dom/base/Document.cpp                         |  5 +-
 dom/ipc/ContentParent.cpp                     |  3 +-
 .../permissions/nsPermissionManager.cpp       |  2 +-
 .../antitracking/AntiTrackingCommon.cpp       | 69 +--------------
 .../antitracking/AntiTrackingCommon.h         |  6 --
 .../AntiTrackingRedirectHeuristic.cpp         |  3 +-
 .../ContentBlockingUserInteraction.cpp        | 84 +++++++++++++++++++
 .../ContentBlockingUserInteraction.h          | 29 +++++++
 .../antitracking/SettingsChangeObserver.cpp   |  2 +-
 toolkit/components/antitracking/moz.build     |  2 +
 10 files changed, 127 insertions(+), 78 deletions(-)
 create mode 100644 toolkit/components/antitracking/ContentBlockingUserInteraction.cpp
 create mode 100644 toolkit/components/antitracking/ContentBlockingUserInteraction.h

diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp
index 55e35795cbbf..24d4affb78cb 100644
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -17,6 +17,7 @@
 #include "mozilla/AutoRestore.h"
 #include "mozilla/BinarySearch.h"
 #include "mozilla/ContentBlockingAllowList.h"
+#include "mozilla/ContentBlockingUserInteraction.h"
 #include "mozilla/CSSEnabledState.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/EditorCommands.h"
@@ -15167,7 +15168,7 @@ class UserIntractionTimer final : public Runnable,
     // If the document is not gone, let's reset its timer flag.
     nsCOMPtr<Document> document = do_QueryReferent(mDocument);
     if (document) {
-      AntiTrackingCommon::StoreUserInteractionFor(mPrincipal);
+      ContentBlockingUserInteraction::Observe(mPrincipal);
       document->ResetUserInteractionTimer();
     }
   }
@@ -15213,7 +15214,7 @@ void Document::MaybeStoreUserInteractionAsPermission() {
 
   if (!mUserHasInteracted) {
     // First interaction, let's store this info now.
-    AntiTrackingCommon::StoreUserInteractionFor(NodePrincipal());
+    ContentBlockingUserInteraction::Observe(NodePrincipal());
     return;
   }
 
diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
index 7bd19d2a1d1d..cbb6e9d67617 100644
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -43,6 +43,7 @@
 #include "mozilla/AntiTrackingCommon.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/BenchmarkStorageParent.h"
+#include "mozilla/ContentBlockingUserInteraction.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Components.h"
 #include "mozilla/DataStorage.h"
@@ -5837,7 +5838,7 @@ ContentParent::RecvFirstPartyStorageAccessGrantedForOrigin(
 
 mozilla::ipc::IPCResult ContentParent::RecvStoreUserInteractionAsPermission(
     const Principal& aPrincipal) {
-  AntiTrackingCommon::StoreUserInteractionFor(aPrincipal);
+  ContentBlockingUserInteraction::Observe(aPrincipal);
   return IPC_OK();
 }
 
diff --git a/extensions/permissions/nsPermissionManager.cpp b/extensions/permissions/nsPermissionManager.cpp
index 02f18c7f13c5..6709c5342789 100644
--- a/extensions/permissions/nsPermissionManager.cpp
+++ b/extensions/permissions/nsPermissionManager.cpp
@@ -5,9 +5,9 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Attributes.h"
-#include "mozilla/AntiTrackingCommon.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/BasePrincipal.h"
+#include "mozilla/ContentBlockingUserInteraction.h"
 #include "mozilla/ContentPrincipal.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Pair.h"
diff --git a/toolkit/components/antitracking/AntiTrackingCommon.cpp b/toolkit/components/antitracking/AntiTrackingCommon.cpp
index c1f331659212..37f150d0066a 100644
--- a/toolkit/components/antitracking/AntiTrackingCommon.cpp
+++ b/toolkit/components/antitracking/AntiTrackingCommon.cpp
@@ -9,6 +9,7 @@
 #include "AntiTrackingUtils.h"
 
 #include "mozilla/ContentBlockingAllowList.h"
+#include "mozilla/ContentBlockingUserInteraction.h"
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/CanonicalBrowsingContext.h"
 #include "mozilla/dom/ContentChild.h"
@@ -45,7 +46,6 @@
 #include "nsPIDOMWindow.h"
 #include "nsPrintfCString.h"
 #include "nsScriptSecurityManager.h"
-#include "prtime.h"
 
 namespace mozilla {
 
@@ -573,7 +573,8 @@ AntiTrackingCommon::AddFirstPartyStorageAccessGrantedFor(
       "privacy.restrict3rdpartystorage."
       "userInteractionRequiredForHosts",
       &isInPrefList);
-  if (isInPrefList && !HasUserInteraction(trackingPrincipal)) {
+  if (isInPrefList &&
+      !ContentBlockingUserInteraction::Exists(trackingPrincipal)) {
     LOG_PRIN(("Tracking principal (%s) hasn't been interacted with before, "
               "refusing to add a first-party storage permission to access it",
               _spec),
@@ -1296,67 +1297,3 @@ bool AntiTrackingCommon::MaybeIsFirstPartyStorageAccessGrantedFor(
       parentPrincipal, type,
       nsContentUtils::IsInPrivateBrowsing(parentDocument), nullptr, 0);
 }
-
-/* static */
-void AntiTrackingCommon::StoreUserInteractionFor(nsIPrincipal* aPrincipal) {
-  if (!aPrincipal) {
-    // The content process may have sent us garbage data.
-    return;
-  }
-
-  if (XRE_IsParentProcess()) {
-    LOG_PRIN(("Saving the userInteraction for %s", _spec), aPrincipal);
-
-    nsPermissionManager* permManager = nsPermissionManager::GetInstance();
-    if (NS_WARN_IF(!permManager)) {
-      LOG(("Permission manager is null, bailing out early"));
-      return;
-    }
-
-    // Remember that this pref is stored in seconds!
-    uint32_t expirationType = nsIPermissionManager::EXPIRE_TIME;
-    uint32_t expirationTime =
-        StaticPrefs::privacy_userInteraction_expiration() * 1000;
-    int64_t when = (PR_Now() / PR_USEC_PER_MSEC) + expirationTime;
-
-    uint32_t privateBrowsingId = 0;
-    nsresult rv = aPrincipal->GetPrivateBrowsingId(&privateBrowsingId);
-    if (!NS_WARN_IF(NS_FAILED(rv)) && privateBrowsingId > 0) {
-      // If we are coming from a private window, make sure to store a
-      // session-only permission which won't get persisted to disk.
-      expirationType = nsIPermissionManager::EXPIRE_SESSION;
-      when = 0;
-    }
-
-    rv = permManager->AddFromPrincipal(aPrincipal, USER_INTERACTION_PERM,
-                                       nsIPermissionManager::ALLOW_ACTION,
-                                       expirationType, when);
-    Unused << NS_WARN_IF(NS_FAILED(rv));
-    return;
-  }
-
-  ContentChild* cc = ContentChild::GetSingleton();
-  MOZ_ASSERT(cc);
-
-  LOG_PRIN(("Asking the parent process to save the user-interaction for us: %s",
-            _spec),
-           aPrincipal);
-  cc->SendStoreUserInteractionAsPermission(IPC::Principal(aPrincipal));
-}
-
-/* static */
-bool AntiTrackingCommon::HasUserInteraction(nsIPrincipal* aPrincipal) {
-  nsPermissionManager* permManager = nsPermissionManager::GetInstance();
-  if (NS_WARN_IF(!permManager)) {
-    return false;
-  }
-
-  uint32_t result = 0;
-  nsresult rv = permManager->TestPermissionWithoutDefaultsFromPrincipal(
-      aPrincipal, USER_INTERACTION_PERM, &result);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return false;
-  }
-
-  return result == nsIPermissionManager::ALLOW_ACTION;
-}
diff --git a/toolkit/components/antitracking/AntiTrackingCommon.h b/toolkit/components/antitracking/AntiTrackingCommon.h
index 8426d6e3e885..ed0456f23083 100644
--- a/toolkit/components/antitracking/AntiTrackingCommon.h
+++ b/toolkit/components/antitracking/AntiTrackingCommon.h
@@ -13,8 +13,6 @@
 #include "mozilla/RefPtr.h"
 #include "mozilla/StaticPrefs_privacy.h"
 
-#define USER_INTERACTION_PERM NS_LITERAL_CSTRING("storageAccessAPI")
-
 class nsIChannel;
 class nsICookieJarSettings;
 class nsIPermission;
@@ -101,10 +99,6 @@ class AntiTrackingCommon final {
       ContentBlockingNotifier::StorageAccessGrantedReason aReason,
       const PerformFinalChecks& aPerformFinalChecks = nullptr);
 
-  static void StoreUserInteractionFor(nsIPrincipal* aPrincipal);
-
-  static bool HasUserInteraction(nsIPrincipal* aPrincipal);
-
   // For IPC only.
   typedef MozPromise<nsresult, bool, true> FirstPartyStorageAccessGrantPromise;
   static RefPtr<FirstPartyStorageAccessGrantPromise>
diff --git a/toolkit/components/antitracking/AntiTrackingRedirectHeuristic.cpp b/toolkit/components/antitracking/AntiTrackingRedirectHeuristic.cpp
index c1ea54eb3f24..64b18bea372b 100644
--- a/toolkit/components/antitracking/AntiTrackingRedirectHeuristic.cpp
+++ b/toolkit/components/antitracking/AntiTrackingRedirectHeuristic.cpp
@@ -8,6 +8,7 @@
 #include "AntiTrackingRedirectHeuristic.h"
 #include "AntiTrackingCommon.h"
 #include "ContentBlockingAllowList.h"
+#include "ContentBlockingUserInteraction.h"
 
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/Document.h"
@@ -136,7 +137,7 @@ void AntiTrackingRedirectHeuristic(nsIChannel* aOldChannel, nsIURI* aOldURI,
     return;
   }
 
-  if (!AntiTrackingCommon::HasUserInteraction(trackingPrincipal)) {
+  if (!ContentBlockingUserInteraction::Exists(trackingPrincipal)) {
     LOG_SPEC2(("Ignoring redirect for %s to %s because no user-interaction on "
                "tracker",
                _spec1, _spec2),
diff --git a/toolkit/components/antitracking/ContentBlockingUserInteraction.cpp b/toolkit/components/antitracking/ContentBlockingUserInteraction.cpp
new file mode 100644
index 000000000000..c8b60e8b34c2
--- /dev/null
+++ b/toolkit/components/antitracking/ContentBlockingUserInteraction.cpp
@@ -0,0 +1,84 @@
+/* -*- 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 "AntiTrackingLog.h"
+#include "ContentBlockingUserInteraction.h"
+#include "AntiTrackingCommon.h"
+#include "AntiTrackingUtils.h"
+
+#include "mozilla/dom/ContentChild.h"
+#include "nsIPrincipal.h"
+#include "nsPermissionManager.h"
+#include "nsXULAppAPI.h"
+#include "prtime.h"
+
+namespace mozilla {
+
+/* static */
+void ContentBlockingUserInteraction::Observe(nsIPrincipal* aPrincipal) {
+  if (!aPrincipal) {
+    // The content process may have sent us garbage data.
+    return;
+  }
+
+  if (XRE_IsParentProcess()) {
+    LOG_PRIN(("Saving the userInteraction for %s", _spec), aPrincipal);
+
+    nsPermissionManager* permManager = nsPermissionManager::GetInstance();
+    if (NS_WARN_IF(!permManager)) {
+      LOG(("Permission manager is null, bailing out early"));
+      return;
+    }
+
+    // Remember that this pref is stored in seconds!
+    uint32_t expirationType = nsIPermissionManager::EXPIRE_TIME;
+    uint32_t expirationTime =
+        StaticPrefs::privacy_userInteraction_expiration() * 1000;
+    int64_t when = (PR_Now() / PR_USEC_PER_MSEC) + expirationTime;
+
+    uint32_t privateBrowsingId = 0;
+    nsresult rv = aPrincipal->GetPrivateBrowsingId(&privateBrowsingId);
+    if (!NS_WARN_IF(NS_FAILED(rv)) && privateBrowsingId > 0) {
+      // If we are coming from a private window, make sure to store a
+      // session-only permission which won't get persisted to disk.
+      expirationType = nsIPermissionManager::EXPIRE_SESSION;
+      when = 0;
+    }
+
+    rv = permManager->AddFromPrincipal(aPrincipal, USER_INTERACTION_PERM,
+                                       nsIPermissionManager::ALLOW_ACTION,
+                                       expirationType, when);
+    Unused << NS_WARN_IF(NS_FAILED(rv));
+    return;
+  }
+
+  dom::ContentChild* cc = dom::ContentChild::GetSingleton();
+  MOZ_ASSERT(cc);
+
+  LOG_PRIN(("Asking the parent process to save the user-interaction for us: %s",
+            _spec),
+           aPrincipal);
+  cc->SendStoreUserInteractionAsPermission(IPC::Principal(aPrincipal));
+}
+
+/* static */
+bool ContentBlockingUserInteraction::Exists(nsIPrincipal* aPrincipal) {
+  nsPermissionManager* permManager = nsPermissionManager::GetInstance();
+  if (NS_WARN_IF(!permManager)) {
+    return false;
+  }
+
+  uint32_t result = 0;
+  nsresult rv = permManager->TestPermissionWithoutDefaultsFromPrincipal(
+      aPrincipal, USER_INTERACTION_PERM, &result);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  return result == nsIPermissionManager::ALLOW_ACTION;
+}
+
+}  // namespace mozilla
diff --git a/toolkit/components/antitracking/ContentBlockingUserInteraction.h b/toolkit/components/antitracking/ContentBlockingUserInteraction.h
new file mode 100644
index 000000000000..31d105702bac
--- /dev/null
+++ b/toolkit/components/antitracking/ContentBlockingUserInteraction.h
@@ -0,0 +1,29 @@
+/* -*- 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_contentblockinguserinteraction_h
+#define mozilla_contentblockinguserinteraction_h
+
+#define USER_INTERACTION_PERM NS_LITERAL_CSTRING("storageAccessAPI")
+
+class nsIPrincipal;
+
+namespace mozilla {
+
+class ContentBlockingUserInteraction final {
+ public:
+  // Used to remember that we observed a user interaction that is significant
+  // for content blocking.
+  static void Observe(nsIPrincipal* aPrincipal);
+
+  // Used to query whether we've observed a user interaction that is significant
+  // for content blocking for the given principal in the past.
+  static bool Exists(nsIPrincipal* aPrincipal);
+};
+
+}  // namespace mozilla
+
+#endif  // mozilla_contentblockinguserinteraction_h
diff --git a/toolkit/components/antitracking/SettingsChangeObserver.cpp b/toolkit/components/antitracking/SettingsChangeObserver.cpp
index d4bdb2c39711..eb2ba5bbd334 100644
--- a/toolkit/components/antitracking/SettingsChangeObserver.cpp
+++ b/toolkit/components/antitracking/SettingsChangeObserver.cpp
@@ -5,7 +5,7 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SettingsChangeObserver.h"
-#include "AntiTrackingCommon.h"
+#include "ContentBlockingUserInteraction.h"
 
 #include "mozilla/Services.h"
 #include "mozilla/Preferences.h"
diff --git a/toolkit/components/antitracking/moz.build b/toolkit/components/antitracking/moz.build
index 7078a77d7db1..fa654508bb58 100644
--- a/toolkit/components/antitracking/moz.build
+++ b/toolkit/components/antitracking/moz.build
@@ -37,6 +37,7 @@ EXPORTS.mozilla = [
     'AntiTrackingUtils.h',
     'ContentBlockingAllowList.h',
     'ContentBlockingNotifier.h',
+    'ContentBlockingUserInteraction.h',
     'StorageAccess.h',
     'StoragePrincipalHelper.h',
     'URLDecorationStripper.h',
@@ -48,6 +49,7 @@ UNIFIED_SOURCES += [
     'AntiTrackingUtils.cpp',
     'ContentBlockingAllowList.cpp',
     'ContentBlockingNotifier.cpp',
+    'ContentBlockingUserInteraction.cpp',
     'SettingsChangeObserver.cpp',
     'StorageAccess.cpp',
     'StoragePrincipalHelper.cpp',