Bug 1509047 - Part 1: Add a permission manager API for enumerating all permissions with a type prefix r=nika
☠☠ backed out by b11a6804aaca ☠ ☠
authorEhsan Akhgari <ehsan@mozilla.com>
Tue, 27 Nov 2018 16:50:39 +0000
changeset 504762 f8fc57f3ab6450a5f32e282c4f0d02cc8a9eb73e
parent 504761 2b4f08a645a0385021b64b4f995c18cb2250a5c6
child 504763 e45d7cae915a56013eaa2f6a8f09788fa0b032c7
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika
bugs1509047
milestone65.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 1509047 - Part 1: Add a permission manager API for enumerating all permissions with a type prefix r=nika Differential Revision: https://phabricator.services.mozilla.com/D12862
extensions/cookie/nsPermissionManager.cpp
extensions/cookie/test/unit/test_permmanager_getAllWithTypePrefix.js
extensions/cookie/test/unit/xpcshell.ini
netwerk/base/nsIPermissionManager.idl
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -2570,57 +2570,77 @@ nsPermissionManager::GetPermissionHashKe
   }
 
   // No entry, really...
   return nullptr;
 }
 
 NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum)
 {
+  nsTArray<RefPtr<nsIPermission>> array;
+  nsresult rv = GetAllWithTypePrefix(NS_LITERAL_CSTRING(""), array);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsCOMArray<nsIPermission> comArray;
+  comArray.SetCapacity(array.Length());
+  for (size_t i = 0; i < array.Length(); i++) {
+    comArray.AppendElement(array[i].forget());
+  }
+
+  return NS_NewArrayEnumerator(aEnum, comArray, NS_GET_IID(nsIPermission));
+}
+
+NS_IMETHODIMP nsPermissionManager::GetAllWithTypePrefix(const nsACString& aPrefix,
+                                                        nsTArray<RefPtr<nsIPermission>>& aResult)
+{
+  aResult.Clear();
   if (XRE_IsContentProcess()) {
-    NS_WARNING("nsPermissionManager's enumerator is not available in the "
+    NS_WARNING("nsPermissionManager's getAllWithTypePrefix is not available in the "
                "content process, as not all permissions may be available.");
-    *aEnum = nullptr;
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  // roll an nsCOMArray of all our permissions, then hand out an enumerator
-  nsCOMArray<nsIPermission> array;
-
   for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
     PermissionHashKey* entry = iter.Get();
     for (const auto& permEntry : entry->GetPermissions()) {
       // Given how "default" permissions work and the possibility of them being
       // overridden with UNKNOWN_ACTION, we might see this value here - but we
       // do *not* want to return them via the enumerator.
       if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
         continue;
       }
 
+      if (!aPrefix.IsEmpty() &&
+          !StringBeginsWith(mTypeArray.ElementAt(permEntry.mType), aPrefix)) {
+        continue;
+      }
+
       nsCOMPtr<nsIPrincipal> principal;
       nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin,
                                            getter_AddRefs(principal));
       if (NS_FAILED(rv)) {
         continue;
       }
 
-      nsCOMPtr<nsIPermission> permission =
+      RefPtr<nsIPermission> permission =
         nsPermission::Create(principal,
                              mTypeArray.ElementAt(permEntry.mType),
                              permEntry.mPermission,
                              permEntry.mExpireType,
                              permEntry.mExpireTime);
       if (NS_WARN_IF(!permission)) {
         continue;
       }
-      array.AppendObject(permission);
+      aResult.AppendElement(std::move(permission));
     }
   }
 
-  return NS_NewArrayEnumerator(aEnum, array, NS_GET_IID(nsIPermission));
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsPermissionManager::GetAllForURI(nsIURI* aURI, nsISimpleEnumerator **aEnum)
 {
   nsCOMPtr<nsIPrincipal> principal;
   nsresult rv = GetPrincipal(aURI, getter_AddRefs(principal));
   NS_ENSURE_SUCCESS(rv, rv);
 
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/unit/test_permmanager_getAllWithTypePrefix.js
@@ -0,0 +1,69 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function check_enumerator(prefix, permissions) {
+  let pm = Cc["@mozilla.org/permissionmanager;1"]
+           .getService(Ci.nsIPermissionManager);
+
+  let array = pm.getAllWithTypePrefix(prefix);
+  for (let [uri, type, capability] of permissions) {
+    let perm = array.shift();
+    Assert.ok(perm != null);
+    Assert.ok(perm.principal.URI.equals(uri));
+    Assert.equal(perm.type, type);
+    Assert.equal(perm.capability, capability);
+    Assert.equal(perm.expireType, pm.EXPIRE_NEVER);
+  }
+  Assert.equal(array.length, 0);
+}
+
+function run_test() {
+  let pm = Cc["@mozilla.org/permissionmanager;1"]
+           .getService(Ci.nsIPermissionManager);
+
+  let uri = NetUtil.newURI("http://example.com");
+  let sub = NetUtil.newURI("http://sub.example.com");
+
+  check_enumerator("test/", [ ]);
+
+  pm.add(uri, "test/getallwithtypeprefix", pm.ALLOW_ACTION);
+  pm.add(sub, "other-test/getallwithtypeprefix", pm.PROMPT_ACTION);
+  check_enumerator("test/", [
+    [ uri, "test/getallwithtypeprefix", pm.ALLOW_ACTION ],
+  ]);
+
+  pm.add(sub, "test/getallwithtypeprefix", pm.PROMPT_ACTION);
+  check_enumerator("test/", [
+    [ sub, "test/getallwithtypeprefix", pm.PROMPT_ACTION ],
+    [ uri, "test/getallwithtypeprefix", pm.ALLOW_ACTION ],
+  ]);
+
+  check_enumerator("test/getallwithtypeprefix", [
+    [ sub, "test/getallwithtypeprefix", pm.PROMPT_ACTION ],
+    [ uri, "test/getallwithtypeprefix", pm.ALLOW_ACTION ],
+  ]);
+
+  // check that UNKNOWN_ACTION permissions are ignored
+  pm.add(uri, "test/getallwithtypeprefix2", pm.UNKNOWN_ACTION);
+  check_enumerator("test/", [
+    [ sub, "test/getallwithtypeprefix", pm.PROMPT_ACTION ],
+    [ uri, "test/getallwithtypeprefix", pm.ALLOW_ACTION ],
+  ]);
+
+  // check that permission updates are reflected
+  pm.add(uri, "test/getallwithtypeprefix", pm.PROMPT_ACTION);
+  check_enumerator("test/", [
+    [ sub, "test/getallwithtypeprefix", pm.PROMPT_ACTION ],
+    [ uri, "test/getallwithtypeprefix", pm.PROMPT_ACTION ],
+  ]);
+
+  // check that permission removals are reflected
+  pm.remove(uri, "test/getallwithtypeprefix");
+  check_enumerator("test/", [
+    [ sub, "test/getallwithtypeprefix", pm.PROMPT_ACTION ],
+  ]);
+
+  pm.removeAll();
+  check_enumerator("test/", [ ]);
+}
+
--- a/extensions/cookie/test/unit/xpcshell.ini
+++ b/extensions/cookie/test/unit/xpcshell.ini
@@ -16,16 +16,17 @@ skip-if = true # Bug 863738
 [test_cookies_thirdparty_nonsecure_session.js]
 [test_cookies_thirdparty_session.js]
 [test_domain_eviction.js]
 [test_eviction.js]
 [test_permmanager_default_pref.js]
 [test_permmanager_defaults.js]
 [test_permmanager_expiration.js]
 [test_permmanager_getAllForURI.js]
+[test_permmanager_getAllWithTypePrefix.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
--- a/netwerk/base/nsIPermissionManager.idl
+++ b/netwerk/base/nsIPermissionManager.idl
@@ -121,16 +121,26 @@ interface nsIPermissionManager : nsISupp
    * enumerator of all permissions which are not set to default and which
    * belong to the matching principal of the given nsIPrincipal.
    *
    * @param principal  the URI to get all permissions for
    */
   nsISimpleEnumerator getAllForPrincipal(in nsIPrincipal principal);
 
   /**
+   * Get all custom permissions of a specific type, specified with a prefix
+   * string.  This will return an array of all permissions which are not set to
+   * default.  Also the passed type argument is either equal to or a prefix of
+   * the type of the returned permissions.
+   *
+   * @param prefix  the type prefix string
+   */
+  Array<nsIPermission> getAllWithTypePrefix(in ACString prefix);
+
+  /**
    * Add permission information for a given principal.
    * It is internally calling the other add() method using the nsIURI from the
    * principal.
    * Passing a system principal will be a no-op because they will always be
    * granted permissions.
    */
   void addFromPrincipal(in nsIPrincipal principal, in string type,
                         in uint32_t permission,