Bug 1885602 - Part 5: Implement navigating to the SUMO help topic from the menu heade...
[gecko.git] / dom / ipc / RefMessageBodyService.cpp
blobe340443a532e5f77bc7cf6a924b3bef991c57449
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "RefMessageBodyService.h"
9 #include <cstdint>
10 #include <cstdlib>
11 #include "mozilla/ErrorResult.h"
12 #include "mozilla/RefPtr.h"
13 #include "mozilla/dom/ipc/StructuredCloneData.h"
14 #include "nsBaseHashtable.h"
15 #include "nsDebug.h"
17 namespace mozilla::dom {
19 // Guards sService and its members.
20 StaticMutex sRefMessageBodyServiceMutex;
22 // Raw pointer because the service is kept alive by other objects.
23 // See the CTOR and the DTOR of this object.
24 RefMessageBodyService* sService;
26 // static
27 already_AddRefed<RefMessageBodyService> RefMessageBodyService::GetOrCreate() {
28 StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
30 RefPtr<RefMessageBodyService> service = GetOrCreateInternal(lock);
31 return service.forget();
34 // static
35 RefMessageBodyService* RefMessageBodyService::GetOrCreateInternal(
36 const StaticMutexAutoLock& aProofOfLock) {
37 if (!sService) {
38 sService = new RefMessageBodyService(aProofOfLock);
40 return sService;
43 RefMessageBodyService::RefMessageBodyService(
44 const StaticMutexAutoLock& aProofOfLock) {
45 MOZ_DIAGNOSTIC_ASSERT(sService == nullptr);
48 RefMessageBodyService::~RefMessageBodyService() {
49 StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
50 MOZ_DIAGNOSTIC_ASSERT(sService == this);
51 sService = nullptr;
54 const nsID RefMessageBodyService::Register(
55 already_AddRefed<RefMessageBody> aBody, ErrorResult& aRv) {
56 RefPtr<RefMessageBody> body = aBody;
57 MOZ_ASSERT(body);
59 nsID uuid = {};
60 aRv = nsID::GenerateUUIDInPlace(uuid);
61 if (NS_WARN_IF(aRv.Failed())) {
62 return nsID();
65 StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
66 GetOrCreateInternal(lock)->mMessages.InsertOrUpdate(uuid, std::move(body));
67 return uuid;
70 already_AddRefed<RefMessageBody> RefMessageBodyService::Steal(const nsID& aID) {
71 StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
72 if (!sService) {
73 return nullptr;
76 RefPtr<RefMessageBody> body;
77 sService->mMessages.Remove(aID, getter_AddRefs(body));
79 return body.forget();
82 already_AddRefed<RefMessageBody> RefMessageBodyService::GetAndCount(
83 const nsID& aID) {
84 StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
85 if (!sService) {
86 return nullptr;
89 RefPtr<RefMessageBody> body = sService->mMessages.Get(aID);
90 if (!body) {
91 return nullptr;
94 ++body->mCount;
96 MOZ_ASSERT_IF(body->mMaxCount.isSome(),
97 body->mCount <= body->mMaxCount.value());
98 if (body->mMaxCount.isSome() && body->mCount >= body->mMaxCount.value()) {
99 sService->mMessages.Remove(aID);
102 return body.forget();
105 void RefMessageBodyService::SetMaxCount(const nsID& aID, uint32_t aMaxCount) {
106 StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
107 if (!sService) {
108 return;
111 RefPtr<RefMessageBody> body = sService->mMessages.Get(aID);
112 if (!body) {
113 return;
116 MOZ_ASSERT(body->mMaxCount.isNothing());
117 body->mMaxCount.emplace(aMaxCount);
119 MOZ_ASSERT(body->mCount <= body->mMaxCount.value());
120 if (body->mCount >= body->mMaxCount.value()) {
121 sService->mMessages.Remove(aID);
125 void RefMessageBodyService::ForgetPort(const nsID& aPortID) {
126 StaticMutexAutoLock lock(sRefMessageBodyServiceMutex);
127 if (!sService) {
128 return;
131 for (auto iter = sService->mMessages.Iter(); !iter.Done(); iter.Next()) {
132 if (iter.UserData()->PortID() == aPortID) {
133 iter.Remove();
138 RefMessageBody::RefMessageBody(const nsID& aPortID,
139 UniquePtr<ipc::StructuredCloneData>&& aCloneData)
140 : mPortID(aPortID),
141 mMutex("RefMessageBody::mMutex"),
142 mCloneData(std::move(aCloneData)),
143 mMaxCount(Nothing()),
144 mCount(0) {}
146 RefMessageBody::~RefMessageBody() = default;
148 void RefMessageBody::Read(JSContext* aCx, JS::MutableHandle<JS::Value> aValue,
149 const JS::CloneDataPolicy& aCloneDataPolicy,
150 ErrorResult& aRv) {
151 MutexAutoLock lock(mMutex);
152 mCloneData->Read(aCx, aValue, aCloneDataPolicy, aRv);
155 bool RefMessageBody::TakeTransferredPortsAsSequence(
156 Sequence<OwningNonNull<mozilla::dom::MessagePort>>& aPorts) {
157 MOZ_ASSERT(mMaxCount.isNothing());
158 return mCloneData->TakeTransferredPortsAsSequence(aPorts);
161 } // namespace mozilla::dom