Backed out 4 changesets (bug 1596843) for causing nsPermissionManager related failures

Backed out changeset 48577632f4b3 (bug 1596843)
Backed out changeset b9061f93d045 (bug 1596843)
Backed out changeset 691397c2fde6 (bug 1596843)
Backed out changeset 88e8383dc3e4 (bug 1596843)
This commit is contained in:
Noemi Erli 2019-11-17 23:00:23 +02:00
parent eb9d6a4b1b
commit 117375bafe
10 changed files with 271 additions and 116 deletions

View File

@ -3560,11 +3560,9 @@ nsresult ContentChild::AsyncOpenAnonymousTemporaryFile(
mozilla::ipc::IPCResult ContentChild::RecvSetPermissionsWithKey(
const nsCString& aPermissionKey, nsTArray<IPC::Permission>&& aPerms) {
RefPtr<nsPermissionManager> permManager = nsPermissionManager::GetInstance();
if (permManager) {
permManager->SetPermissionsWithKey(aPermissionKey, aPerms);
}
nsCOMPtr<nsIPermissionManager> permissionManager =
services::GetPermissionManager();
permissionManager->SetPermissionsWithKey(aPermissionKey, aPerms);
return IPC_OK();
}

View File

@ -5500,10 +5500,7 @@ void ContentParent::EnsurePermissionsByKey(const nsCString& aKey) {
// by this call to GetPermissionManager, and we've added the key to
// mActivePermissionKeys, then the permission manager will send down a
// SendAddPermission before receiving the SendSetPermissionsWithKey message.
RefPtr<nsPermissionManager> permManager = nsPermissionManager::GetInstance();
if (!permManager) {
return;
}
nsCOMPtr<nsIPermissionManager> permManager = services::GetPermissionManager();
if (mActivePermissionKeys.Contains(aKey)) {
return;
@ -5511,9 +5508,12 @@ void ContentParent::EnsurePermissionsByKey(const nsCString& aKey) {
mActivePermissionKeys.PutEntry(aKey);
nsTArray<IPC::Permission> perms;
if (permManager->GetPermissionsWithKey(aKey, perms)) {
Unused << SendSetPermissionsWithKey(aKey, perms);
nsresult rv = permManager->GetPermissionsWithKey(aKey, perms);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
Unused << SendSetPermissionsWithKey(aKey, perms);
}
bool ContentParent::NeedsPermissionsUpdate(

View File

@ -63,7 +63,6 @@
#include "nsContentUtils.h"
#include "nsNetUtil.h"
#include "nsPermissionManager.h"
#include "nsProxyRelease.h"
#include "nsQueryObject.h"
#include "nsTArray.h"
@ -2132,7 +2131,7 @@ void ServiceWorkerManager::DispatchFetchEvent(nsIInterceptedChannel* aChannel,
MOZ_DIAGNOSTIC_ASSERT(serviceWorker);
RefPtr<ContinueDispatchFetchEventRunnable> continueRunnable =
nsCOMPtr<nsIRunnable> continueRunnable =
new ContinueDispatchFetchEventRunnable(serviceWorker->WorkerPrivate(),
aChannel, loadGroup,
loadInfo->GetIsDocshellReload());
@ -2142,14 +2141,10 @@ void ServiceWorkerManager::DispatchFetchEvent(nsIInterceptedChannel* aChannel,
// wait for them if they have not.
nsCOMPtr<nsIRunnable> permissionsRunnable = NS_NewRunnableFunction(
"dom::ServiceWorkerManager::DispatchFetchEvent", [=]() {
RefPtr<nsPermissionManager> permMgr =
nsPermissionManager::GetInstance();
if (permMgr) {
permMgr->WhenPermissionsAvailable(serviceWorker->Principal(),
continueRunnable);
} else {
continueRunnable->HandleError();
}
nsCOMPtr<nsIPermissionManager> permMgr =
services::GetPermissionManager();
MOZ_ALWAYS_SUCCEEDS(permMgr->WhenPermissionsAvailable(
serviceWorker->Principal(), continueRunnable));
});
nsCOMPtr<nsIUploadChannel2> uploadChannel =

View File

@ -14,8 +14,8 @@
#include "nsIConsoleReportCollector.h"
#include "nsIInterfaceRequestor.h"
#include "nsIPrincipal.h"
#include "nsIPermissionManager.h"
#include "nsNetUtil.h"
#include "nsPermissionManager.h"
#include "nsProxyRelease.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
@ -474,12 +474,10 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(RemoteWorkerData&& aData) {
}
});
RefPtr<nsPermissionManager> permissionManager =
nsPermissionManager::GetInstance();
if (!permissionManager) {
return NS_ERROR_FAILURE;
}
permissionManager->WhenPermissionsAvailable(principal, r);
nsCOMPtr<nsIPermissionManager> permissionManager =
services::GetPermissionManager();
MOZ_ALWAYS_SUCCEEDS(
permissionManager->WhenPermissionsAvailable(principal, r));
} else {
if (NS_WARN_IF(!runnable->Dispatch())) {
rv = NS_ERROR_FAILURE;

View File

@ -29,7 +29,6 @@ UNIFIED_SOURCES += [
LOCAL_INCLUDES += [
'/dom/serviceworkers',
'/extensions/permissions',
'/xpcom/build',
]

View File

@ -293,7 +293,7 @@ nsresult nsContentBlocker::TestPermission(nsIURI* aCurrentURI,
// bother actually checking with the permission manager unless we have a
// preload permission.
uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
if (mPermissionManager->HasPreloadPermissions()) {
if (mPermissionManager->GetHasPreloadPermissions()) {
rv = mPermissionManager->LegacyTestPermissionFromURI(
aCurrentURI, nullptr, kTypeString[aContentType - 1], &permission);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -2249,6 +2249,21 @@ nsresult nsPermissionManager::LegacyTestPermissionFromURI(
false, true);
}
NS_IMETHODIMP
nsPermissionManager::TestPermissionFromWindow(mozIDOMWindow* aWindow,
const nsACString& aType,
uint32_t* aPermission) {
NS_ENSURE_ARG(aWindow);
nsCOMPtr<nsPIDOMWindowInner> window = nsPIDOMWindowInner::From(aWindow);
// Get the document for security check
RefPtr<Document> document = window->GetExtantDoc();
NS_ENSURE_TRUE(document, NS_NOINTERFACE);
nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
return TestPermissionFromPrincipal(principal, aType, aPermission);
}
NS_IMETHODIMP
nsPermissionManager::TestPermissionFromPrincipal(nsIPrincipal* aPrincipal,
const nsACString& aType,
@ -2622,7 +2637,8 @@ nsresult nsPermissionManager::RemoveAllModifiedSince(
});
}
nsresult nsPermissionManager::RemovePermissionsWithAttributes(
NS_IMETHODIMP
nsPermissionManager::RemovePermissionsWithAttributes(
const nsAString& aPattern) {
ENSURE_NOT_CHILD_PROCESS;
mozilla::OriginAttributesPattern pattern;
@ -2997,11 +3013,61 @@ void nsPermissionManager::UpdateDB(
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
bool nsPermissionManager::GetPermissionsWithKey(
const nsACString& aPermissionKey, nsTArray<IPC::Permission>& aPerms) {
NS_IMETHODIMP
nsPermissionManager::UpdateExpireTime(nsIPrincipal* aPrincipal,
const nsACString& aType,
bool aExactHostMatch,
uint64_t aSessionExpireTime,
uint64_t aPersistentExpireTime) {
NS_ENSURE_ARG_POINTER(aPrincipal);
uint64_t nowms = PR_Now() / 1000;
if (aSessionExpireTime < nowms || aPersistentExpireTime < nowms) {
return NS_ERROR_INVALID_ARG;
}
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
return NS_OK;
}
// Setting the expire time of an nsEP is non-sensical.
if (IsExpandedPrincipal(aPrincipal)) {
return NS_ERROR_INVALID_ARG;
}
MOZ_ASSERT(PermissionAvailable(aPrincipal, aType));
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;
PermissionHashKey* entry =
GetPermissionHashKey(aPrincipal, typeIndex, aExactHostMatch);
if (!entry) {
return NS_OK;
}
int32_t idx = entry->GetPermissionIndex(typeIndex);
if (-1 == idx) {
return NS_OK;
}
PermissionEntry& perm = entry->GetPermissions()[idx];
if (perm.mExpireType == EXPIRE_TIME) {
perm.mExpireTime = aPersistentExpireTime;
} else if (perm.mExpireType == EXPIRE_SESSION && perm.mExpireTime != 0) {
perm.mExpireTime = aSessionExpireTime;
}
return NS_OK;
}
NS_IMETHODIMP
nsPermissionManager::GetPermissionsWithKey(const nsACString& aPermissionKey,
nsTArray<IPC::Permission>& aPerms) {
aPerms.Clear();
if (NS_WARN_IF(XRE_IsContentProcess())) {
return false;
return NS_ERROR_NOT_AVAILABLE;
}
for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
@ -3036,13 +3102,14 @@ bool nsPermissionManager::GetPermissionsWithKey(
}
}
return true;
return NS_OK;
}
void nsPermissionManager::SetPermissionsWithKey(
const nsACString& aPermissionKey, nsTArray<IPC::Permission>& aPerms) {
if (NS_WARN_IF(XRE_IsContentProcess())) {
return;
NS_IMETHODIMP
nsPermissionManager::SetPermissionsWithKey(const nsACString& aPermissionKey,
nsTArray<IPC::Permission>& aPerms) {
if (NS_WARN_IF(XRE_IsParentProcess())) {
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<GenericNonExclusivePromise::Private> promise;
@ -3057,7 +3124,7 @@ void nsPermissionManager::SetPermissionsWithKey(
} else if (foundKey) {
// NOTE: We shouldn't be sent two InitializePermissionsWithKey for the same
// key, but it's possible.
return;
return NS_OK;
}
mPermissionKeyPromiseMap.Put(aPermissionKey, nullptr);
@ -3085,6 +3152,7 @@ void nsPermissionManager::SetPermissionsWithKey(
perm.expireTime, modificationTime, eNotify, eNoDBOperation,
true /* ignoreSessionPermissions */);
}
return NS_OK;
}
/* static */
@ -3214,13 +3282,14 @@ bool nsPermissionManager::PermissionAvailable(nsIPrincipal* aPrincipal,
return true;
}
void nsPermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
nsIRunnable* aRunnable) {
NS_IMETHODIMP
nsPermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
nsIRunnable* aRunnable) {
MOZ_ASSERT(aRunnable);
if (!XRE_IsContentProcess()) {
aRunnable->Run();
return;
return NS_OK;
}
nsTArray<RefPtr<GenericNonExclusivePromise>> promises;
@ -3246,7 +3315,7 @@ void nsPermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
// sensitive.
if (promises.IsEmpty()) {
aRunnable->Run();
return;
return NS_OK;
}
auto* thread = SystemGroup::AbstractMainThreadFor(TaskCategory::Other);
@ -3260,8 +3329,11 @@ void nsPermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
"nsPermissionManager permission promise rejected. We're "
"probably shutting down.");
});
return NS_OK;
}
bool nsPermissionManager::HasPreloadPermissions() {
return sPreloadPermissionCount > 0;
NS_IMETHODIMP
nsPermissionManager::GetHasPreloadPermissions(bool* aResult) {
*aResult = sPreloadPermissionCount > 0;
return NS_OK;
}

View File

@ -29,10 +29,6 @@
#include "mozilla/Variant.h"
#include "mozilla/Vector.h"
namespace IPC {
struct Permission;
}
namespace mozilla {
class OriginAttributesPattern;
}
@ -210,6 +206,9 @@ class nsPermissionManager final : public nsIPermissionManager,
*/
static void Startup();
nsresult RemovePermissionsWithAttributes(
mozilla::OriginAttributesPattern& aAttrs);
/**
* See `nsIPermissionManager::GetPermissionsWithKey` for more info on
* permission keys.
@ -294,68 +293,6 @@ class nsPermissionManager final : public nsIPermissionManager,
*/
bool PermissionAvailable(nsIPrincipal* aPrincipal, const nsACString& aType);
/**
* The content process doesn't have access to every permission. Instead, when
* LOAD_DOCUMENT_URI channels for http://, https://, and ftp:// URIs are
* opened, the permissions for those channels are sent down to the content
* process before the OnStartRequest message. Permissions for principals with
* other schemes are sent down at process startup.
*
* Permissions are keyed and grouped by "Permission Key"s.
* `nsPermissionManager::GetKeyForPrincipal` provides the mechanism for
* 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.
*
* @param permissionKey The key to use to find the permissions of interest.
* @param perms An array which will be filled with the permissions which
* match the given permission key.
*/
bool GetPermissionsWithKey(const nsACString& aPermissionKey,
nsTArray<IPC::Permission>& aPerms);
/**
* See `nsPermissionManager::GetPermissionsWithKey` for more info on
* Permission keys.
*
* `SetPermissionsWithKey` may only be called in the Child process, and
* initializes the permission manager with the permissions for a given
* Permission key. marking permissions with that key as available.
*
* @param permissionKey The key for the permissions which have been sent
* over.
* @param perms An array with the permissions which match the given key.
*/
void SetPermissionsWithKey(const nsACString& aPermissionKey,
nsTArray<IPC::Permission>& aPerms);
/**
* Add a callback which should be run when all permissions are available for
* the given nsIPrincipal. This method invokes the callback runnable
* synchronously when the permissions are already available. Otherwise the
* callback will be run asynchronously in SystemGroup when all permissions
* are available in the future.
*
* NOTE: This method will not request the permissions be sent by the parent
* process. This should only be used to wait for permissions which may not
* have arrived yet in order to ensure they are present.
*
* @param aPrincipal The principal to wait for permissions to be available
* for.
* @param aRunnable The runnable to run when permissions are available for
* the given principal.
*/
void WhenPermissionsAvailable(nsIPrincipal* aPrincipal,
nsIRunnable* aRunnable);
/**
* True if any "preload" permissions are present. This is used to avoid making
* potentially expensive permissions checks in nsContentBlocker.
*/
bool HasPreloadPermissions();
private:
virtual ~nsPermissionManager();
@ -590,10 +527,6 @@ class nsPermissionManager final : public nsIPermissionManager,
template <class T>
nsresult RemovePermissionEntries(T aCondition);
nsresult RemovePermissionsWithAttributes(const nsAString& aPattern);
nsresult RemovePermissionsWithAttributes(
mozilla::OriginAttributesPattern& aAttrs);
nsRefPtrHashtable<nsCStringHashKey,
mozilla::GenericNonExclusivePromise::Private>
mPermissionKeyPromiseMap;

View File

@ -84,6 +84,38 @@ function* do_run_test() {
0
);
// add a permission for renewal
pm.addFromPrincipal(
principal,
"test/expiration-perm-renewable",
1,
pm.EXPIRE_TIME,
now + 100
);
pm.addFromPrincipal(
principal,
"test/expiration-session-renewable",
1,
pm.EXPIRE_SESSION,
now + 100
);
// And immediately renew them with longer timeouts
pm.updateExpireTime(
principal,
"test/expiration-perm-renewable",
true,
now + 100,
now + 1e6
);
pm.updateExpireTime(
principal,
"test/expiration-session-renewable",
true,
now + 1e6,
now + 100
);
// check that the second two haven't expired yet
Assert.equal(
1,
@ -97,6 +129,17 @@ function* do_run_test() {
1,
pm.testPermissionFromPrincipal(principal, "test/expiration-perm-nexp")
);
Assert.equal(
1,
pm.testPermissionFromPrincipal(principal, "test/expiration-perm-renewable")
);
Assert.equal(
1,
pm.testPermissionFromPrincipal(
principal,
"test/expiration-session-renewable"
)
);
// ... and the first one has
do_timeout(10, continue_test);
@ -140,5 +183,18 @@ function* do_run_test() {
pm.getPermissionObject(principal, "test/expiration-session-exp2", false)
);
// Check that the renewable permissions actually got renewed
Assert.equal(
1,
pm.testPermissionFromPrincipal(principal, "test/expiration-perm-renewable")
);
Assert.equal(
1,
pm.testPermissionFromPrincipal(
principal,
"test/expiration-session-renewable"
)
);
do_finish_generator_test(test_generator);
}

View File

@ -30,8 +30,19 @@
#include "nsISupports.idl"
interface nsIObserver;
interface nsIPrincipal;
interface mozIDOMWindow;
interface nsIPermission;
interface nsIRunnable;
%{ C++
namespace IPC {
struct Permission;
}
#include "nsTArrayForwardDeclare.h"
%}
[ref] native IPCPermissionArrayRef(nsTArray<IPC::Permission>);
[scriptable, builtinclass, uuid(4dcb3851-eba2-4e42-b236-82d2596fca22)]
interface nsIPermissionManager : nsISupports
@ -141,6 +152,16 @@ interface nsIPermissionManager : nsISupports
uint32_t testPermissionFromPrincipal(in nsIPrincipal principal,
in ACString type);
/**
* Test whether the principal associated with the window's document has the
* permission to perform a given action. System principals will always
* have permissions granted.
* This function will perform a pref lookup to permissions.default.<type>
* if the specific permission type is part of the whitelist for that functionality.
*/
uint32_t testPermissionFromWindow(in mozIDOMWindow window,
in ACString type);
/**
* See testExactPermission() above.
* System principals will always have permissions granted.
@ -188,6 +209,65 @@ interface nsIPermissionManager : nsISupports
*/
readonly attribute Array<nsIPermission> all;
/**
* Remove all permissions that will match the origin pattern.
*/
void removePermissionsWithAttributes(in AString patternAsJSON);
/**
* If the current permission is set to expire, reset the expiration time. If
* there is no permission or the current permission does not expire, this
* method will silently return.
*
* @param sessionExpiretime an integer representation of when this permission
* should be forgotten (milliseconds since
* Jan 1 1970 0:00:00), if it is currently
* EXPIRE_SESSION.
* @param sessionExpiretime an integer representation of when this permission
* should be forgotten (milliseconds since
* Jan 1 1970 0:00:00), if it is currently
* EXPIRE_TIME.
*/
void updateExpireTime(in nsIPrincipal principal,
in ACString type,
in boolean exactHost,
in uint64_t sessionExpireTime,
in uint64_t persistentExpireTime);
/**
* The content process doesn't have access to every permission. Instead, when
* LOAD_DOCUMENT_URI channels for http://, https://, and ftp:// URIs are
* opened, the permissions for those channels are sent down to the content
* process before the OnStartRequest message. Permissions for principals with
* other schemes are sent down at process startup.
*
* Permissions are keyed and grouped by "Permission Key"s.
* `nsPermissionManager::GetKeyForPrincipal` provides the mechanism for
* 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.
*
* @param permissionKey The key to use to find the permissions of interest.
* @param perms An array which will be filled with the permissions which
* match the given permission key.
*/
void getPermissionsWithKey(in ACString permissionKey, out IPCPermissionArrayRef perms);
/**
* See `nsIPermissionManager::GetPermissionsWithKey` for more info on
* Permission keys.
*
* `SetPermissionsWithKey` may only be called in the Child process, and
* initializes the permission manager with the permissions for a given
* Permission key. marking permissions with that key as available.
*
* @param permissionKey The key for the permissions which have been sent over.
* @param perms An array with the permissions which match the given key.
*/
void setPermissionsWithKey(in ACString permissionKey, in IPCPermissionArrayRef perms);
/**
* Broadcasts permissions for the given principal to all content processes.
*
@ -198,6 +278,30 @@ interface nsIPermissionManager : nsISupports
* @param aPrincipal The principal to broadcast permissions for.
*/
void broadcastPermissionsForPrincipalToAllContentProcesses(in nsIPrincipal aPrincipal);
/**
* Add a callback which should be run when all permissions are available for
* the given nsIPrincipal. This method invokes the callback runnable
* synchronously when the permissions are already available. Otherwise the
* callback will be run asynchronously in SystemGroup when all permissions
* are available in the future.
*
* NOTE: This method will not request the permissions be sent by the parent
* process. This should only be used to wait for permissions which may not
* have arrived yet in order to ensure they are present.
*
* @param aPrincipal The principal to wait for permissions to be available for.
* @param aRunnable The runnable to run when permissions are available for the
* given principal.
*/
void whenPermissionsAvailable(in nsIPrincipal aPrincipal,
in nsIRunnable aRunnable);
/**
* True if any "preload" permissions are present. This is used to avoid making
* potentially expensive permissions checks in nsContentBlocker.
*/
[infallible] readonly attribute boolean hasPreloadPermissions;
};
%{ C++