/src/mozilla-central/dom/ipc/nsIContentChild.cpp
Line | Count | Source (jump to first uncovered line) |
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 "nsIContentChild.h" |
8 | | |
9 | | #include "mozilla/dom/ContentChild.h" |
10 | | #include "mozilla/dom/ChildProcessMessageManager.h" |
11 | | #include "mozilla/dom/DOMTypes.h" |
12 | | #include "mozilla/dom/File.h" |
13 | | #include "mozilla/dom/PermissionMessageUtils.h" |
14 | | #include "mozilla/dom/TabChild.h" |
15 | | #include "mozilla/dom/TabGroup.h" |
16 | | #include "mozilla/dom/ipc/StructuredCloneData.h" |
17 | | #include "mozilla/ipc/FileDescriptorSetChild.h" |
18 | | #include "mozilla/ipc/InputStreamUtils.h" |
19 | | #include "mozilla/ipc/IPCStreamAlloc.h" |
20 | | #include "mozilla/ipc/IPCStreamDestination.h" |
21 | | #include "mozilla/ipc/IPCStreamSource.h" |
22 | | #include "mozilla/ipc/PChildToParentStreamChild.h" |
23 | | #include "mozilla/ipc/PParentToChildStreamChild.h" |
24 | | #include "mozilla/dom/ipc/IPCBlobInputStreamChild.h" |
25 | | |
26 | | #include "nsPrintfCString.h" |
27 | | #include "xpcpublic.h" |
28 | | |
29 | | using namespace mozilla::ipc; |
30 | | using namespace mozilla::jsipc; |
31 | | |
32 | | namespace mozilla { |
33 | | namespace dom { |
34 | | |
35 | | PJavaScriptChild* |
36 | | nsIContentChild::AllocPJavaScriptChild() |
37 | 0 | { |
38 | 0 | return NewJavaScriptChild(); |
39 | 0 | } |
40 | | |
41 | | bool |
42 | | nsIContentChild::DeallocPJavaScriptChild(PJavaScriptChild* aChild) |
43 | 0 | { |
44 | 0 | ReleaseJavaScriptChild(aChild); |
45 | 0 | return true; |
46 | 0 | } |
47 | | |
48 | | PBrowserChild* |
49 | | nsIContentChild::AllocPBrowserChild(const TabId& aTabId, |
50 | | const TabId& aSameTabGroupAs, |
51 | | const IPCTabContext& aContext, |
52 | | const uint32_t& aChromeFlags, |
53 | | const ContentParentId& aCpID, |
54 | | const bool& aIsForBrowser) |
55 | 0 | { |
56 | 0 | // We'll happily accept any kind of IPCTabContext here; we don't need to |
57 | 0 | // check that it's of a certain type for security purposes, because we |
58 | 0 | // believe whatever the parent process tells us. |
59 | 0 |
|
60 | 0 | MaybeInvalidTabContext tc(aContext); |
61 | 0 | if (!tc.IsValid()) { |
62 | 0 | NS_ERROR(nsPrintfCString("Received an invalid TabContext from " |
63 | 0 | "the parent process. (%s) Crashing...", |
64 | 0 | tc.GetInvalidReason()).get()); |
65 | 0 | MOZ_CRASH("Invalid TabContext received from the parent process."); |
66 | 0 | } |
67 | 0 |
|
68 | 0 | RefPtr<TabChild> child = |
69 | 0 | TabChild::Create(this, aTabId, aSameTabGroupAs, |
70 | 0 | tc.GetTabContext(), aChromeFlags); |
71 | 0 |
|
72 | 0 | // The ref here is released in DeallocPBrowserChild. |
73 | 0 | return child.forget().take(); |
74 | 0 | } |
75 | | |
76 | | bool |
77 | | nsIContentChild::DeallocPBrowserChild(PBrowserChild* aIframe) |
78 | 0 | { |
79 | 0 | TabChild* child = static_cast<TabChild*>(aIframe); |
80 | 0 | NS_RELEASE(child); |
81 | 0 | return true; |
82 | 0 | } |
83 | | |
84 | | mozilla::ipc::IPCResult |
85 | | nsIContentChild::RecvPBrowserConstructor(PBrowserChild* aActor, |
86 | | const TabId& aTabId, |
87 | | const TabId& aSameTabGroupAs, |
88 | | const IPCTabContext& aContext, |
89 | | const uint32_t& aChromeFlags, |
90 | | const ContentParentId& aCpID, |
91 | | const bool& aIsForBrowser) |
92 | 0 | { |
93 | 0 | // This runs after AllocPBrowserChild() returns and the IPC machinery for this |
94 | 0 | // PBrowserChild has been set up. |
95 | 0 |
|
96 | 0 | auto tabChild = static_cast<TabChild*>(static_cast<TabChild*>(aActor)); |
97 | 0 |
|
98 | 0 | if (NS_WARN_IF(NS_FAILED(tabChild->Init()))) { |
99 | 0 | return IPC_FAIL(tabChild, "TabChild::Init failed"); |
100 | 0 | } |
101 | 0 |
|
102 | 0 | nsCOMPtr<nsIObserverService> os = services::GetObserverService(); |
103 | 0 | if (os) { |
104 | 0 | os->NotifyObservers(static_cast<nsITabChild*>(tabChild), "tab-child-created", nullptr); |
105 | 0 | } |
106 | 0 | // Notify parent that we are ready to handle input events. |
107 | 0 | tabChild->SendRemoteIsReadyToHandleInputEvents(); |
108 | 0 | return IPC_OK(); |
109 | 0 | } |
110 | | |
111 | | PIPCBlobInputStreamChild* |
112 | | nsIContentChild::AllocPIPCBlobInputStreamChild(const nsID& aID, |
113 | | const uint64_t& aSize) |
114 | 0 | { |
115 | 0 | // IPCBlobInputStreamChild is refcounted. Here it's created and in |
116 | 0 | // DeallocPIPCBlobInputStreamChild is released. |
117 | 0 |
|
118 | 0 | RefPtr<IPCBlobInputStreamChild> actor = |
119 | 0 | new IPCBlobInputStreamChild(aID, aSize); |
120 | 0 | return actor.forget().take(); |
121 | 0 | } |
122 | | |
123 | | bool |
124 | | nsIContentChild::DeallocPIPCBlobInputStreamChild(PIPCBlobInputStreamChild* aActor) |
125 | 0 | { |
126 | 0 | RefPtr<IPCBlobInputStreamChild> actor = |
127 | 0 | dont_AddRef(static_cast<IPCBlobInputStreamChild*>(aActor)); |
128 | 0 | return true; |
129 | 0 | } |
130 | | |
131 | | PChildToParentStreamChild* |
132 | | nsIContentChild::AllocPChildToParentStreamChild() |
133 | 0 | { |
134 | 0 | MOZ_CRASH("PChildToParentStreamChild actors should be manually constructed!"); |
135 | 0 | } |
136 | | |
137 | | bool |
138 | | nsIContentChild::DeallocPChildToParentStreamChild(PChildToParentStreamChild* aActor) |
139 | 0 | { |
140 | 0 | delete aActor; |
141 | 0 | return true; |
142 | 0 | } |
143 | | |
144 | | PParentToChildStreamChild* |
145 | | nsIContentChild::AllocPParentToChildStreamChild() |
146 | 0 | { |
147 | 0 | return mozilla::ipc::AllocPParentToChildStreamChild(); |
148 | 0 | } |
149 | | |
150 | | bool |
151 | | nsIContentChild::DeallocPParentToChildStreamChild(PParentToChildStreamChild* aActor) |
152 | 0 | { |
153 | 0 | delete aActor; |
154 | 0 | return true; |
155 | 0 | } |
156 | | |
157 | | PFileDescriptorSetChild* |
158 | | nsIContentChild::AllocPFileDescriptorSetChild(const FileDescriptor& aFD) |
159 | 0 | { |
160 | 0 | return new FileDescriptorSetChild(aFD); |
161 | 0 | } |
162 | | |
163 | | bool |
164 | | nsIContentChild::DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor) |
165 | 0 | { |
166 | 0 | delete static_cast<FileDescriptorSetChild*>(aActor); |
167 | 0 | return true; |
168 | 0 | } |
169 | | |
170 | | mozilla::ipc::IPCResult |
171 | | nsIContentChild::RecvAsyncMessage(const nsString& aMsg, |
172 | | InfallibleTArray<CpowEntry>&& aCpows, |
173 | | const IPC::Principal& aPrincipal, |
174 | | const ClonedMessageData& aData) |
175 | 0 | { |
176 | 0 | AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING( |
177 | 0 | "nsIContentChild::RecvAsyncMessage", OTHER, aMsg); |
178 | 0 |
|
179 | 0 | CrossProcessCpowHolder cpows(this, aCpows); |
180 | 0 | RefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::GetChildProcessManager(); |
181 | 0 | if (cpm) { |
182 | 0 | ipc::StructuredCloneData data; |
183 | 0 | ipc::UnpackClonedMessageDataForChild(aData, data); |
184 | 0 |
|
185 | 0 | cpm->ReceiveMessage(cpm, nullptr, aMsg, false, &data, &cpows, aPrincipal, nullptr, |
186 | 0 | IgnoreErrors()); |
187 | 0 | } |
188 | 0 | return IPC_OK(); |
189 | 0 | } |
190 | | |
191 | | /* static */ |
192 | | already_AddRefed<nsIEventTarget> |
193 | | nsIContentChild::GetConstructedEventTarget(const IPC::Message& aMsg) |
194 | 0 | { |
195 | 0 | ActorHandle handle; |
196 | 0 | TabId tabId, sameTabGroupAs; |
197 | 0 | PickleIterator iter(aMsg); |
198 | 0 | if (!IPC::ReadParam(&aMsg, &iter, &handle)) { |
199 | 0 | return nullptr; |
200 | 0 | } |
201 | 0 | aMsg.IgnoreSentinel(&iter); |
202 | 0 | if (!IPC::ReadParam(&aMsg, &iter, &tabId)) { |
203 | 0 | return nullptr; |
204 | 0 | } |
205 | 0 | aMsg.IgnoreSentinel(&iter); |
206 | 0 | if (!IPC::ReadParam(&aMsg, &iter, &sameTabGroupAs)) { |
207 | 0 | return nullptr; |
208 | 0 | } |
209 | 0 | |
210 | 0 | // If sameTabGroupAs is non-zero, then the new tab will be in the same |
211 | 0 | // TabGroup as a previously created tab. Rather than try to find the |
212 | 0 | // previously created tab (whose constructor message may not even have been |
213 | 0 | // processed yet, in theory) and look up its event target, we just use the |
214 | 0 | // default event target. This means that runnables for this tab will not be |
215 | 0 | // labeled. However, this path is only taken for print preview and view |
216 | 0 | // source, which are not performance-sensitive. |
217 | 0 | if (sameTabGroupAs) { |
218 | 0 | return nullptr; |
219 | 0 | } |
220 | 0 | |
221 | 0 | // If the request for a new TabChild is coming from the parent process, then |
222 | 0 | // there is no opener. Therefore, we create a fresh TabGroup. |
223 | 0 | RefPtr<TabGroup> tabGroup = new TabGroup(); |
224 | 0 | nsCOMPtr<nsIEventTarget> target = tabGroup->EventTargetFor(TaskCategory::Other); |
225 | 0 | return target.forget(); |
226 | 0 | } |
227 | | |
228 | | |
229 | | } // namespace dom |
230 | | } // namespace mozilla |