diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /dom/workers/remoteworkers/RemoteWorkerService.cpp | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/workers/remoteworkers/RemoteWorkerService.cpp')
-rw-r--r-- | dom/workers/remoteworkers/RemoteWorkerService.cpp | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/dom/workers/remoteworkers/RemoteWorkerService.cpp b/dom/workers/remoteworkers/RemoteWorkerService.cpp new file mode 100644 index 0000000000..6cdbb79d94 --- /dev/null +++ b/dom/workers/remoteworkers/RemoteWorkerService.cpp @@ -0,0 +1,190 @@ +/* -*- 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 "RemoteWorkerService.h" + +#include "mozilla/dom/PRemoteWorkerParent.h" +#include "mozilla/ipc/BackgroundChild.h" +#include "mozilla/ipc/BackgroundParent.h" +#include "mozilla/ipc/PBackgroundChild.h" +#include "mozilla/ipc/PBackgroundParent.h" +#include "mozilla/SchedulerGroup.h" +#include "mozilla/Services.h" +#include "mozilla/StaticMutex.h" +#include "mozilla/StaticPtr.h" +#include "nsIObserverService.h" +#include "nsIThread.h" +#include "nsThreadUtils.h" +#include "nsXPCOMPrivate.h" +#include "RemoteWorkerController.h" +#include "RemoteWorkerServiceChild.h" +#include "RemoteWorkerServiceParent.h" + +namespace mozilla { + +using namespace ipc; + +namespace dom { + +namespace { + +StaticMutex sRemoteWorkerServiceMutex; +StaticRefPtr<RemoteWorkerService> sRemoteWorkerService; + +} // namespace + +/* static */ +void RemoteWorkerService::Initialize() { + MOZ_ASSERT(NS_IsMainThread()); + + StaticMutexAutoLock lock(sRemoteWorkerServiceMutex); + MOZ_ASSERT(!sRemoteWorkerService); + + RefPtr<RemoteWorkerService> service = new RemoteWorkerService(); + + if (!XRE_IsParentProcess()) { + nsresult rv = service->InitializeOnMainThread(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + sRemoteWorkerService = service; + return; + } + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + if (NS_WARN_IF(!obs)) { + return; + } + + nsresult rv = obs->AddObserver(service, "profile-after-change", false); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + sRemoteWorkerService = service; +} + +/* static */ +nsIThread* RemoteWorkerService::Thread() { + StaticMutexAutoLock lock(sRemoteWorkerServiceMutex); + MOZ_ASSERT(sRemoteWorkerService); + MOZ_ASSERT(sRemoteWorkerService->mThread); + return sRemoteWorkerService->mThread; +} + +nsresult RemoteWorkerService::InitializeOnMainThread() { + // I would like to call this thread "DOM Remote Worker Launcher", but the max + // length is 16 chars. + nsresult rv = NS_NewNamedThread("Worker Launcher", getter_AddRefs(mThread)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + if (NS_WARN_IF(!obs)) { + return NS_ERROR_FAILURE; + } + + rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + RefPtr<RemoteWorkerService> self = this; + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "InitializeThread", [self]() { self->InitializeOnTargetThread(); }); + + rv = mThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} + +RemoteWorkerService::RemoteWorkerService() { MOZ_ASSERT(NS_IsMainThread()); } + +RemoteWorkerService::~RemoteWorkerService() = default; + +void RemoteWorkerService::InitializeOnTargetThread() { + MOZ_ASSERT(mThread); + MOZ_ASSERT(mThread->IsOnCurrentThread()); + + PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread(); + if (NS_WARN_IF(!actorChild)) { + return; + } + + RemoteWorkerServiceChild* actor = static_cast<RemoteWorkerServiceChild*>( + actorChild->SendPRemoteWorkerServiceConstructor()); + if (NS_WARN_IF(!actor)) { + return; + } + + // Now we are ready! + mActor = actor; +} + +void RemoteWorkerService::ShutdownOnTargetThread() { + MOZ_ASSERT(mThread); + MOZ_ASSERT(mThread->IsOnCurrentThread()); + + // If mActor is nullptr it means that initialization failed. + if (mActor) { + // Here we need to shutdown the IPC protocol. + mActor->Send__delete__(mActor); + mActor = nullptr; + } + + // Then we can terminate the thread on the main-thread. + RefPtr<RemoteWorkerService> self = this; + nsCOMPtr<nsIRunnable> r = + NS_NewRunnableFunction("ShutdownOnMainThread", [self]() { + self->mThread->Shutdown(); + self->mThread = nullptr; + }); + + SchedulerGroup::Dispatch(TaskCategory::Other, r.forget()); +} + +NS_IMETHODIMP +RemoteWorkerService::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) { + if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { + MOZ_ASSERT(mThread); + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + if (obs) { + obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); + } + + RefPtr<RemoteWorkerService> self = this; + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "ShutdownThread", [self]() { self->ShutdownOnTargetThread(); }); + + mThread->Dispatch(r.forget(), NS_DISPATCH_NORMAL); + + StaticMutexAutoLock lock(sRemoteWorkerServiceMutex); + sRemoteWorkerService = nullptr; + return NS_OK; + } + + MOZ_ASSERT(!strcmp(aTopic, "profile-after-change")); + MOZ_ASSERT(XRE_IsParentProcess()); + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + if (obs) { + obs->RemoveObserver(this, "profile-after-change"); + } + + return InitializeOnMainThread(); +} + +NS_IMPL_ISUPPORTS(RemoteWorkerService, nsIObserver) + +} // namespace dom +} // namespace mozilla |