123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "WorkerScope.h"
- #include "jsapi.h"
- #include "mozilla/EventListenerManager.h"
- #include "mozilla/dom/BindingDeclarations.h"
- #include "mozilla/dom/Console.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/ServiceWorkerGlobalScopeBinding.h"
- #include "mozilla/dom/SharedWorkerGlobalScopeBinding.h"
- #include "mozilla/dom/SimpleGlobalObject.h"
- #include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
- #include "mozilla/dom/WorkerGlobalScopeBinding.h"
- #include "mozilla/dom/WorkerLocation.h"
- #include "mozilla/dom/WorkerNavigator.h"
- #include "mozilla/dom/cache/CacheStorage.h"
- #include "mozilla/Services.h"
- #include "nsServiceManagerUtils.h"
- #include "nsIDocument.h"
- #include "nsIServiceWorkerManager.h"
- #include "nsIScriptTimeoutHandler.h"
- #include "Crypto.h"
- #include "Principal.h"
- #include "RuntimeService.h"
- #include "ScriptLoader.h"
- #include "WorkerPrivate.h"
- #include "WorkerRunnable.h"
- #include "ServiceWorkerClients.h"
- #include "ServiceWorkerManager.h"
- #include "ServiceWorkerRegistration.h"
- #ifdef XP_WIN
- #undef PostMessage
- #endif
- extern already_AddRefed<nsIScriptTimeoutHandler>
- NS_CreateJSTimeoutHandler(JSContext* aCx,
- mozilla::dom::workers::WorkerPrivate* aWorkerPrivate,
- mozilla::dom::Function& aFunction,
- const mozilla::dom::Sequence<JS::Value>& aArguments,
- mozilla::ErrorResult& aError);
- extern already_AddRefed<nsIScriptTimeoutHandler>
- NS_CreateJSTimeoutHandler(JSContext* aCx,
- mozilla::dom::workers::WorkerPrivate* aWorkerPrivate,
- const nsAString& aExpression);
- using namespace mozilla;
- using namespace mozilla::dom;
- USING_WORKERS_NAMESPACE
- using mozilla::dom::cache::CacheStorage;
- using mozilla::ipc::PrincipalInfo;
- WorkerGlobalScope::WorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
- : mWindowInteractionsAllowed(0)
- , mWorkerPrivate(aWorkerPrivate)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- }
- WorkerGlobalScope::~WorkerGlobalScope()
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- }
- 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)
- tmp->TraverseHostObjectURIs(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)
- tmp->UnlinkHostObjectURIs();
- tmp->mWorkerPrivate->UnlinkTimeouts();
- 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!");
- }
- Console*
- WorkerGlobalScope::GetConsole(ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- if (!mConsole) {
- mConsole = Console::Create(nullptr, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return nullptr;
- }
- }
- return mConsole;
- }
- Crypto*
- WorkerGlobalScope::GetCrypto(ErrorResult& aError)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- if (!mCrypto) {
- mCrypto = new Crypto();
- mCrypto->Init(this);
- }
- return mCrypto;
- }
- already_AddRefed<CacheStorage>
- WorkerGlobalScope::GetCaches(ErrorResult& aRv)
- {
- if (!mCacheStorage) {
- MOZ_ASSERT(mWorkerPrivate);
- mCacheStorage = CacheStorage::CreateOnWorker(cache::DEFAULT_NAMESPACE, this,
- mWorkerPrivate, aRv);
- }
- RefPtr<CacheStorage> ref = mCacheStorage;
- return ref.forget();
- }
- bool
- WorkerGlobalScope::IsSecureContext() const
- {
- bool globalSecure =
- JS_GetIsSecureContext(js::GetObjectCompartment(GetWrapperPreserveColor()));
- MOZ_ASSERT(globalSecure == mWorkerPrivate->IsSecureContext());
- return globalSecure;
- }
- already_AddRefed<WorkerLocation>
- WorkerGlobalScope::Location()
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- if (!mLocation) {
- WorkerPrivate::LocationInfo& info = mWorkerPrivate->GetLocationInfo();
- mLocation = WorkerLocation::Create(info);
- MOZ_ASSERT(mLocation);
- }
- RefPtr<WorkerLocation> location = mLocation;
- return location.forget();
- }
- already_AddRefed<WorkerNavigator>
- WorkerGlobalScope::Navigator()
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- if (!mNavigator) {
- mNavigator = WorkerNavigator::Create(mWorkerPrivate->OnLine());
- MOZ_ASSERT(mNavigator);
- }
- RefPtr<WorkerNavigator> navigator = mNavigator;
- return navigator.forget();
- }
- already_AddRefed<WorkerNavigator>
- WorkerGlobalScope::GetExistingNavigator() const
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- RefPtr<WorkerNavigator> navigator = mNavigator;
- return navigator.forget();
- }
- void
- WorkerGlobalScope::Close(JSContext* aCx, ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- if (mWorkerPrivate->IsServiceWorker()) {
- aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
- } else {
- mWorkerPrivate->CloseInternal(aCx);
- }
- }
- OnErrorEventHandlerNonNull*
- WorkerGlobalScope::GetOnerror()
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- EventListenerManager* elm = GetExistingListenerManager();
- return elm ? elm->GetOnErrorEventHandler() : nullptr;
- }
- void
- WorkerGlobalScope::SetOnerror(OnErrorEventHandlerNonNull* aHandler)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- EventListenerManager* elm = GetOrCreateListenerManager();
- if (elm) {
- elm->SetEventHandler(aHandler);
- }
- }
- void
- WorkerGlobalScope::ImportScripts(const Sequence<nsString>& aScriptURLs,
- ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- scriptloader::Load(mWorkerPrivate, aScriptURLs, WorkerScript, aRv);
- }
- int32_t
- WorkerGlobalScope::SetTimeout(JSContext* aCx,
- Function& aHandler,
- const int32_t aTimeout,
- const Sequence<JS::Value>& aArguments,
- ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- nsCOMPtr<nsIScriptTimeoutHandler> handler =
- NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aArguments, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return 0;
- }
- return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, false, aRv);
- }
- int32_t
- WorkerGlobalScope::SetTimeout(JSContext* aCx,
- const nsAString& aHandler,
- const int32_t aTimeout,
- const Sequence<JS::Value>& /* unused */,
- ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- nsCOMPtr<nsIScriptTimeoutHandler> handler =
- NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler);
- return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, false, aRv);
- }
- void
- WorkerGlobalScope::ClearTimeout(int32_t aHandle)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- mWorkerPrivate->ClearTimeout(aHandle);
- }
- int32_t
- WorkerGlobalScope::SetInterval(JSContext* aCx,
- Function& aHandler,
- const Optional<int32_t>& aTimeout,
- const Sequence<JS::Value>& aArguments,
- ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- bool isInterval = aTimeout.WasPassed();
- int32_t timeout = aTimeout.WasPassed() ? aTimeout.Value() : 0;
- nsCOMPtr<nsIScriptTimeoutHandler> handler =
- NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aArguments, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return 0;
- }
- return mWorkerPrivate->SetTimeout(aCx, handler, timeout, isInterval, aRv);
- }
- int32_t
- WorkerGlobalScope::SetInterval(JSContext* aCx,
- const nsAString& aHandler,
- const Optional<int32_t>& aTimeout,
- const Sequence<JS::Value>& /* unused */,
- ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- Sequence<JS::Value> dummy;
- bool isInterval = aTimeout.WasPassed();
- int32_t timeout = aTimeout.WasPassed() ? aTimeout.Value() : 0;
- nsCOMPtr<nsIScriptTimeoutHandler> handler =
- NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler);
- return mWorkerPrivate->SetTimeout(aCx, handler, timeout, isInterval, aRv);
- }
- void
- WorkerGlobalScope::ClearInterval(int32_t aHandle)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- mWorkerPrivate->ClearTimeout(aHandle);
- }
- 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::GetOrigin(nsAString& aOrigin) const
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- aOrigin = mWorkerPrivate->Origin();
- }
- void
- WorkerGlobalScope::Dump(const Optional<nsAString>& aString) const
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- if (!aString.WasPassed()) {
- return;
- }
- #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
- if (!mWorkerPrivate->DumpEnabled()) {
- return;
- }
- #endif
- NS_ConvertUTF16toUTF8 str(aString.Value());
- MOZ_LOG(nsContentUtils::DOMDumpLog(), LogLevel::Debug, ("[Worker.Dump] %s", str.get()));
- fputs(str.get(), stdout);
- fflush(stdout);
- }
- Performance*
- WorkerGlobalScope::GetPerformance()
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- if (!mPerformance) {
- mPerformance = Performance::CreateForWorker(mWorkerPrivate);
- }
- return mPerformance;
- }
- already_AddRefed<Promise>
- WorkerGlobalScope::Fetch(const RequestOrUSVString& aInput,
- const RequestInit& aInit, ErrorResult& aRv)
- {
- return FetchRequest(this, aInput, aInit, aRv);
- }
- already_AddRefed<IDBFactory>
- WorkerGlobalScope::GetIndexedDB(ErrorResult& aErrorResult)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- RefPtr<IDBFactory> indexedDB = mIndexedDB;
- if (!indexedDB) {
- if (!mWorkerPrivate->IsStorageAllowed()) {
- NS_WARNING("IndexedDB is not allowed in this worker!");
- aErrorResult = NS_ERROR_DOM_SECURITY_ERR;
- return nullptr;
- }
- JSContext* cx = mWorkerPrivate->GetJSContext();
- MOZ_ASSERT(cx);
- JS::Rooted<JSObject*> owningObject(cx, GetGlobalJSObject());
- MOZ_ASSERT(owningObject);
- const PrincipalInfo& principalInfo = mWorkerPrivate->GetPrincipalInfo();
- nsresult rv =
- IDBFactory::CreateForWorker(cx,
- owningObject,
- principalInfo,
- mWorkerPrivate->WindowID(),
- getter_AddRefs(indexedDB));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- aErrorResult = rv;
- return nullptr;
- }
- mIndexedDB = indexedDB;
- }
- return indexedDB.forget();
- }
- already_AddRefed<Promise>
- WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage,
- ErrorResult& aRv)
- {
- if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
- aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
- return nullptr;
- }
- return ImageBitmap::Create(this, aImage, Nothing(), aRv);
- }
- already_AddRefed<Promise>
- WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage,
- int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh,
- ErrorResult& aRv)
- {
- if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
- aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
- return nullptr;
- }
- return ImageBitmap::Create(this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
- }
- already_AddRefed<mozilla::dom::Promise>
- WorkerGlobalScope::CreateImageBitmap(const ImageBitmapSource& aImage,
- int32_t aOffset, int32_t aLength,
- ImageBitmapFormat aFormat,
- const Sequence<ChannelPixelLayout>& aLayout,
- ErrorResult& aRv)
- {
- JSContext* cx = GetCurrentThreadJSContext();
- MOZ_ASSERT(cx);
- if (!ImageBitmap::ExtensionsEnabled(cx, nullptr)) {
- aRv.Throw(NS_ERROR_TYPE_ERR);
- return nullptr;
- }
- if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
- return ImageBitmap::Create(this, aImage, aOffset, aLength, aFormat, aLayout,
- aRv);
- } else {
- aRv.Throw(NS_ERROR_TYPE_ERR);
- return nullptr;
- }
- }
- DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
- : WorkerGlobalScope(aWorkerPrivate)
- {
- }
- bool
- DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
- JS::MutableHandle<JSObject*> aReflector)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- MOZ_ASSERT(!mWorkerPrivate->IsSharedWorker());
- JS::CompartmentOptions options;
- mWorkerPrivate->CopyJSCompartmentOptions(options);
- const bool usesSystemPrincipal = mWorkerPrivate->UsesSystemPrincipal();
- // Note that xpc::ShouldDiscardSystemSource() and
- // xpc::ExtraWarningsForSystemJS() read prefs that are cached on the main
- // thread. This is benignly racey.
- const bool discardSource = usesSystemPrincipal &&
- xpc::ShouldDiscardSystemSource();
- const bool extraWarnings = usesSystemPrincipal &&
- xpc::ExtraWarningsForSystemJS();
- JS::CompartmentBehaviors& behaviors = options.behaviors();
- behaviors.setDiscardSource(discardSource)
- .extraWarningsOverride().set(extraWarnings);
- const bool sharedMemoryEnabled = xpc::SharedMemoryEnabled();
- JS::CompartmentCreationOptions& creationOptions = options.creationOptions();
- creationOptions.setSharedMemoryAndAtomicsEnabled(sharedMemoryEnabled);
- return DedicatedWorkerGlobalScopeBinding::Wrap(aCx, this, this,
- options,
- GetWorkerPrincipal(),
- true, aReflector);
- }
- void
- DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx,
- JS::Handle<JS::Value> aMessage,
- const Optional<Sequence<JS::Value>>& aTransferable,
- ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- mWorkerPrivate->PostMessageToParent(aCx, aMessage, aTransferable, aRv);
- }
- SharedWorkerGlobalScope::SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
- const nsCString& aName)
- : WorkerGlobalScope(aWorkerPrivate), mName(aName)
- {
- }
- bool
- SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
- JS::MutableHandle<JSObject*> aReflector)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- MOZ_ASSERT(mWorkerPrivate->IsSharedWorker());
- JS::CompartmentOptions options;
- mWorkerPrivate->CopyJSCompartmentOptions(options);
- return SharedWorkerGlobalScopeBinding::Wrap(aCx, this, this, options,
- GetWorkerPrincipal(),
- true, aReflector);
- }
- NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope,
- mClients, mRegistration)
- NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorkerGlobalScope)
- NS_INTERFACE_MAP_END_INHERITING(WorkerGlobalScope)
- NS_IMPL_ADDREF_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
- NS_IMPL_RELEASE_INHERITED(ServiceWorkerGlobalScope, WorkerGlobalScope)
- ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
- const nsACString& aScope)
- : WorkerGlobalScope(aWorkerPrivate),
- mScope(NS_ConvertUTF8toUTF16(aScope))
- {
- }
- ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope()
- {
- }
- bool
- ServiceWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
- JS::MutableHandle<JSObject*> aReflector)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
- JS::CompartmentOptions options;
- mWorkerPrivate->CopyJSCompartmentOptions(options);
- return ServiceWorkerGlobalScopeBinding::Wrap(aCx, this, this, options,
- GetWorkerPrincipal(),
- true, aReflector);
- }
- ServiceWorkerClients*
- ServiceWorkerGlobalScope::Clients()
- {
- if (!mClients) {
- mClients = new ServiceWorkerClients(this);
- }
- return mClients;
- }
- ServiceWorkerRegistration*
- ServiceWorkerGlobalScope::Registration()
- {
- if (!mRegistration) {
- mRegistration =
- ServiceWorkerRegistration::CreateForWorker(mWorkerPrivate, mScope);
- }
- return mRegistration;
- }
- namespace {
- class SkipWaitingResultRunnable final : public WorkerRunnable
- {
- RefPtr<PromiseWorkerProxy> mPromiseProxy;
- public:
- SkipWaitingResultRunnable(WorkerPrivate* aWorkerPrivate,
- PromiseWorkerProxy* aPromiseProxy)
- : WorkerRunnable(aWorkerPrivate)
- , mPromiseProxy(aPromiseProxy)
- {
- AssertIsOnMainThread();
- }
- virtual bool
- WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
- {
- MOZ_ASSERT(aWorkerPrivate);
- aWorkerPrivate->AssertIsOnWorkerThread();
- RefPtr<Promise> promise = mPromiseProxy->WorkerPromise();
- promise->MaybeResolveWithUndefined();
- // Release the reference on the worker thread.
- mPromiseProxy->CleanUp();
- return true;
- }
- };
- class WorkerScopeSkipWaitingRunnable final : public Runnable
- {
- RefPtr<PromiseWorkerProxy> mPromiseProxy;
- nsCString mScope;
- public:
- WorkerScopeSkipWaitingRunnable(PromiseWorkerProxy* aPromiseProxy,
- const nsCString& aScope)
- : mPromiseProxy(aPromiseProxy)
- , mScope(aScope)
- {
- MOZ_ASSERT(aPromiseProxy);
- }
- NS_IMETHOD
- Run() override
- {
- AssertIsOnMainThread();
- MutexAutoLock lock(mPromiseProxy->Lock());
- if (mPromiseProxy->CleanedUp()) {
- return NS_OK;
- }
- WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
- MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
- RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
- if (swm) {
- swm->SetSkipWaitingFlag(workerPrivate->GetPrincipal(), mScope,
- workerPrivate->ServiceWorkerID());
- }
- RefPtr<SkipWaitingResultRunnable> runnable =
- new SkipWaitingResultRunnable(workerPrivate, mPromiseProxy);
- if (!runnable->Dispatch()) {
- NS_WARNING("Failed to dispatch SkipWaitingResultRunnable to the worker.");
- }
- return NS_OK;
- }
- };
- } // namespace
- already_AddRefed<Promise>
- ServiceWorkerGlobalScope::SkipWaiting(ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- MOZ_ASSERT(mWorkerPrivate->IsServiceWorker());
- RefPtr<Promise> promise = Promise::Create(this, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return nullptr;
- }
- RefPtr<PromiseWorkerProxy> promiseProxy =
- PromiseWorkerProxy::Create(mWorkerPrivate, promise);
- if (!promiseProxy) {
- promise->MaybeResolveWithUndefined();
- return promise.forget();
- }
- RefPtr<WorkerScopeSkipWaitingRunnable> runnable =
- new WorkerScopeSkipWaitingRunnable(promiseProxy,
- NS_ConvertUTF16toUTF8(mScope));
- MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
- return promise.forget();
- }
- bool
- ServiceWorkerGlobalScope::OpenWindowEnabled(JSContext* aCx, JSObject* aObj)
- {
- WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
- MOZ_ASSERT(worker);
- worker->AssertIsOnWorkerThread();
- return worker->OpenWindowEnabled();
- }
- WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
- WorkerPrivate* aWorkerPrivate)
- : mWorkerPrivate(aWorkerPrivate)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- }
- 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();
- JS::CompartmentOptions options;
- mWorkerPrivate->CopyJSCompartmentOptions(options);
- return WorkerDebuggerGlobalScopeBinding::Wrap(aCx, this, this, options,
- GetWorkerPrincipal(), true,
- aReflector);
- }
- void
- WorkerDebuggerGlobalScope::GetGlobal(JSContext* aCx,
- JS::MutableHandle<JSObject*> aGlobal,
- ErrorResult& aRv)
- {
- WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
- if (!scope) {
- aRv.Throw(NS_ERROR_FAILURE);
- }
- aGlobal.set(scope->GetWrapper());
- }
- void
- WorkerDebuggerGlobalScope::CreateSandbox(JSContext* aCx, const nsAString& aName,
- JS::Handle<JSObject*> aPrototype,
- JS::MutableHandle<JSObject*> aResult,
- ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- aResult.set(nullptr);
- JS::Rooted<JS::Value> protoVal(aCx);
- protoVal.setObjectOrNull(aPrototype);
- JS::Rooted<JSObject*> sandbox(aCx,
- SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox,
- protoVal));
- if (!sandbox) {
- aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
- return;
- }
- if (!JS_WrapObject(aCx, &sandbox)) {
- aRv.NoteJSContextException(aCx);
- return;
- }
- aResult.set(sandbox);
- }
- void
- WorkerDebuggerGlobalScope::LoadSubScript(JSContext* aCx,
- const nsAString& aURL,
- const Optional<JS::Handle<JSObject*>>& aSandbox,
- ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- Maybe<JSAutoCompartment> ac;
- if (aSandbox.WasPassed()) {
- JS::Rooted<JSObject*> sandbox(aCx, js::CheckedUnwrap(aSandbox.Value()));
- if (!IsDebuggerSandbox(sandbox)) {
- aRv.Throw(NS_ERROR_INVALID_ARG);
- return;
- }
- ac.emplace(aCx, sandbox);
- }
- nsTArray<nsString> urls;
- urls.AppendElement(aURL);
- scriptloader::Load(mWorkerPrivate, urls, DebuggerScript, aRv);
- }
- void
- WorkerDebuggerGlobalScope::EnterEventLoop()
- {
- mWorkerPrivate->EnterDebuggerEventLoop();
- }
- void
- WorkerDebuggerGlobalScope::LeaveEventLoop()
- {
- mWorkerPrivate->LeaveDebuggerEventLoop();
- }
- void
- WorkerDebuggerGlobalScope::PostMessage(const nsAString& aMessage)
- {
- mWorkerPrivate->PostMessageToDebugger(aMessage);
- }
- void
- WorkerDebuggerGlobalScope::SetImmediate(Function& aHandler, ErrorResult& aRv)
- {
- mWorkerPrivate->SetDebuggerImmediate(aHandler, aRv);
- }
- void
- WorkerDebuggerGlobalScope::ReportError(JSContext* aCx,
- const nsAString& aMessage)
- {
- JS::AutoFilename chars;
- uint32_t lineno = 0;
- JS::DescribeScriptedCaller(aCx, &chars, &lineno);
- nsString filename(NS_ConvertUTF8toUTF16(chars.get()));
- mWorkerPrivate->ReportErrorToDebugger(filename, lineno, aMessage);
- }
- void
- WorkerDebuggerGlobalScope::RetrieveConsoleEvents(JSContext* aCx,
- nsTArray<JS::Value>& aEvents,
- ErrorResult& aRv)
- {
- WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
- if (!scope) {
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
- RefPtr<Console> console = scope->GetConsole(aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- console->RetrieveConsoleEvents(aCx, aEvents, aRv);
- }
- void
- WorkerDebuggerGlobalScope::SetConsoleEventHandler(JSContext* aCx,
- AnyCallback* aHandler,
- ErrorResult& aRv)
- {
- WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
- if (!scope) {
- aRv.Throw(NS_ERROR_FAILURE);
- return;
- }
- RefPtr<Console> console = scope->GetConsole(aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return;
- }
- console->SetConsoleEventHandler(aHandler);
- }
- Console*
- WorkerDebuggerGlobalScope::GetConsole(ErrorResult& aRv)
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- // Debugger console has its own console object.
- if (!mConsole) {
- mConsole = Console::Create(nullptr, aRv);
- if (NS_WARN_IF(aRv.Failed())) {
- return nullptr;
- }
- }
- return mConsole;
- }
- void
- WorkerDebuggerGlobalScope::Dump(JSContext* aCx,
- const Optional<nsAString>& aString) const
- {
- WorkerGlobalScope* scope = mWorkerPrivate->GetOrCreateGlobalScope(aCx);
- if (scope) {
- scope->Dump(aString);
- }
- }
- BEGIN_WORKERS_NAMESPACE
- bool
- IsWorkerGlobal(JSObject* object)
- {
- return IS_INSTANCE_OF(WorkerGlobalScope, object);
- }
- bool
- IsDebuggerGlobal(JSObject* object)
- {
- return IS_INSTANCE_OF(WorkerDebuggerGlobalScope, object);
- }
- bool
- IsDebuggerSandbox(JSObject* object)
- {
- return SimpleGlobalObject::SimpleGlobalType(object) ==
- SimpleGlobalObject::GlobalType::WorkerDebuggerSandbox;
- }
- END_WORKERS_NAMESPACE
|