Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #include "nsWyciwyg.h"
6 :
7 : #include "mozilla/net/WyciwygChannelParent.h"
8 : #include "nsWyciwygChannel.h"
9 : #include "nsNetUtil.h"
10 : #include "nsCharsetSource.h"
11 : #include "nsISerializable.h"
12 : #include "nsSerializationHelper.h"
13 : #include "mozilla/ipc/URIUtils.h"
14 : #include "mozilla/net/NeckoParent.h"
15 : #include "SerializedLoadContext.h"
16 : #include "nsIContentPolicy.h"
17 : #include "mozilla/ipc/BackgroundUtils.h"
18 : #include "mozilla/dom/ContentParent.h"
19 :
20 : using namespace mozilla::ipc;
21 :
22 : namespace mozilla {
23 : namespace net {
24 :
25 0 : WyciwygChannelParent::WyciwygChannelParent()
26 : : mIPCClosed(false)
27 0 : , mReceivedAppData(false)
28 : {
29 0 : }
30 :
31 0 : WyciwygChannelParent::~WyciwygChannelParent()
32 : {
33 0 : }
34 :
35 : void
36 0 : WyciwygChannelParent::ActorDestroy(ActorDestroyReason why)
37 : {
38 : // We may still have refcount>0 if the channel hasn't called OnStopRequest
39 : // yet, but we must not send any more msgs to child.
40 0 : mIPCClosed = true;
41 :
42 : // We need to force the cycle to break here
43 0 : if (mChannel) {
44 0 : mChannel->SetNotificationCallbacks(nullptr);
45 : }
46 0 : }
47 :
48 : //-----------------------------------------------------------------------------
49 : // WyciwygChannelParent::nsISupports
50 : //-----------------------------------------------------------------------------
51 :
52 0 : NS_IMPL_ISUPPORTS(WyciwygChannelParent,
53 : nsIStreamListener,
54 : nsIInterfaceRequestor,
55 : nsIRequestObserver)
56 :
57 : //-----------------------------------------------------------------------------
58 : // WyciwygChannelParent::PWyciwygChannelParent
59 : //-----------------------------------------------------------------------------
60 :
61 : mozilla::ipc::IPCResult
62 0 : WyciwygChannelParent::RecvInit(const URIParams& aURI,
63 : const ipc::PrincipalInfo& aRequestingPrincipalInfo,
64 : const ipc::PrincipalInfo& aTriggeringPrincipalInfo,
65 : const ipc::PrincipalInfo& aPrincipalToInheritInfo,
66 : const uint32_t& aSecurityFlags,
67 : const uint32_t& aContentPolicyType)
68 : {
69 : nsresult rv;
70 :
71 0 : nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
72 0 : if (!uri)
73 0 : return IPC_FAIL_NO_REASON(this);
74 :
75 0 : LOG(("WyciwygChannelParent RecvInit [this=%p uri=%s]\n",
76 : this, uri->GetSpecOrDefault().get()));
77 :
78 0 : nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
79 0 : if (NS_FAILED(rv)) {
80 0 : if (!SendCancelEarly(rv)) {
81 0 : return IPC_FAIL_NO_REASON(this);
82 : }
83 0 : return IPC_OK();
84 : }
85 :
86 : nsCOMPtr<nsIPrincipal> requestingPrincipal =
87 0 : mozilla::ipc::PrincipalInfoToPrincipal(aRequestingPrincipalInfo, &rv);
88 0 : if (NS_FAILED(rv)) {
89 0 : if (!SendCancelEarly(rv)) {
90 0 : return IPC_FAIL_NO_REASON(this);
91 : }
92 0 : return IPC_OK();
93 : }
94 :
95 : nsCOMPtr<nsIPrincipal> triggeringPrincipal =
96 0 : mozilla::ipc::PrincipalInfoToPrincipal(aTriggeringPrincipalInfo, &rv);
97 0 : if (NS_FAILED(rv)) {
98 0 : if (!SendCancelEarly(rv)) {
99 0 : return IPC_FAIL_NO_REASON(this);
100 : }
101 0 : return IPC_OK();
102 : }
103 :
104 : nsCOMPtr<nsIPrincipal> principalToInherit =
105 0 : mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalToInheritInfo, &rv);
106 0 : if (NS_FAILED(rv)) {
107 0 : if (!SendCancelEarly(rv)) {
108 0 : return IPC_FAIL_NO_REASON(this);
109 : }
110 0 : return IPC_OK();
111 : }
112 :
113 0 : nsCOMPtr<nsIChannel> chan;
114 0 : rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(chan),
115 : uri,
116 : requestingPrincipal,
117 : triggeringPrincipal,
118 : aSecurityFlags,
119 : aContentPolicyType,
120 : nullptr, // loadGroup
121 : nullptr, // aCallbacks
122 : nsIRequest::LOAD_NORMAL,
123 : ios);
124 :
125 0 : if (NS_FAILED(rv)) {
126 0 : if (!SendCancelEarly(rv)) {
127 0 : return IPC_FAIL_NO_REASON(this);
128 : }
129 0 : return IPC_OK();
130 : }
131 :
132 0 : nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo();
133 0 : if (loadInfo) {
134 0 : rv = loadInfo->SetPrincipalToInherit(principalToInherit);
135 : }
136 0 : if (NS_FAILED(rv)) {
137 0 : if (!SendCancelEarly(rv)) {
138 0 : return IPC_FAIL_NO_REASON(this);
139 : }
140 0 : return IPC_OK();
141 : }
142 :
143 0 : mChannel = do_QueryInterface(chan, &rv);
144 0 : if (NS_FAILED(rv)) {
145 0 : if (!SendCancelEarly(rv)) {
146 0 : return IPC_FAIL_NO_REASON(this);
147 : }
148 0 : return IPC_OK();
149 : }
150 :
151 0 : return IPC_OK();
152 : }
153 :
154 : mozilla::ipc::IPCResult
155 0 : WyciwygChannelParent::RecvAppData(const IPC::SerializedLoadContext& loadContext,
156 : const PBrowserOrId &parent)
157 : {
158 0 : LOG(("WyciwygChannelParent RecvAppData [this=%p]\n", this));
159 :
160 0 : if (!SetupAppData(loadContext, parent))
161 0 : return IPC_FAIL_NO_REASON(this);
162 :
163 0 : mChannel->SetNotificationCallbacks(this);
164 0 : return IPC_OK();
165 : }
166 :
167 : bool
168 0 : WyciwygChannelParent::SetupAppData(const IPC::SerializedLoadContext& loadContext,
169 : const PBrowserOrId &aParent)
170 : {
171 0 : if (!mChannel)
172 0 : return true;
173 :
174 0 : const char* error = NeckoParent::CreateChannelLoadContext(aParent,
175 : Manager()->Manager(),
176 : loadContext,
177 : nullptr,
178 0 : mLoadContext);
179 0 : if (error) {
180 : printf_stderr("WyciwygChannelParent::SetupAppData: FATAL ERROR: %s\n",
181 0 : error);
182 0 : return false;
183 : }
184 :
185 0 : if (!mLoadContext && loadContext.IsPrivateBitValid()) {
186 0 : nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(mChannel);
187 0 : if (pbChannel)
188 0 : pbChannel->SetPrivate(loadContext.mOriginAttributes.mPrivateBrowsingId > 0);
189 : }
190 :
191 0 : mReceivedAppData = true;
192 0 : return true;
193 : }
194 :
195 : mozilla::ipc::IPCResult
196 0 : WyciwygChannelParent::RecvAsyncOpen(const URIParams& aOriginal,
197 : const uint32_t& aLoadFlags,
198 : const IPC::SerializedLoadContext& loadContext,
199 : const PBrowserOrId &aParent)
200 : {
201 0 : nsCOMPtr<nsIURI> original = DeserializeURI(aOriginal);
202 0 : if (!original)
203 0 : return IPC_FAIL_NO_REASON(this);
204 :
205 0 : LOG(("WyciwygChannelParent RecvAsyncOpen [this=%p]\n", this));
206 :
207 0 : if (!mChannel)
208 0 : return IPC_OK();
209 :
210 : nsresult rv;
211 :
212 0 : rv = mChannel->SetOriginalURI(original);
213 0 : if (NS_FAILED(rv)) {
214 0 : if (!SendCancelEarly(rv)) {
215 0 : return IPC_FAIL_NO_REASON(this);
216 : }
217 0 : return IPC_OK();
218 : }
219 :
220 0 : rv = mChannel->SetLoadFlags(aLoadFlags);
221 0 : if (NS_FAILED(rv)) {
222 0 : if (!SendCancelEarly(rv)) {
223 0 : return IPC_FAIL_NO_REASON(this);
224 : }
225 0 : return IPC_OK();
226 : }
227 :
228 0 : if (!mReceivedAppData && !SetupAppData(loadContext, aParent)) {
229 0 : return IPC_FAIL_NO_REASON(this);
230 : }
231 :
232 0 : rv = mChannel->SetNotificationCallbacks(this);
233 0 : if (NS_FAILED(rv)) {
234 0 : if (!SendCancelEarly(rv)) {
235 0 : return IPC_FAIL_NO_REASON(this);
236 : }
237 0 : return IPC_OK();
238 : }
239 :
240 0 : nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
241 0 : if (loadInfo && loadInfo->GetEnforceSecurity()) {
242 0 : rv = mChannel->AsyncOpen2(this);
243 : }
244 : else {
245 0 : rv = mChannel->AsyncOpen(this, nullptr);
246 : }
247 :
248 0 : if (NS_FAILED(rv)) {
249 0 : if (!SendCancelEarly(rv)) {
250 0 : return IPC_FAIL_NO_REASON(this);
251 : }
252 0 : return IPC_OK();
253 : }
254 :
255 0 : return IPC_OK();
256 : }
257 :
258 : mozilla::ipc::IPCResult
259 0 : WyciwygChannelParent::RecvWriteToCacheEntry(const nsDependentSubstring& data)
260 : {
261 0 : if (!mReceivedAppData) {
262 0 : printf_stderr("WyciwygChannelParent::RecvWriteToCacheEntry: FATAL ERROR: didn't receive app data\n");
263 0 : return IPC_FAIL_NO_REASON(this);
264 : }
265 :
266 0 : if (mChannel)
267 0 : mChannel->WriteToCacheEntry(data);
268 :
269 0 : return IPC_OK();
270 : }
271 :
272 : mozilla::ipc::IPCResult
273 0 : WyciwygChannelParent::RecvCloseCacheEntry(const nsresult& reason)
274 : {
275 0 : if (mChannel) {
276 0 : mChannel->CloseCacheEntry(reason);
277 : }
278 :
279 0 : return IPC_OK();
280 : }
281 :
282 : mozilla::ipc::IPCResult
283 0 : WyciwygChannelParent::RecvSetCharsetAndSource(const int32_t& aCharsetSource,
284 : const nsCString& aCharset)
285 : {
286 0 : if (mChannel)
287 0 : mChannel->SetCharsetAndSource(aCharsetSource, aCharset);
288 :
289 0 : return IPC_OK();
290 : }
291 :
292 : mozilla::ipc::IPCResult
293 0 : WyciwygChannelParent::RecvSetSecurityInfo(const nsCString& aSecurityInfo)
294 : {
295 0 : if (mChannel) {
296 0 : nsCOMPtr<nsISupports> securityInfo;
297 0 : NS_DeserializeObject(aSecurityInfo, getter_AddRefs(securityInfo));
298 0 : mChannel->SetSecurityInfo(securityInfo);
299 : }
300 :
301 0 : return IPC_OK();
302 : }
303 :
304 : mozilla::ipc::IPCResult
305 0 : WyciwygChannelParent::RecvCancel(const nsresult& aStatusCode)
306 : {
307 0 : if (mChannel)
308 0 : mChannel->Cancel(aStatusCode);
309 0 : return IPC_OK();
310 : }
311 :
312 : //-----------------------------------------------------------------------------
313 : // WyciwygChannelParent::nsIRequestObserver
314 : //-----------------------------------------------------------------------------
315 :
316 : NS_IMETHODIMP
317 0 : WyciwygChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
318 : {
319 0 : LOG(("WyciwygChannelParent::OnStartRequest [this=%p]\n", this));
320 :
321 : nsresult rv;
322 :
323 0 : nsCOMPtr<nsIWyciwygChannel> chan = do_QueryInterface(aRequest, &rv);
324 0 : NS_ENSURE_SUCCESS(rv, rv);
325 :
326 : // Send down any permissions which are relevant to this URL if we are
327 : // performing a document load.
328 0 : PContentParent* pcp = Manager()->Manager();
329 0 : rv = static_cast<ContentParent*>(pcp)->AboutToLoadHttpFtpWyciwygDocumentForChild(chan);
330 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
331 :
332 : nsresult status;
333 0 : chan->GetStatus(&status);
334 :
335 0 : int64_t contentLength = -1;
336 0 : chan->GetContentLength(&contentLength);
337 :
338 0 : int32_t charsetSource = kCharsetUninitialized;
339 0 : nsAutoCString charset;
340 0 : chan->GetCharsetAndSource(&charsetSource, charset);
341 :
342 0 : nsCOMPtr<nsISupports> securityInfo;
343 0 : chan->GetSecurityInfo(getter_AddRefs(securityInfo));
344 0 : nsCString secInfoStr;
345 0 : if (securityInfo) {
346 0 : nsCOMPtr<nsISerializable> serializable = do_QueryInterface(securityInfo);
347 0 : if (serializable)
348 0 : NS_SerializeToString(serializable, secInfoStr);
349 : else {
350 0 : NS_ERROR("Can't serialize security info");
351 0 : return NS_ERROR_UNEXPECTED;
352 : }
353 : }
354 :
355 0 : if (mIPCClosed ||
356 0 : !SendOnStartRequest(status, contentLength, charsetSource, charset, secInfoStr)) {
357 0 : return NS_ERROR_UNEXPECTED;
358 : }
359 :
360 0 : return NS_OK;
361 : }
362 :
363 : NS_IMETHODIMP
364 0 : WyciwygChannelParent::OnStopRequest(nsIRequest *aRequest,
365 : nsISupports *aContext,
366 : nsresult aStatusCode)
367 : {
368 0 : LOG(("WyciwygChannelParent::OnStopRequest: [this=%p status=%" PRIu32 "]\n",
369 : this, static_cast<uint32_t>(aStatusCode)));
370 :
371 0 : if (mIPCClosed || !SendOnStopRequest(aStatusCode)) {
372 0 : return NS_ERROR_UNEXPECTED;
373 : }
374 :
375 0 : return NS_OK;
376 : }
377 :
378 : //-----------------------------------------------------------------------------
379 : // WyciwygChannelParent::nsIStreamListener
380 : //-----------------------------------------------------------------------------
381 :
382 : NS_IMETHODIMP
383 0 : WyciwygChannelParent::OnDataAvailable(nsIRequest *aRequest,
384 : nsISupports *aContext,
385 : nsIInputStream *aInputStream,
386 : uint64_t aOffset,
387 : uint32_t aCount)
388 : {
389 0 : LOG(("WyciwygChannelParent::OnDataAvailable [this=%p]\n", this));
390 :
391 0 : nsCString data;
392 0 : nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
393 0 : if (NS_FAILED(rv))
394 0 : return rv;
395 :
396 0 : if (mIPCClosed || !SendOnDataAvailable(data, aOffset)) {
397 0 : return NS_ERROR_UNEXPECTED;
398 : }
399 :
400 0 : return NS_OK;
401 : }
402 :
403 : //-----------------------------------------------------------------------------
404 : // WyciwygChannelParent::nsIInterfaceRequestor
405 : //-----------------------------------------------------------------------------
406 :
407 : NS_IMETHODIMP
408 0 : WyciwygChannelParent::GetInterface(const nsIID& uuid, void** result)
409 : {
410 : // Only support nsILoadContext if child channel's callbacks did too
411 0 : if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
412 0 : nsCOMPtr<nsILoadContext> copy = mLoadContext;
413 0 : copy.forget(result);
414 0 : return NS_OK;
415 : }
416 :
417 0 : return QueryInterface(uuid, result);
418 : }
419 :
420 :
421 : } // namespace net
422 : } // namespace mozilla
|