already_AddRefed<Promise> WorkerDataStore::Remove(JSContext* aCx, const StringOrUnsignedLong& aId, const nsAString& aRevisionId, 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<DataStoreRemoveRunnable> runnable = new DataStoreRemoveRunnable(workerPrivate, mBackingStore, promise, aId, aRevisionId); 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::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::Add(JSContext* aCx, JS::Handle<JS::Value> aObj, const Optional<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<DataStoreAddRunnable> runnable = new DataStoreAddRunnable(workerPrivate, mBackingStore, promise, aCx, aObj, 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(); }
already_AddRefed<Promise> PushManager::PerformSubscriptionActionFromWorker( SubscriptionAction aAction, ErrorResult& aRv) { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); nsCOMPtr<nsIGlobalObject> global = worker->GlobalScope(); RefPtr<Promise> p = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } RefPtr<PromiseWorkerProxy> proxy = PromiseWorkerProxy::Create(worker, p); if (!proxy) { p->MaybeReject(NS_ERROR_DOM_PUSH_ABORT_ERR); return p.forget(); } RefPtr<GetSubscriptionRunnable> r = new GetSubscriptionRunnable(proxy, mScope, aAction); MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r)); return p.forget(); }
already_AddRefed<Promise> PushSubscription::UnsubscribeFromWorker(ErrorResult& aRv) { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); nsCOMPtr<nsIGlobalObject> global = worker->GlobalScope(); RefPtr<Promise> p = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } RefPtr<PromiseWorkerProxy> proxy = PromiseWorkerProxy::Create(worker, p); if (!proxy) { p->MaybeReject(NS_ERROR_DOM_PUSH_SERVICE_UNREACHABLE); return p.forget(); } RefPtr<UnsubscribeRunnable> r = new UnsubscribeRunnable(proxy, mScope); MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r)); return p.forget(); }
already_AddRefed<Promise> PushManager::PermissionState(ErrorResult& aRv) { if (mImpl) { MOZ_ASSERT(NS_IsMainThread()); return mImpl->PermissionState(aRv); } WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); nsCOMPtr<nsIGlobalObject> global = worker->GlobalScope(); RefPtr<Promise> p = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } RefPtr<PromiseWorkerProxy> proxy = PromiseWorkerProxy::Create(worker, p); if (!proxy) { p->MaybeReject(worker->GetJSContext(), JS::UndefinedHandleValue); return p.forget(); } RefPtr<PermissionStateRunnable> r = new PermissionStateRunnable(proxy); NS_DispatchToMainThread(r); return p.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<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(); }
already_AddRefed<Promise> WorkerNavigator::GetDataStores(JSContext* aCx, const nsAString& aName, const nsAString& aOwner, 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<NavigatorGetDataStoresRunnable> runnable = new NavigatorGetDataStoresRunnable(workerPrivate, promise, aName, aOwner, aRv); runnable->Dispatch(aCx); return promise.forget(); }
already_AddRefed<Promise> WorkerDataStore::Put(JSContext* aCx, JS::Handle<JS::Value> aObj, const StringOrUnsignedLong& aId, const nsAString& aRevisionId, 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<DataStorePutRunnable> runnable = new DataStorePutRunnable(workerPrivate, mBackingStore, promise, aId, aRevisionId); runnable->Write(aCx, aObj, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } runnable->Dispatch(aRv); if (aRv.Failed()) { return nullptr; } if (NS_FAILED(runnable->ErrorCode())) { aRv.Throw(runnable->ErrorCode()); return nullptr; } return promise.forget(); }
already_AddRefed<Promise> WorkerDataStore::Get(JSContext* aCx, const Sequence<OwningStringOrUnsignedLong>& aId, 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<DataStoreGetRunnable> runnable = new DataStoreGetRunnable(workerPrivate, mBackingStore, promise); if (!runnable->Id().AppendElements(aId, fallible)) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return nullptr; } 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::Clear(JSContext* aCx, 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<DataStoreClearRunnable> runnable = new DataStoreClearRunnable(workerPrivate, mBackingStore, promise, aRevisionId, aRv); runnable->Dispatch(aCx); return promise.forget(); }
bool BroadcastChannelChild::RecvNotify(const ClonedMessageData& aData) { // Make sure to retrieve all blobs from the message before returning to avoid // leaking their actors. nsTArray<nsRefPtr<BlobImpl>> blobs; if (!aData.blobsChild().IsEmpty()) { blobs.SetCapacity(aData.blobsChild().Length()); for (uint32_t i = 0, len = aData.blobsChild().Length(); i < len; ++i) { nsRefPtr<BlobImpl> impl = static_cast<BlobChild*>(aData.blobsChild()[i])->GetBlobImpl(); blobs.AppendElement(impl); } } nsCOMPtr<DOMEventTargetHelper> helper = mBC; nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(helper); // This object has been already closed by content or is going to be deleted // soon. No notify is required. if (!eventTarget || mBC->IsClosed()) { return true; } // CheckInnerWindowCorrectness can be used also without a window when // BroadcastChannel is running in a worker. In this case, it's a NOP. if (NS_FAILED(mBC->CheckInnerWindowCorrectness())) { return true; } AutoJSAPI jsapi; nsCOMPtr<nsIGlobalObject> globalObject; if (NS_IsMainThread()) { globalObject = do_QueryInterface(mBC->GetParentObject()); } else { WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); globalObject = workerPrivate->GlobalScope(); } if (!globalObject || !jsapi.Init(globalObject)) { NS_WARNING("Failed to initialize AutoJSAPI object."); return true; } JSContext* cx = jsapi.cx(); const SerializedStructuredCloneBuffer& buffer = aData.data(); StructuredCloneHelper cloneHelper(StructuredCloneHelper::CloningSupported, StructuredCloneHelper::TransferringNotSupported, StructuredCloneHelper::DifferentProcess); cloneHelper.BlobImpls().AppendElements(blobs); JS::Rooted<JS::Value> value(cx, JS::NullValue()); if (buffer.dataLength) { ErrorResult rv; cloneHelper.ReadFromBuffer(mBC->GetParentObject(), cx, buffer.data, buffer.dataLength, &value, rv); if (NS_WARN_IF(rv.Failed())) { return true; } } RootedDictionary<MessageEventInit> init(cx); init.mBubbles = false; init.mCancelable = false; init.mOrigin.Construct(mOrigin); init.mData = value; ErrorResult rv; nsRefPtr<MessageEvent> event = MessageEvent::Constructor(mBC, NS_LITERAL_STRING("message"), init, rv); if (rv.Failed()) { NS_WARNING("Failed to create a MessageEvent object."); return true; } event->SetTrusted(true); bool status; mBC->DispatchEvent(static_cast<Event*>(event.get()), &status); return true; }
// static nsresult IndexedDatabaseManager::CommonPostHandleEvent(EventChainPostVisitor& aVisitor, IDBFactory* aFactory) { MOZ_ASSERT(aVisitor.mDOMEvent); MOZ_ASSERT(aFactory); if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault) { return NS_OK; } Event* internalEvent = aVisitor.mDOMEvent->InternalDOMEvent(); MOZ_ASSERT(internalEvent); if (!internalEvent->IsTrusted()) { return NS_OK; } nsString type; MOZ_ALWAYS_SUCCEEDS(internalEvent->GetType(type)); MOZ_ASSERT(nsDependentString(kErrorEventType).EqualsLiteral("error")); if (!type.EqualsLiteral("error")) { return NS_OK; } nsCOMPtr<EventTarget> eventTarget = internalEvent->GetTarget(); MOZ_ASSERT(eventTarget); // Only mess with events that were originally targeted to an IDBRequest. RefPtr<IDBRequest> request; if (NS_FAILED(eventTarget->QueryInterface(kIDBRequestIID, getter_AddRefs(request))) || !request) { return NS_OK; } RefPtr<DOMError> error = request->GetErrorAfterResult(); nsString errorName; if (error) { error->GetName(errorName); } RootedDictionary<ErrorEventInit> init(nsContentUtils::RootingCxForThread()); request->GetCallerLocation(init.mFilename, &init.mLineno, &init.mColno); init.mMessage = errorName; init.mCancelable = true; init.mBubbles = true; nsEventStatus status = nsEventStatus_eIgnore; if (NS_IsMainThread()) { nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(eventTarget->GetOwnerGlobal()); if (window) { nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window); MOZ_ASSERT(sgo); if (NS_WARN_IF(NS_FAILED(sgo->HandleScriptError(init, &status)))) { status = nsEventStatus_eIgnore; } } else { // We don't fire error events at any global for non-window JS on the main // thread. } } else { // Not on the main thread, must be in a worker. WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(workerPrivate); RefPtr<WorkerGlobalScope> globalScope = workerPrivate->GlobalScope(); MOZ_ASSERT(globalScope); RefPtr<ErrorEvent> errorEvent = ErrorEvent::Constructor(globalScope, nsDependentString(kErrorEventType), init); MOZ_ASSERT(errorEvent); errorEvent->SetTrusted(true); auto* target = static_cast<EventTarget*>(globalScope.get()); if (NS_WARN_IF(NS_FAILED( EventDispatcher::DispatchDOMEvent(target, /* aWidgetEvent */ nullptr, errorEvent, /* aPresContext */ nullptr, &status)))) { status = nsEventStatus_eIgnore; } } if (status == nsEventStatus_eConsumeNoDefault) { return NS_OK; } // Log the error to the error console. ScriptErrorHelper::Dump(errorName, init.mFilename, init.mLineno, init.mColno, nsIScriptError::errorFlag, aFactory->IsChrome(), aFactory->InnerWindowID()); return NS_OK; }