Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / ipc / SharedMessageBody.cpp
blobe09ff2fd55ebed0ef47249ad5e30e13c73325af5
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 "SharedMessageBody.h"
8 #include "mozilla/dom/File.h"
9 #include "mozilla/dom/MessagePort.h"
10 #include "mozilla/dom/RefMessageBodyService.h"
11 #include "mozilla/dom/PMessagePort.h"
12 #include "mozilla/ipc/BackgroundChild.h"
13 #include "mozilla/ipc/BackgroundParent.h"
14 #include "xpcpublic.h"
16 namespace mozilla {
18 using namespace ipc;
20 namespace dom {
22 SharedMessageBody::SharedMessageBody(
23 StructuredCloneHolder::TransferringSupport aSupportsTransferring,
24 const Maybe<nsID>& aAgentClusterId)
25 : mRefDataId(Nothing()),
26 mSupportsTransferring(aSupportsTransferring),
27 mAgentClusterId(aAgentClusterId) {}
29 void SharedMessageBody::Write(JSContext* aCx, JS::Handle<JS::Value> aValue,
30 JS::Handle<JS::Value> aTransfers, nsID& aPortID,
31 RefMessageBodyService* aRefMessageBodyService,
32 ErrorResult& aRv) {
33 MOZ_ASSERT(!mCloneData && !mRefData);
34 MOZ_ASSERT(aRefMessageBodyService);
36 JS::CloneDataPolicy cloneDataPolicy;
37 // During a writing, we don't know the destination, so we assume it is part of
38 // the same agent cluster.
39 cloneDataPolicy.allowIntraClusterClonableSharedObjects();
41 nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
42 MOZ_ASSERT(global);
44 if (global->IsSharedMemoryAllowed()) {
45 cloneDataPolicy.allowSharedMemoryObjects();
48 mCloneData = MakeUnique<ipc::StructuredCloneData>(
49 JS::StructuredCloneScope::UnknownDestination, mSupportsTransferring);
50 mCloneData->Write(aCx, aValue, aTransfers, cloneDataPolicy, aRv);
51 if (NS_WARN_IF(aRv.Failed())) {
52 return;
55 if (mCloneData->CloneScope() == JS::StructuredCloneScope::DifferentProcess) {
56 return;
59 MOZ_ASSERT(mCloneData->CloneScope() == JS::StructuredCloneScope::SameProcess);
60 RefPtr<RefMessageBody> refData =
61 new RefMessageBody(aPortID, std::move(mCloneData));
63 mRefDataId.emplace(aRefMessageBodyService->Register(refData.forget(), aRv));
66 void SharedMessageBody::Read(JSContext* aCx,
67 JS::MutableHandle<JS::Value> aValue,
68 RefMessageBodyService* aRefMessageBodyService,
69 SharedMessageBody::ReadMethod aReadMethod,
70 ErrorResult& aRv) {
71 MOZ_ASSERT(aRefMessageBodyService);
73 if (mCloneData) {
74 // Use a default cloneDataPolicy here, because SharedArrayBuffers and WASM
75 // are not supported.
76 return mCloneData->Read(aCx, aValue, JS::CloneDataPolicy(), aRv);
79 JS::CloneDataPolicy cloneDataPolicy;
81 nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
82 MOZ_ASSERT(global);
84 // Clones within the same agent cluster are allowed to use shared array
85 // buffers and WASM modules.
86 if (mAgentClusterId.isSome()) {
87 Maybe<nsID> agentClusterId = global->GetAgentClusterId();
88 if (agentClusterId.isSome() &&
89 mAgentClusterId.value().Equals(agentClusterId.value())) {
90 cloneDataPolicy.allowIntraClusterClonableSharedObjects();
94 if (global->IsSharedMemoryAllowed()) {
95 cloneDataPolicy.allowSharedMemoryObjects();
98 MOZ_ASSERT(!mRefData);
99 MOZ_ASSERT(mRefDataId.isSome());
101 if (aReadMethod == SharedMessageBody::StealRefMessageBody) {
102 mRefData = aRefMessageBodyService->Steal(mRefDataId.value());
103 } else {
104 MOZ_ASSERT(aReadMethod == SharedMessageBody::KeepRefMessageBody);
105 mRefData = aRefMessageBodyService->GetAndCount(mRefDataId.value());
108 if (!mRefData) {
109 aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
110 return;
113 mRefData->Read(aCx, aValue, cloneDataPolicy, aRv);
116 bool SharedMessageBody::TakeTransferredPortsAsSequence(
117 Sequence<OwningNonNull<mozilla::dom::MessagePort>>& aPorts) {
118 if (mCloneData) {
119 return mCloneData->TakeTransferredPortsAsSequence(aPorts);
122 MOZ_ASSERT(mRefData);
123 return mRefData->TakeTransferredPortsAsSequence(aPorts);
126 /* static */
127 void SharedMessageBody::FromSharedToMessageChild(
128 mozilla::ipc::PBackgroundChild* aManager, SharedMessageBody* aData,
129 MessageData& aMessage) {
130 MOZ_ASSERT(aManager);
131 MOZ_ASSERT(aData);
133 aMessage.agentClusterId() = aData->mAgentClusterId;
135 if (aData->mCloneData) {
136 ClonedMessageData clonedData;
137 aData->mCloneData->BuildClonedMessageData(clonedData);
138 aMessage.data() = std::move(clonedData);
139 return;
142 MOZ_ASSERT(aData->mRefDataId.isSome());
143 aMessage.data() = RefMessageData(aData->mRefDataId.value());
146 /* static */
147 void SharedMessageBody::FromSharedToMessagesChild(
148 PBackgroundChild* aManager,
149 const nsTArray<RefPtr<SharedMessageBody>>& aData,
150 nsTArray<MessageData>& aArray) {
151 MOZ_ASSERT(aManager);
152 MOZ_ASSERT(aArray.IsEmpty());
153 aArray.SetCapacity(aData.Length());
155 for (auto& data : aData) {
156 MessageData* message = aArray.AppendElement();
157 FromSharedToMessageChild(aManager, data, *message);
161 /* static */
162 already_AddRefed<SharedMessageBody> SharedMessageBody::FromMessageToSharedChild(
163 MessageData& aMessage,
164 StructuredCloneHolder::TransferringSupport aSupportsTransferring) {
165 RefPtr<SharedMessageBody> data =
166 new SharedMessageBody(aSupportsTransferring, aMessage.agentClusterId());
168 if (aMessage.data().type() == MessageDataType::TClonedMessageData) {
169 data->mCloneData = MakeUnique<ipc::StructuredCloneData>(
170 JS::StructuredCloneScope::UnknownDestination, aSupportsTransferring);
171 data->mCloneData->StealFromClonedMessageData(
172 aMessage.data().get_ClonedMessageData());
173 } else {
174 MOZ_ASSERT(aMessage.data().type() == MessageDataType::TRefMessageData);
175 data->mRefDataId.emplace(aMessage.data().get_RefMessageData().uuid());
178 return data.forget();
181 /* static */
182 already_AddRefed<SharedMessageBody> SharedMessageBody::FromMessageToSharedChild(
183 const MessageData& aMessage,
184 StructuredCloneHolder::TransferringSupport aSupportsTransferring) {
185 RefPtr<SharedMessageBody> data =
186 new SharedMessageBody(aSupportsTransferring, aMessage.agentClusterId());
188 if (aMessage.data().type() == MessageDataType::TClonedMessageData) {
189 data->mCloneData = MakeUnique<ipc::StructuredCloneData>(
190 JS::StructuredCloneScope::UnknownDestination, aSupportsTransferring);
191 data->mCloneData->BorrowFromClonedMessageData(
192 aMessage.data().get_ClonedMessageData());
193 } else {
194 MOZ_ASSERT(aMessage.data().type() == MessageDataType::TRefMessageData);
195 data->mRefDataId.emplace(aMessage.data().get_RefMessageData().uuid());
198 return data.forget();
201 /* static */
202 bool SharedMessageBody::FromMessagesToSharedChild(
203 nsTArray<MessageData>& aArray,
204 FallibleTArray<RefPtr<SharedMessageBody>>& aData,
205 StructuredCloneHolder::TransferringSupport aSupportsTransferring) {
206 MOZ_ASSERT(aData.IsEmpty());
208 if (NS_WARN_IF(!aData.SetCapacity(aArray.Length(), mozilla::fallible))) {
209 return false;
212 for (auto& message : aArray) {
213 RefPtr<SharedMessageBody> data =
214 FromMessageToSharedChild(message, aSupportsTransferring);
215 if (!data || !aData.AppendElement(data, mozilla::fallible)) {
216 return false;
220 return true;
223 /* static */
224 bool SharedMessageBody::FromSharedToMessagesParent(
225 PBackgroundParent* aManager,
226 const nsTArray<RefPtr<SharedMessageBody>>& aData,
227 nsTArray<MessageData>& aArray) {
228 MOZ_ASSERT(aManager);
229 MOZ_ASSERT(aArray.IsEmpty());
231 if (NS_WARN_IF(!aArray.SetCapacity(aData.Length(), mozilla::fallible))) {
232 return false;
235 for (auto& data : aData) {
236 MessageData* message = aArray.AppendElement();
237 message->agentClusterId() = data->mAgentClusterId;
239 if (data->mCloneData) {
240 ClonedMessageData clonedData;
241 data->mCloneData->BuildClonedMessageData(clonedData);
242 message->data() = std::move(clonedData);
243 continue;
246 MOZ_ASSERT(data->mRefDataId.isSome());
247 message->data() = RefMessageData(data->mRefDataId.value());
250 return true;
253 /* static */
254 already_AddRefed<SharedMessageBody>
255 SharedMessageBody::FromMessageToSharedParent(
256 MessageData& aMessage,
257 StructuredCloneHolder::TransferringSupport aSupportsTransferring) {
258 // TODO: This alloc is not fallible and there is no codepath that returns
259 // nullptr. But the caller checks for nullptr and handles array allocations
260 // for these items as fallible. See bug 1750497.
261 RefPtr<SharedMessageBody> data =
262 new SharedMessageBody(aSupportsTransferring, aMessage.agentClusterId());
264 if (aMessage.data().type() == MessageDataType::TClonedMessageData) {
265 data->mCloneData = MakeUnique<ipc::StructuredCloneData>(
266 JS::StructuredCloneScope::UnknownDestination, aSupportsTransferring);
267 data->mCloneData->StealFromClonedMessageData(
268 aMessage.data().get_ClonedMessageData());
269 } else {
270 MOZ_ASSERT(aMessage.data().type() == MessageDataType::TRefMessageData);
271 data->mRefDataId.emplace(aMessage.data().get_RefMessageData().uuid());
274 return data.forget();
277 bool SharedMessageBody::FromMessagesToSharedParent(
278 nsTArray<MessageData>& aArray,
279 FallibleTArray<RefPtr<SharedMessageBody>>& aData,
280 StructuredCloneHolder::TransferringSupport aSupportsTransferring) {
281 MOZ_ASSERT(aData.IsEmpty());
283 if (NS_WARN_IF(!aData.SetCapacity(aArray.Length(), mozilla::fallible))) {
284 return false;
287 for (auto& message : aArray) {
288 RefPtr<SharedMessageBody> data = FromMessageToSharedParent(message);
289 if (!data || !aData.AppendElement(data, mozilla::fallible)) {
290 return false;
294 return true;
297 } // namespace dom
298 } // namespace mozilla