Bug 1484868 - Add the nsIPermissionManager::removeByType() API; r=nika
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 20 Aug 2018 19:15:06 -0400
changeset 487730 dade0d8f79ea0db4e7a6741fd3931a5a5362cb0a
parent 487729 1860f2aa532d6312145e198f095018dcf3bebae2
child 487731 566a5b21073a2899b9ee539236ac057d3b81b382
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika
bugs1484868
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1484868 - Add the nsIPermissionManager::removeByType() API; r=nika
extensions/cookie/nsPermissionManager.cpp
extensions/cookie/nsPermissionManager.h
extensions/cookie/test/unit/test_permmanager_removebytype.js
extensions/cookie/test/unit/xpcshell.ini
netwerk/base/nsIPermissionManager.idl
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -2096,16 +2096,97 @@ nsPermissionManager::RemoveAll()
 
 NS_IMETHODIMP
 nsPermissionManager::RemoveAllSince(int64_t aSince)
 {
   ENSURE_NOT_CHILD_PROCESS;
   return RemoveAllModifiedSince(aSince);
 }
 
+template<class T>
+nsresult
+nsPermissionManager::RemovePermissionEntries(T aCondition)
+{
+  nsCOMArray<nsIPermission> array;
+  for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
+    PermissionHashKey* entry = iter.Get();
+    for (const auto& permEntry : entry->GetPermissions()) {
+      if (!aCondition(permEntry)) {
+        continue;
+      }
+
+      nsCOMPtr<nsIPrincipal> principal;
+      nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin,
+                                           getter_AddRefs(principal));
+      if (NS_FAILED(rv)) {
+        continue;
+      }
+
+      nsCOMPtr<nsIPermission> permission =
+        nsPermission::Create(principal,
+                             mTypeArray.ElementAt(permEntry.mType),
+                             permEntry.mPermission,
+                             permEntry.mExpireType,
+                             permEntry.mExpireTime);
+      if (NS_WARN_IF(!permission)) {
+        continue;
+      }
+      array.AppendObject(permission);
+    }
+  }
+
+  for (int32_t i = 0; i<array.Count(); ++i) {
+    nsCOMPtr<nsIPrincipal> principal;
+    nsAutoCString type;
+
+    nsresult rv = array[i]->GetPrincipal(getter_AddRefs(principal));
+    if (NS_FAILED(rv)) {
+      NS_ERROR("GetPrincipal() failed!");
+      continue;
+    }
+
+    rv = array[i]->GetType(type);
+    if (NS_FAILED(rv)) {
+      NS_ERROR("GetType() failed!");
+      continue;
+    }
+
+    // AddInternal handles removal, so let it do the work...
+    AddInternal(
+      principal,
+      type,
+      nsIPermissionManager::UNKNOWN_ACTION,
+      0,
+      nsIPermissionManager::EXPIRE_NEVER, 0, 0,
+      nsPermissionManager::eNotify,
+      nsPermissionManager::eWriteToDB);
+  }
+  // now re-import any defaults as they may now be required if we just deleted
+  // an override.
+  ImportDefaults();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPermissionManager::RemoveByType(const char* aType)
+{
+  ENSURE_NOT_CHILD_PROCESS;
+
+  int32_t typeIndex = GetTypeIndex(aType, false);
+  // If type == -1, the type isn't known,
+  // so just return NS_OK
+  if (typeIndex == -1) {
+    return NS_OK;
+  }
+
+  return RemovePermissionEntries([typeIndex] (const PermissionEntry& aPermEntry) {
+    return static_cast<uint32_t> (typeIndex) == aPermEntry.mType;
+  });
+}
+
 void
 nsPermissionManager::CloseDB(bool aRebuildOnSuccess)
 {
   // Null the statements, this will finalize them.
   mStmtInsert = nullptr;
   mStmtDelete = nullptr;
   mStmtUpdate = nullptr;
   if (mDBConn) {
@@ -2622,74 +2703,19 @@ NS_IMETHODIMP nsPermissionManager::Obser
   return NS_OK;
 }
 
 nsresult
 nsPermissionManager::RemoveAllModifiedSince(int64_t aModificationTime)
 {
   ENSURE_NOT_CHILD_PROCESS;
 
-  nsCOMArray<nsIPermission> array;
-  for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
-    PermissionHashKey* entry = iter.Get();
-    for (const auto& permEntry : entry->GetPermissions()) {
-      if (aModificationTime > permEntry.mModificationTime) {
-        continue;
-      }
-
-      nsCOMPtr<nsIPrincipal> principal;
-      nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin,
-                                           getter_AddRefs(principal));
-      if (NS_FAILED(rv)) {
-        continue;
-      }
-
-      nsCOMPtr<nsIPermission> permission =
-        nsPermission::Create(principal,
-                             mTypeArray.ElementAt(permEntry.mType),
-                             permEntry.mPermission,
-                             permEntry.mExpireType,
-                             permEntry.mExpireTime);
-      if (NS_WARN_IF(!permission)) {
-        continue;
-      }
-      array.AppendObject(permission);
-    }
-  }
-
-  for (int32_t i = 0; i<array.Count(); ++i) {
-    nsCOMPtr<nsIPrincipal> principal;
-    nsAutoCString type;
-
-    nsresult rv = array[i]->GetPrincipal(getter_AddRefs(principal));
-    if (NS_FAILED(rv)) {
-      NS_ERROR("GetPrincipal() failed!");
-      continue;
-    }
-
-    rv = array[i]->GetType(type);
-    if (NS_FAILED(rv)) {
-      NS_ERROR("GetType() failed!");
-      continue;
-    }
-
-    // AddInternal handles removal, so let it do the work...
-    AddInternal(
-      principal,
-      type,
-      nsIPermissionManager::UNKNOWN_ACTION,
-      0,
-      nsIPermissionManager::EXPIRE_NEVER, 0, 0,
-      nsPermissionManager::eNotify,
-      nsPermissionManager::eWriteToDB);
-  }
-  // now re-import any defaults as they may now be required if we just deleted
-  // an override.
-  ImportDefaults();
-  return NS_OK;
+  return RemovePermissionEntries([aModificationTime] (const PermissionEntry& aPermEntry) {
+    return aModificationTime <= aPermEntry.mModificationTime;
+  });
 }
 
 NS_IMETHODIMP
 nsPermissionManager::RemovePermissionsWithAttributes(const nsAString& aPattern)
 {
   ENSURE_NOT_CHILD_PROCESS;
   mozilla::OriginAttributesPattern pattern;
   if (!pattern.Init(aPattern)) {
--- a/extensions/cookie/nsPermissionManager.h
+++ b/extensions/cookie/nsPermissionManager.h
@@ -359,16 +359,20 @@ private:
                        int64_t aModificationTime);
 
   /**
    * This method removes all permissions modified after the specified time.
    */
   nsresult
   RemoveAllModifiedSince(int64_t aModificationTime);
 
+  template<class T>
+  nsresult
+  RemovePermissionEntries(T aCondition);
+
   /**
    * Returns false if this permission manager wouldn't have the permission
    * requested available.
    *
    * If aType is nullptr, checks that the permission manager would have all
    * permissions available for the given principal.
    */
   bool PermissionAvailable(nsIPrincipal* aPrincipal, const char* aType);
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/unit/test_permmanager_removebytype.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function run_test() {
+  // initialize the permission manager service
+  let pm = Cc["@mozilla.org/permissionmanager;1"].
+        getService(Ci.nsIPermissionManager);
+
+  Assert.equal(perm_count(), 0);
+
+  // add some permissions
+  let uri = NetUtil.newURI("http://amazon.com:8080/foobarbaz");
+  let uri2 = NetUtil.newURI("http://google.com:2048/quxx");
+  let uri3 = NetUtil.newURI("https://google.com/search");
+
+  pm.add(uri, "apple", 3);
+  pm.add(uri, "pear", 1);
+  pm.add(uri, "cucumber", 1);
+
+  pm.add(uri2, "apple", 2);
+  pm.add(uri2, "pear", 2);
+
+  pm.add(uri3, "cucumber", 3);
+  pm.add(uri3, "apple", 1);
+
+  Assert.equal(perm_count(), 7);
+
+  pm.removeByType("apple");
+  Assert.equal(perm_count(), 4);
+
+  Assert.equal(pm.testPermission(uri, "pear"), 1);
+  Assert.equal(pm.testPermission(uri2, "pear"), 2);
+
+  Assert.equal(pm.testPermission(uri, "apple"), 0);
+  Assert.equal(pm.testPermission(uri2, "apple"), 0);
+  Assert.equal(pm.testPermission(uri3, "apple"), 0);
+
+  Assert.equal(pm.testPermission(uri, "cucumber"), 1);
+  Assert.equal(pm.testPermission(uri3, "cucumber"), 3);
+
+  pm.removeByType("cucumber");
+  Assert.equal(perm_count(), 2);
+
+  Assert.equal(pm.testPermission(uri, "pear"), 1);
+  Assert.equal(pm.testPermission(uri2, "pear"), 2);
+
+  Assert.equal(pm.testPermission(uri, "apple"), 0);
+  Assert.equal(pm.testPermission(uri2, "apple"), 0);
+  Assert.equal(pm.testPermission(uri3, "apple"), 0);
+
+  Assert.equal(pm.testPermission(uri, "cucumber"), 0);
+  Assert.equal(pm.testPermission(uri3, "cucumber"), 0);
+
+  pm.removeByType("pear");
+  Assert.equal(perm_count(), 0);
+
+  Assert.equal(pm.testPermission(uri, "pear"), 0);
+  Assert.equal(pm.testPermission(uri2, "pear"), 0);
+
+  Assert.equal(pm.testPermission(uri, "apple"), 0);
+  Assert.equal(pm.testPermission(uri2, "apple"), 0);
+  Assert.equal(pm.testPermission(uri3, "apple"), 0);
+
+  Assert.equal(pm.testPermission(uri, "cucumber"), 0);
+  Assert.equal(pm.testPermission(uri3, "cucumber"), 0);
+
+  function perm_count() {
+    let enumerator = pm.enumerator;
+    let count = 0;
+    while (enumerator.hasMoreElements()) {
+      count++;
+      enumerator.getNext();
+    }
+
+    return count;
+  }
+}
--- a/extensions/cookie/test/unit/xpcshell.ini
+++ b/extensions/cookie/test/unit/xpcshell.ini
@@ -19,16 +19,17 @@ skip-if = true # Bug 863738
 [test_eviction.js]
 [test_permmanager_default_pref.js]
 [test_permmanager_defaults.js]
 [test_permmanager_expiration.js]
 [test_permmanager_getAllForURI.js]
 [test_permmanager_getPermissionObject.js]
 [test_permmanager_notifications.js]
 [test_permmanager_removeall.js]
+[test_permmanager_removebytype.js]
 [test_permmanager_removesince.js]
 [test_permmanager_removeforapp.js]
 [test_permmanager_load_invalid_entries.js]
 skip-if = debug == true
 [test_permmanager_idn.js]
 [test_permmanager_subdomains.js]
 [test_permmanager_local_files.js]
 [test_permmanager_cleardata.js]
--- a/netwerk/base/nsIPermissionManager.idl
+++ b/netwerk/base/nsIPermissionManager.idl
@@ -171,16 +171,21 @@ interface nsIPermissionManager : nsISupp
   void removeAll();
 
   /**
    * Clear all permission information added since the specified time.
    */
   void removeAllSince(in int64_t since);
 
   /**
+   * Clear all permissions of the passed type.
+   */
+  void removeByType(in string type);
+
+  /**
    * Test whether a website has permission to perform the given action.
    * This function will perform a pref lookup to permissions.default.<type>
    * if the specific permission type is part of the whitelist for that functionality.
    * @param uri     the uri to be tested
    * @param type    a case-sensitive ASCII string, identifying the consumer
    * @param return  see add(), param permission. returns UNKNOWN_ACTION when
    *                there is no stored permission for this uri and / or type.
    */