summaryrefslogtreecommitdiffstats
path: root/dom/plugins/ipc/FunctionBrokerChild.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/plugins/ipc/FunctionBrokerChild.cpp111
1 files changed, 111 insertions, 0 deletions
diff --git a/dom/plugins/ipc/FunctionBrokerChild.cpp b/dom/plugins/ipc/FunctionBrokerChild.cpp
new file mode 100644
index 0000000000..a0780d853f
--- /dev/null
+++ b/dom/plugins/ipc/FunctionBrokerChild.cpp
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=4 et :
+ * 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 "FunctionBrokerChild.h"
+#include "FunctionBrokerThread.h"
+
+#include "mozilla/ipc/Endpoint.h"
+
+namespace mozilla::plugins {
+
+FunctionBrokerChild* FunctionBrokerChild::sInstance = nullptr;
+
+bool FunctionBrokerChild::IsDispatchThread() { return mThread->IsOnThread(); }
+
+void FunctionBrokerChild::PostToDispatchThread(
+ already_AddRefed<nsIRunnable>&& runnable) {
+ mThread->Dispatch(std::move(runnable));
+}
+
+/* static */
+bool FunctionBrokerChild::Initialize(
+ Endpoint<PFunctionBrokerChild>&& aBrokerEndpoint) {
+ MOZ_RELEASE_ASSERT(
+ XRE_IsPluginProcess(),
+ "FunctionBrokerChild can only be used in plugin processes");
+
+ MOZ_ASSERT(!sInstance);
+ FunctionBrokerThread* thread = FunctionBrokerThread::Create();
+ if (!thread) {
+ return false;
+ }
+ sInstance = new FunctionBrokerChild(thread, std::move(aBrokerEndpoint));
+ return true;
+}
+
+/* static */
+FunctionBrokerChild* FunctionBrokerChild::GetInstance() {
+ MOZ_RELEASE_ASSERT(
+ XRE_IsPluginProcess(),
+ "FunctionBrokerChild can only be used in plugin processes");
+
+ MOZ_ASSERT(sInstance, "Must initialize FunctionBrokerChild before using it");
+ return sInstance;
+}
+
+FunctionBrokerChild::FunctionBrokerChild(
+ FunctionBrokerThread* aThread, Endpoint<PFunctionBrokerChild>&& aEndpoint)
+ : mThread(aThread),
+ mShutdownDone(false),
+ mMonitor("FunctionBrokerChild Lock") {
+ MOZ_ASSERT(aThread);
+ PostToDispatchThread(
+ NewNonOwningRunnableMethod<Endpoint<PFunctionBrokerChild>&&>(
+ "FunctionBrokerChild::Bind", this, &FunctionBrokerChild::Bind,
+ std::move(aEndpoint)));
+}
+
+void FunctionBrokerChild::Bind(Endpoint<PFunctionBrokerChild>&& aEndpoint) {
+ MOZ_RELEASE_ASSERT(mThread->IsOnThread());
+ DebugOnly<bool> ok = aEndpoint.Bind(this);
+ MOZ_ASSERT(ok);
+}
+
+void FunctionBrokerChild::ShutdownOnDispatchThread() {
+ MOZ_ASSERT(mThread->IsOnThread());
+
+ // Set mShutdownDone and notify waiting thread (if any) that we are done.
+ MonitorAutoLock lock(mMonitor);
+ mShutdownDone = true;
+ mMonitor.Notify();
+}
+
+void FunctionBrokerChild::ActorDestroy(ActorDestroyReason aWhy) {
+ MOZ_ASSERT(mThread->IsOnThread());
+
+ // Queue up a task on the PD thread. When that task is executed then
+ // we know that anything queued before ActorDestroy has completed.
+ // At that point, we can set mShutdownDone and alert any waiting
+ // threads that it is safe to destroy us.
+ sInstance->PostToDispatchThread(NewNonOwningRunnableMethod(
+ "FunctionBrokerChild::ShutdownOnDispatchThread", sInstance,
+ &FunctionBrokerChild::ShutdownOnDispatchThread));
+}
+
+void FunctionBrokerChild::Destroy() {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ if (!sInstance) {
+ return;
+ }
+
+ // mShutdownDone will tell us when ActorDestroy has been run and any tasks
+ // on the FunctionBrokerThread have completed. At that point, we can
+ // safely delete the actor.
+ {
+ MonitorAutoLock lock(sInstance->mMonitor);
+ while (!sInstance->mShutdownDone) {
+ // Release lock and wait. Regain lock when we are notified that
+ // we have ShutdownOnDispatchThread.
+ sInstance->mMonitor.Wait();
+ }
+ }
+
+ delete sInstance;
+ sInstance = nullptr;
+}
+
+} // namespace mozilla::plugins