зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1728326 - Notify WebExtensions internals when a WebExtensions background service worker is destroyed. r=asuth
This patch introduces the following changes: - In WorkerPrivate::ExtensionAPIAllowed: removed assertion on StaticPrefs::extensions_backgroundServiceWorker_enabled_AtStartup, replaced with just ignoring mExtensionAPIAllowed if the feature is turned out by prefs - Added a new CreateAndDispatchWorkerDestroyedRunnable helper function to create and dispatch a runnable (as a low priority one) to call a new mozIExtensionAPIRequestHandler.onExtensionWorkerDestroyed method. The service worker that has been destroyed is identified by its descriptor ID (the descriptor ID is an integer, assigned on the main process to each ServiceWorkerPrivate instance, and still available when the worker is already being destroyed). Differential Revision: https://phabricator.services.mozilla.com/D124697
This commit is contained in:
Родитель
b3adb549de
Коммит
fe6d66f09d
|
@ -52,6 +52,7 @@
|
|||
#include "mozilla/dom/WorkerBinding.h"
|
||||
#include "mozilla/dom/JSExecutionManager.h"
|
||||
#include "mozilla/dom/WindowContext.h"
|
||||
#include "mozilla/extensions/ExtensionBrowser.h" // extensions::CreateWorkerDestroyedRunnable
|
||||
#include "mozilla/extensions/WebExtensionPolicy.h"
|
||||
#include "mozilla/StorageAccess.h"
|
||||
#include "mozilla/StoragePrincipalHelper.h"
|
||||
|
@ -3528,6 +3529,20 @@ void WorkerPrivate::ScheduleDeletion(WorkerRanOrNot aRanOrNot) {
|
|||
NS_WARNING("Failed to dispatch runnable!");
|
||||
}
|
||||
} else {
|
||||
if (ExtensionAPIAllowed()) {
|
||||
MOZ_ASSERT(IsServiceWorker());
|
||||
RefPtr<Runnable> extWorkerRunnable =
|
||||
extensions::CreateWorkerDestroyedRunnable(ServiceWorkerID(),
|
||||
GetBaseURI());
|
||||
// Dispatch as a low priority runnable.
|
||||
if (NS_FAILED(
|
||||
DispatchToMainThreadForMessaging(extWorkerRunnable.forget()))) {
|
||||
NS_WARNING(
|
||||
"Failed to dispatch runnable to notify extensions worker "
|
||||
"destroyed");
|
||||
}
|
||||
}
|
||||
|
||||
// Note, this uses the lower priority DispatchToMainThreadForMessaging for
|
||||
// dispatching TopLevelWorkerFinishedRunnable to the main thread so that
|
||||
// other relevant runnables are guaranteed to run before it.
|
||||
|
@ -3536,6 +3551,12 @@ void WorkerPrivate::ScheduleDeletion(WorkerRanOrNot aRanOrNot) {
|
|||
if (NS_FAILED(DispatchToMainThreadForMessaging(runnable.forget()))) {
|
||||
NS_WARNING("Failed to dispatch runnable!");
|
||||
}
|
||||
|
||||
// NOTE: Calling any WorkerPrivate methods (or accessing member data) after
|
||||
// this point is unsafe (the TopLevelWorkerFinishedRunnable just dispatched
|
||||
// may be able to call ClearSelfAndParentEventTargetRef on this
|
||||
// WorkerPrivate instance and by the time we get here the WorkerPrivate
|
||||
// instance destructor may have been already called).
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -170,11 +170,9 @@ class WorkerPrivate final : public RelativeTimeline {
|
|||
}
|
||||
|
||||
bool ExtensionAPIAllowed() {
|
||||
// This method should never be actually called if the extension background
|
||||
// service worker is disabled by pref.
|
||||
MOZ_ASSERT(
|
||||
StaticPrefs::extensions_backgroundServiceWorker_enabled_AtStartup());
|
||||
return mExtensionAPIAllowed;
|
||||
return (
|
||||
StaticPrefs::extensions_backgroundServiceWorker_enabled_AtStartup() &&
|
||||
mExtensionAPIAllowed);
|
||||
}
|
||||
|
||||
void SetIsDebuggerRegistered(bool aDebuggerRegistered) {
|
||||
|
|
|
@ -159,4 +159,13 @@ interface mozIExtensionAPIRequestHandler : nsISupports
|
|||
void handleAPIRequest(in nsISupports extension,
|
||||
in mozIExtensionAPIRequest apiRequest,
|
||||
[optional, retval] out mozIExtensionAPIRequestResult apiRequestResult);
|
||||
|
||||
/**
|
||||
* A method called when an extension background service worker is destroyed.
|
||||
*
|
||||
* @param extension An instance of the WebExtensionPolicy webidl interface.
|
||||
* @param serviceWorkerDescriptorId
|
||||
*/
|
||||
void onExtensionWorkerDestroyed(in nsISupports extension,
|
||||
in unsigned long long serviceWorkerDescriptorId);
|
||||
};
|
||||
|
|
|
@ -625,5 +625,25 @@ void RequestWorkerRunnable::ReadResult(JSContext* aCx,
|
|||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
// NotifyWorkerDestroyedRunnable
|
||||
|
||||
nsresult NotifyWorkerDestroyedRunnable::Run() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<WebExtensionPolicy> policy =
|
||||
ExtensionPolicyService::GetSingleton().GetByURL(mSWBaseURI.get());
|
||||
|
||||
nsCOMPtr<mozIExtensionAPIRequestHandler> handler =
|
||||
&ExtensionAPIRequestForwarder::APIRequestHandler();
|
||||
MOZ_ASSERT(handler);
|
||||
|
||||
if (NS_FAILED(handler->OnExtensionWorkerDestroyed(policy, mSWDescriptorId))) {
|
||||
NS_WARNING(
|
||||
"nsIExtensionAPIRequestHandler.onExtensionWorkerDestroyed call failed");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace extensions
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -195,6 +195,29 @@ class RequestWorkerRunnable : public dom::WorkerMainThreadRunnable {
|
|||
ExtensionAPIRequestForwarder* mOuterRequest;
|
||||
};
|
||||
|
||||
class NotifyWorkerDestroyedRunnable : public Runnable {
|
||||
uint64_t mSWDescriptorId;
|
||||
nsCOMPtr<nsIURI> mSWBaseURI;
|
||||
|
||||
public:
|
||||
explicit NotifyWorkerDestroyedRunnable(
|
||||
const uint64_t aServiceWorkerDescriptorId,
|
||||
const nsCOMPtr<nsIURI>& aWorkerBaseURI)
|
||||
: Runnable("extensions::NotifyWorkerDestroyedRunnable"),
|
||||
mSWDescriptorId(aServiceWorkerDescriptorId),
|
||||
mSWBaseURI(aWorkerBaseURI) {
|
||||
MOZ_ASSERT(mSWDescriptorId > 0);
|
||||
MOZ_ASSERT(mSWBaseURI);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING_INHERITED(NotifyWorkerDestroyedRunnable, Runnable)
|
||||
|
||||
private:
|
||||
~NotifyWorkerDestroyedRunnable() = default;
|
||||
};
|
||||
|
||||
} // namespace extensions
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -97,6 +97,15 @@ bool ExtensionAPIAllowed(JSContext* aCx, JSObject* aGlobal) {
|
|||
#endif
|
||||
}
|
||||
|
||||
already_AddRefed<Runnable> CreateWorkerDestroyedRunnable(
|
||||
const uint64_t aServiceWorkerDescriptorId,
|
||||
const nsCOMPtr<nsIURI>& aWorkerBaseURI) {
|
||||
RefPtr<NotifyWorkerDestroyedRunnable> runnable =
|
||||
new NotifyWorkerDestroyedRunnable(aServiceWorkerDescriptorId,
|
||||
aWorkerBaseURI);
|
||||
return runnable.forget();
|
||||
}
|
||||
|
||||
void ExtensionBrowser::SetLastError(JS::Handle<JS::Value> aLastError) {
|
||||
mLastError.set(aLastError);
|
||||
mCheckedLastError = false;
|
||||
|
|
|
@ -27,6 +27,10 @@ class ExtensionTest;
|
|||
|
||||
bool ExtensionAPIAllowed(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
already_AddRefed<Runnable> CreateWorkerDestroyedRunnable(
|
||||
const uint64_t aServiceWorkerDescriptorId,
|
||||
const nsCOMPtr<nsIURI>& aWorkerBaseURI);
|
||||
|
||||
class ExtensionBrowser final : public nsISupports, public nsWrapperCache {
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
JS::Heap<JS::Value> mLastError;
|
||||
|
|
Загрузка…
Ссылка в новой задаче