summaryrefslogtreecommitdiffstats
path: root/dom/locks/LockManagerChild.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/locks/LockManagerChild.cpp')
-rw-r--r--dom/locks/LockManagerChild.cpp106
1 files changed, 106 insertions, 0 deletions
diff --git a/dom/locks/LockManagerChild.cpp b/dom/locks/LockManagerChild.cpp
new file mode 100644
index 0000000000..9794ccd6ab
--- /dev/null
+++ b/dom/locks/LockManagerChild.cpp
@@ -0,0 +1,106 @@
+/* -*- 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 "LockManagerChild.h"
+#include "LockRequestChild.h"
+
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/RemoteWorkerChild.h"
+#include "mozilla/dom/WindowGlobalChild.h"
+#include "mozilla/dom/WorkerCommon.h"
+#include "mozilla/dom/WorkerPrivate.h"
+#include "mozilla/dom/WorkerRunnable.h"
+
+namespace mozilla::dom::locks {
+
+LockManagerChild::LockManagerChild(nsIGlobalObject* aOwner) : mOwner(aOwner) {
+ if (!NS_IsMainThread()) {
+ mWorkerRef = IPCWorkerRef::Create(GetCurrentThreadWorkerPrivate(),
+ "LockManagerChild");
+ }
+}
+
+void LockManagerChild::NotifyBFCacheOnMainThread(nsPIDOMWindowInner* aInner,
+ bool aCreated) {
+ AssertIsOnMainThread();
+ if (!aInner) {
+ return;
+ }
+ if (aCreated) {
+ aInner->RemoveFromBFCacheSync();
+ }
+
+ uint32_t count = aInner->UpdateLockCount(aCreated);
+ // It's okay for WindowGlobalChild to not exist, as it should mean it already
+ // is destroyed and can't enter bfcache anyway.
+ if (WindowGlobalChild* child = aInner->GetWindowGlobalChild()) {
+ if (aCreated && count == 1) {
+ // The first lock is active.
+ child->BlockBFCacheFor(BFCacheStatus::ACTIVE_LOCK);
+ } else if (count == 0) {
+ child->UnblockBFCacheFor(BFCacheStatus::ACTIVE_LOCK);
+ }
+ }
+}
+
+class BFCacheNotifyLockRunnable final : public WorkerProxyToMainThreadRunnable {
+ public:
+ explicit BFCacheNotifyLockRunnable(bool aCreated) : mCreated(aCreated) {}
+
+ void RunOnMainThread(WorkerPrivate* aWorkerPrivate) override {
+ MOZ_ASSERT(aWorkerPrivate);
+ AssertIsOnMainThread();
+ if (aWorkerPrivate->IsDedicatedWorker()) {
+ LockManagerChild::NotifyBFCacheOnMainThread(
+ aWorkerPrivate->GetAncestorWindow(), mCreated);
+ return;
+ }
+ if (aWorkerPrivate->IsSharedWorker()) {
+ aWorkerPrivate->GetRemoteWorkerController()->NotifyLock(mCreated);
+ return;
+ }
+ MOZ_ASSERT_UNREACHABLE("Unexpected worker type");
+ }
+
+ void RunBackOnWorkerThreadForCleanup(WorkerPrivate* aWorkerPrivate) override {
+ MOZ_ASSERT(aWorkerPrivate);
+ aWorkerPrivate->AssertIsOnWorkerThread();
+ }
+
+ private:
+ bool mCreated;
+};
+
+NS_IMPL_CYCLE_COLLECTION(LockManagerChild, mOwner)
+
+void LockManagerChild::RequestLock(const LockRequest& aRequest,
+ const LockOptions& aOptions) {
+ auto requestActor = MakeRefPtr<LockRequestChild>(aRequest, aOptions.mSignal);
+ requestActor->MaybeSetWorkerRef();
+ SendPLockRequestConstructor(
+ requestActor, IPCLockRequest(nsString(aRequest.mName), aOptions.mMode,
+ aOptions.mIfAvailable, aOptions.mSteal));
+ NotifyToWindow(true);
+}
+
+void LockManagerChild::NotifyRequestDestroy() const { NotifyToWindow(false); }
+
+void LockManagerChild::NotifyToWindow(bool aCreated) const {
+ if (NS_IsMainThread()) {
+ NotifyBFCacheOnMainThread(GetParentObject()->AsInnerWindow(), aCreated);
+ return;
+ }
+
+ WorkerPrivate* wp = GetCurrentThreadWorkerPrivate();
+ if (wp->IsDedicatedWorker() || wp->IsSharedWorker()) {
+ RefPtr<BFCacheNotifyLockRunnable> runnable =
+ new BFCacheNotifyLockRunnable(aCreated);
+
+ runnable->Dispatch(wp);
+ }
+};
+
+} // namespace mozilla::dom::locks