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