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();
}
Example #2
0
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();
}
Example #3
0
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();
  }
}
Example #4
0
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();
}
Example #5
0
// 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;
}
Example #6
0
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();
}
Example #7
0
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();
}
Example #9
0
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;
}
Example #10
0
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();
}
Example #11
0
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();
  }
}
Example #12
0
  ~WorkerFeature()
  {
    mWorkerPrivate->AssertIsOnWorkerThread();

    MOZ_COUNT_DTOR(IDBOpenDBRequest::WorkerFeature);

    mWorkerPrivate->RemoveFeature(mWorkerPrivate->GetJSContext(), this);
  }
Example #13
0
bool
ServiceWorkerGlobalScope::OpenWindowEnabled(JSContext* aCx, JSObject* aObj)
{
  WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
  MOZ_ASSERT(worker);
  worker->AssertIsOnWorkerThread();
  return worker->OpenWindowEnabled();
}
Example #14
0
// 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();
}
Example #15
0
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
}
Example #16
0
Promise*
PromiseWorkerProxy::WorkerPromise() const
{
#ifdef DEBUG
  WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
  MOZ_ASSERT(worker);
  worker->AssertIsOnWorkerThread();
#endif
  MOZ_ASSERT(mWorkerPromise);
  return mWorkerPromise;
}
Example #17
0
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);
  }
}
Example #18
0
/* 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();
    }
}
Example #19
0
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();
}
Example #20
0
  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;
  }
Example #21
0
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;
  }
}
Example #22
0
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;
  }
}
Example #23
0
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());
  }
}
Example #24
0
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);
}
Example #25
0
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;
}
Example #27
0
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);
}
Example #28
0
  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);
  }
Example #29
0
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();
}
Example #30
0
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();
}