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 "mozilla/dom/ContentBridgeParent.h"
8 #include "mozilla/dom/TabParent.h"
9 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
10 #include "nsXULAppAPI.h"
11 #include "nsIObserverService.h"
12 #include "base/task.h"
13 
14 using namespace mozilla::ipc;
15 using namespace mozilla::jsipc;
16 
17 namespace mozilla {
18 namespace dom {
19 
NS_IMPL_ISUPPORTS(ContentBridgeParent,nsIContentParent,nsIObserver)20 NS_IMPL_ISUPPORTS(ContentBridgeParent,
21                   nsIContentParent,
22                   nsIObserver)
23 
24 ContentBridgeParent::ContentBridgeParent(Transport* aTransport)
25   : mTransport(aTransport)
26 {}
27 
~ContentBridgeParent()28 ContentBridgeParent::~ContentBridgeParent()
29 {
30 }
31 
32 void
ActorDestroy(ActorDestroyReason aWhy)33 ContentBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
34 {
35   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
36   if (os) {
37     os->RemoveObserver(this, "content-child-shutdown");
38   }
39   MessageLoop::current()->PostTask(NewRunnableMethod(this, &ContentBridgeParent::DeferredDestroy));
40 }
41 
42 /*static*/ ContentBridgeParent*
Create(Transport * aTransport,ProcessId aOtherPid)43 ContentBridgeParent::Create(Transport* aTransport, ProcessId aOtherPid)
44 {
45   RefPtr<ContentBridgeParent> bridge =
46     new ContentBridgeParent(aTransport);
47   bridge->mSelfRef = bridge;
48 
49   DebugOnly<bool> ok = bridge->Open(aTransport, aOtherPid,
50                                     XRE_GetIOMessageLoop());
51   MOZ_ASSERT(ok);
52 
53   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
54   if (os) {
55     os->AddObserver(bridge, "content-child-shutdown", false);
56   }
57 
58   // Initialize the message manager (and load delayed scripts) now that we
59   // have established communications with the child.
60   bridge->mMessageManager->InitWithCallback(bridge);
61 
62   return bridge.get();
63 }
64 
65 void
DeferredDestroy()66 ContentBridgeParent::DeferredDestroy()
67 {
68   mSelfRef = nullptr;
69   // |this| was just destroyed, hands off
70 }
71 
72 bool
RecvSyncMessage(const nsString & aMsg,const ClonedMessageData & aData,InfallibleTArray<jsipc::CpowEntry> && aCpows,const IPC::Principal & aPrincipal,nsTArray<StructuredCloneData> * aRetvals)73 ContentBridgeParent::RecvSyncMessage(const nsString& aMsg,
74                                      const ClonedMessageData& aData,
75                                      InfallibleTArray<jsipc::CpowEntry>&& aCpows,
76                                      const IPC::Principal& aPrincipal,
77                                      nsTArray<StructuredCloneData>* aRetvals)
78 {
79   return nsIContentParent::RecvSyncMessage(aMsg, aData, Move(aCpows),
80                                            aPrincipal, aRetvals);
81 }
82 
83 bool
RecvAsyncMessage(const nsString & aMsg,InfallibleTArray<jsipc::CpowEntry> && aCpows,const IPC::Principal & aPrincipal,const ClonedMessageData & aData)84 ContentBridgeParent::RecvAsyncMessage(const nsString& aMsg,
85                                       InfallibleTArray<jsipc::CpowEntry>&& aCpows,
86                                       const IPC::Principal& aPrincipal,
87                                       const ClonedMessageData& aData)
88 {
89   return nsIContentParent::RecvAsyncMessage(aMsg, Move(aCpows),
90                                             aPrincipal, aData);
91 }
92 
93 PBlobParent*
SendPBlobConstructor(PBlobParent * actor,const BlobConstructorParams & params)94 ContentBridgeParent::SendPBlobConstructor(PBlobParent* actor,
95                                           const BlobConstructorParams& params)
96 {
97   return PContentBridgeParent::SendPBlobConstructor(actor, params);
98 }
99 
100 PBrowserParent*
SendPBrowserConstructor(PBrowserParent * aActor,const TabId & aTabId,const IPCTabContext & aContext,const uint32_t & aChromeFlags,const ContentParentId & aCpID,const bool & aIsForApp,const bool & aIsForBrowser)101 ContentBridgeParent::SendPBrowserConstructor(PBrowserParent* aActor,
102                                              const TabId& aTabId,
103                                              const IPCTabContext& aContext,
104                                              const uint32_t& aChromeFlags,
105                                              const ContentParentId& aCpID,
106                                              const bool& aIsForApp,
107                                              const bool& aIsForBrowser)
108 {
109   return PContentBridgeParent::SendPBrowserConstructor(aActor,
110                                                        aTabId,
111                                                        aContext,
112                                                        aChromeFlags,
113                                                        aCpID,
114                                                        aIsForApp,
115                                                        aIsForBrowser);
116 }
117 
118 PBlobParent*
AllocPBlobParent(const BlobConstructorParams & aParams)119 ContentBridgeParent::AllocPBlobParent(const BlobConstructorParams& aParams)
120 {
121   return nsIContentParent::AllocPBlobParent(aParams);
122 }
123 
124 bool
DeallocPBlobParent(PBlobParent * aActor)125 ContentBridgeParent::DeallocPBlobParent(PBlobParent* aActor)
126 {
127   return nsIContentParent::DeallocPBlobParent(aActor);
128 }
129 
130 mozilla::jsipc::PJavaScriptParent *
AllocPJavaScriptParent()131 ContentBridgeParent::AllocPJavaScriptParent()
132 {
133   return nsIContentParent::AllocPJavaScriptParent();
134 }
135 
136 bool
DeallocPJavaScriptParent(PJavaScriptParent * parent)137 ContentBridgeParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
138 {
139   return nsIContentParent::DeallocPJavaScriptParent(parent);
140 }
141 
142 PBrowserParent*
AllocPBrowserParent(const TabId & aTabId,const IPCTabContext & aContext,const uint32_t & aChromeFlags,const ContentParentId & aCpID,const bool & aIsForApp,const bool & aIsForBrowser)143 ContentBridgeParent::AllocPBrowserParent(const TabId& aTabId,
144                                          const IPCTabContext &aContext,
145                                          const uint32_t& aChromeFlags,
146                                          const ContentParentId& aCpID,
147                                          const bool& aIsForApp,
148                                          const bool& aIsForBrowser)
149 {
150   return nsIContentParent::AllocPBrowserParent(aTabId,
151                                                aContext,
152                                                aChromeFlags,
153                                                aCpID,
154                                                aIsForApp,
155                                                aIsForBrowser);
156 }
157 
158 bool
DeallocPBrowserParent(PBrowserParent * aParent)159 ContentBridgeParent::DeallocPBrowserParent(PBrowserParent* aParent)
160 {
161   return nsIContentParent::DeallocPBrowserParent(aParent);
162 }
163 
164 void
NotifyTabDestroyed()165 ContentBridgeParent::NotifyTabDestroyed()
166 {
167   int32_t numLiveTabs = ManagedPBrowserParent().Count();
168   if (numLiveTabs == 1) {
169     MessageLoop::current()->PostTask(NewRunnableMethod(this, &ContentBridgeParent::Close));
170   }
171 }
172 
173 // This implementation is identical to ContentParent::GetCPOWManager but we can't
174 // move it to nsIContentParent because it calls ManagedPJavaScriptParent() which
175 // only exists in PContentParent and PContentBridgeParent.
176 jsipc::CPOWManager*
GetCPOWManager()177 ContentBridgeParent::GetCPOWManager()
178 {
179   if (PJavaScriptParent* p = LoneManagedOrNullAsserts(ManagedPJavaScriptParent())) {
180     return CPOWManagerFor(p);
181   }
182   return nullptr;
183 }
184 
185 NS_IMETHODIMP
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * aData)186 ContentBridgeParent::Observe(nsISupports* aSubject,
187                              const char* aTopic,
188                              const char16_t* aData)
189 {
190   if (!strcmp(aTopic, "content-child-shutdown")) {
191     Close();
192   }
193   return NS_OK;
194 }
195 
196 PFileDescriptorSetParent*
AllocPFileDescriptorSetParent(const FileDescriptor & aFD)197 ContentBridgeParent::AllocPFileDescriptorSetParent(const FileDescriptor& aFD)
198 {
199   return nsIContentParent::AllocPFileDescriptorSetParent(aFD);
200 }
201 
202 bool
DeallocPFileDescriptorSetParent(PFileDescriptorSetParent * aActor)203 ContentBridgeParent::DeallocPFileDescriptorSetParent(PFileDescriptorSetParent* aActor)
204 {
205   return nsIContentParent::DeallocPFileDescriptorSetParent(aActor);
206 }
207 
208 PSendStreamParent*
AllocPSendStreamParent()209 ContentBridgeParent::AllocPSendStreamParent()
210 {
211   return nsIContentParent::AllocPSendStreamParent();
212 }
213 
214 bool
DeallocPSendStreamParent(PSendStreamParent * aActor)215 ContentBridgeParent::DeallocPSendStreamParent(PSendStreamParent* aActor)
216 {
217   return nsIContentParent::DeallocPSendStreamParent(aActor);
218 }
219 
220 } // namespace dom
221 } // namespace mozilla
222