diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp index 5617f6877091..5940a5344255 100644 --- a/extensions/cookie/nsPermissionManager.cpp +++ b/extensions/cookie/nsPermissionManager.cpp @@ -2575,15 +2575,30 @@ nsPermissionManager::GetPermissionHashKey(nsIURI* aURI, NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum) { - if (XRE_IsContentProcess()) { - NS_WARNING("nsPermissionManager's enumerator is not available in the " - "content process, as not all permissions may be available."); - *aEnum = nullptr; - return NS_ERROR_NOT_AVAILABLE; + nsTArray> array; + nsresult rv = GetAllWithTypePrefix(NS_LITERAL_CSTRING(""), array); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; } - // roll an nsCOMArray of all our permissions, then hand out an enumerator - nsCOMArray array; + nsCOMArray 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>& aResult) +{ + aResult.Clear(); + if (XRE_IsContentProcess()) { + NS_WARNING("nsPermissionManager's getAllWithTypePrefix is not available in the " + "content process, as not all permissions may be available."); + return NS_ERROR_NOT_AVAILABLE; + } for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) { PermissionHashKey* entry = iter.Get(); @@ -2595,6 +2610,11 @@ NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum) continue; } + if (!aPrefix.IsEmpty() && + !StringBeginsWith(mTypeArray.ElementAt(permEntry.mType), aPrefix)) { + continue; + } + nsCOMPtr principal; nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal)); @@ -2602,7 +2622,7 @@ NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum) continue; } - nsCOMPtr permission = + RefPtr permission = nsPermission::Create(principal, mTypeArray.ElementAt(permEntry.mType), permEntry.mPermission, @@ -2611,11 +2631,11 @@ NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum) 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) diff --git a/extensions/cookie/test/unit/test_permmanager_getAllWithTypePrefix.js b/extensions/cookie/test/unit/test_permmanager_getAllWithTypePrefix.js new file mode 100644 index 000000000000..62a629c8f0b1 --- /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/", [ ]); +} + diff --git a/extensions/cookie/test/unit/xpcshell.ini b/extensions/cookie/test/unit/xpcshell.ini index c2d92ee7c256..87fb30cff86b 100644 --- a/extensions/cookie/test/unit/xpcshell.ini +++ b/extensions/cookie/test/unit/xpcshell.ini @@ -21,6 +21,7 @@ skip-if = true # Bug 863738 [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] diff --git a/netwerk/base/nsIPermissionManager.idl b/netwerk/base/nsIPermissionManager.idl index 7eebadbdad3f..4925b90743a6 100644 --- a/netwerk/base/nsIPermissionManager.idl +++ b/netwerk/base/nsIPermissionManager.idl @@ -125,6 +125,16 @@ interface nsIPermissionManager : nsISupports */ 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 getAllWithTypePrefix(in ACString prefix); + /** * Add permission information for a given principal. * It is internally calling the other add() method using the nsIURI from the