зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1614831
- Speed up the transmission of permissions to content processes upon navigation; r=baku
Differential Revision: https://phabricator.services.mozilla.com/D63674 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
4f58cf3e36
Коммит
a8ca0713ed
|
@ -1466,7 +1466,7 @@ void ContentParent::Init() {
|
|||
|
||||
// Ensure that the default set of permissions are avaliable in the content
|
||||
// process before we try to load any URIs in it.
|
||||
EnsurePermissionsByKey(EmptyCString());
|
||||
EnsurePermissionsByKey(EmptyCString(), EmptyCString());
|
||||
|
||||
RefPtr<GeckoMediaPluginServiceParent> gmps(
|
||||
GeckoMediaPluginServiceParent::GetSingleton());
|
||||
|
@ -5644,11 +5644,11 @@ nsresult ContentParent::AboutToLoadHttpFtpDocumentForChild(
|
|||
nsresult ContentParent::TransmitPermissionsForPrincipal(
|
||||
nsIPrincipal* aPrincipal) {
|
||||
// Create the key, and send it down to the content process.
|
||||
nsTArray<nsCString> keys =
|
||||
nsTArray<Pair<nsCString, nsCString>> pairs =
|
||||
nsPermissionManager::GetAllKeysForPrincipal(aPrincipal);
|
||||
MOZ_ASSERT(keys.Length() >= 1);
|
||||
for (auto& key : keys) {
|
||||
EnsurePermissionsByKey(key);
|
||||
MOZ_ASSERT(pairs.Length() >= 1);
|
||||
for (auto& pair : pairs) {
|
||||
EnsurePermissionsByKey(pair.first(), pair.second());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -5688,7 +5688,8 @@ void ContentParent::TransmitBlobURLsForPrincipal(nsIPrincipal* aPrincipal) {
|
|||
}
|
||||
}
|
||||
|
||||
void ContentParent::EnsurePermissionsByKey(const nsCString& aKey) {
|
||||
void ContentParent::EnsurePermissionsByKey(const nsCString& aKey,
|
||||
const nsCString& aOrigin) {
|
||||
// NOTE: Make sure to initialize the permission manager before updating the
|
||||
// mActivePermissionKeys list. If the permission manager is being initialized
|
||||
// by this call to GetPermissionManager, and we've added the key to
|
||||
|
@ -5705,7 +5706,7 @@ void ContentParent::EnsurePermissionsByKey(const nsCString& aKey) {
|
|||
mActivePermissionKeys.PutEntry(aKey);
|
||||
|
||||
nsTArray<IPC::Permission> perms;
|
||||
if (permManager->GetPermissionsWithKey(aKey, perms)) {
|
||||
if (permManager->GetPermissionsFromOriginOrKey(aOrigin, aKey, perms)) {
|
||||
Unused << SendSetPermissionsWithKey(aKey, perms);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -874,7 +874,7 @@ class ContentParent final
|
|||
//
|
||||
// See nsIPermissionManager::GetPermissionsForKey for more information on
|
||||
// these keys.
|
||||
void EnsurePermissionsByKey(const nsCString& aKey);
|
||||
void EnsurePermissionsByKey(const nsCString& aKey, const nsCString& aOrigin);
|
||||
|
||||
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
|
|
|
@ -3040,8 +3040,9 @@ void nsPermissionManager::UpdateDB(
|
|||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
bool nsPermissionManager::GetPermissionsWithKey(
|
||||
const nsACString& aPermissionKey, nsTArray<IPC::Permission>& aPerms) {
|
||||
bool nsPermissionManager::GetPermissionsFromOriginOrKey(
|
||||
const nsACString& aOrigin, const nsACString& aKey,
|
||||
nsTArray<IPC::Permission>& aPerms) {
|
||||
aPerms.Clear();
|
||||
if (NS_WARN_IF(XRE_IsContentProcess())) {
|
||||
return false;
|
||||
|
@ -3051,28 +3052,41 @@ bool nsPermissionManager::GetPermissionsWithKey(
|
|||
PermissionHashKey* entry = iter.Get();
|
||||
|
||||
nsAutoCString permissionKey;
|
||||
// We can't check for individual OA strip perms here.
|
||||
// Don't force strip origin attributes.
|
||||
GetKeyForOrigin(entry->GetKey()->mOrigin, false, permissionKey);
|
||||
if (aOrigin.IsEmpty()) {
|
||||
// We can't check for individual OA strip perms here.
|
||||
// Don't force strip origin attributes.
|
||||
GetKeyForOrigin(entry->GetKey()->mOrigin, false, permissionKey);
|
||||
|
||||
// If the keys don't match, and we aren't getting the default "" key, then
|
||||
// we can exit early. We have to keep looking if we're getting the default
|
||||
// key, as we may see a preload permission which should be transmitted.
|
||||
if (aPermissionKey != permissionKey && !aPermissionKey.IsEmpty()) {
|
||||
// If the keys don't match, and we aren't getting the default "" key, then
|
||||
// we can exit early. We have to keep looking if we're getting the default
|
||||
// key, as we may see a preload permission which should be transmitted.
|
||||
if (aKey != permissionKey && !aKey.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
} else if (aOrigin != entry->GetKey()->mOrigin) {
|
||||
// If the origins don't match, then we can exit early. We have to keep
|
||||
// looking if we're getting the default origin, as we may see a preload
|
||||
// permission which should be transmitted.
|
||||
continue;
|
||||
}
|
||||
|
||||
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 send it to the content process.
|
||||
// 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 send it to the content process.
|
||||
if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isPreload = IsPreloadPermission(mTypeArray[permEntry.mType]);
|
||||
if ((isPreload && aPermissionKey.IsEmpty()) ||
|
||||
(!isPreload && aPermissionKey == permissionKey)) {
|
||||
bool shouldAppend;
|
||||
if (aOrigin.IsEmpty()) {
|
||||
shouldAppend = (isPreload && aKey.IsEmpty()) ||
|
||||
(!isPreload && aKey == permissionKey);
|
||||
} else {
|
||||
shouldAppend = (!isPreload && aOrigin == entry->GetKey()->mOrigin);
|
||||
}
|
||||
if (shouldAppend) {
|
||||
aPerms.AppendElement(
|
||||
IPC::Permission(entry->GetKey()->mOrigin,
|
||||
mTypeArray[permEntry.mType], permEntry.mPermission,
|
||||
|
@ -3205,26 +3219,30 @@ void nsPermissionManager::GetKeyForPermission(nsIPrincipal* aPrincipal,
|
|||
}
|
||||
|
||||
/* static */
|
||||
nsTArray<nsCString> nsPermissionManager::GetAllKeysForPrincipal(
|
||||
nsIPrincipal* aPrincipal) {
|
||||
nsTArray<Pair<nsCString, nsCString>>
|
||||
nsPermissionManager::GetAllKeysForPrincipal(nsIPrincipal* aPrincipal) {
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
|
||||
nsTArray<nsCString> keys;
|
||||
nsTArray<Pair<nsCString, nsCString>> pairs;
|
||||
nsCOMPtr<nsIPrincipal> prin = aPrincipal;
|
||||
while (prin) {
|
||||
// Add the key to the list
|
||||
nsCString* key = keys.AppendElement();
|
||||
// Add the pair to the list
|
||||
Pair<nsCString, nsCString>* pair =
|
||||
pairs.AppendElement(MakePair(EmptyCString(), EmptyCString()));
|
||||
GetKeyForPrincipal(prin, false, pair->first());
|
||||
// We can't check for individual OA strip perms here.
|
||||
// Don't force strip origin attributes.
|
||||
GetKeyForPrincipal(prin, false, *key);
|
||||
GetKeyForPrincipal(prin, false, pair->first());
|
||||
|
||||
Unused << prin->GetOrigin(pair->second());
|
||||
|
||||
// Get the next subdomain principal and loop back around.
|
||||
prin = GetNextSubDomainPrincipal(prin);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(keys.Length() >= 1,
|
||||
"Every principal should have at least one key.");
|
||||
return keys;
|
||||
MOZ_ASSERT(pairs.Length() >= 1,
|
||||
"Every principal should have at least one pair item.");
|
||||
return pairs;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -3274,16 +3292,17 @@ void nsPermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
|
|||
}
|
||||
|
||||
nsTArray<RefPtr<GenericNonExclusivePromise>> promises;
|
||||
for (auto& key : GetAllKeysForPrincipal(aPrincipal)) {
|
||||
for (auto& pair : GetAllKeysForPrincipal(aPrincipal)) {
|
||||
RefPtr<GenericNonExclusivePromise::Private> promise;
|
||||
if (!mPermissionKeyPromiseMap.Get(key, getter_AddRefs(promise))) {
|
||||
if (!mPermissionKeyPromiseMap.Get(pair.first(), getter_AddRefs(promise))) {
|
||||
// In this case we have found a permission which isn't available in the
|
||||
// content process and hasn't been requested yet. We need to create a new
|
||||
// promise, and send the request to the parent (if we have not already
|
||||
// done so).
|
||||
promise = new GenericNonExclusivePromise::Private(__func__);
|
||||
mPermissionKeyPromiseMap.Put(
|
||||
key, RefPtr<GenericNonExclusivePromise::Private>(promise).forget());
|
||||
pair.first(),
|
||||
RefPtr<GenericNonExclusivePromise::Private>(promise).forget());
|
||||
}
|
||||
|
||||
if (promise) {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/ExpandedPrincipal.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/Pair.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/Variant.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
@ -278,7 +279,7 @@ class nsPermissionManager final : public nsIPermissionManager,
|
|||
*
|
||||
* Get all permissions keys which could correspond to the given principal.
|
||||
* This method, like GetKeyForPrincipal, is infallible and should always
|
||||
* produce at least one key.
|
||||
* produce at least one (key, origin) pair.
|
||||
*
|
||||
* Unlike GetKeyForPrincipal, this method also gets the keys for base domains
|
||||
* of the given principal. All keys returned by this method must be available
|
||||
|
@ -286,8 +287,10 @@ class nsPermissionManager final : public nsIPermissionManager,
|
|||
* checked in the `aExactHostMatch = false` situation.
|
||||
*
|
||||
* @param aPrincipal The Principal which the key is to be extracted from.
|
||||
* @return returns an array of (key, origin) pairs.
|
||||
*/
|
||||
static nsTArray<nsCString> GetAllKeysForPrincipal(nsIPrincipal* aPrincipal);
|
||||
static nsTArray<mozilla::Pair<nsCString, nsCString>> GetAllKeysForPrincipal(
|
||||
nsIPrincipal* aPrincipal);
|
||||
|
||||
// From ContentChild.
|
||||
nsresult RemoveAllFromIPC();
|
||||
|
@ -313,15 +316,17 @@ class nsPermissionManager final : public nsIPermissionManager,
|
|||
* determining the permission key for a given principal.
|
||||
*
|
||||
* This method may only be called in the parent process. It fills the nsTArray
|
||||
* argument with the IPC::Permission objects which have a matching permission
|
||||
* key.
|
||||
* argument with the IPC::Permission objects which have a matching origin.
|
||||
*
|
||||
* @param permissionKey The key to use to find the permissions of interest.
|
||||
* @param origin The origin to use to find the permissions of interest.
|
||||
* @param key The key to use to find the permissions of interest. Only used
|
||||
* when the origin argument is empty.
|
||||
* @param perms An array which will be filled with the permissions which
|
||||
* match the given permission key.
|
||||
* match the given origin.
|
||||
*/
|
||||
bool GetPermissionsWithKey(const nsACString& aPermissionKey,
|
||||
nsTArray<IPC::Permission>& aPerms);
|
||||
bool GetPermissionsFromOriginOrKey(const nsACString& aOrigin,
|
||||
const nsACString& aKey,
|
||||
nsTArray<IPC::Permission>& aPerms);
|
||||
|
||||
/**
|
||||
* See `nsPermissionManager::GetPermissionsWithKey` for more info on
|
||||
|
|
Загрузка…
Ссылка в новой задаче