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 "BackgroundChildImpl.h"
8
9 #include "ActorsChild.h" // IndexedDB
10 #include "BroadcastChannelChild.h"
11 #include "ServiceWorkerManagerChild.h"
12 #include "FileDescriptorSetChild.h"
13 #ifdef MOZ_WEBRTC
14 #include "CamerasChild.h"
15 #endif
16 #include "mozilla/media/MediaChild.h"
17 #include "mozilla/Assertions.h"
18 #include "mozilla/dom/PBlobChild.h"
19 #include "mozilla/dom/PFileSystemRequestChild.h"
20 #include "mozilla/dom/FileSystemTaskBase.h"
21 #include "mozilla/dom/asmjscache/AsmJSCache.h"
22 #include "mozilla/dom/cache/ActorUtils.h"
23 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
24 #include "mozilla/dom/indexedDB/PBackgroundIndexedDBUtilsChild.h"
25 #include "mozilla/dom/ipc/BlobChild.h"
26 #include "mozilla/dom/quota/PQuotaChild.h"
27 #ifdef MOZ_GAMEPAD
28 #include "mozilla/dom/GamepadEventChannelChild.h"
29 #include "mozilla/dom/GamepadTestChannelChild.h"
30 #endif
31 #include "mozilla/dom/MessagePortChild.h"
32 #include "mozilla/ipc/PBackgroundTestChild.h"
33 #include "mozilla/ipc/PSendStreamChild.h"
34 #include "mozilla/layout/VsyncChild.h"
35 #include "mozilla/net/PUDPSocketChild.h"
36 #include "mozilla/dom/network/UDPSocketChild.h"
37 #include "nsID.h"
38 #include "nsTraceRefcnt.h"
39
40 namespace {
41
42 class TestChild final : public mozilla::ipc::PBackgroundTestChild
43 {
44 friend class mozilla::ipc::BackgroundChildImpl;
45
46 nsCString mTestArg;
47
TestChild(const nsCString & aTestArg)48 explicit TestChild(const nsCString& aTestArg)
49 : mTestArg(aTestArg)
50 {
51 MOZ_COUNT_CTOR(TestChild);
52 }
53
54 protected:
~TestChild()55 ~TestChild()
56 {
57 MOZ_COUNT_DTOR(TestChild);
58 }
59
60 public:
61 virtual bool
62 Recv__delete__(const nsCString& aTestArg) override;
63 };
64
65 } // namespace
66
67 namespace mozilla {
68 namespace ipc {
69
70 using mozilla::dom::UDPSocketChild;
71 using mozilla::net::PUDPSocketChild;
72
73 using mozilla::dom::asmjscache::PAsmJSCacheEntryChild;
74 using mozilla::dom::cache::PCacheChild;
75 using mozilla::dom::cache::PCacheStorageChild;
76 using mozilla::dom::cache::PCacheStreamControlChild;
77
78 // -----------------------------------------------------------------------------
79 // BackgroundChildImpl::ThreadLocal
80 // -----------------------------------------------------------------------------
81
82 BackgroundChildImpl::
ThreadLocal()83 ThreadLocal::ThreadLocal()
84 : mCurrentFileHandle(nullptr)
85 {
86 // May happen on any thread!
87 MOZ_COUNT_CTOR(mozilla::ipc::BackgroundChildImpl::ThreadLocal);
88 }
89
90 BackgroundChildImpl::
~ThreadLocal()91 ThreadLocal::~ThreadLocal()
92 {
93 // May happen on any thread!
94 MOZ_COUNT_DTOR(mozilla::ipc::BackgroundChildImpl::ThreadLocal);
95 }
96
97 // -----------------------------------------------------------------------------
98 // BackgroundChildImpl
99 // -----------------------------------------------------------------------------
100
BackgroundChildImpl()101 BackgroundChildImpl::BackgroundChildImpl()
102 {
103 // May happen on any thread!
104 MOZ_COUNT_CTOR(mozilla::ipc::BackgroundChildImpl);
105 }
106
~BackgroundChildImpl()107 BackgroundChildImpl::~BackgroundChildImpl()
108 {
109 // May happen on any thread!
110 MOZ_COUNT_DTOR(mozilla::ipc::BackgroundChildImpl);
111 }
112
113 void
ProcessingError(Result aCode,const char * aReason)114 BackgroundChildImpl::ProcessingError(Result aCode, const char* aReason)
115 {
116 // May happen on any thread!
117
118 nsAutoCString abortMessage;
119
120 switch (aCode) {
121
122 #define HANDLE_CASE(_result) \
123 case _result: \
124 abortMessage.AssignLiteral(#_result); \
125 break
126
127 HANDLE_CASE(MsgDropped);
128 HANDLE_CASE(MsgNotKnown);
129 HANDLE_CASE(MsgNotAllowed);
130 HANDLE_CASE(MsgPayloadError);
131 HANDLE_CASE(MsgProcessingError);
132 HANDLE_CASE(MsgRouteError);
133 HANDLE_CASE(MsgValueError);
134
135 #undef HANDLE_CASE
136
137 default:
138 MOZ_CRASH("Unknown error code!");
139 }
140
141 MOZ_CRASH_UNSAFE_PRINTF("%s: %s", abortMessage.get(), aReason);
142 }
143
144 void
ActorDestroy(ActorDestroyReason aWhy)145 BackgroundChildImpl::ActorDestroy(ActorDestroyReason aWhy)
146 {
147 // May happen on any thread!
148 }
149
150 PBackgroundTestChild*
AllocPBackgroundTestChild(const nsCString & aTestArg)151 BackgroundChildImpl::AllocPBackgroundTestChild(const nsCString& aTestArg)
152 {
153 return new TestChild(aTestArg);
154 }
155
156 bool
DeallocPBackgroundTestChild(PBackgroundTestChild * aActor)157 BackgroundChildImpl::DeallocPBackgroundTestChild(PBackgroundTestChild* aActor)
158 {
159 MOZ_ASSERT(aActor);
160
161 delete static_cast<TestChild*>(aActor);
162 return true;
163 }
164
165 BackgroundChildImpl::PBackgroundIDBFactoryChild*
AllocPBackgroundIDBFactoryChild(const LoggingInfo & aLoggingInfo)166 BackgroundChildImpl::AllocPBackgroundIDBFactoryChild(
167 const LoggingInfo& aLoggingInfo)
168 {
169 MOZ_CRASH("PBackgroundIDBFactoryChild actors should be manually "
170 "constructed!");
171 }
172
173 bool
DeallocPBackgroundIDBFactoryChild(PBackgroundIDBFactoryChild * aActor)174 BackgroundChildImpl::DeallocPBackgroundIDBFactoryChild(
175 PBackgroundIDBFactoryChild* aActor)
176 {
177 MOZ_ASSERT(aActor);
178
179 delete aActor;
180 return true;
181 }
182
183 BackgroundChildImpl::PBackgroundIndexedDBUtilsChild*
AllocPBackgroundIndexedDBUtilsChild()184 BackgroundChildImpl::AllocPBackgroundIndexedDBUtilsChild()
185 {
186 MOZ_CRASH("PBackgroundIndexedDBUtilsChild actors should be manually "
187 "constructed!");
188 }
189
190 bool
DeallocPBackgroundIndexedDBUtilsChild(PBackgroundIndexedDBUtilsChild * aActor)191 BackgroundChildImpl::DeallocPBackgroundIndexedDBUtilsChild(
192 PBackgroundIndexedDBUtilsChild* aActor)
193 {
194 MOZ_ASSERT(aActor);
195
196 delete aActor;
197 return true;
198 }
199
200 auto
AllocPBlobChild(const BlobConstructorParams & aParams)201 BackgroundChildImpl::AllocPBlobChild(const BlobConstructorParams& aParams)
202 -> PBlobChild*
203 {
204 MOZ_ASSERT(aParams.type() != BlobConstructorParams::T__None);
205
206 return mozilla::dom::BlobChild::Create(this, aParams);
207 }
208
209 bool
DeallocPBlobChild(PBlobChild * aActor)210 BackgroundChildImpl::DeallocPBlobChild(PBlobChild* aActor)
211 {
212 MOZ_ASSERT(aActor);
213
214 mozilla::dom::BlobChild::Destroy(aActor);
215 return true;
216 }
217
218 PFileDescriptorSetChild*
AllocPFileDescriptorSetChild(const FileDescriptor & aFileDescriptor)219 BackgroundChildImpl::AllocPFileDescriptorSetChild(
220 const FileDescriptor& aFileDescriptor)
221 {
222 return new FileDescriptorSetChild(aFileDescriptor);
223 }
224
225 bool
DeallocPFileDescriptorSetChild(PFileDescriptorSetChild * aActor)226 BackgroundChildImpl::DeallocPFileDescriptorSetChild(
227 PFileDescriptorSetChild* aActor)
228 {
229 MOZ_ASSERT(aActor);
230
231 delete static_cast<FileDescriptorSetChild*>(aActor);
232 return true;
233 }
234
235 BackgroundChildImpl::PVsyncChild*
AllocPVsyncChild()236 BackgroundChildImpl::AllocPVsyncChild()
237 {
238 RefPtr<mozilla::layout::VsyncChild> actor = new mozilla::layout::VsyncChild();
239 // There still has one ref-count after return, and it will be released in
240 // DeallocPVsyncChild().
241 return actor.forget().take();
242 }
243
244 bool
DeallocPVsyncChild(PVsyncChild * aActor)245 BackgroundChildImpl::DeallocPVsyncChild(PVsyncChild* aActor)
246 {
247 MOZ_ASSERT(aActor);
248
249 // This actor already has one ref-count. Please check AllocPVsyncChild().
250 RefPtr<mozilla::layout::VsyncChild> actor =
251 dont_AddRef(static_cast<mozilla::layout::VsyncChild*>(aActor));
252 return true;
253 }
254
255 PUDPSocketChild*
AllocPUDPSocketChild(const OptionalPrincipalInfo & aPrincipalInfo,const nsCString & aFilter)256 BackgroundChildImpl::AllocPUDPSocketChild(const OptionalPrincipalInfo& aPrincipalInfo,
257 const nsCString& aFilter)
258 {
259 MOZ_CRASH("AllocPUDPSocket should not be called");
260 return nullptr;
261 }
262
263 bool
DeallocPUDPSocketChild(PUDPSocketChild * child)264 BackgroundChildImpl::DeallocPUDPSocketChild(PUDPSocketChild* child)
265 {
266
267 UDPSocketChild* p = static_cast<UDPSocketChild*>(child);
268 p->ReleaseIPDLReference();
269 return true;
270 }
271
272 // -----------------------------------------------------------------------------
273 // BroadcastChannel API
274 // -----------------------------------------------------------------------------
275
276 dom::PBroadcastChannelChild*
AllocPBroadcastChannelChild(const PrincipalInfo & aPrincipalInfo,const nsCString & aOrigin,const nsString & aChannel)277 BackgroundChildImpl::AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo,
278 const nsCString& aOrigin,
279 const nsString& aChannel)
280 {
281 RefPtr<dom::BroadcastChannelChild> agent =
282 new dom::BroadcastChannelChild(aOrigin);
283 return agent.forget().take();
284 }
285
286 bool
DeallocPBroadcastChannelChild(PBroadcastChannelChild * aActor)287 BackgroundChildImpl::DeallocPBroadcastChannelChild(
288 PBroadcastChannelChild* aActor)
289 {
290 RefPtr<dom::BroadcastChannelChild> child =
291 dont_AddRef(static_cast<dom::BroadcastChannelChild*>(aActor));
292 MOZ_ASSERT(child);
293 return true;
294 }
295
296 camera::PCamerasChild*
AllocPCamerasChild()297 BackgroundChildImpl::AllocPCamerasChild()
298 {
299 #ifdef MOZ_WEBRTC
300 RefPtr<camera::CamerasChild> agent =
301 new camera::CamerasChild();
302 return agent.forget().take();
303 #else
304 return nullptr;
305 #endif
306 }
307
308 bool
DeallocPCamerasChild(camera::PCamerasChild * aActor)309 BackgroundChildImpl::DeallocPCamerasChild(camera::PCamerasChild *aActor)
310 {
311 #ifdef MOZ_WEBRTC
312 RefPtr<camera::CamerasChild> child =
313 dont_AddRef(static_cast<camera::CamerasChild*>(aActor));
314 MOZ_ASSERT(aActor);
315 #endif
316 return true;
317 }
318
319 // -----------------------------------------------------------------------------
320 // ServiceWorkerManager
321 // -----------------------------------------------------------------------------
322
323 dom::PServiceWorkerManagerChild*
AllocPServiceWorkerManagerChild()324 BackgroundChildImpl::AllocPServiceWorkerManagerChild()
325 {
326 RefPtr<dom::workers::ServiceWorkerManagerChild> agent =
327 new dom::workers::ServiceWorkerManagerChild();
328 return agent.forget().take();
329 }
330
331 bool
DeallocPServiceWorkerManagerChild(PServiceWorkerManagerChild * aActor)332 BackgroundChildImpl::DeallocPServiceWorkerManagerChild(
333 PServiceWorkerManagerChild* aActor)
334 {
335 RefPtr<dom::workers::ServiceWorkerManagerChild> child =
336 dont_AddRef(static_cast<dom::workers::ServiceWorkerManagerChild*>(aActor));
337 MOZ_ASSERT(child);
338 return true;
339 }
340
341 // -----------------------------------------------------------------------------
342 // Cache API
343 // -----------------------------------------------------------------------------
344
345 PCacheStorageChild*
AllocPCacheStorageChild(const Namespace & aNamespace,const PrincipalInfo & aPrincipalInfo)346 BackgroundChildImpl::AllocPCacheStorageChild(const Namespace& aNamespace,
347 const PrincipalInfo& aPrincipalInfo)
348 {
349 MOZ_CRASH("CacheStorageChild actor must be provided to PBackground manager");
350 return nullptr;
351 }
352
353 bool
DeallocPCacheStorageChild(PCacheStorageChild * aActor)354 BackgroundChildImpl::DeallocPCacheStorageChild(PCacheStorageChild* aActor)
355 {
356 dom::cache::DeallocPCacheStorageChild(aActor);
357 return true;
358 }
359
360 PCacheChild*
AllocPCacheChild()361 BackgroundChildImpl::AllocPCacheChild()
362 {
363 return dom::cache::AllocPCacheChild();
364 }
365
366 bool
DeallocPCacheChild(PCacheChild * aActor)367 BackgroundChildImpl::DeallocPCacheChild(PCacheChild* aActor)
368 {
369 dom::cache::DeallocPCacheChild(aActor);
370 return true;
371 }
372
373 PCacheStreamControlChild*
AllocPCacheStreamControlChild()374 BackgroundChildImpl::AllocPCacheStreamControlChild()
375 {
376 return dom::cache::AllocPCacheStreamControlChild();
377 }
378
379 bool
DeallocPCacheStreamControlChild(PCacheStreamControlChild * aActor)380 BackgroundChildImpl::DeallocPCacheStreamControlChild(PCacheStreamControlChild* aActor)
381 {
382 dom::cache::DeallocPCacheStreamControlChild(aActor);
383 return true;
384 }
385
386 // -----------------------------------------------------------------------------
387 // MessageChannel/MessagePort API
388 // -----------------------------------------------------------------------------
389
390 dom::PMessagePortChild*
AllocPMessagePortChild(const nsID & aUUID,const nsID & aDestinationUUID,const uint32_t & aSequenceID)391 BackgroundChildImpl::AllocPMessagePortChild(const nsID& aUUID,
392 const nsID& aDestinationUUID,
393 const uint32_t& aSequenceID)
394 {
395 RefPtr<dom::MessagePortChild> agent = new dom::MessagePortChild();
396 return agent.forget().take();
397 }
398
399 bool
DeallocPMessagePortChild(PMessagePortChild * aActor)400 BackgroundChildImpl::DeallocPMessagePortChild(PMessagePortChild* aActor)
401 {
402 RefPtr<dom::MessagePortChild> child =
403 dont_AddRef(static_cast<dom::MessagePortChild*>(aActor));
404 MOZ_ASSERT(child);
405 return true;
406 }
407
408 PSendStreamChild*
AllocPSendStreamChild()409 BackgroundChildImpl::AllocPSendStreamChild()
410 {
411 MOZ_CRASH("PSendStreamChild actors should be manually constructed!");
412 }
413
414 bool
DeallocPSendStreamChild(PSendStreamChild * aActor)415 BackgroundChildImpl::DeallocPSendStreamChild(PSendStreamChild* aActor)
416 {
417 delete aActor;
418 return true;
419 }
420
421 PAsmJSCacheEntryChild*
AllocPAsmJSCacheEntryChild(const dom::asmjscache::OpenMode & aOpenMode,const dom::asmjscache::WriteParams & aWriteParams,const PrincipalInfo & aPrincipalInfo)422 BackgroundChildImpl::AllocPAsmJSCacheEntryChild(
423 const dom::asmjscache::OpenMode& aOpenMode,
424 const dom::asmjscache::WriteParams& aWriteParams,
425 const PrincipalInfo& aPrincipalInfo)
426 {
427 MOZ_CRASH("PAsmJSCacheEntryChild actors should be manually constructed!");
428 }
429
430 bool
DeallocPAsmJSCacheEntryChild(PAsmJSCacheEntryChild * aActor)431 BackgroundChildImpl::DeallocPAsmJSCacheEntryChild(PAsmJSCacheEntryChild* aActor)
432 {
433 MOZ_ASSERT(aActor);
434
435 dom::asmjscache::DeallocEntryChild(aActor);
436 return true;
437 }
438
439 BackgroundChildImpl::PQuotaChild*
AllocPQuotaChild()440 BackgroundChildImpl::AllocPQuotaChild()
441 {
442 MOZ_CRASH("PQuotaChild actor should be manually constructed!");
443 }
444
445 bool
DeallocPQuotaChild(PQuotaChild * aActor)446 BackgroundChildImpl::DeallocPQuotaChild(PQuotaChild* aActor)
447 {
448 MOZ_ASSERT(aActor);
449
450 delete aActor;
451 return true;
452 }
453
454 dom::PFileSystemRequestChild*
AllocPFileSystemRequestChild(const FileSystemParams & aParams)455 BackgroundChildImpl::AllocPFileSystemRequestChild(const FileSystemParams& aParams)
456 {
457 MOZ_CRASH("Should never get here!");
458 return nullptr;
459 }
460
461 bool
DeallocPFileSystemRequestChild(PFileSystemRequestChild * aActor)462 BackgroundChildImpl::DeallocPFileSystemRequestChild(PFileSystemRequestChild* aActor)
463 {
464 // The reference is increased in FileSystemTaskBase::Start of
465 // FileSystemTaskBase.cpp. We should decrease it after IPC.
466 RefPtr<dom::FileSystemTaskChildBase> child =
467 dont_AddRef(static_cast<dom::FileSystemTaskChildBase*>(aActor));
468 return true;
469 }
470
471 // Gamepad API Background IPC
472 dom::PGamepadEventChannelChild*
AllocPGamepadEventChannelChild()473 BackgroundChildImpl::AllocPGamepadEventChannelChild()
474 {
475 MOZ_CRASH("PGamepadEventChannelChild actor should be manually constructed!");
476 return nullptr;
477 }
478
479 bool
DeallocPGamepadEventChannelChild(PGamepadEventChannelChild * aActor)480 BackgroundChildImpl::DeallocPGamepadEventChannelChild(PGamepadEventChannelChild* aActor)
481 {
482 #ifdef MOZ_GAMEPAD
483 MOZ_ASSERT(aActor);
484 delete static_cast<dom::GamepadEventChannelChild*>(aActor);
485 #endif
486 return true;
487 }
488
489 dom::PGamepadTestChannelChild*
AllocPGamepadTestChannelChild()490 BackgroundChildImpl::AllocPGamepadTestChannelChild()
491 {
492 #ifdef MOZ_GAMEPAD
493 MOZ_CRASH("PGamepadTestChannelChild actor should be manually constructed!");
494 #endif
495 return nullptr;
496 }
497
498 bool
DeallocPGamepadTestChannelChild(PGamepadTestChannelChild * aActor)499 BackgroundChildImpl::DeallocPGamepadTestChannelChild(PGamepadTestChannelChild* aActor)
500 {
501 #ifdef MOZ_GAMEPAD
502 MOZ_ASSERT(aActor);
503 delete static_cast<dom::GamepadTestChannelChild*>(aActor);
504 #endif
505 return true;
506 }
507
508 } // namespace ipc
509 } // namespace mozilla
510
511 bool
Recv__delete__(const nsCString & aTestArg)512 TestChild::Recv__delete__(const nsCString& aTestArg)
513 {
514 MOZ_RELEASE_ASSERT(aTestArg == mTestArg,
515 "BackgroundTest message was corrupted!");
516
517 return true;
518 }
519