LockManagerChild.cpp (3511B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "LockManagerChild.h" 8 9 #include "LockRequestChild.h" 10 #include "mozilla/dom/Document.h" 11 #include "mozilla/dom/RemoteWorkerChild.h" 12 #include "mozilla/dom/WindowGlobalChild.h" 13 #include "mozilla/dom/WorkerCommon.h" 14 #include "mozilla/dom/WorkerPrivate.h" 15 #include "mozilla/dom/WorkerRunnable.h" 16 17 namespace mozilla::dom::locks { 18 19 LockManagerChild::LockManagerChild(nsIGlobalObject* aOwner) : mOwner(aOwner) { 20 if (!NS_IsMainThread()) { 21 mWorkerRef = IPCWorkerRef::Create(GetCurrentThreadWorkerPrivate(), 22 "LockManagerChild"); 23 } 24 } 25 26 void LockManagerChild::NotifyBFCacheOnMainThread(nsPIDOMWindowInner* aInner, 27 bool aCreated) { 28 AssertIsOnMainThread(); 29 if (!aInner) { 30 return; 31 } 32 if (aCreated) { 33 aInner->RemoveFromBFCacheSync(); 34 } 35 36 uint32_t count = aInner->UpdateLockCount(aCreated); 37 // It's okay for WindowGlobalChild to not exist, as it should mean it already 38 // is destroyed and can't enter bfcache anyway. 39 if (WindowGlobalChild* child = aInner->GetWindowGlobalChild()) { 40 if (aCreated && count == 1) { 41 // The first lock is active. 42 child->BlockBFCacheFor(BFCacheStatus::ACTIVE_LOCK); 43 } else if (count == 0) { 44 child->UnblockBFCacheFor(BFCacheStatus::ACTIVE_LOCK); 45 } 46 } 47 } 48 49 class BFCacheNotifyLockRunnable final : public WorkerProxyToMainThreadRunnable { 50 public: 51 explicit BFCacheNotifyLockRunnable(bool aCreated) : mCreated(aCreated) {} 52 53 void RunOnMainThread(WorkerPrivate* aWorkerPrivate) override { 54 MOZ_ASSERT(aWorkerPrivate); 55 AssertIsOnMainThread(); 56 if (aWorkerPrivate->IsDedicatedWorker()) { 57 LockManagerChild::NotifyBFCacheOnMainThread( 58 aWorkerPrivate->GetAncestorWindow(), mCreated); 59 return; 60 } 61 if (aWorkerPrivate->IsSharedWorker()) { 62 aWorkerPrivate->GetRemoteWorkerController()->NotifyLock(mCreated); 63 return; 64 } 65 MOZ_ASSERT_UNREACHABLE("Unexpected worker type"); 66 } 67 68 void RunBackOnWorkerThreadForCleanup(WorkerPrivate* aWorkerPrivate) override { 69 MOZ_ASSERT(aWorkerPrivate); 70 aWorkerPrivate->AssertIsOnWorkerThread(); 71 } 72 73 private: 74 bool mCreated; 75 }; 76 77 void LockManagerChild::RequestLock(const LockRequest& aRequest, 78 const LockOptions& aOptions) { 79 auto requestActor = MakeRefPtr<LockRequestChild>(aRequest, aOptions.mSignal); 80 requestActor->MaybeSetWorkerRef(); 81 SendPLockRequestConstructor( 82 requestActor, IPCLockRequest(nsString(aRequest.mName), aOptions.mMode, 83 aOptions.mIfAvailable, aOptions.mSteal)); 84 NotifyToWindow(true); 85 } 86 87 void LockManagerChild::NotifyRequestDestroy() const { NotifyToWindow(false); } 88 89 void LockManagerChild::NotifyToWindow(bool aCreated) const { 90 if (NS_IsMainThread()) { 91 NotifyBFCacheOnMainThread(GetParentObject()->GetAsInnerWindow(), aCreated); 92 return; 93 } 94 95 WorkerPrivate* wp = GetCurrentThreadWorkerPrivate(); 96 if (wp->IsDedicatedWorker() || wp->IsSharedWorker()) { 97 RefPtr<BFCacheNotifyLockRunnable> runnable = 98 new BFCacheNotifyLockRunnable(aCreated); 99 100 runnable->Dispatch(wp); 101 } 102 }; 103 104 } // namespace mozilla::dom::locks