diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 4558515b7921..20d459e150cd 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -3560,9 +3560,11 @@ nsresult ContentChild::AsyncOpenAnonymousTemporaryFile( mozilla::ipc::IPCResult ContentChild::RecvSetPermissionsWithKey( const nsCString& aPermissionKey, nsTArray&& aPerms) { - nsCOMPtr permissionManager = - services::GetPermissionManager(); - permissionManager->SetPermissionsWithKey(aPermissionKey, aPerms); + RefPtr permManager = nsPermissionManager::GetInstance(); + if (permManager) { + permManager->SetPermissionsWithKey(aPermissionKey, aPerms); + } + return IPC_OK(); } diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index bf2481f8688a..9184803bbff6 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -5500,7 +5500,10 @@ 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. - nsCOMPtr permManager = services::GetPermissionManager(); + RefPtr permManager = nsPermissionManager::GetInstance(); + if (!permManager) { + return; + } if (mActivePermissionKeys.Contains(aKey)) { return; @@ -5508,12 +5511,9 @@ void ContentParent::EnsurePermissionsByKey(const nsCString& aKey) { mActivePermissionKeys.PutEntry(aKey); nsTArray perms; - nsresult rv = permManager->GetPermissionsWithKey(aKey, perms); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; + if (permManager->GetPermissionsWithKey(aKey, perms)) { + Unused << SendSetPermissionsWithKey(aKey, perms); } - - Unused << SendSetPermissionsWithKey(aKey, perms); } bool ContentParent::NeedsPermissionsUpdate( diff --git a/dom/serviceworkers/ServiceWorkerManager.cpp b/dom/serviceworkers/ServiceWorkerManager.cpp index f658f9c47bc1..b8a82d32c96a 100644 --- a/dom/serviceworkers/ServiceWorkerManager.cpp +++ b/dom/serviceworkers/ServiceWorkerManager.cpp @@ -63,6 +63,7 @@ #include "nsContentUtils.h" #include "nsNetUtil.h" +#include "nsPermissionManager.h" #include "nsProxyRelease.h" #include "nsQueryObject.h" #include "nsTArray.h" @@ -2131,7 +2132,7 @@ void ServiceWorkerManager::DispatchFetchEvent(nsIInterceptedChannel* aChannel, MOZ_DIAGNOSTIC_ASSERT(serviceWorker); - nsCOMPtr continueRunnable = + RefPtr continueRunnable = new ContinueDispatchFetchEventRunnable(serviceWorker->WorkerPrivate(), aChannel, loadGroup, loadInfo->GetIsDocshellReload()); @@ -2141,10 +2142,14 @@ void ServiceWorkerManager::DispatchFetchEvent(nsIInterceptedChannel* aChannel, // wait for them if they have not. nsCOMPtr permissionsRunnable = NS_NewRunnableFunction( "dom::ServiceWorkerManager::DispatchFetchEvent", [=]() { - nsCOMPtr permMgr = - services::GetPermissionManager(); - MOZ_ALWAYS_SUCCEEDS(permMgr->WhenPermissionsAvailable( - serviceWorker->Principal(), continueRunnable)); + RefPtr permMgr = + nsPermissionManager::GetInstance(); + if (permMgr) { + permMgr->WhenPermissionsAvailable(serviceWorker->Principal(), + continueRunnable); + } else { + continueRunnable->HandleError(); + } }); nsCOMPtr uploadChannel = diff --git a/dom/workers/remoteworkers/RemoteWorkerChild.cpp b/dom/workers/remoteworkers/RemoteWorkerChild.cpp index 0e934a5796ab..caa066a4dbb6 100644 --- a/dom/workers/remoteworkers/RemoteWorkerChild.cpp +++ b/dom/workers/remoteworkers/RemoteWorkerChild.cpp @@ -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,10 +474,12 @@ nsresult RemoteWorkerChild::ExecWorkerOnMainThread(RemoteWorkerData&& aData) { } }); - nsCOMPtr permissionManager = - services::GetPermissionManager(); - MOZ_ALWAYS_SUCCEEDS( - permissionManager->WhenPermissionsAvailable(principal, r)); + RefPtr permissionManager = + nsPermissionManager::GetInstance(); + if (!permissionManager) { + return NS_ERROR_FAILURE; + } + permissionManager->WhenPermissionsAvailable(principal, r); } else { if (NS_WARN_IF(!runnable->Dispatch())) { rv = NS_ERROR_FAILURE; diff --git a/dom/workers/remoteworkers/moz.build b/dom/workers/remoteworkers/moz.build index a512f8ed53f6..bfb8efb30a08 100644 --- a/dom/workers/remoteworkers/moz.build +++ b/dom/workers/remoteworkers/moz.build @@ -29,6 +29,7 @@ UNIFIED_SOURCES += [ LOCAL_INCLUDES += [ '/dom/serviceworkers', + '/extensions/permissions', '/xpcom/build', ] diff --git a/extensions/permissions/nsContentBlocker.cpp b/extensions/permissions/nsContentBlocker.cpp index f3b6e9f22f79..c1e31d788e27 100644 --- a/extensions/permissions/nsContentBlocker.cpp +++ b/extensions/permissions/nsContentBlocker.cpp @@ -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->GetHasPreloadPermissions()) { + if (mPermissionManager->HasPreloadPermissions()) { rv = mPermissionManager->LegacyTestPermissionFromURI( aCurrentURI, nullptr, kTypeString[aContentType - 1], &permission); NS_ENSURE_SUCCESS(rv, rv); diff --git a/extensions/permissions/nsPermissionManager.cpp b/extensions/permissions/nsPermissionManager.cpp index b43f1172edb7..5926fa51a253 100644 --- a/extensions/permissions/nsPermissionManager.cpp +++ b/extensions/permissions/nsPermissionManager.cpp @@ -2997,12 +2997,11 @@ void nsPermissionManager::UpdateDB( MOZ_ASSERT(NS_SUCCEEDED(rv)); } -NS_IMETHODIMP -nsPermissionManager::GetPermissionsWithKey(const nsACString& aPermissionKey, - nsTArray& aPerms) { +bool nsPermissionManager::GetPermissionsWithKey( + const nsACString& aPermissionKey, nsTArray& aPerms) { aPerms.Clear(); if (NS_WARN_IF(XRE_IsContentProcess())) { - return NS_ERROR_NOT_AVAILABLE; + return false; } for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) { @@ -3037,14 +3036,13 @@ nsPermissionManager::GetPermissionsWithKey(const nsACString& aPermissionKey, } } - return NS_OK; + return true; } -NS_IMETHODIMP -nsPermissionManager::SetPermissionsWithKey(const nsACString& aPermissionKey, - nsTArray& aPerms) { - if (NS_WARN_IF(XRE_IsParentProcess())) { - return NS_ERROR_NOT_AVAILABLE; +void nsPermissionManager::SetPermissionsWithKey( + const nsACString& aPermissionKey, nsTArray& aPerms) { + if (NS_WARN_IF(XRE_IsContentProcess())) { + return; } RefPtr promise; @@ -3059,7 +3057,7 @@ nsPermissionManager::SetPermissionsWithKey(const nsACString& aPermissionKey, } else if (foundKey) { // NOTE: We shouldn't be sent two InitializePermissionsWithKey for the same // key, but it's possible. - return NS_OK; + return; } mPermissionKeyPromiseMap.Put(aPermissionKey, nullptr); @@ -3087,7 +3085,6 @@ nsPermissionManager::SetPermissionsWithKey(const nsACString& aPermissionKey, perm.expireTime, modificationTime, eNotify, eNoDBOperation, true /* ignoreSessionPermissions */); } - return NS_OK; } /* static */ @@ -3217,14 +3214,13 @@ bool nsPermissionManager::PermissionAvailable(nsIPrincipal* aPrincipal, return true; } -NS_IMETHODIMP -nsPermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal, - nsIRunnable* aRunnable) { +void nsPermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal, + nsIRunnable* aRunnable) { MOZ_ASSERT(aRunnable); if (!XRE_IsContentProcess()) { aRunnable->Run(); - return NS_OK; + return; } nsTArray> promises; @@ -3250,7 +3246,7 @@ nsPermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal, // sensitive. if (promises.IsEmpty()) { aRunnable->Run(); - return NS_OK; + return; } auto* thread = SystemGroup::AbstractMainThreadFor(TaskCategory::Other); @@ -3264,11 +3260,8 @@ nsPermissionManager::WhenPermissionsAvailable(nsIPrincipal* aPrincipal, "nsPermissionManager permission promise rejected. We're " "probably shutting down."); }); - return NS_OK; } -NS_IMETHODIMP -nsPermissionManager::GetHasPreloadPermissions(bool* aResult) { - *aResult = sPreloadPermissionCount > 0; - return NS_OK; +bool nsPermissionManager::HasPreloadPermissions() { + return sPreloadPermissionCount > 0; } diff --git a/extensions/permissions/nsPermissionManager.h b/extensions/permissions/nsPermissionManager.h index 0df12a2fe097..283c1a8cfcb4 100644 --- a/extensions/permissions/nsPermissionManager.h +++ b/extensions/permissions/nsPermissionManager.h @@ -29,6 +29,10 @@ #include "mozilla/Variant.h" #include "mozilla/Vector.h" +namespace IPC { +struct Permission; +} + namespace mozilla { class OriginAttributesPattern; } @@ -290,6 +294,68 @@ 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& 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& 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(); diff --git a/netwerk/base/nsIPermissionManager.idl b/netwerk/base/nsIPermissionManager.idl index b13ce5606560..cd79680623f4 100644 --- a/netwerk/base/nsIPermissionManager.idl +++ b/netwerk/base/nsIPermissionManager.idl @@ -30,18 +30,8 @@ #include "nsISupports.idl" -interface nsIObserver; interface nsIPrincipal; interface nsIPermission; -interface nsIRunnable; - -%{ C++ -namespace IPC { -struct Permission; -} -#include "nsTArrayForwardDeclare.h" -%} -[ref] native IPCPermissionArrayRef(nsTArray); [scriptable, builtinclass, uuid(4dcb3851-eba2-4e42-b236-82d2596fca22)] interface nsIPermissionManager : nsISupports @@ -198,40 +188,6 @@ interface nsIPermissionManager : nsISupports */ readonly attribute Array all; - /** - * 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. * @@ -242,30 +198,6 @@ 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++