Bug 1912230 - shorten messaging to avoid truncation. r=android-reviewers,mcarare
[gecko.git] / dom / ipc / jsactor / JSActorService.cpp
blob5b6c63d2a4fc80be4dbd199e06454b5331f05595
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "mozilla/dom/JSActorService.h"
9 #include "mozilla/dom/ChromeUtilsBinding.h"
10 #include "mozilla/dom/BrowserChild.h"
11 #include "mozilla/dom/BrowserParent.h"
12 #include "mozilla/dom/EventListenerBinding.h"
13 #include "mozilla/dom/Event.h"
14 #include "mozilla/dom/EventTargetBinding.h"
15 #include "mozilla/dom/EventTarget.h"
16 #include "mozilla/dom/InProcessChild.h"
17 #include "mozilla/dom/InProcessParent.h"
18 #include "mozilla/dom/JSActorManager.h"
19 #include "mozilla/dom/JSProcessActorBinding.h"
20 #include "mozilla/dom/JSProcessActorChild.h"
21 #include "mozilla/dom/JSProcessActorProtocol.h"
22 #include "mozilla/dom/JSWindowActorBinding.h"
23 #include "mozilla/dom/JSWindowActorChild.h"
24 #include "mozilla/dom/JSWindowActorProtocol.h"
25 #include "mozilla/dom/MessageManagerBinding.h"
26 #include "mozilla/dom/PContent.h"
27 #include "mozilla/dom/ContentChild.h"
28 #include "mozilla/dom/ContentParent.h"
29 #include "mozilla/dom/WindowGlobalChild.h"
30 #include "mozilla/dom/WindowGlobalParent.h"
31 #include "mozilla/ArrayAlgorithm.h"
32 #include "mozilla/Services.h"
33 #include "mozilla/StaticPtr.h"
34 #include "mozilla/Logging.h"
35 #include "nsIObserverService.h"
37 namespace mozilla::dom {
38 namespace {
39 StaticRefPtr<JSActorService> gJSActorService;
42 JSActorService::JSActorService() { MOZ_ASSERT(NS_IsMainThread()); }
44 JSActorService::~JSActorService() { MOZ_ASSERT(NS_IsMainThread()); }
46 /* static */
47 already_AddRefed<JSActorService> JSActorService::GetSingleton() {
48 MOZ_ASSERT(NS_IsMainThread());
49 if (!gJSActorService) {
50 gJSActorService = new JSActorService();
51 ClearOnShutdown(&gJSActorService);
54 RefPtr<JSActorService> service = gJSActorService.get();
55 return service.forget();
58 void JSActorService::RegisterWindowActor(const nsACString& aName,
59 const WindowActorOptions& aOptions,
60 ErrorResult& aRv) {
61 MOZ_ASSERT(NS_IsMainThread());
62 MOZ_ASSERT(XRE_IsParentProcess());
64 const auto proto = mWindowActorDescriptors.WithEntryHandle(
65 aName, [&](auto&& entry) -> RefPtr<JSWindowActorProtocol> {
66 if (entry) {
67 aRv.ThrowNotSupportedError(
68 nsPrintfCString("'%s' actor is already registered.",
69 PromiseFlatCString(aName).get()));
70 return nullptr;
73 // Insert a new entry for the protocol.
74 RefPtr<JSWindowActorProtocol> protocol =
75 JSWindowActorProtocol::FromWebIDLOptions(aName, aOptions, aRv);
76 if (NS_WARN_IF(aRv.Failed())) {
77 return nullptr;
80 entry.Insert(protocol);
82 return protocol;
83 });
85 if (!proto) {
86 MOZ_ASSERT(aRv.Failed());
87 return;
90 // Send information about the newly added entry to every existing content
91 // process.
92 AutoTArray<JSWindowActorInfo, 1> windowInfos{proto->ToIPC()};
93 nsTArray<JSProcessActorInfo> contentInfos{};
94 for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
95 Unused << cp->SendInitJSActorInfos(contentInfos, windowInfos);
98 // Register event listeners for any existing chrome targets.
99 for (EventTarget* target : mChromeEventTargets) {
100 proto->RegisterListenersFor(target);
103 // Add observers to the protocol.
104 proto->AddObservers();
107 void JSActorService::UnregisterWindowActor(const nsACString& aName) {
108 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
109 CrashReporter::AutoRecordAnnotation autoActorName(
110 CrashReporter::Annotation::JSActorName, aName);
111 CrashReporter::AutoRecordAnnotation autoMessageName(
112 CrashReporter::Annotation::JSActorMessage, "<Unregister>"_ns);
114 nsAutoCString name(aName);
115 RefPtr<JSWindowActorProtocol> proto;
116 if (mWindowActorDescriptors.Remove(name, getter_AddRefs(proto))) {
117 // Remove listeners for this actor from each of our chrome targets.
118 for (EventTarget* target : mChromeEventTargets) {
119 proto->UnregisterListenersFor(target);
122 // Remove observers for this actor from observer serivce.
123 proto->RemoveObservers();
125 // Tell every content process to also unregister, and accumulate the set of
126 // potential managers, to have the actor disabled.
127 nsTArray<RefPtr<JSActorManager>> managers;
128 if (XRE_IsParentProcess()) {
129 for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
130 Unused << cp->SendUnregisterJSWindowActor(name);
131 for (const auto& bp : cp->ManagedPBrowserParent()) {
132 for (const auto& wgp : bp->ManagedPWindowGlobalParent()) {
133 managers.AppendElement(static_cast<WindowGlobalParent*>(wgp));
138 for (const auto& wgp :
139 InProcessParent::Singleton()->ManagedPWindowGlobalParent()) {
140 managers.AppendElement(static_cast<WindowGlobalParent*>(wgp));
142 for (const auto& wgc :
143 InProcessChild::Singleton()->ManagedPWindowGlobalChild()) {
144 managers.AppendElement(static_cast<WindowGlobalChild*>(wgc));
146 } else {
147 for (const auto& bc :
148 ContentChild::GetSingleton()->ManagedPBrowserChild()) {
149 for (const auto& wgc : bc->ManagedPWindowGlobalChild()) {
150 managers.AppendElement(static_cast<WindowGlobalChild*>(wgc));
155 for (auto& mgr : managers) {
156 mgr->JSActorUnregister(name);
161 void JSActorService::LoadJSActorInfos(nsTArray<JSProcessActorInfo>& aProcess,
162 nsTArray<JSWindowActorInfo>& aWindow) {
163 MOZ_ASSERT(NS_IsMainThread());
164 MOZ_ASSERT(XRE_IsContentProcess());
166 for (auto& info : aProcess) {
167 // Create our JSProcessActorProtocol, register it in
168 // mProcessActorDescriptors.
169 auto name = info.name();
170 RefPtr<JSProcessActorProtocol> proto =
171 JSProcessActorProtocol::FromIPC(std::move(info));
172 mProcessActorDescriptors.InsertOrUpdate(std::move(name), RefPtr{proto});
174 // Add observers for each actor.
175 proto->AddObservers();
178 for (auto& info : aWindow) {
179 auto name = info.name();
180 RefPtr<JSWindowActorProtocol> proto =
181 JSWindowActorProtocol::FromIPC(std::move(info));
182 mWindowActorDescriptors.InsertOrUpdate(std::move(name), RefPtr{proto});
184 // Register listeners for each chrome target.
185 for (EventTarget* target : mChromeEventTargets) {
186 proto->RegisterListenersFor(target);
189 // Add observers for each actor.
190 proto->AddObservers();
194 void JSActorService::GetJSWindowActorInfos(
195 nsTArray<JSWindowActorInfo>& aInfos) {
196 MOZ_ASSERT(NS_IsMainThread());
197 MOZ_ASSERT(XRE_IsParentProcess());
199 for (const auto& data : mWindowActorDescriptors.Values()) {
200 aInfos.AppendElement(data->ToIPC());
204 void JSActorService::RegisterChromeEventTarget(EventTarget* aTarget) {
205 MOZ_ASSERT(!mChromeEventTargets.Contains(aTarget));
206 mChromeEventTargets.AppendElement(aTarget);
208 // Register event listeners on the newly added Window Root.
209 for (const auto& data : mWindowActorDescriptors.Values()) {
210 data->RegisterListenersFor(aTarget);
213 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
214 obs->NotifyObservers(aTarget, "chrome-event-target-created", nullptr);
217 /* static */
218 void JSActorService::UnregisterChromeEventTarget(EventTarget* aTarget) {
219 if (gJSActorService) {
220 // NOTE: No need to unregister listeners here, as the target is going away.
221 gJSActorService->mChromeEventTargets.RemoveElement(aTarget);
225 void JSActorService::RegisterProcessActor(const nsACString& aName,
226 const ProcessActorOptions& aOptions,
227 ErrorResult& aRv) {
228 MOZ_ASSERT(NS_IsMainThread());
229 MOZ_ASSERT(XRE_IsParentProcess());
231 const auto proto = mProcessActorDescriptors.WithEntryHandle(
232 aName, [&](auto&& entry) -> RefPtr<JSProcessActorProtocol> {
233 if (entry) {
234 aRv.ThrowNotSupportedError(
235 nsPrintfCString("'%s' actor is already registered.",
236 PromiseFlatCString(aName).get()));
237 return nullptr;
240 // Insert a new entry for the protocol.
241 RefPtr<JSProcessActorProtocol> protocol =
242 JSProcessActorProtocol::FromWebIDLOptions(aName, aOptions, aRv);
243 if (NS_WARN_IF(aRv.Failed())) {
244 return nullptr;
247 entry.Insert(protocol);
249 return protocol;
252 if (!proto) {
253 MOZ_ASSERT(aRv.Failed());
254 return;
257 // Send information about the newly added entry to every existing content
258 // process.
259 AutoTArray<JSProcessActorInfo, 1> contentInfos{proto->ToIPC()};
260 nsTArray<JSWindowActorInfo> windowInfos{};
261 for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
262 Unused << cp->SendInitJSActorInfos(contentInfos, windowInfos);
265 // Add observers to the protocol.
266 proto->AddObservers();
269 void JSActorService::UnregisterProcessActor(const nsACString& aName) {
270 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
271 CrashReporter::AutoRecordAnnotation autoActorName(
272 CrashReporter::Annotation::JSActorName, aName);
273 CrashReporter::AutoRecordAnnotation autoMessageName(
274 CrashReporter::Annotation::JSActorMessage, "<Unregister>"_ns);
276 nsAutoCString name(aName);
277 RefPtr<JSProcessActorProtocol> proto;
278 if (mProcessActorDescriptors.Remove(name, getter_AddRefs(proto))) {
279 // Remove observers for this actor from observer serivce.
280 proto->RemoveObservers();
282 // Tell every content process to also unregister, and accumulate the set of
283 // potential managers, to have the actor disabled.
284 nsTArray<RefPtr<JSActorManager>> managers;
285 if (XRE_IsParentProcess()) {
286 for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
287 Unused << cp->SendUnregisterJSProcessActor(name);
288 managers.AppendElement(cp);
290 managers.AppendElement(InProcessChild::Singleton());
291 managers.AppendElement(InProcessParent::Singleton());
292 } else {
293 managers.AppendElement(ContentChild::GetSingleton());
296 for (auto& mgr : managers) {
297 mgr->JSActorUnregister(name);
302 void JSActorService::GetJSProcessActorInfos(
303 nsTArray<JSProcessActorInfo>& aInfos) {
304 MOZ_ASSERT(NS_IsMainThread());
305 MOZ_ASSERT(XRE_IsParentProcess());
307 for (const auto& data : mProcessActorDescriptors.Values()) {
308 aInfos.AppendElement(data->ToIPC());
312 already_AddRefed<JSProcessActorProtocol>
313 JSActorService::GetJSProcessActorProtocol(const nsACString& aName) {
314 return mProcessActorDescriptors.Get(aName);
317 already_AddRefed<JSWindowActorProtocol>
318 JSActorService::GetJSWindowActorProtocol(const nsACString& aName) {
319 return mWindowActorDescriptors.Get(aName);
322 } // namespace mozilla::dom