Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/dom/workers/sharedworkers/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 6 kB image not shown  

Quelle  SharedWorkerOp.cpp   Sprache: C

 
/* 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 "SharedWorkerOp.h"
#include "mozilla/dom/MessagePort.h"
#include "mozilla/dom/RemoteWorkerChild.h"
#include "mozilla/dom/RemoteWorkerNonLifeCycleOpControllerChild.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRunnable.h"
#include "mozilla/dom/WorkerScope.h"

namespace mozilla::dom {

using remoteworker::Canceled;
using remoteworker::Killed;
using remoteworker::Pending;
using remoteworker::Running;

namespace {

// Normal runnable because AddPortIdentifier() is going to exec JS code.
class MessagePortIdentifierRunnable final : public WorkerSameThreadRunnable {
 public:
  MessagePortIdentifierRunnable(
      RemoteWorkerNonLifeCycleOpControllerChild* aActor,
      const MessagePortIdentifier& aPortIdentifier)
      : WorkerSameThreadRunnable("MessagePortIdentifierRunnable"),
        mActor(aActor),
        mPortIdentifier(aPortIdentifier) {}

 private:
  bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
    if (aWorkerPrivate->GlobalScope()->IsDying()) {
      mPortIdentifier.ForceClose();
      return true;
    }
    if (!aWorkerPrivate->ConnectMessagePort(aCx, mPortIdentifier)) {
      mActor->ErrorPropagation(NS_ERROR_FAILURE);
    }
    return true;
  }

  RefPtr<RemoteWorkerNonLifeCycleOpControllerChild> mActor;
  UniqueMessagePortId mPortIdentifier;
};

}  // namespace

SharedWorkerOp::SharedWorkerOp(SharedWorkerOpArgs&& aArgs)
    : mOpArgs(std::move(aArgs)) {}

SharedWorkerOp::~SharedWorkerOp() { MOZ_ASSERT(mStarted); }

void SharedWorkerOp::Cancel() {
#ifdef DEBUG
  mStarted = true;
#endif
}

bool SharedWorkerOp::MaybeStart(RemoteWorkerChild* aOwner,
                                RemoteWorkerState& aState) {
  MOZ_ASSERT(!mStarted);
  MOZ_ASSERT(aOwner);
  // Thread: We are on the Worker Launcher thread.

  // Return false, indicating we should queue this op if our current state is
  // pending and this isn't a termination op (which should skip the line).
  if (aState.is<Pending>() && !IsTerminationOp()) {
    return false;
  }

  // If the worker is already shutting down (which should be unexpected
  // because we should be told new operations after a termination op), just
  // return true to indicate the op should be discarded.
  if (aState.is<Canceled>() || aState.is<Killed>()) {
#ifdef DEBUG
    mStarted = true;
#endif
    return true;
  }

  MOZ_ASSERT(aState.is<Running>() || IsTerminationOp());

  RefPtr<SharedWorkerOp> self = this;
  RefPtr<RemoteWorkerChild> owner = aOwner;

  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
      __func__, [self = std::move(self), owner = std::move(owner)]() mutable {
        {
          auto lock = owner->mState.Lock();

          if (NS_WARN_IF(lock->is<Canceled>() || lock->is<Killed>())) {
            self->Cancel();
            return;
          }
        }

        self->StartOnMainThread(owner);
      });

  MOZ_ALWAYS_SUCCEEDS(SchedulerGroup::Dispatch(r.forget()));

#ifdef DEBUG
  mStarted = true;
#endif

  return true;
}

void SharedWorkerOp::StartOnMainThread(RefPtr<RemoteWorkerChild>& aOwner) {
  AssertIsOnMainThread();

  if (IsTerminationOp()) {
    aOwner->CloseWorkerOnMainThread();
    return;
  }

  auto lock = aOwner->mState.Lock();
  MOZ_ASSERT(lock->is<Running>());
  if (!lock->is<Running>()) {
    aOwner->ErrorPropagationDispatch(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }

  RefPtr<WorkerPrivate> workerPrivate = lock->as<Running>().mWorkerPrivate;

  MOZ_ASSERT(workerPrivate);

  if (mOpArgs.type() == SharedWorkerOpArgs::TSharedWorkerSuspendOpArgs) {
    workerPrivate->ParentWindowPaused();
  } else if (mOpArgs.type() == SharedWorkerOpArgs::TSharedWorkerResumeOpArgs) {
    workerPrivate->ParentWindowResumed();
  } else if (mOpArgs.type() == SharedWorkerOpArgs::TSharedWorkerFreezeOpArgs) {
    workerPrivate->Freeze(nullptr);
  } else if (mOpArgs.type() == SharedWorkerOpArgs::TSharedWorkerThawOpArgs) {
    workerPrivate->Thaw(nullptr);
  } else if (mOpArgs.type() ==
             SharedWorkerOpArgs::TSharedWorkerPortIdentifierOpArgs) {
    MOZ_CRASH(
        "PortIdentifierOpArgs should not be processed by "
        "StartOnMainThread!!!");
  } else if (mOpArgs.type() ==
             SharedWorkerOpArgs::TSharedWorkerAddWindowIDOpArgs) {
    aOwner->mWindowIDs.AppendElement(
        mOpArgs.get_SharedWorkerAddWindowIDOpArgs().windowID());
  } else if (mOpArgs.type() ==
             SharedWorkerOpArgs::TSharedWorkerRemoveWindowIDOpArgs) {
    aOwner->mWindowIDs.RemoveElement(
        mOpArgs.get_SharedWorkerRemoveWindowIDOpArgs().windowID());
  } else {
    MOZ_CRASH("Unknown SharedWorkerOpArgs type!");
  }
}

void SharedWorkerOp::Start(RemoteWorkerNonLifeCycleOpControllerChild* aOwner,
                           RemoteWorkerState& aState) {
  MOZ_ASSERT(!mStarted);
  MOZ_ASSERT(aOwner);
  // Thread: We are on the Worker thread.

  // Only PortIdentifierOp is NonLifeCycle related opertaion.
  MOZ_ASSERT(mOpArgs.type() ==
             SharedWorkerOpArgs::TSharedWorkerPortIdentifierOpArgs);

  // Should never be Pending state.
  MOZ_ASSERT(!aState.is<Pending>());

  // If the worker is already shutting down (which should be unexpected
  // because we should be told new operations after a termination op), just
  // return directly.
  if (aState.is<Canceled>() || aState.is<Killed>()) {
#ifdef DEBUG
    mStarted = true;
#endif
    MessagePort::ForceClose(
        mOpArgs.get_SharedWorkerPortIdentifierOpArgs().portIdentifier());
    return;
  }

  MOZ_ASSERT(aState.is<Running>());

  // RefPtr<WorkerPrivate> workerPrivate = aState.as<Running>().mWorkerPrivate;
  WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();

  RefPtr<MessagePortIdentifierRunnable> r = new MessagePortIdentifierRunnable(
      aOwner, mOpArgs.get_SharedWorkerPortIdentifierOpArgs().portIdentifier());

  if (NS_WARN_IF(!r->Dispatch(workerPrivate))) {
    aOwner->ErrorPropagation(NS_ERROR_FAILURE);
  }

#ifdef DEBUG
  mStarted = true;
#endif
}

bool SharedWorkerOp::IsTerminationOp() const {
  return mOpArgs.type() == SharedWorkerOpArgs::TSharedWorkerTerminateOpArgs;
}

}  // namespace mozilla::dom

100%


¤ Dauer der Verarbeitung: 0.31 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.