mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
a503acdd23
Differential Revision: https://phabricator.services.mozilla.com/D219687
214 lines
6.1 KiB
C++
214 lines
6.1 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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 "WorkerEventTarget.h"
|
|
#include "WorkerPrivate.h"
|
|
#include "WorkerRunnable.h"
|
|
|
|
#include "mozilla/Logging.h"
|
|
#include "mozilla/dom/ReferrerInfo.h"
|
|
|
|
namespace mozilla::dom {
|
|
|
|
static mozilla::LazyLogModule sWorkerEventTargetLog("WorkerEventTarget");
|
|
|
|
#ifdef LOG
|
|
# undef LOG
|
|
#endif
|
|
#ifdef LOGV
|
|
# undef LOGV
|
|
#endif
|
|
#define LOG(args) MOZ_LOG(sWorkerEventTargetLog, LogLevel::Debug, args);
|
|
#define LOGV(args) MOZ_LOG(sWorkerEventTargetLog, LogLevel::Verbose, args);
|
|
|
|
namespace {
|
|
|
|
class WrappedControlRunnable final : public WorkerControlRunnable {
|
|
nsCOMPtr<nsIRunnable> mInner;
|
|
|
|
~WrappedControlRunnable() = default;
|
|
|
|
public:
|
|
WrappedControlRunnable(WorkerPrivate* aWorkerPrivate,
|
|
nsCOMPtr<nsIRunnable>&& aInner)
|
|
: WorkerControlRunnable("WrappedControlRunnable"),
|
|
mInner(std::move(aInner)) {}
|
|
|
|
virtual bool PreDispatch(WorkerPrivate* aWorkerPrivate) override {
|
|
// Silence bad assertions, this can be dispatched from any thread.
|
|
return true;
|
|
}
|
|
|
|
virtual void PostDispatch(WorkerPrivate* aWorkerPrivate,
|
|
bool aDispatchResult) override {
|
|
// Silence bad assertions, this can be dispatched from any thread.
|
|
}
|
|
|
|
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
|
|
mInner->Run();
|
|
return true;
|
|
}
|
|
|
|
nsresult Cancel() override {
|
|
nsCOMPtr<nsICancelableRunnable> cr = do_QueryInterface(mInner);
|
|
|
|
// If the inner runnable is not cancellable, then just do the normal
|
|
// WorkerControlRunnable thing. This will end up calling Run().
|
|
if (!cr) {
|
|
return Run();
|
|
}
|
|
|
|
// Otherwise call the inner runnable's Cancel() and treat this like
|
|
// a WorkerRunnable cancel. We can't call WorkerControlRunnable::Cancel()
|
|
// in this case since that would result in both Run() and the inner
|
|
// Cancel() being called.
|
|
return cr->Cancel();
|
|
}
|
|
|
|
#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
|
|
NS_IMETHOD GetName(nsACString& aName) override {
|
|
aName.AssignLiteral("WrappedControlRunnable(");
|
|
if (nsCOMPtr<nsINamed> named = do_QueryInterface(mInner)) {
|
|
nsAutoCString containedName;
|
|
named->GetName(containedName);
|
|
aName.Append(containedName);
|
|
} else {
|
|
aName.AppendLiteral("?");
|
|
}
|
|
aName.AppendLiteral(")");
|
|
return NS_OK;
|
|
}
|
|
#endif
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
NS_IMPL_ISUPPORTS(WorkerEventTarget, nsIEventTarget, nsISerialEventTarget)
|
|
|
|
WorkerEventTarget::WorkerEventTarget(WorkerPrivate* aWorkerPrivate,
|
|
Behavior aBehavior)
|
|
: mMutex("WorkerEventTarget"),
|
|
mWorkerPrivate(aWorkerPrivate),
|
|
mBehavior(aBehavior) {
|
|
LOG(("WorkerEventTarget::WorkerEventTarget [%p] aBehavior: %u", this,
|
|
(uint8_t)aBehavior));
|
|
MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate);
|
|
}
|
|
|
|
void WorkerEventTarget::ForgetWorkerPrivate(WorkerPrivate* aWorkerPrivate) {
|
|
LOG(("WorkerEventTarget::ForgetWorkerPrivate [%p] aWorkerPrivate: %p", this,
|
|
aWorkerPrivate));
|
|
MutexAutoLock lock(mMutex);
|
|
MOZ_DIAGNOSTIC_ASSERT(!mWorkerPrivate || mWorkerPrivate == aWorkerPrivate);
|
|
mWorkerPrivate = nullptr;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
WorkerEventTarget::DispatchFromScript(nsIRunnable* aRunnable, uint32_t aFlags) {
|
|
LOGV(("WorkerEventTarget::DispatchFromScript [%p] aRunnable: %p", this,
|
|
aRunnable));
|
|
nsCOMPtr<nsIRunnable> runnable(aRunnable);
|
|
return Dispatch(runnable.forget(), aFlags);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
WorkerEventTarget::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
|
uint32_t aFlags) {
|
|
nsCOMPtr<nsIRunnable> runnable(aRunnable);
|
|
LOGV(
|
|
("WorkerEventTarget::Dispatch [%p] aRunnable: %p", this, runnable.get()));
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
if (!mWorkerPrivate) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
if (mBehavior == Behavior::Hybrid) {
|
|
LOGV(("WorkerEventTarget::Dispatch [%p] Dispatch as normal runnable(%p)",
|
|
this, runnable.get()));
|
|
|
|
RefPtr<WorkerRunnable> r =
|
|
mWorkerPrivate->MaybeWrapAsWorkerRunnable(runnable.forget());
|
|
if (r->Dispatch(mWorkerPrivate)) {
|
|
return NS_OK;
|
|
}
|
|
runnable = std::move(r);
|
|
LOGV((
|
|
"WorkerEventTarget::Dispatch [%p] Dispatch as normal runnable(%p) fail",
|
|
this, runnable.get()));
|
|
}
|
|
|
|
RefPtr<WorkerControlRunnable> r =
|
|
new WrappedControlRunnable(mWorkerPrivate, std::move(runnable));
|
|
LOGV(
|
|
("WorkerEventTarget::Dispatch [%p] Wrapped runnable as control "
|
|
"runnable(%p)",
|
|
this, r.get()));
|
|
if (!r->Dispatch(mWorkerPrivate)) {
|
|
LOGV(
|
|
("WorkerEventTarget::Dispatch [%p] Dispatch as control runnable(%p) "
|
|
"fail",
|
|
this, r.get()));
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
WorkerEventTarget::DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t) {
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
WorkerEventTarget::RegisterShutdownTask(nsITargetShutdownTask* aTask) {
|
|
NS_ENSURE_ARG(aTask);
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
// If mWorkerPrivate is gone, the event target is already late during
|
|
// shutdown, return NS_ERROR_UNEXPECTED as documented in `nsIEventTarget.idl`.
|
|
if (!mWorkerPrivate) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
return mWorkerPrivate->RegisterShutdownTask(aTask);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
WorkerEventTarget::UnregisterShutdownTask(nsITargetShutdownTask* aTask) {
|
|
NS_ENSURE_ARG(aTask);
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
if (!mWorkerPrivate) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
return mWorkerPrivate->UnregisterShutdownTask(aTask);
|
|
}
|
|
|
|
NS_IMETHODIMP_(bool)
|
|
WorkerEventTarget::IsOnCurrentThreadInfallible() {
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
if (!mWorkerPrivate) {
|
|
return false;
|
|
}
|
|
|
|
return mWorkerPrivate->IsOnCurrentThread();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
WorkerEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread) {
|
|
MOZ_ASSERT(aIsOnCurrentThread);
|
|
*aIsOnCurrentThread = IsOnCurrentThreadInfallible();
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace mozilla::dom
|