Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / dom / locks / LockManagerParent.cpp
blob4af7fe212914e35b55027e3034e9789f2f932264
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/. */
7 #include "LockManagerParent.h"
8 #include "LockRequestParent.h"
10 #include "mozilla/PrincipalHashKey.h"
11 #include "mozilla/RefPtr.h"
12 #include "mozilla/StaticPtr.h"
13 #include "mozilla/dom/locks/PLockManager.h"
14 #include "mozilla/media/MediaUtils.h"
15 #include "nsIDUtils.h"
16 #include "nsTHashMap.h"
18 namespace mozilla::dom::locks {
20 static StaticAutoPtr<nsTHashMap<PrincipalHashKey, WeakPtr<ManagedLocks>>>
21 sManagedLocksMap;
23 using IPCResult = mozilla::ipc::IPCResult;
25 LockManagerParent::LockManagerParent(NotNull<nsIPrincipal*> aPrincipal,
26 const nsID& aClientId)
27 : mClientId(NSID_TrimBracketsUTF16(aClientId)), mPrincipal(aPrincipal) {
28 if (!sManagedLocksMap) {
29 sManagedLocksMap =
30 new nsTHashMap<PrincipalHashKey, WeakPtr<ManagedLocks>>();
31 } else {
32 mManagedLocks = sManagedLocksMap->Get(aPrincipal);
35 if (!mManagedLocks) {
36 mManagedLocks = new ManagedLocks();
37 sManagedLocksMap->LookupOrInsert(aPrincipal, mManagedLocks);
41 void LockManagerParent::ActorDestroy(ActorDestroyReason aWhy) {
42 if (!mManagedLocks) {
43 return;
46 nsTArray<nsString> affectedResourceNames;
48 mManagedLocks->mHeldLocks.RemoveElementsBy(
49 [this, &affectedResourceNames](const RefPtr<LockRequestParent>& request) {
50 bool equals = request->Manager() == this;
51 if (equals) {
52 affectedResourceNames.AppendElement(request->Data().name());
54 return equals;
55 });
57 for (auto& queue : mManagedLocks->mQueueMap) {
58 queue.GetModifiableData()->RemoveElementsBy(
59 [this, &name = queue.GetKey(),
60 &affectedResourceNames](const RefPtr<LockRequestParent>& request) {
61 bool equals = request->Manager() == this;
62 if (equals) {
63 affectedResourceNames.AppendElement(name);
65 return equals;
66 });
69 for (const nsString& name : affectedResourceNames) {
70 if (auto queue = mManagedLocks->mQueueMap.Lookup(name)) {
71 ProcessRequestQueue(queue.Data());
75 mManagedLocks = nullptr;
76 // We just decreased the refcount and potentially deleted it, so check whether
77 // the weak pointer still points to anything and remove the entry if not.
78 if (!sManagedLocksMap->Get(mPrincipal)) {
79 sManagedLocksMap->Remove(mPrincipal);
83 void LockManagerParent::ProcessRequestQueue(
84 nsTArray<RefPtr<LockRequestParent>>& aQueue) {
85 while (aQueue.Length()) {
86 RefPtr<LockRequestParent> first = aQueue[0];
87 if (!IsGrantableRequest(first->Data())) {
88 break;
90 aQueue.RemoveElementAt(0);
91 mManagedLocks->mHeldLocks.AppendElement(first);
92 Unused << NS_WARN_IF(!first->SendResolve(first->Data().lockMode(), true));
96 bool LockManagerParent::IsGrantableRequest(const IPCLockRequest& aRequest) {
97 for (const auto& held : mManagedLocks->mHeldLocks) {
98 if (held->Data().name() == aRequest.name()) {
99 if (aRequest.lockMode() == LockMode::Exclusive) {
100 return false;
102 MOZ_ASSERT(aRequest.lockMode() == LockMode::Shared);
103 if (held->Data().lockMode() == LockMode::Exclusive) {
104 return false;
108 return true;
111 IPCResult LockManagerParent::RecvQuery(QueryResolver&& aResolver) {
112 LockManagerSnapshot snapshot;
113 snapshot.mHeld.Construct();
114 snapshot.mPending.Construct();
115 for (const auto& queueMapEntry : mManagedLocks->mQueueMap) {
116 for (const RefPtr<LockRequestParent>& request : queueMapEntry.GetData()) {
117 LockInfo info;
118 info.mMode.Construct(request->Data().lockMode());
119 info.mName.Construct(request->Data().name());
120 info.mClientId.Construct(
121 static_cast<LockManagerParent*>(request->Manager())->mClientId);
122 if (!snapshot.mPending.Value().AppendElement(info, mozilla::fallible)) {
123 return IPC_FAIL(this, "Out of memory");
127 for (const RefPtr<LockRequestParent>& request : mManagedLocks->mHeldLocks) {
128 LockInfo info;
129 info.mMode.Construct(request->Data().lockMode());
130 info.mName.Construct(request->Data().name());
131 info.mClientId.Construct(
132 static_cast<LockManagerParent*>(request->Manager())->mClientId);
133 if (!snapshot.mHeld.Value().AppendElement(info, mozilla::fallible)) {
134 return IPC_FAIL(this, "Out of memory");
137 aResolver(snapshot);
138 return IPC_OK();
141 already_AddRefed<PLockRequestParent> LockManagerParent::AllocPLockRequestParent(
142 const IPCLockRequest& aRequest) {
143 return MakeAndAddRef<LockRequestParent>(aRequest);
146 IPCResult LockManagerParent::RecvPLockRequestConstructor(
147 PLockRequestParent* aActor, const IPCLockRequest& aRequest) {
148 RefPtr<LockRequestParent> actor = static_cast<LockRequestParent*>(aActor);
149 nsTArray<RefPtr<LockRequestParent>>& queue =
150 mManagedLocks->mQueueMap.LookupOrInsert(aRequest.name());
151 if (aRequest.steal()) {
152 mManagedLocks->mHeldLocks.RemoveElementsBy(
153 [&aRequest](const RefPtr<LockRequestParent>& aHeld) {
154 if (aHeld->Data().name() == aRequest.name()) {
155 Unused << NS_WARN_IF(
156 !PLockRequestParent::Send__delete__(aHeld, true));
157 return true;
159 return false;
161 queue.InsertElementAt(0, actor);
162 } else if (aRequest.ifAvailable() &&
163 (!queue.IsEmpty() || !IsGrantableRequest(actor->Data()))) {
164 Unused << NS_WARN_IF(!aActor->SendResolve(aRequest.lockMode(), false));
165 return IPC_OK();
166 } else {
167 queue.AppendElement(actor);
169 ProcessRequestQueue(queue);
170 return IPC_OK();
173 } // namespace mozilla::dom::locks