Bug 1618546 - give worker debugger globals their own clients r=asuth,webidl,smaug

- Worker debugger globals gets a client with a null principal
- Ensure globals are created before script loads
- Introduce WorkerGlobalScopeBase to share code
- Transfer ClientSource ownership from WorkerPrivate to worker globals
- Require getting clients from the globals instead of WorkerPrivate with the
  exception of getting the reserved client before the non-debugger global is
  created

Differential Revision: https://phabricator.services.mozilla.com/D68936
This commit is contained in:
Perry Jiang 2020-04-21 06:50:53 +00:00
Родитель 044488a3af
Коммит 3446310d6c
10 изменённых файлов: 576 добавлений и 679 удалений

Просмотреть файл

@ -534,7 +534,7 @@ already_AddRefed<Promise> FetchRequest(nsIGlobalObject* aGlobal,
return nullptr;
}
Maybe<ClientInfo> clientInfo(worker->GetClientInfo());
Maybe<ClientInfo> clientInfo(worker->GlobalScope()->GetClientInfo());
if (clientInfo.isNothing()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
@ -546,7 +546,7 @@ already_AddRefed<Promise> FetchRequest(nsIGlobalObject* aGlobal,
}
RefPtr<MainThreadFetchRunnable> run = new MainThreadFetchRunnable(
resolver, clientInfo.ref(), worker->GetController(),
resolver, clientInfo.ref(), worker->GlobalScope()->GetController(),
worker->CSPEventListener(), r, std::move(stack));
worker->DispatchToMainThread(run.forget());
}

Просмотреть файл

@ -22,6 +22,8 @@ interface WorkerDebuggerGlobalScope : EventTarget {
attribute EventHandler onmessage;
attribute EventHandler onmessageerror;
[Throws]
void setImmediate(Function handler);

Просмотреть файл

@ -1941,7 +1941,7 @@ class ChannelGetterRunnable final : public WorkerMainThreadRunnable {
// ClientInfo should always be present since this should not be called
// if parent's status is greater than Running.
,
mClientInfo(aParentWorker->GetClientInfo().ref()),
mClientInfo(aParentWorker->GlobalScope()->GetClientInfo().ref()),
mLoadInfo(aLoadInfo),
mResult(NS_ERROR_FAILURE) {
MOZ_ASSERT(aParentWorker);
@ -2045,23 +2045,6 @@ bool ScriptExecutorRunnable::PreRun(WorkerPrivate* aWorkerPrivate) {
// where the CSP code expects it!
aWorkerPrivate->StoreCSPOnClient();
AutoJSAPI jsapi;
jsapi.Init();
WorkerGlobalScope* globalScope =
aWorkerPrivate->GetOrCreateGlobalScope(jsapi.cx());
if (NS_WARN_IF(!globalScope)) {
NS_WARNING("Failed to make global!");
// There's no way to report the exception on jsapi right now, because there
// is no way to even enter a compartment on this thread anymore. Just clear
// the exception. We'll report some sort of error to our caller in
// ShutdownScriptLoader, but it will get squelched for the same reason we're
// squelching here: all the error reporting machinery relies on being able
// to enter a compartment to report the error.
jsapi.ClearException();
return false;
}
return true;
}
@ -2133,7 +2116,9 @@ bool ScriptExecutorRunnable::WorkerRun(JSContext* aCx,
// Client execution ready and possible controlled by a service worker.
if (mIsWorkerScript) {
if (mScriptLoader.mController.isSome()) {
aWorkerPrivate->Control(mScriptLoader.mController.ref());
MOZ_ASSERT(mScriptLoader.mWorkerScriptType == WorkerScript,
"Debugger clients can't be controlled.");
aWorkerPrivate->GlobalScope()->Control(mScriptLoader.mController.ref());
}
aWorkerPrivate->ExecutionReady();
}
@ -2294,8 +2279,13 @@ void LoadAllScripts(WorkerPrivate* aWorkerPrivate,
Maybe<ClientInfo> clientInfo;
Maybe<ServiceWorkerDescriptor> controller;
if (!aIsMainScript) {
clientInfo = aWorkerPrivate->GetClientInfo();
controller = aWorkerPrivate->GetController();
nsIGlobalObject* global =
aWorkerScriptType == WorkerScript
? static_cast<nsIGlobalObject*>(aWorkerPrivate->GlobalScope())
: aWorkerPrivate->DebuggerGlobalScope();
clientInfo = global->GetClientInfo();
controller = global->GetController();
}
RefPtr<ScriptLoaderRunnable> loader = new ScriptLoaderRunnable(
@ -2428,7 +2418,12 @@ void LoadMainScript(WorkerPrivate* aWorkerPrivate,
// We are loading the main script, so the worker's Client must be
// reserved.
info->mReservedClientInfo = aWorkerPrivate->GetClientInfo();
if (aWorkerScriptType == WorkerScript) {
info->mReservedClientInfo = aWorkerPrivate->GlobalScope()->GetClientInfo();
} else {
info->mReservedClientInfo =
aWorkerPrivate->DebuggerGlobalScope()->GetClientInfo();
}
LoadAllScripts(aWorkerPrivate, std::move(aOriginStack), loadInfos, true,
aWorkerScriptType, aRv);

Просмотреть файл

@ -8,14 +8,15 @@
#define mozilla_dom_workers_scriptloader_h__
#include "mozilla/dom/WorkerCommon.h"
#include "nsIContentPolicy.h"
#include "nsStringFwd.h"
class nsIPrincipal;
class nsIURI;
class nsILoadGroup;
class nsIChannel;
class nsICookieJarSettings;
class nsILoadGroup;
class nsIPrincipal;
class nsIReferrerInfo;
class nsIURI;
namespace mozilla {
@ -23,6 +24,8 @@ class ErrorResult;
namespace dom {
class ClientInfo;
class Document;
struct WorkerLoadInfo;
class WorkerPrivate;
class SerializedStackHolder;

Просмотреть файл

@ -85,10 +85,6 @@ class CompileDebuggerScriptRunnable final : public WorkerDebuggerRunnable {
return false;
}
if (NS_WARN_IF(!aWorkerPrivate->EnsureClientSource())) {
return false;
}
if (NS_WARN_IF(!aWorkerPrivate->EnsureCSPEventListener())) {
return false;
}

Просмотреть файл

@ -19,10 +19,8 @@
#include "mozilla/ScopeExit.h"
#include "mozilla/StaticPrefs_browser.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/CallbackDebuggerNotification.h"
#include "mozilla/dom/ClientManager.h"
#include "mozilla/dom/ClientSource.h"
#include "mozilla/dom/ClientState.h"
#include "mozilla/dom/Console.h"
#include "mozilla/dom/DOMTypes.h"
@ -53,6 +51,7 @@
#include "nsNetUtil.h"
#include "nsIMemoryReporter.h"
#include "nsIPermissionManager.h"
#include "nsIProtocolHandler.h"
#include "nsIScriptError.h"
#include "nsIURI.h"
#include "nsIURL.h"
@ -77,7 +76,6 @@
#include "WorkerNavigator.h"
#include "WorkerRef.h"
#include "WorkerRunnable.h"
#include "WorkerScope.h"
#include "WorkerThread.h"
#include "nsThreadManager.h"
@ -333,7 +331,9 @@ class CompileScriptRunnable final : public WorkerDebuggeeRunnable {
WorkerPrivate* aWorkerPrivate) override {
aWorkerPrivate->AssertIsOnWorkerThread();
if (NS_WARN_IF(!aWorkerPrivate->EnsureClientSource())) {
WorkerGlobalScope* globalScope =
aWorkerPrivate->GetOrCreateGlobalScope(aCx);
if (NS_WARN_IF(!globalScope)) {
return false;
}
@ -354,15 +354,6 @@ class CompileScriptRunnable final : public WorkerDebuggeeRunnable {
return false;
}
WorkerGlobalScope* globalScope = aWorkerPrivate->GlobalScope();
if (NS_WARN_IF(!globalScope)) {
// We never got as far as calling GetOrCreateGlobalScope, or it failed.
// We have no way to enter a compartment, hence no sane way to report this
// error. :(
rv.SuppressException();
return false;
}
// Make sure to propagate exceptions from rv onto aCx, so that they will get
// reported after we return. We want to propagate just JS exceptions,
// because all the other errors are handled when the script is loaded.
@ -1377,8 +1368,9 @@ nsresult WorkerPrivate::SetCSPFromHeaderValues(
void WorkerPrivate::StoreCSPOnClient() {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
if (data->mClientSource && mLoadInfo.mCSPInfo) {
data->mClientSource->SetCspInfo(*mLoadInfo.mCSPInfo.get());
MOZ_ASSERT(data->mScope);
if (mLoadInfo.mCSPInfo) {
data->mScope->GetClientSource()->SetCspInfo(*mLoadInfo.mCSPInfo);
}
}
@ -2545,7 +2537,7 @@ nsresult WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
loadInfo.mOriginAttributes = aParent->GetOriginAttributes();
loadInfo.mServiceWorkersTestingInWindow =
aParent->ServiceWorkersTestingInWindow();
loadInfo.mParentController = aParent->GetController();
loadInfo.mParentController = aParent->GlobalScope()->GetController();
loadInfo.mWatchedByDevtools = aParent->IsWatchedByDevtools();
} else {
AssertIsOnMainThread();
@ -2893,10 +2885,6 @@ void WorkerPrivate::DoRunLoop(JSContext* aCx) {
// If we're supposed to die then we should exit the loop.
if (currentStatus == Killing) {
// The ClientSource should be cleared in NotifyInternal() when we reach
// or pass Canceling.
MOZ_DIAGNOSTIC_ASSERT(!data->mClientSource);
// Flush uncaught rejections immediately, without
// waiting for a next tick.
PromiseDebugging::FlushUncaughtRejections();
@ -3060,36 +3048,31 @@ nsISerialEventTarget* WorkerPrivate::HybridEventTarget() {
return mWorkerHybridEventTarget;
}
bool WorkerPrivate::EnsureClientSource() {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
if (data->mClientSource) {
return true;
}
ClientType type;
ClientType WorkerPrivate::GetClientType() const {
switch (Type()) {
case WorkerTypeDedicated:
type = ClientType::Worker;
break;
return ClientType::Worker;
case WorkerTypeShared:
type = ClientType::Sharedworker;
break;
return ClientType::Sharedworker;
case WorkerTypeService:
type = ClientType::Serviceworker;
break;
return ClientType::Serviceworker;
default:
MOZ_CRASH("unknown worker type!");
}
}
data->mClientSource = ClientManager::CreateSource(
type, mWorkerHybridEventTarget, GetPrincipalInfo());
MOZ_DIAGNOSTIC_ASSERT(data->mClientSource);
UniquePtr<ClientSource> WorkerPrivate::CreateClientSource() {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
MOZ_ASSERT(!data->mScope, "Client should be created before the global");
data->mClientSource->SetAgentClusterId(mAgentClusterId);
auto clientSource = ClientManager::CreateSource(
GetClientType(), mWorkerHybridEventTarget, GetPrincipalInfo());
MOZ_DIAGNOSTIC_ASSERT(clientSource);
clientSource->SetAgentClusterId(mAgentClusterId);
if (data->mFrozen) {
data->mClientSource->Freeze();
clientSource->Freeze();
}
// Shortly after the client is reserved we will try loading the main script
@ -3112,10 +3095,10 @@ bool WorkerPrivate::EnsureClientSource() {
// service worker. So avoid the sync overhead here if we are starting a
// service worker or a chrome worker.
if (Type() != WorkerTypeService && !IsChromeWorker()) {
data->mClientSource->WorkerSyncPing(this);
clientSource->WorkerSyncPing(this);
}
return true;
return clientSource;
}
bool WorkerPrivate::EnsureCSPEventListener() {
@ -3141,31 +3124,6 @@ void WorkerPrivate::EnsurePerformanceStorage() {
}
}
Maybe<ClientInfo> WorkerPrivate::GetClientInfo() const {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
Maybe<ClientInfo> clientInfo;
if (!data->mClientSource) {
MOZ_DIAGNOSTIC_ASSERT(mStatus >= Canceling);
return clientInfo;
}
clientInfo.emplace(data->mClientSource->Info());
return clientInfo;
}
const ClientState WorkerPrivate::GetClientState() const {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
MOZ_DIAGNOSTIC_ASSERT(data->mClientSource);
Result<ClientState, ErrorResult> res = data->mClientSource->SnapshotState();
if (res.isOk()) {
return res.unwrap();
}
// XXXbz Why is it OK to just ignore errors and return a default-initialized
// state here?
res.unwrapErr().SuppressException();
return ClientState();
}
bool WorkerPrivate::GetExecutionGranted() const {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
return data->mJSThreadExecutionGranted;
@ -3209,41 +3167,6 @@ void WorkerPrivate::SetExecutionManager(JSExecutionManager* aManager) {
data->mExecutionManager = aManager;
}
const Maybe<ServiceWorkerDescriptor> WorkerPrivate::GetController() {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
{
MutexAutoLock lock(mMutex);
if (mStatus >= Canceling) {
return Maybe<ServiceWorkerDescriptor>();
}
}
MOZ_DIAGNOSTIC_ASSERT(data->mClientSource);
return data->mClientSource->GetController();
}
void WorkerPrivate::Control(const ServiceWorkerDescriptor& aServiceWorker) {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
MOZ_DIAGNOSTIC_ASSERT(!IsChromeWorker());
MOZ_DIAGNOSTIC_ASSERT(Type() != WorkerTypeService);
{
MutexAutoLock lock(mMutex);
if (mStatus >= Canceling) {
return;
}
}
MOZ_DIAGNOSTIC_ASSERT(data->mClientSource);
if (IsBlobURI(mLoadInfo.mBaseURI)) {
// Blob URL workers can only become controlled by inheriting from
// their parent. Make sure to note this properly.
data->mClientSource->InheritController(aServiceWorker);
} else {
// Otherwise this is a normal interception and we simply record the
// controller locally.
data->mClientSource->SetController(aServiceWorker);
}
}
void WorkerPrivate::ExecutionReady() {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
{
@ -3252,8 +3175,11 @@ void WorkerPrivate::ExecutionReady() {
return;
}
}
MOZ_DIAGNOSTIC_ASSERT(data->mClientSource);
data->mClientSource->WorkerExecutionReady(this);
MOZ_ASSERT(data->mScope);
auto& clientSource = data->mScope->GetClientSource();
MOZ_DIAGNOSTIC_ASSERT(clientSource);
clientSource->WorkerExecutionReady(this);
}
void WorkerPrivate::InitializeGCTimers() {
@ -3613,12 +3539,14 @@ void WorkerPrivate::ClearDebuggerEventQueue() {
bool WorkerPrivate::FreezeInternal() {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
MOZ_ASSERT(data->mScope);
NS_ASSERTION(!data->mFrozen, "Already frozen!");
AutoYieldJSThreadExecution yield;
if (data->mClientSource) {
data->mClientSource->Freeze();
auto& clientSource = data->mScope->GetClientSource();
if (clientSource) {
clientSource->Freeze();
}
data->mFrozen = true;
@ -3632,7 +3560,7 @@ bool WorkerPrivate::FreezeInternal() {
bool WorkerPrivate::ThawInternal() {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
MOZ_ASSERT(data->mScope);
NS_ASSERTION(data->mFrozen, "Not yet frozen!");
for (uint32_t index = 0; index < data->mChildWorkers.Length(); index++) {
@ -3641,8 +3569,9 @@ bool WorkerPrivate::ThawInternal() {
data->mFrozen = false;
if (data->mClientSource) {
data->mClientSource->Thaw();
auto& clientSource = data->mScope->GetClientSource();
if (clientSource) {
clientSource->Thaw();
}
return true;
@ -4343,7 +4272,6 @@ bool WorkerPrivate::NotifyInternal(WorkerStatus aStatus) {
if (aStatus >= Canceling) {
MutexAutoUnlock unlock(mMutex);
data->mClientSource.reset();
if (data->mScope) {
data->mScope->NoteTerminating();
}
@ -5080,56 +5008,55 @@ bool WorkerPrivate::ConnectMessagePort(JSContext* aCx,
WorkerGlobalScope* WorkerPrivate::GetOrCreateGlobalScope(JSContext* aCx) {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
if (!data->mScope) {
RefPtr<WorkerGlobalScope> globalScope;
if (IsSharedWorker()) {
globalScope = new SharedWorkerGlobalScope(this, WorkerName());
} else if (IsServiceWorker()) {
globalScope = new ServiceWorkerGlobalScope(
this, GetServiceWorkerRegistrationDescriptor());
} else {
globalScope = new DedicatedWorkerGlobalScope(this, WorkerName());
}
JS::Rooted<JSObject*> global(aCx);
NS_ENSURE_TRUE(globalScope->WrapGlobalObject(aCx, &global), nullptr);
JSAutoRealm ar(aCx, global);
// RegisterBindings() can spin a nested event loop so we have to set mScope
// before calling it, and we have to make sure to unset mScope if it fails.
data->mScope = std::move(globalScope);
if (!RegisterBindings(aCx, global)) {
data->mScope = nullptr;
return nullptr;
}
JS_FireOnNewGlobalObject(aCx, global);
if (data->mScope) {
return data->mScope;
}
if (IsSharedWorker()) {
data->mScope = new SharedWorkerGlobalScope(
WrapNotNull(this), CreateClientSource(), WorkerName());
} else if (IsServiceWorker()) {
data->mScope =
new ServiceWorkerGlobalScope(WrapNotNull(this), CreateClientSource(),
GetServiceWorkerRegistrationDescriptor());
} else {
data->mScope = new DedicatedWorkerGlobalScope(
WrapNotNull(this), CreateClientSource(), WorkerName());
}
JS::Rooted<JSObject*> global(aCx);
NS_ENSURE_TRUE(data->mScope->WrapGlobalObject(aCx, &global), nullptr);
JSAutoRealm ar(aCx, global);
if (!RegisterBindings(aCx, global)) {
data->mScope = nullptr;
return nullptr;
}
JS_FireOnNewGlobalObject(aCx, global);
return data->mScope;
}
WorkerDebuggerGlobalScope* WorkerPrivate::CreateDebuggerGlobalScope(
JSContext* aCx) {
MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
MOZ_ASSERT(!data->mDebuggerScope);
RefPtr<WorkerDebuggerGlobalScope> globalScope =
new WorkerDebuggerGlobalScope(this);
// The debugger global gets a dummy client, not the "real" client used by the
// debugee worker.
auto clientSource = ClientManager::CreateSource(
GetClientType(), HybridEventTarget(), NullPrincipalInfo());
data->mDebuggerScope =
new WorkerDebuggerGlobalScope(WrapNotNull(this), std::move(clientSource));
JS::Rooted<JSObject*> global(aCx);
NS_ENSURE_TRUE(globalScope->WrapGlobalObject(aCx, &global), nullptr);
NS_ENSURE_TRUE(data->mDebuggerScope->WrapGlobalObject(aCx, &global), nullptr);
JSAutoRealm ar(aCx, global);
// RegisterDebuggerBindings() can spin a nested event loop so we have to set
// mDebuggerScope before calling it, and we have to make sure to unset
// mDebuggerScope if it fails.
data->mDebuggerScope = std::move(globalScope);
if (!RegisterDebuggerBindings(aCx, global)) {
data->mDebuggerScope = nullptr;
return nullptr;

Просмотреть файл

@ -9,33 +9,36 @@
#define mozilla_dom_workers_workerprivate_h__
#include "MainThreadUtils.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/dom/WorkerStatus.h"
#include "mozilla/Assertions.h"
#include "ScriptLoader.h"
#include "js/ContextOptions.h"
#include "mozilla/Attributes.h"
#include "mozilla/CondVar.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/Maybe.h"
#include "mozilla/MozPromise.h"
#include "mozilla/PerformanceCounter.h"
#include "mozilla/RelativeTimeline.h"
#include "mozilla/Result.h"
#include "mozilla/StorageAccess.h"
#include "mozilla/ThreadBound.h"
#include "mozilla/ThreadSafeWeakPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/UseCounter.h"
#include "mozilla/dom/ClientSource.h"
#include "mozilla/dom/RemoteWorkerChild.h"
#include "mozilla/dom/Worker.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/dom/WorkerLoadInfo.h"
#include "mozilla/dom/WorkerScope.h"
#include "mozilla/dom/WorkerStatus.h"
#include "mozilla/dom/workerinternals/JSSettings.h"
#include "mozilla/dom/workerinternals/Queue.h"
#include "nsContentUtils.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIEventTarget.h"
#include "nsILoadInfo.h"
#include "nsTObserverArray.h"
#include "js/ContextOptions.h"
#include "mozilla/dom/RemoteWorkerChild.h"
#include "mozilla/dom/Worker.h"
#include "mozilla/dom/WorkerLoadInfo.h"
#include "mozilla/dom/workerinternals/JSSettings.h"
#include "mozilla/dom/workerinternals/Queue.h"
#include "mozilla/PerformanceCounter.h"
#include "mozilla/ThreadBound.h"
class nsIThreadInternal;
namespace mozilla {
@ -453,7 +456,7 @@ class WorkerPrivate : public RelativeTimeline {
void DumpCrashInformation(nsACString& aString);
bool EnsureClientSource();
ClientType GetClientType() const;
bool EnsureCSPEventListener();
@ -461,10 +464,6 @@ class WorkerPrivate : public RelativeTimeline {
void EnsurePerformanceCounter();
Maybe<ClientInfo> GetClientInfo() const;
const ClientState GetClientState() const;
bool GetExecutionGranted() const;
void SetExecutionGranted(bool aGranted);
@ -474,10 +473,6 @@ class WorkerPrivate : public RelativeTimeline {
JSExecutionManager* GetExecutionManager() const;
void SetExecutionManager(JSExecutionManager* aManager);
const Maybe<ServiceWorkerDescriptor> GetController();
void Control(const ServiceWorkerDescriptor& aServiceWorker);
void ExecutionReady();
PerformanceStorage* GetPerformanceStorage();
@ -624,10 +619,9 @@ class WorkerPrivate : public RelativeTimeline {
return GetServiceWorkerDescriptor().Scope();
}
nsIURI* GetBaseURI() const {
AssertIsOnMainThread();
return mLoadInfo.mBaseURI;
}
// This value should never change after the script load completes. Before
// then, it may only be called on the main thread.
nsIURI* GetBaseURI() const { return mLoadInfo.mBaseURI; }
void SetBaseURI(nsIURI* aBaseURI);
@ -1047,6 +1041,8 @@ class WorkerPrivate : public RelativeTimeline {
void ReportUseCounters();
UniquePtr<ClientSource> CreateClientSource();
Maybe<nsILoadInfo::CrossOriginEmbedderPolicy> GetOwnerEmbedderPolicy() const;
class EventTarget;
@ -1070,7 +1066,7 @@ class WorkerPrivate : public RelativeTimeline {
// This is the worker name for shared workers and dedicated workers.
nsString mWorkerName;
WorkerType mWorkerType;
const WorkerType mWorkerType;
// The worker is owned by its thread, which is represented here. This is set
// in Constructor() and emptied by WorkerFinishedRunnable, and conditionally
@ -1194,8 +1190,6 @@ class WorkerPrivate : public RelativeTimeline {
RefPtr<MemoryReporter> mMemoryReporter;
UniquePtr<ClientSource> mClientSource;
// While running a nested event loop, whether a sync loop or a debugger
// event loop we want to keep track of which global is running it, if any,
// so runnables that run off that event loop can get at that information. In

Просмотреть файл

@ -6,58 +6,52 @@
#include "WorkerScope.h"
#include <utility>
#include "Crypto.h"
#include "Principal.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/MozPromise.h"
#include "mozilla/StorageAccess.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/Clients.h"
#include "mozilla/dom/ClientState.h"
#include "mozilla/dom/Console.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/CSPEvalChecker.h"
#include "mozilla/dom/Clients.h"
#include "mozilla/dom/DOMMozPromiseRequestHolder.h"
#include "mozilla/dom/DebuggerNotification.h"
#include "mozilla/dom/DedicatedWorkerGlobalScopeBinding.h"
#include "mozilla/dom/Fetch.h"
#include "mozilla/dom/FunctionBinding.h"
#include "mozilla/dom/IDBFactory.h"
#include "mozilla/dom/ImageBitmap.h"
#include "mozilla/dom/ImageBitmapBinding.h"
#include "mozilla/dom/Performance.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseWorkerProxy.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h"
#include "mozilla/dom/ServiceWorkerManager.h"
#include "mozilla/dom/ServiceWorkerRegistration.h"
#include "mozilla/dom/ServiceWorkerUtils.h"
#include "mozilla/dom/SharedWorkerGlobalScopeBinding.h"
#include "mozilla/dom/SimpleGlobalObject.h"
#include "mozilla/dom/TimeoutHandler.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
#include "mozilla/dom/JSExecutionManager.h"
#include "mozilla/dom/WorkerGlobalScopeBinding.h"
#include "mozilla/dom/WorkerLocation.h"
#include "mozilla/dom/WorkerNavigator.h"
#include "mozilla/dom/WorkerRunnable.h"
#include "mozilla/dom/cache/CacheStorage.h"
#include "mozilla/StorageAccess.h"
#include "GeckoProfiler.h"
#include "nsContentUtils.h"
#include "nsAtom.h"
#include "nsDebug.h"
#include "nsISerialEventTarget.h"
#include "nsJSUtils.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/dom/Document.h"
#include "nsIScriptError.h"
#include "xpcpublic.h"
#ifdef ANDROID
# include <android/log.h>
#endif
#include "Crypto.h"
#include "Principal.h"
#include "RuntimeService.h"
#include "ScriptLoader.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#include "mozilla/dom/ServiceWorkerManager.h"
#include "mozilla/dom/ServiceWorkerRegistration.h"
#ifdef XP_WIN
# undef PostMessage
#endif
@ -66,6 +60,7 @@ namespace mozilla {
namespace dom {
using mozilla::dom::cache::CacheStorage;
using mozilla::dom::workerinternals::NamedWorkerGlobalScopeMixin;
using mozilla::ipc::PrincipalInfo;
class WorkerScriptTimeoutHandler final : public ScriptTimeoutHandler {
@ -114,78 +109,113 @@ bool WorkerScriptTimeoutHandler::Call(const char* aExecutionReason) {
return true;
};
WorkerGlobalScope::WorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
: mSerialEventTarget(aWorkerPrivate->HybridEventTarget()),
mWindowInteractionsAllowed(0),
mWorkerPrivate(aWorkerPrivate) {
mWorkerPrivate->AssertIsOnWorkerThread();
NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScopeBase)
// We should always have an event target when the global is created.
MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScopeBase,
DOMEventTargetHelper)
tmp->mWorkerPrivate->AssertIsOnWorkerThread();
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSerialEventTarget)
tmp->TraverseObjectsInGlobal(cb);
tmp->mWorkerPrivate->TraverseTimeouts(cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScopeBase,
DOMEventTargetHelper)
tmp->mWorkerPrivate->AssertIsOnWorkerThread();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSerialEventTarget)
tmp->UnlinkObjectsInGlobal();
tmp->mWorkerPrivate->UnlinkTimeouts();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerGlobalScopeBase,
DOMEventTargetHelper)
tmp->mWorkerPrivate->AssertIsOnWorkerThread();
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_ADDREF_INHERITED(WorkerGlobalScopeBase, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(WorkerGlobalScopeBase, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerGlobalScopeBase)
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
WorkerGlobalScopeBase::WorkerGlobalScopeBase(
NotNull<WorkerPrivate*> aWorkerPrivate,
UniquePtr<ClientSource> aClientSource)
: mWorkerPrivate(aWorkerPrivate),
mClientSource(std::move(aClientSource)),
mSerialEventTarget(aWorkerPrivate->HybridEventTarget()) {
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(mClientSource);
MOZ_DIAGNOSTIC_ASSERT(
mSerialEventTarget,
"There should be an event target when a worker global is created.");
// In workers, each DETH must have an owner. Because the global scope doesn't
// have one, let's set it as owner of itself.
BindToOwner(static_cast<nsIGlobalObject*>(this));
}
WorkerGlobalScope::~WorkerGlobalScope() {
JSObject* WorkerGlobalScopeBase::GetGlobalJSObject() {
mWorkerPrivate->AssertIsOnWorkerThread();
return GetWrapper();
}
NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScope)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScope,
DOMEventTargetHelper)
tmp->mWorkerPrivate->AssertIsOnWorkerThread();
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDebuggerNotificationManager)
tmp->TraverseObjectsInGlobal(cb);
tmp->mWorkerPrivate->TraverseTimeouts(cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScope,
DOMEventTargetHelper)
tmp->mWorkerPrivate->AssertIsOnWorkerThread();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDebuggerNotificationManager)
tmp->UnlinkObjectsInGlobal();
tmp->mWorkerPrivate->UnlinkTimeouts();
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerGlobalScope,
DOMEventTargetHelper)
tmp->mWorkerPrivate->AssertIsOnWorkerThread();
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_ADDREF_INHERITED(WorkerGlobalScope, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(WorkerGlobalScope, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerGlobalScope)
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
JSObject* WorkerGlobalScope::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
MOZ_CRASH("We should never get here!");
JSObject* WorkerGlobalScopeBase::GetGlobalJSObjectPreserveColor() const {
mWorkerPrivate->AssertIsOnWorkerThread();
return GetWrapperPreserveColor();
}
void WorkerGlobalScope::NoteTerminating() { StartDying(); }
bool WorkerGlobalScopeBase::IsSharedMemoryAllowed() const {
mWorkerPrivate->AssertIsOnWorkerThread();
return mWorkerPrivate->IsSharedMemoryAllowed();
}
already_AddRefed<Console> WorkerGlobalScope::GetConsole(ErrorResult& aRv) {
void WorkerGlobalScopeBase::Control(
const ServiceWorkerDescriptor& aServiceWorker) {
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_DIAGNOSTIC_ASSERT(!mWorkerPrivate->IsChromeWorker());
MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate->Type() != WorkerTypeService);
if (IsBlobURI(mWorkerPrivate->GetBaseURI())) {
// Blob URL workers can only become controlled by inheriting from
// their parent. Make sure to note this properly.
mClientSource->InheritController(aServiceWorker);
} else {
// Otherwise this is a normal interception and we simply record the
// controller locally.
mClientSource->SetController(aServiceWorker);
}
}
nsresult WorkerGlobalScopeBase::Dispatch(
TaskCategory aCategory, already_AddRefed<nsIRunnable>&& aRunnable) {
return EventTargetFor(aCategory)->Dispatch(std::move(aRunnable),
NS_DISPATCH_NORMAL);
}
nsISerialEventTarget* WorkerGlobalScopeBase::EventTargetFor(
TaskCategory) const {
mWorkerPrivate->AssertIsOnWorkerThread();
return mSerialEventTarget;
}
void WorkerGlobalScopeBase::Atob(const nsAString& aAtob, nsAString& aOut,
ErrorResult& aRv) const {
mWorkerPrivate->AssertIsOnWorkerThread();
aRv = nsContentUtils::Atob(aAtob, aOut);
}
void WorkerGlobalScopeBase::Btoa(const nsAString& aBtoa, nsAString& aOut,
ErrorResult& aRv) const {
mWorkerPrivate->AssertIsOnWorkerThread();
aRv = nsContentUtils::Btoa(aBtoa, aOut);
}
already_AddRefed<Console> WorkerGlobalScopeBase::GetConsole(ErrorResult& aRv) {
mWorkerPrivate->AssertIsOnWorkerThread();
if (!mConsole) {
@ -199,6 +229,39 @@ already_AddRefed<Console> WorkerGlobalScope::GetConsole(ErrorResult& aRv) {
return console.forget();
}
uint64_t WorkerGlobalScopeBase::WindowID() const {
return mWorkerPrivate->WindowID();
}
NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerGlobalScope)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerGlobalScope,
WorkerGlobalScopeBase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDebuggerNotificationManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerGlobalScope,
WorkerGlobalScopeBase)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDebuggerNotificationManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(WorkerGlobalScope,
WorkerGlobalScopeBase,
nsISupportsWeakReference)
Crypto* WorkerGlobalScope::GetCrypto(ErrorResult& aError) {
mWorkerPrivate->AssertIsOnWorkerThread();
@ -211,7 +274,6 @@ Crypto* WorkerGlobalScope::GetCrypto(ErrorResult& aError) {
already_AddRefed<CacheStorage> WorkerGlobalScope::GetCaches(ErrorResult& aRv) {
if (!mCacheStorage) {
MOZ_ASSERT(mWorkerPrivate);
mCacheStorage = CacheStorage::CreateOnWorker(cache::DEFAULT_NAMESPACE, this,
mWorkerPrivate, aRv);
}
@ -231,9 +293,7 @@ already_AddRefed<WorkerLocation> WorkerGlobalScope::Location() {
mWorkerPrivate->AssertIsOnWorkerThread();
if (!mLocation) {
WorkerPrivate::LocationInfo& info = mWorkerPrivate->GetLocationInfo();
mLocation = WorkerLocation::Create(info);
mLocation = WorkerLocation::Create(mWorkerPrivate->GetLocationInfo());
MOZ_ASSERT(mLocation);
}
@ -407,18 +467,6 @@ bool WorkerGlobalScope::CrossOriginIsolated() const {
return mWorkerPrivate->CrossOriginIsolated();
}
void WorkerGlobalScope::Atob(const nsAString& aAtob, nsAString& aOutput,
ErrorResult& aRv) const {
mWorkerPrivate->AssertIsOnWorkerThread();
aRv = nsContentUtils::Atob(aAtob, aOutput);
}
void WorkerGlobalScope::Btoa(const nsAString& aBtoa, nsAString& aOutput,
ErrorResult& aRv) const {
mWorkerPrivate->AssertIsOnWorkerThread();
aRv = nsContentUtils::Btoa(aBtoa, aOutput);
}
void WorkerGlobalScope::Dump(const Optional<nsAString>& aString) const {
mWorkerPrivate->AssertIsOnWorkerThread();
@ -524,22 +572,6 @@ already_AddRefed<Promise> WorkerGlobalScope::CreateImageBitmap(
Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
}
nsresult WorkerGlobalScope::Dispatch(
TaskCategory aCategory, already_AddRefed<nsIRunnable>&& aRunnable) {
return EventTargetFor(aCategory)->Dispatch(std::move(aRunnable),
NS_DISPATCH_NORMAL);
}
nsISerialEventTarget* WorkerGlobalScope::EventTargetFor(
TaskCategory aCategory) const {
return mSerialEventTarget;
}
AbstractThread* WorkerGlobalScope::AbstractMainThreadFor(
TaskCategory aCategory) {
MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
}
mozilla::dom::DebuggerNotificationManager*
WorkerGlobalScope::GetOrCreateDebuggerNotificationManager() {
if (!mDebuggerNotificationManager) {
@ -554,25 +586,7 @@ WorkerGlobalScope::GetExistingDebuggerNotificationManager() {
return mDebuggerNotificationManager;
}
bool WorkerGlobalScope::IsSharedMemoryAllowed() const {
return mWorkerPrivate->IsSharedMemoryAllowed();
}
Maybe<ClientInfo> WorkerGlobalScope::GetClientInfo() const {
return mWorkerPrivate->GetClientInfo();
}
Maybe<ClientState> WorkerGlobalScope::GetClientState() const {
Maybe<ClientState> state;
state.emplace(mWorkerPrivate->GetClientState());
return state;
}
Maybe<ServiceWorkerDescriptor> WorkerGlobalScope::GetController() const {
return mWorkerPrivate->GetController();
}
RefPtr<mozilla::dom::ServiceWorkerRegistration>
RefPtr<ServiceWorkerRegistration>
WorkerGlobalScope::GetServiceWorkerRegistration(
const ServiceWorkerRegistrationDescriptor& aDescriptor) const {
mWorkerPrivate->AssertIsOnWorkerThread();
@ -602,10 +616,6 @@ WorkerGlobalScope::GetOrCreateServiceWorkerRegistration(
return ref;
}
uint64_t WorkerGlobalScope::WindowID() const {
return mWorkerPrivate->WindowID();
}
void WorkerGlobalScope::FirstPartyStorageAccessGranted() {
// Reset the IndexedDB factory.
mIndexedDB = nullptr;
@ -614,9 +624,27 @@ void WorkerGlobalScope::FirstPartyStorageAccessGranted() {
mCacheStorage = nullptr;
}
bool WorkerGlobalScope::WindowInteractionAllowed() const {
mWorkerPrivate->AssertIsOnWorkerThread();
return mWindowInteractionsAllowed > 0;
}
void WorkerGlobalScope::AllowWindowInteraction() {
mWorkerPrivate->AssertIsOnWorkerThread();
mWindowInteractionsAllowed++;
}
void WorkerGlobalScope::ConsumeWindowInteraction() {
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(mWindowInteractionsAllowed);
mWindowInteractionsAllowed--;
}
DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(
WorkerPrivate* aWorkerPrivate, const nsString& aName)
: WorkerGlobalScope(aWorkerPrivate), mName(aName) {}
NotNull<WorkerPrivate*> aWorkerPrivate,
UniquePtr<ClientSource> aClientSource, const nsString& aName)
: WorkerGlobalScope(aWorkerPrivate, std::move(aClientSource)),
NamedWorkerGlobalScopeMixin(aName) {}
bool DedicatedWorkerGlobalScope::WrapGlobalObject(
JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
@ -665,9 +693,11 @@ void DedicatedWorkerGlobalScope::Close() {
mWorkerPrivate->CloseInternal();
}
SharedWorkerGlobalScope::SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
const nsString& aName)
: WorkerGlobalScope(aWorkerPrivate), mName(aName) {}
SharedWorkerGlobalScope::SharedWorkerGlobalScope(
NotNull<WorkerPrivate*> aWorkerPrivate,
UniquePtr<ClientSource> aClientSource, const nsString& aName)
: WorkerGlobalScope(aWorkerPrivate, std::move(aClientSource)),
NamedWorkerGlobalScopeMixin(aName) {}
bool SharedWorkerGlobalScope::WrapGlobalObject(
JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
@ -698,20 +728,19 @@ NS_IMPL_ADDREF_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
NS_IMPL_RELEASE_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(
WorkerPrivate* aWorkerPrivate,
NotNull<WorkerPrivate*> aWorkerPrivate,
UniquePtr<ClientSource> aClientSource,
const ServiceWorkerRegistrationDescriptor& aRegistrationDescriptor)
: WorkerGlobalScope(aWorkerPrivate),
: WorkerGlobalScope(aWorkerPrivate, std::move(aClientSource)),
mScope(NS_ConvertUTF8toUTF16(aRegistrationDescriptor.Scope()))
// Eagerly create the registration because we will need to receive updates
// about the state of the registration. We can't wait until first access
// to start receiving these.
// Eagerly create the registration because we will need to receive
// updates about the state of the registration. We can't wait until
// first access to start receiving these.
,
mRegistration(
GetOrCreateServiceWorkerRegistration(aRegistrationDescriptor)) {}
ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope() = default;
bool ServiceWorkerGlobalScope::WrapGlobalObject(
JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
mWorkerPrivate->AssertIsOnWorkerThread();
@ -741,7 +770,6 @@ ServiceWorkerRegistration* ServiceWorkerGlobalScope::Registration() {
}
EventHandlerNonNull* ServiceWorkerGlobalScope::GetOnfetch() {
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
return GetEventHandler(nsGkAtoms::onfetch);
@ -782,35 +810,30 @@ class ReportFetchListenerWarningRunnable final : public Runnable {
} // anonymous namespace
void ServiceWorkerGlobalScope::NoteFetchHandlerWasAdded() const {
if (mWorkerPrivate->WorkerScriptExecutedSuccessfully()) {
RefPtr<Runnable> r = new ReportFetchListenerWarningRunnable(mScope);
mWorkerPrivate->DispatchToMainThreadForMessaging(r.forget());
}
mWorkerPrivate->SetFetchHandlerWasAdded();
}
void ServiceWorkerGlobalScope::SetOnfetch(
mozilla::dom::EventHandlerNonNull* aCallback) {
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
if (aCallback) {
if (mWorkerPrivate->WorkerScriptExecutedSuccessfully()) {
RefPtr<Runnable> r = new ReportFetchListenerWarningRunnable(mScope);
mWorkerPrivate->DispatchToMainThreadForMessaging(r.forget());
}
mWorkerPrivate->SetFetchHandlerWasAdded();
NoteFetchHandlerWasAdded();
}
SetEventHandler(nsGkAtoms::onfetch, aCallback);
}
void ServiceWorkerGlobalScope::EventListenerAdded(nsAtom* aType) {
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
if (aType != nsGkAtoms::onfetch) {
return;
if (aType == nsGkAtoms::onfetch) {
NoteFetchHandlerWasAdded();
}
if (mWorkerPrivate->WorkerScriptExecutedSuccessfully()) {
RefPtr<Runnable> r = new ReportFetchListenerWarningRunnable(mScope);
mWorkerPrivate->DispatchToMainThreadForMessaging(r.forget());
}
mWorkerPrivate->SetFetchHandlerWasAdded();
}
namespace {
@ -924,50 +947,6 @@ already_AddRefed<Promise> ServiceWorkerGlobalScope::SkipWaiting(
return promise.forget();
}
WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
WorkerPrivate* aWorkerPrivate)
: mWorkerPrivate(aWorkerPrivate),
mSerialEventTarget(aWorkerPrivate->HybridEventTarget()) {
mWorkerPrivate->AssertIsOnWorkerThread();
// We should always have an event target when the global is created.
MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
// In workers, each DETH must have an owner. Because the global scope doesn't
// have an owner, let's set it as owner of itself.
BindToOwner(static_cast<nsIGlobalObject*>(this));
}
WorkerDebuggerGlobalScope::~WorkerDebuggerGlobalScope() {
mWorkerPrivate->AssertIsOnWorkerThread();
}
NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerDebuggerGlobalScope)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WorkerDebuggerGlobalScope,
DOMEventTargetHelper)
tmp->mWorkerPrivate->AssertIsOnWorkerThread();
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WorkerDebuggerGlobalScope,
DOMEventTargetHelper)
tmp->mWorkerPrivate->AssertIsOnWorkerThread();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WorkerDebuggerGlobalScope,
DOMEventTargetHelper)
tmp->mWorkerPrivate->AssertIsOnWorkerThread();
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_ADDREF_INHERITED(WorkerDebuggerGlobalScope, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(WorkerDebuggerGlobalScope, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerDebuggerGlobalScope)
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
bool WorkerDebuggerGlobalScope::WrapGlobalObject(
JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) {
mWorkerPrivate->AssertIsOnWorkerThread();
@ -1108,22 +1087,6 @@ void WorkerDebuggerGlobalScope::SetConsoleEventHandler(JSContext* aCx,
console->SetConsoleEventHandler(aHandler);
}
already_AddRefed<Console> WorkerDebuggerGlobalScope::GetConsole(
ErrorResult& aRv) {
mWorkerPrivate->AssertIsOnWorkerThread();
// Debugger console has its own console object.
if (!mConsole) {
mConsole = Console::Create(mWorkerPrivate->GetJSContext(), nullptr, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
}
RefPtr<Console> console = mConsole;
return console.forget();
}
void WorkerDebuggerGlobalScope::Dump(JSContext* aCx,
const Optional<nsAString>& aString) const {
WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
@ -1132,34 +1095,6 @@ void WorkerDebuggerGlobalScope::Dump(JSContext* aCx,
}
}
void WorkerDebuggerGlobalScope::Atob(const nsAString& aAtob, nsAString& aOutput,
ErrorResult& aRv) const {
mWorkerPrivate->AssertIsOnWorkerThread();
aRv = nsContentUtils::Atob(aAtob, aOutput);
}
void WorkerDebuggerGlobalScope::Btoa(const nsAString& aBtoa, nsAString& aOutput,
ErrorResult& aRv) const {
mWorkerPrivate->AssertIsOnWorkerThread();
aRv = nsContentUtils::Btoa(aBtoa, aOutput);
}
nsresult WorkerDebuggerGlobalScope::Dispatch(
TaskCategory aCategory, already_AddRefed<nsIRunnable>&& aRunnable) {
return EventTargetFor(aCategory)->Dispatch(std::move(aRunnable),
NS_DISPATCH_NORMAL);
}
nsISerialEventTarget* WorkerDebuggerGlobalScope::EventTargetFor(
TaskCategory aCategory) const {
return mSerialEventTarget;
}
AbstractThread* WorkerDebuggerGlobalScope::AbstractMainThreadFor(
TaskCategory aCategory) {
MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
}
bool IsWorkerGlobal(JSObject* object) {
return IS_INSTANCE_OF(WorkerGlobalScope, object);
}

Просмотреть файл

@ -7,40 +7,60 @@
#ifndef mozilla_dom_workerscope_h__
#define mozilla_dom_workerscope_h__
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/DebuggerNotificationManager.h"
#include "mozilla/dom/Headers.h"
#include "mozilla/dom/RequestBinding.h"
#include "nsWeakReference.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/Maybe.h"
#include "mozilla/NotNull.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/dom/ClientSource.h"
#include "mozilla/dom/Console.h"
#include "mozilla/dom/DOMString.h"
#include "mozilla/dom/EventCallbackDebuggerNotification.h"
#include "mozilla/dom/ImageBitmapSource.h"
#include "mozilla/dom/RequestBinding.h"
#include "mozilla/dom/RequestBinding.h"
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIGlobalObject.h"
#include "nsISupportsImpl.h"
#include "nsWeakReference.h"
#ifdef XP_WIN
# undef PostMessage
#endif
class nsAtom;
class nsISerialEventTarget;
namespace mozilla {
namespace dom {
class AnyCallback;
struct ChannelPixelLayout;
enum class CallerType : uint32_t;
class ClientInfo;
class Clients;
class ClientState;
class Console;
class Crypto;
class DOMString;
class DebuggerNotificationManager;
class Function;
class IDBFactory;
enum class ImageBitmapFormat : uint8_t;
class Performance;
class OnErrorEventHandlerNonNull;
template <typename T>
class Optional;
struct PostMessageOptions;
class Promise;
class RequestOrUSVString;
template <typename T>
class Sequence;
class ServiceWorkerDescriptor;
class ServiceWorkerRegistrationDescriptor;
class WorkerLocation;
class WorkerNavigator;
class WorkerPrivate;
enum class CallerType : uint32_t;
namespace cache {
@ -48,65 +68,132 @@ class CacheStorage;
} // namespace cache
class WorkerGlobalScope : public DOMEventTargetHelper,
public nsIGlobalObject,
public nsSupportsWeakReference {
typedef mozilla::dom::IDBFactory IDBFactory;
RefPtr<Console> mConsole;
RefPtr<Crypto> mCrypto;
RefPtr<WorkerLocation> mLocation;
RefPtr<WorkerNavigator> mNavigator;
RefPtr<Performance> mPerformance;
RefPtr<IDBFactory> mIndexedDB;
RefPtr<cache::CacheStorage> mCacheStorage;
nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
RefPtr<mozilla::dom::DebuggerNotificationManager>
mDebuggerNotificationManager;
uint32_t mWindowInteractionsAllowed;
protected:
WorkerPrivate* mWorkerPrivate;
explicit WorkerGlobalScope(WorkerPrivate* aWorkerPrivate);
virtual ~WorkerGlobalScope();
MOZ_CAN_RUN_SCRIPT
int32_t SetTimeoutOrInterval(JSContext* aCx, Function& aHandler,
const int32_t aTimeout,
const Sequence<JS::Value>& aArguments,
bool aIsInterval, ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
int32_t SetTimeoutOrInterval(JSContext* aCx, const nsAString& aHandler,
const int32_t aTimeout, bool aIsInterval,
ErrorResult& aRv);
class WorkerGlobalScopeBase : public DOMEventTargetHelper,
public nsIGlobalObject {
friend class WorkerPrivate;
public:
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerGlobalScopeBase,
DOMEventTargetHelper)
WorkerGlobalScopeBase(NotNull<WorkerPrivate*> aWorkerPrivate,
UniquePtr<ClientSource> aClientSource);
virtual bool WrapGlobalObject(JSContext* aCx,
JS::MutableHandle<JSObject*> aReflector) = 0;
JSObject* GetGlobalJSObject() override { return GetWrapper(); }
JSObject* GetGlobalJSObjectPreserveColor() const override {
return GetWrapperPreserveColor();
// EventTarget implementation
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) final {
MOZ_CRASH("WrapObject not supported; use WrapGlobalObject.");
}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerGlobalScope,
DOMEventTargetHelper)
// nsIGlobalObject implementation
JSObject* GetGlobalJSObject() final;
WorkerGlobalScope* Self() { return this; }
JSObject* GetGlobalJSObjectPreserveColor() const final;
void NoteTerminating();
bool IsSharedMemoryAllowed() const final;
Maybe<ClientInfo> GetClientInfo() const final {
return Some(mClientSource->Info());
}
Maybe<ServiceWorkerDescriptor> GetController() const final {
return mClientSource->GetController();
}
virtual void Control(const ServiceWorkerDescriptor& aServiceWorker);
// DispatcherTrait implementation
nsresult Dispatch(TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable) final;
nsISerialEventTarget* EventTargetFor(TaskCategory) const final;
AbstractThread* AbstractMainThreadFor(TaskCategory) final {
MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
}
// atob, btoa, and dump are declared (separately) by both WorkerGlobalScope
// and WorkerDebuggerGlobalScope WebIDL interfaces
void Atob(const nsAString& aAtob, nsAString& aOut, ErrorResult& aRv) const;
void Btoa(const nsAString& aBtoa, nsAString& aOut, ErrorResult& aRv) const;
already_AddRefed<Console> GetConsole(ErrorResult& aRv);
Console* GetConsoleIfExists() const { return mConsole; }
Crypto* GetCrypto(ErrorResult& aError);
uint64_t WindowID() const;
void NoteTerminating() { StartDying(); }
const UniquePtr<ClientSource>& GetClientSource() const {
return mClientSource;
}
// WorkerPrivate wants to be able to forbid script when its state machine
// demands it.
void WorkerPrivateSaysForbidScript() { StartForbiddingScript(); }
void WorkerPrivateSaysAllowScript() { StopForbiddingScript(); }
protected:
~WorkerGlobalScopeBase() = default;
const NotNull<WorkerPrivate*> mWorkerPrivate;
private:
RefPtr<Console> mConsole;
const UniquePtr<ClientSource> mClientSource;
nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
};
namespace workerinternals {
class NamedWorkerGlobalScopeMixin {
public:
explicit NamedWorkerGlobalScopeMixin(const nsAString& aName) : mName(aName) {}
void GetName(DOMString& aName) const { aName.AsAString() = mName; }
protected:
~NamedWorkerGlobalScopeMixin() = default;
private:
const nsString mName;
};
} // namespace workerinternals
class WorkerGlobalScope : public WorkerGlobalScopeBase,
public nsSupportsWeakReference {
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WorkerGlobalScope,
WorkerGlobalScopeBase)
using WorkerGlobalScopeBase::WorkerGlobalScopeBase;
// nsIGlobalObject implementation
RefPtr<ServiceWorkerRegistration> GetServiceWorkerRegistration(
const ServiceWorkerRegistrationDescriptor& aDescriptor) const final;
RefPtr<ServiceWorkerRegistration> GetOrCreateServiceWorkerRegistration(
const ServiceWorkerRegistrationDescriptor& aDescriptor) final;
DebuggerNotificationManager* GetOrCreateDebuggerNotificationManager() final;
DebuggerNotificationManager* GetExistingDebuggerNotificationManager() final;
Maybe<EventCallbackDebuggerNotificationType> GetDebuggerNotificationType()
const final {
return Some(EventCallbackDebuggerNotificationType::Global);
}
// WorkerGlobalScope WebIDL implementation
WorkerGlobalScope* Self() { return this; }
already_AddRefed<WorkerLocation> Location();
@ -114,42 +201,16 @@ class WorkerGlobalScope : public DOMEventTargetHelper,
already_AddRefed<WorkerNavigator> GetExistingNavigator() const;
OnErrorEventHandlerNonNull* GetOnerror();
void SetOnerror(OnErrorEventHandlerNonNull* aHandler);
void ImportScripts(JSContext* aCx, const Sequence<nsString>& aScriptURLs,
ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
int32_t SetTimeout(JSContext* aCx, Function& aHandler, const int32_t aTimeout,
const Sequence<JS::Value>& aArguments, ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
int32_t SetTimeout(JSContext* aCx, const nsAString& aHandler,
const int32_t aTimeout,
const Sequence<JS::Value>& /* unused */, ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
void ClearTimeout(int32_t aHandle);
MOZ_CAN_RUN_SCRIPT
int32_t SetInterval(JSContext* aCx, Function& aHandler,
const int32_t aTimeout,
const Sequence<JS::Value>& aArguments, ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
int32_t SetInterval(JSContext* aCx, const nsAString& aHandler,
const int32_t aTimeout,
const Sequence<JS::Value>& /* unused */,
ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
void ClearInterval(int32_t aHandle);
OnErrorEventHandlerNonNull* GetOnerror();
void GetOrigin(nsAString& aOrigin) const;
bool CrossOriginIsolated() const override;
void SetOnerror(OnErrorEventHandlerNonNull* aHandler);
void Atob(const nsAString& aAtob, nsAString& aOutput, ErrorResult& aRv) const;
void Btoa(const nsAString& aBtoa, nsAString& aOutput, ErrorResult& aRv) const;
IMPL_EVENT_HANDLER(online)
IMPL_EVENT_HANDLER(offline)
IMPL_EVENT_HANDLER(languagechange)
IMPL_EVENT_HANDLER(offline)
IMPL_EVENT_HANDLER(online)
IMPL_EVENT_HANDLER(rejectionhandled)
IMPL_EVENT_HANDLER(unhandledrejection)
@ -159,20 +220,42 @@ class WorkerGlobalScope : public DOMEventTargetHelper,
Performance* GetPerformanceIfExists() const { return mPerformance; }
static bool IsInAutomation(JSContext* aCx, JSObject* /* unused */);
static bool IsInAutomation(JSContext* aCx, JSObject*);
void GetJSTestingFunctions(JSContext* aCx,
JS::MutableHandle<JSObject*> aFunctions,
ErrorResult& aRv);
already_AddRefed<Promise> Fetch(const RequestOrUSVString& aInput,
const RequestInit& aInit,
CallerType aCallerType, ErrorResult& aRv);
// GlobalCrypto WebIDL implementation
Crypto* GetCrypto(ErrorResult& aError);
already_AddRefed<IDBFactory> GetIndexedDB(ErrorResult& aErrorResult);
// WindowOrWorkerGlobalScope WebIDL implementation
void GetOrigin(nsAString& aOrigin) const;
already_AddRefed<cache::CacheStorage> GetCaches(ErrorResult& aRv);
bool CrossOriginIsolated() const final;
bool IsSecureContext() const;
MOZ_CAN_RUN_SCRIPT
int32_t SetTimeout(JSContext* aCx, Function& aHandler, int32_t aTimeout,
const Sequence<JS::Value>& aArguments, ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
int32_t SetTimeout(JSContext* aCx, const nsAString& aHandler,
int32_t aTimeout, const Sequence<JS::Value>&,
ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
void ClearTimeout(int32_t aHandle);
MOZ_CAN_RUN_SCRIPT
int32_t SetInterval(JSContext* aCx, Function& aHandler, int32_t aTimeout,
const Sequence<JS::Value>& aArguments, ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
int32_t SetInterval(JSContext* aCx, const nsAString& aHandler,
int32_t aTimeout, const Sequence<JS::Value>&,
ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
void ClearInterval(int32_t aHandle);
already_AddRefed<Promise> CreateImageBitmap(JSContext* aCx,
const ImageBitmapSource& aImage,
@ -184,80 +267,63 @@ class WorkerGlobalScope : public DOMEventTargetHelper,
int32_t aSw, int32_t aSh,
ErrorResult& aRv);
bool WindowInteractionAllowed() const {
return mWindowInteractionsAllowed > 0;
}
already_AddRefed<Promise> Fetch(const RequestOrUSVString& aInput,
const RequestInit& aInit,
CallerType aCallerType, ErrorResult& aRv);
void AllowWindowInteraction() { mWindowInteractionsAllowed++; }
bool IsSecureContext() const;
void ConsumeWindowInteraction() {
MOZ_ASSERT(mWindowInteractionsAllowed > 0);
mWindowInteractionsAllowed--;
}
already_AddRefed<IDBFactory> GetIndexedDB(ErrorResult& aErrorResult);
// Override DispatchTrait API to target the worker thread. Dispatch may
// return failure if the worker thread is not alive.
nsresult Dispatch(TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable) override;
already_AddRefed<cache::CacheStorage> GetCaches(ErrorResult& aRv);
nsISerialEventTarget* EventTargetFor(TaskCategory aCategory) const override;
bool WindowInteractionAllowed() const;
AbstractThread* AbstractMainThreadFor(TaskCategory aCategory) override;
void AllowWindowInteraction();
mozilla::dom::DebuggerNotificationManager*
GetOrCreateDebuggerNotificationManager() override;
mozilla::dom::DebuggerNotificationManager*
GetExistingDebuggerNotificationManager() override;
mozilla::Maybe<mozilla::dom::EventCallbackDebuggerNotificationType>
GetDebuggerNotificationType() const override {
return mozilla::Some(
mozilla::dom::EventCallbackDebuggerNotificationType::Global);
}
bool IsSharedMemoryAllowed() const override;
Maybe<ClientInfo> GetClientInfo() const override;
Maybe<ClientState> GetClientState() const;
Maybe<ServiceWorkerDescriptor> GetController() const override;
RefPtr<mozilla::dom::ServiceWorkerRegistration> GetServiceWorkerRegistration(
const ServiceWorkerRegistrationDescriptor& aDescriptor) const override;
RefPtr<mozilla::dom::ServiceWorkerRegistration>
GetOrCreateServiceWorkerRegistration(
const ServiceWorkerRegistrationDescriptor& aDescriptor) override;
uint64_t WindowID() const;
void ConsumeWindowInteraction();
void FirstPartyStorageAccessGranted();
// WorkerPrivate wants to be able to forbid script when its state machine
// demands it.
friend WorkerPrivate;
void WorkerPrivateSaysForbidScript() { StartForbiddingScript(); }
void WorkerPrivateSaysAllowScript() { StopForbiddingScript(); }
protected:
~WorkerGlobalScope() = default;
private:
MOZ_CAN_RUN_SCRIPT
int32_t SetTimeoutOrInterval(JSContext* aCx, Function& aHandler,
int32_t aTimeout,
const Sequence<JS::Value>& aArguments,
bool aIsInterval, ErrorResult& aRv);
MOZ_CAN_RUN_SCRIPT
int32_t SetTimeoutOrInterval(JSContext* aCx, const nsAString& aHandler,
int32_t aTimeout, bool aIsInterval,
ErrorResult& aRv);
RefPtr<Crypto> mCrypto;
RefPtr<WorkerLocation> mLocation;
RefPtr<WorkerNavigator> mNavigator;
RefPtr<Performance> mPerformance;
RefPtr<IDBFactory> mIndexedDB;
RefPtr<cache::CacheStorage> mCacheStorage;
RefPtr<DebuggerNotificationManager> mDebuggerNotificationManager;
uint32_t mWindowInteractionsAllowed = 0;
};
class DedicatedWorkerGlobalScope final : public WorkerGlobalScope {
const nsString mName;
~DedicatedWorkerGlobalScope() = default;
class DedicatedWorkerGlobalScope final
: public WorkerGlobalScope,
public workerinternals::NamedWorkerGlobalScopeMixin {
public:
DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
DedicatedWorkerGlobalScope(NotNull<WorkerPrivate*> aWorkerPrivate,
UniquePtr<ClientSource> aClientSource,
const nsString& aName);
virtual bool WrapGlobalObject(
JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) override;
void GetName(DOMString& aName) const { aName.AsAString() = mName; }
bool WrapGlobalObject(JSContext* aCx,
JS::MutableHandle<JSObject*> aReflector) override;
void PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Sequence<JSObject*>& aTransferable, ErrorResult& aRv);
void PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const PostMessageOptions& aOptions, ErrorResult& aRv);
@ -265,48 +331,43 @@ class DedicatedWorkerGlobalScope final : public WorkerGlobalScope {
IMPL_EVENT_HANDLER(message)
IMPL_EVENT_HANDLER(messageerror)
private:
~DedicatedWorkerGlobalScope() = default;
};
class SharedWorkerGlobalScope final : public WorkerGlobalScope {
const nsString mName;
~SharedWorkerGlobalScope() = default;
class SharedWorkerGlobalScope final
: public WorkerGlobalScope,
public workerinternals::NamedWorkerGlobalScopeMixin {
public:
SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate, const nsString& aName);
SharedWorkerGlobalScope(NotNull<WorkerPrivate*> aWorkerPrivate,
UniquePtr<ClientSource> aClientSource,
const nsString& aName);
virtual bool WrapGlobalObject(
JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) override;
void GetName(DOMString& aName) const { aName.AsAString() = mName; }
bool WrapGlobalObject(JSContext* aCx,
JS::MutableHandle<JSObject*> aReflector) override;
void Close();
IMPL_EVENT_HANDLER(connect)
private:
~SharedWorkerGlobalScope() = default;
};
class ServiceWorkerGlobalScope final : public WorkerGlobalScope {
const nsString mScope;
RefPtr<Clients> mClients;
RefPtr<ServiceWorkerRegistration> mRegistration;
~ServiceWorkerGlobalScope();
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerGlobalScope,
WorkerGlobalScope)
IMPL_EVENT_HANDLER(notificationclick)
IMPL_EVENT_HANDLER(notificationclose)
ServiceWorkerGlobalScope(
WorkerPrivate* aWorkerPrivate,
NotNull<WorkerPrivate*> aWorkerPrivate,
UniquePtr<ClientSource> aClientSource,
const ServiceWorkerRegistrationDescriptor& aRegistrationDescriptor);
virtual bool WrapGlobalObject(
JSContext* aCx, JS::MutableHandle<JSObject*> aReflector) override;
void GetScope(nsString& aScope) const { aScope = mScope; }
bool WrapGlobalObject(JSContext* aCx,
JS::MutableHandle<JSObject*> aReflector) override;
already_AddRefed<Clients> GetClients();
@ -314,45 +375,43 @@ class ServiceWorkerGlobalScope final : public WorkerGlobalScope {
already_AddRefed<Promise> SkipWaiting(ErrorResult& aRv);
IMPL_EVENT_HANDLER(activate)
IMPL_EVENT_HANDLER(install)
IMPL_EVENT_HANDLER(activate)
EventHandlerNonNull* GetOnfetch();
void SetOnfetch(EventHandlerNonNull* aCallback);
void EventListenerAdded(nsAtom* aType) override;
IMPL_EVENT_HANDLER(message)
IMPL_EVENT_HANDLER(messageerror)
IMPL_EVENT_HANDLER(notificationclick)
IMPL_EVENT_HANDLER(notificationclose)
IMPL_EVENT_HANDLER(push)
IMPL_EVENT_HANDLER(pushsubscriptionchange)
EventHandlerNonNull* GetOnfetch();
private:
~ServiceWorkerGlobalScope() = default;
void SetOnfetch(mozilla::dom::EventHandlerNonNull* aCallback);
void NoteFetchHandlerWasAdded() const;
void EventListenerAdded(nsAtom* aType) override;
RefPtr<Clients> mClients;
const nsString mScope;
RefPtr<ServiceWorkerRegistration> mRegistration;
};
class WorkerDebuggerGlobalScope final : public DOMEventTargetHelper,
public nsIGlobalObject {
WorkerPrivate* mWorkerPrivate;
RefPtr<Console> mConsole;
nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
class WorkerDebuggerGlobalScope final : public WorkerGlobalScopeBase {
public:
explicit WorkerDebuggerGlobalScope(WorkerPrivate* aWorkerPrivate);
using WorkerGlobalScopeBase::WorkerGlobalScopeBase;
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
WorkerDebuggerGlobalScope, DOMEventTargetHelper)
bool WrapGlobalObject(JSContext* aCx,
JS::MutableHandle<JSObject*> aReflector) override;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override {
MOZ_CRASH("Shouldn't get here!");
}
virtual bool WrapGlobalObject(JSContext* aCx,
JS::MutableHandle<JSObject*> aReflector);
JSObject* GetGlobalJSObject(void) override { return GetWrapper(); }
JSObject* GetGlobalJSObjectPreserveColor(void) const override {
return GetWrapperPreserveColor();
void Control(const ServiceWorkerDescriptor& aServiceWorker) override {
MOZ_CRASH("Can't control debugger workers.");
}
void GetGlobal(JSContext* aCx, JS::MutableHandle<JSObject*> aGlobal,
@ -362,7 +421,7 @@ class WorkerDebuggerGlobalScope final : public DOMEventTargetHelper,
JS::Handle<JSObject*> aPrototype,
JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv);
void LoadSubScript(JSContext* aCx, const nsAString& aURL,
void LoadSubScript(JSContext* aCx, const nsAString& aUrl,
const Optional<JS::Handle<JSObject*>>& aSandbox,
ErrorResult& aRv);
@ -372,9 +431,6 @@ class WorkerDebuggerGlobalScope final : public DOMEventTargetHelper,
void PostMessage(const nsAString& aMessage);
IMPL_EVENT_HANDLER(message)
IMPL_EVENT_HANDLER(messageerror)
void SetImmediate(Function& aHandler, ErrorResult& aRv);
void ReportError(JSContext* aCx, const nsAString& aMessage);
@ -385,26 +441,13 @@ class WorkerDebuggerGlobalScope final : public DOMEventTargetHelper,
void SetConsoleEventHandler(JSContext* aCx, AnyCallback* aHandler,
ErrorResult& aRv);
already_AddRefed<Console> GetConsole(ErrorResult& aRv);
Console* GetConsoleIfExists() const { return mConsole; }
void Dump(JSContext* aCx, const Optional<nsAString>& aString) const;
void Atob(const nsAString& aAtob, nsAString& aOutput, ErrorResult& aRv) const;
void Btoa(const nsAString& aBtoa, nsAString& aOutput, ErrorResult& aRv) const;
// Override DispatchTrait API to target the worker thread. Dispatch may
// return failure if the worker thread is not alive.
nsresult Dispatch(TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable) override;
nsISerialEventTarget* EventTargetFor(TaskCategory aCategory) const override;
AbstractThread* AbstractMainThreadFor(TaskCategory aCategory) override;
IMPL_EVENT_HANDLER(message)
IMPL_EVENT_HANDLER(messageerror)
private:
virtual ~WorkerDebuggerGlobalScope();
~WorkerDebuggerGlobalScope() = default;
};
} // namespace dom

Просмотреть файл

@ -1709,13 +1709,15 @@ void XMLHttpRequestWorker::Open(const nsACString& aMethod,
return;
}
} else {
Maybe<ClientInfo> clientInfo(mWorkerPrivate->GetClientInfo());
Maybe<ClientInfo> clientInfo(
mWorkerPrivate->GlobalScope()->GetClientInfo());
if (clientInfo.isNothing()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
mProxy = new Proxy(this, clientInfo.ref(), mWorkerPrivate->GetController(),
mMozAnon, mMozSystem);
mProxy = new Proxy(this, clientInfo.ref(),
mWorkerPrivate->GlobalScope()->GetController(), mMozAnon,
mMozSystem);
alsoOverrideMimeType = true;
}