already_AddRefed<Promise> ServiceWorkerWindowClient::Focus(ErrorResult& aRv) const { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject()); MOZ_ASSERT(global); nsRefPtr<Promise> promise = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } nsRefPtr<PromiseWorkerProxy> promiseProxy = PromiseWorkerProxy::Create(workerPrivate, promise); if (!promiseProxy->GetWorkerPromise()) { // Don't dispatch if adding the worker feature failed. return promise.forget(); } nsRefPtr<ClientFocusRunnable> r = new ClientFocusRunnable(mWindowId, promiseProxy); aRv = NS_DispatchToMainThread(r); if (NS_WARN_IF(aRv.Failed())) { promise->MaybeReject(aRv); } return promise.forget(); }
already_AddRefed<Promise> WorkerPushManager::PerformSubscriptionAction(SubscriptionAction aAction, ErrorResult& aRv) { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); nsCOMPtr<nsIGlobalObject> global = worker->GlobalScope(); nsRefPtr<Promise> p = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } nsRefPtr<PromiseWorkerProxy> proxy = PromiseWorkerProxy::Create(worker, p); if (!proxy) { p->MaybeReject(NS_ERROR_DOM_ABORT_ERR); return p.forget(); } nsRefPtr<GetSubscriptionRunnable> r = new GetSubscriptionRunnable(proxy, mScope, aAction); MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r))); return p.forget(); }
void MessagePort::UpdateMustKeepAlive() { if (mState == eStateDisentangled && mIsKeptAlive) { mIsKeptAlive = false; if (mWorkerFeature) { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); workerPrivate->RemoveFeature(workerPrivate->GetJSContext(), mWorkerFeature); mWorkerFeature = nullptr; } if (NS_IsMainThread()) { nsCOMPtr<nsIObserverService> obs = do_GetService("@mozilla.org/observer-service;1"); if (obs) { obs->RemoveObserver(this, "inner-window-destroyed"); } } Release(); return; } if (mState < eStateDisentangled && !mIsKeptAlive) { mIsKeptAlive = true; AddRef(); } }
already_AddRefed<WorkerDataStoreCursor> WorkerDataStore::Sync(JSContext* aCx, const nsAString& aRevisionId, ErrorResult& aRv) { WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); // Create a WorkerDataStoreCursor on the worker. Note that we need to pass // this WorkerDataStore into the WorkerDataStoreCursor, so that it can keep // track of which WorkerDataStore owns the WorkerDataStoreCursor. nsRefPtr<WorkerDataStoreCursor> workerCursor = new WorkerDataStoreCursor(this); // DataStoreSyncStoreRunnable will point the WorkerDataStoreCursor to the // DataStoreCursor created on the main thread. nsRefPtr<DataStoreSyncStoreRunnable> runnable = new DataStoreSyncStoreRunnable(workerPrivate, mBackingStore, workerCursor, aRevisionId, aRv); runnable->Dispatch(aCx); return workerCursor.forget(); }
// static PLDHashOperator RuntimeService::AddAllTopLevelWorkersToArray(const nsACString& aKey, WorkerDomainInfo* aData, void* aUserArg) { nsTArray<WorkerPrivate*>* array = static_cast<nsTArray<WorkerPrivate*>*>(aUserArg); #ifdef DEBUG for (PRUint32 index = 0; index < aData->mActiveWorkers.Length(); index++) { NS_ASSERTION(!aData->mActiveWorkers[index]->GetParent(), "Shouldn't have a parent in this list!"); } #endif array->AppendElements(aData->mActiveWorkers); // These might not be top-level workers... for (PRUint32 index = 0; index < aData->mQueuedWorkers.Length(); index++) { WorkerPrivate* worker = aData->mQueuedWorkers[index]; if (!worker->GetParent()) { array->AppendElement(worker); } } return PL_DHASH_NEXT; }
already_AddRefed<Promise> WorkerDataStore::GetLength(JSContext* aCx, ErrorResult& aRv) { WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); RefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv); if (aRv.Failed()) { return nullptr; } RefPtr<DataStoreGetLengthRunnable> runnable = new DataStoreGetLengthRunnable(workerPrivate, mBackingStore, promise); runnable->Dispatch(aRv); if (aRv.Failed()) { return nullptr; } if (runnable->Failed()) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } return promise.forget(); }
already_AddRefed<Promise> WorkerDataStore::Remove(JSContext* aCx, const StringOrUnsignedLong& aId, const nsAString& aRevisionId, ErrorResult& aRv) { WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); nsRefPtr<Promise> promise = Promise::Create(workerPrivate->GlobalScope(), aRv); if (aRv.Failed()) { return nullptr; } nsRefPtr<DataStoreRemoveRunnable> runnable = new DataStoreRemoveRunnable(workerPrivate, mBackingStore, promise, aId, aRevisionId, aRv); runnable->Dispatch(aCx); return promise.forget(); }
already_AddRefed<Promise> ServiceWorkerWindowClient::Focus(ErrorResult& aRv) const { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject()); MOZ_ASSERT(global); RefPtr<Promise> promise = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } if (workerPrivate->GlobalScope()->WindowInteractionAllowed()) { RefPtr<PromiseWorkerProxy> promiseProxy = PromiseWorkerProxy::Create(workerPrivate, promise); if (promiseProxy) { RefPtr<ClientFocusRunnable> r = new ClientFocusRunnable(mWindowId, promiseProxy); MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r)); } else { promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); } } else { promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); } return promise.forget(); }
static JSObject* GetDataStoresStructuredCloneCallbacksRead(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag, uint32_t aData, void* aClosure) { WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); if (aTag != WORKER_DATA_STORES_TAG) { MOZ_ASSERT(false, "aTag must be WORKER_DATA_STORES_TAG!"); return nullptr; } NS_ASSERTION(!aData, "aData should be empty"); // Read the holder from the buffer, which points to the data store. nsMainThreadPtrHolder<DataStore>* dataStoreholder; if (!JS_ReadBytes(aReader, &dataStoreholder, sizeof(dataStoreholder))) { MOZ_ASSERT(false, "cannot read bytes for dataStoreholder!"); return nullptr; } // Protect workerStoreObj from moving GC during ~nsRefPtr. JS::Rooted<JSObject*> workerStoreObj(aCx, nullptr); { nsRefPtr<WorkerDataStore> workerStore = new WorkerDataStore(workerPrivate->GlobalScope()); nsMainThreadPtrHandle<DataStore> backingStore(dataStoreholder); // When we're on the worker thread, prepare a DataStoreChangeEventProxy. nsRefPtr<DataStoreChangeEventProxy> eventProxy = new DataStoreChangeEventProxy(workerPrivate, workerStore); // Add the DataStoreChangeEventProxy as an event listener on the main thread. nsRefPtr<DataStoreAddEventListenerRunnable> runnable = new DataStoreAddEventListenerRunnable(workerPrivate, backingStore, eventProxy); runnable->Dispatch(aCx); // Point WorkerDataStore to DataStore. workerStore->SetBackingDataStore(backingStore); JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx)); if (!global) { MOZ_ASSERT(false, "cannot get global!"); } else { workerStoreObj = workerStore->WrapObject(aCx); if (!JS_WrapObject(aCx, &workerStoreObj)) { MOZ_ASSERT(false, "cannot wrap object for workerStoreObj!"); workerStoreObj = nullptr; } } } return workerStoreObj; }
already_AddRefed<Promise> WorkerPushManager::PermissionState(ErrorResult& aRv) { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); nsCOMPtr<nsIGlobalObject> global = worker->GlobalScope(); nsRefPtr<Promise> p = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } nsRefPtr<PromiseWorkerProxy> proxy = PromiseWorkerProxy::Create(worker, p); if (!proxy) { p->MaybeReject(worker->GetJSContext(), JS::UndefinedHandleValue); return p.forget(); } nsRefPtr<PermissionStateRunnable> r = new PermissionStateRunnable(proxy); NS_DispatchToMainThread(r); return p.forget(); }
void BroadcastChannel::Shutdown() { mState = StateClosed; if (mWorkerFeature) { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); workerPrivate->RemoveFeature(workerPrivate->GetJSContext(), mWorkerFeature); mWorkerFeature = nullptr; } if (mActor) { mActor->SetParent(nullptr); nsRefPtr<TeardownRunnable> runnable = new TeardownRunnable(mActor); NS_DispatchToCurrentThread(runnable); mActor = nullptr; } // If shutdown() is called we have to release the reference if we still keep // it. if (mIsKeptAlive) { mIsKeptAlive = false; Release(); } }
~WorkerFeature() { mWorkerPrivate->AssertIsOnWorkerThread(); MOZ_COUNT_DTOR(IDBOpenDBRequest::WorkerFeature); mWorkerPrivate->RemoveFeature(mWorkerPrivate->GetJSContext(), this); }
bool ServiceWorkerGlobalScope::OpenWindowEnabled(JSContext* aCx, JSObject* aObj) { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); return worker->OpenWindowEnabled(); }
// static already_AddRefed<WorkerPushSubscription> WorkerPushSubscription::Constructor(GlobalObject& aGlobal, const nsAString& aEndpoint, const nsAString& aScope, ErrorResult& aRv) { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); nsRefPtr<WorkerPushSubscription> sub = new WorkerPushSubscription(aEndpoint, aScope); return sub.forget(); }
PushManager::PushManager(const nsAString& aScope) : mScope(aScope) { #ifdef DEBUG // There's only one global on a worker, so we don't need to pass a global // object to the constructor. WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); #endif }
Promise* PromiseWorkerProxy::WorkerPromise() const { #ifdef DEBUG WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); #endif MOZ_ASSERT(mWorkerPromise); return mWorkerPromise; }
void MessagePort::Initialize(const nsID& aUUID, const nsID& aDestinationUUID, uint32_t aSequenceID, bool mNeutered, State aState, ErrorResult& aRv) { MOZ_ASSERT(mIdentifier); mIdentifier->uuid() = aUUID; mIdentifier->destinationUuid() = aDestinationUUID; mIdentifier->sequenceId() = aSequenceID; mState = aState; mNextStep = eNextStepNone; if (mNeutered) { // If this port is neutered we don't want to keep it alive artificially nor // we want to add listeners or workerFeatures. mState = eStateDisentangled; return; } if (mState == eStateEntangling) { ConnectToPBackground(); } else { MOZ_ASSERT(mState == eStateUnshippedEntangled); } // The port has to keep itself alive until it's entangled. UpdateMustKeepAlive(); if (NS_IsMainThread()) { MOZ_ASSERT(GetOwner()); MOZ_ASSERT(GetOwner()->IsInnerWindow()); mInnerID = GetOwner()->WindowID(); nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->AddObserver(this, "inner-window-destroyed", false); } } else { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); MOZ_ASSERT(!mWorkerFeature); nsAutoPtr<WorkerFeature> feature(new MessagePortFeature(this)); JSContext* cx = workerPrivate->GetJSContext(); if (NS_WARN_IF(!workerPrivate->AddFeature(cx, feature))) { aRv.Throw(NS_ERROR_FAILURE); return; } mWorkerFeature = Move(feature); } }
/* static */ bool OffscreenCanvas::PrefEnabled(JSContext* aCx, JSObject* aObj) { if (NS_IsMainThread()) { return Preferences::GetBool("gfx.offscreencanvas.enabled"); } else { WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); return workerPrivate->OffscreenCanvasEnabled(); } }
already_AddRefed<WorkerDataStore> WorkerDataStore::Constructor(GlobalObject& aGlobal, ErrorResult& aRv) { JSContext* cx = aGlobal.GetContext(); WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); nsRefPtr<WorkerDataStore> store = new WorkerDataStore(workerPrivate->GlobalScope()); return store.forget(); }
bool MainThreadRun() override { MOZ_ASSERT(NS_IsMainThread()); nsIPrincipal* principal = GetPrincipalFromWorkerPrivate(mWorkerPrivate); if (!principal) { mRv.Throw(NS_ERROR_FAILURE); return true; } bool isNullPrincipal; mRv = principal->GetIsNullPrincipal(&isNullPrincipal); if (NS_WARN_IF(mRv.Failed())) { return true; } if (NS_WARN_IF(isNullPrincipal)) { mRv.Throw(NS_ERROR_FAILURE); return true; } mRv = PrincipalToPrincipalInfo(principal, &mPrincipalInfo); if (NS_WARN_IF(mRv.Failed())) { return true; } mRv = principal->GetOrigin(mOrigin); if (NS_WARN_IF(mRv.Failed())) { return true; } // Walk up to our containing page WorkerPrivate* wp = mWorkerPrivate; while (wp->GetParent()) { wp = wp->GetParent(); } // Window doesn't exist for some kind of workers (eg: SharedWorkers) nsPIDOMWindow* window = wp->GetWindow(); if (!window) { return true; } nsIDocument* doc = window->GetExtantDoc(); if (doc) { mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc); // No bfcache when BroadcastChannel is used. doc->DisallowBFCaching(); } return true; }
void WorkerNavigator::GetAppVersion(nsString& aAppVersion) const { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); if (!mProperties.mAppVersionOverridden.IsEmpty() && !workerPrivate->UsesSystemPrincipal()) { aAppVersion = mProperties.mAppVersionOverridden; } else { aAppVersion = mProperties.mAppVersion; } }
void WorkerNavigator::GetPlatform(nsString& aPlatform) const { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); if (!mProperties.mPlatformOverridden.IsEmpty() && !workerPrivate->UsesSystemPrincipal()) { aPlatform = mProperties.mPlatformOverridden; } else { aPlatform = mProperties.mPlatform; } }
void WorkerNavigator::GetUserAgent(nsString& aUserAgent) const { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); nsRefPtr<GetUserAgentRunnable> runnable = new GetUserAgentRunnable(workerPrivate, aUserAgent); if (!runnable->Dispatch(workerPrivate->GetJSContext())) { JS_ReportPendingException(workerPrivate->GetJSContext()); } }
bool LoadWorkerScript(JSContext* aCx) { WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx); NS_ASSERTION(worker, "This should never be null!"); nsTArray<ScriptLoadInfo> loadInfos; ScriptLoadInfo* info = loadInfos.AppendElement(); info->mURL = worker->ScriptURL(); return LoadAllScripts(aCx, worker, loadInfos, true); }
bool WorkerDataStore::GetReadOnly(JSContext* aCx, ErrorResult& aRv) { WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); nsRefPtr<DataStoreGetReadOnlyRunnable> runnable = new DataStoreGetReadOnlyRunnable(workerPrivate, mBackingStore, aRv); runnable->Dispatch(aCx); return runnable->mReadOnly; }
void RespondWithHandler::CancelRequest(nsresult aStatus) { nsCOMPtr<nsIRunnable> runnable = new CancelChannelRunnable(mInterceptedChannel, mRegistration, aStatus); // Note, this may run off the worker thread during worker termination. WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); if (worker) { MOZ_ALWAYS_SUCCEEDS(worker->DispatchToMainThread(runnable.forget())); } else { MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable.forget())); } mRequestWasHandled = true; }
void WorkerDataStore::GetOwner(JSContext* aCx, nsAString& aOwner, ErrorResult& aRv) { WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); RefPtr<DataStoreGetStringRunnable> runnable = new DataStoreGetStringRunnable(workerPrivate, mBackingStore, &DataStore::GetOwner, aOwner); runnable->Dispatch(aRv); }
bool Dispatch(JSContext* aCx) { mWorkerPrivate->AssertIsOnWorkerThread(); mSyncQueueKey = mWorkerPrivate->CreateNewSyncLoop(); if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) { JS_ReportError(aCx, "Failed to dispatch to main thread!"); mWorkerPrivate->StopSyncLoop(mSyncQueueKey, false); return false; } return mWorkerPrivate->RunSyncLoop(aCx, mSyncQueueKey); }
already_AddRefed<URL> ParseURLFromWorker(const GlobalObject& aGlobal, const nsAString& aInput, ErrorResult& aRv) { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); NS_ConvertUTF8toUTF16 baseURL(worker->GetLocationInfo().mHref); RefPtr<URL> url = URL::WorkerConstructor(aGlobal, aInput, baseURL, aRv); if (NS_WARN_IF(aRv.Failed())) { aRv.ThrowTypeError<MSG_INVALID_URL>(aInput); } return url.forget(); }
WorkerCrossThreadDispatcher* GetWorkerCrossThreadDispatcher(JSContext* aCx, jsval aWorker) { if (JSVAL_IS_PRIMITIVE(aWorker)) { return NULL; } WorkerPrivate* w = Worker::GetInstancePrivate(aCx, JSVAL_TO_OBJECT(aWorker), "GetWorkerCrossThreadDispatcher"); if (!w) { return NULL; } return w->GetCrossThreadDispatcher(); }