Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set sw=2 ts=8 et 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
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : // HttpLog.h should generally be included first
8 : #include "HttpLog.h"
9 :
10 : #include "mozilla/ipc/FileDescriptorSetParent.h"
11 : #include "mozilla/ipc/IPCStreamUtils.h"
12 : #include "mozilla/net/HttpChannelParent.h"
13 : #include "mozilla/dom/ContentParent.h"
14 : #include "mozilla/dom/Element.h"
15 : #include "mozilla/dom/TabParent.h"
16 : #include "mozilla/net/NeckoParent.h"
17 : #include "mozilla/IntegerPrintfMacros.h"
18 : #include "mozilla/UniquePtr.h"
19 : #include "mozilla/Unused.h"
20 : #include "HttpBackgroundChannelParent.h"
21 : #include "HttpChannelParentListener.h"
22 : #include "nsHttpHandler.h"
23 : #include "nsNetCID.h"
24 : #include "nsNetUtil.h"
25 : #include "nsISupportsPriority.h"
26 : #include "nsIAuthPromptProvider.h"
27 : #include "nsIBackgroundChannelRegistrar.h"
28 : #include "nsSerializationHelper.h"
29 : #include "nsISerializable.h"
30 : #include "nsIAssociatedContentSecurity.h"
31 : #include "nsIApplicationCacheService.h"
32 : #include "mozilla/ipc/InputStreamUtils.h"
33 : #include "mozilla/ipc/URIUtils.h"
34 : #include "SerializedLoadContext.h"
35 : #include "nsIAuthInformation.h"
36 : #include "nsIAuthPromptCallback.h"
37 : #include "nsIContentPolicy.h"
38 : #include "mozilla/ipc/BackgroundUtils.h"
39 : #include "nsICachingChannel.h"
40 : #include "mozilla/LoadInfo.h"
41 : #include "nsQueryObject.h"
42 : #include "mozilla/BasePrincipal.h"
43 : #include "nsCORSListenerProxy.h"
44 : #include "nsIIPCSerializableInputStream.h"
45 : #include "nsIPrompt.h"
46 : #include "nsIRedirectChannelRegistrar.h"
47 : #include "nsIWindowWatcher.h"
48 : #include "nsIDocument.h"
49 : #include "nsStreamUtils.h"
50 : #include "nsStringStream.h"
51 : #include "nsIStorageStream.h"
52 : #include "nsThreadUtils.h"
53 : #include "nsQueryObject.h"
54 : #include "nsIURIClassifier.h"
55 :
56 : using mozilla::BasePrincipal;
57 : using namespace mozilla::dom;
58 : using namespace mozilla::ipc;
59 :
60 : namespace mozilla {
61 : namespace net {
62 :
63 3 : HttpChannelParent::HttpChannelParent(const PBrowserOrId& iframeEmbedding,
64 : nsILoadContext* aLoadContext,
65 3 : PBOverrideStatus aOverrideStatus)
66 : : mIPCClosed(false)
67 : , mIgnoreProgress(false)
68 : , mSentRedirect1BeginFailed(false)
69 : , mReceivedRedirect2Verify(false)
70 : , mPBOverride(aOverrideStatus)
71 : , mLoadContext(aLoadContext)
72 : , mStatus(NS_OK)
73 : , mPendingDiversion(false)
74 : , mDivertingFromChild(false)
75 : , mDivertedOnStartRequest(false)
76 : , mSuspendedForDiversion(false)
77 : , mSuspendAfterSynthesizeResponse(false)
78 : , mWillSynthesizeResponse(false)
79 3 : , mNestedFrameId(0)
80 : {
81 3 : LOG(("Creating HttpChannelParent [this=%p]\n", this));
82 :
83 : // Ensure gHttpHandler is initialized: we need the atom table up and running.
84 : nsCOMPtr<nsIHttpProtocolHandler> dummyInitializer =
85 6 : do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http");
86 :
87 3 : MOZ_ASSERT(gHttpHandler);
88 3 : mHttpHandler = gHttpHandler;
89 :
90 3 : if (iframeEmbedding.type() == PBrowserOrId::TPBrowserParent) {
91 3 : mTabParent = static_cast<dom::TabParent*>(iframeEmbedding.get_PBrowserParent());
92 : } else {
93 0 : mNestedFrameId = iframeEmbedding.get_TabId();
94 : }
95 :
96 3 : mEventQ = new ChannelEventQueue(static_cast<nsIParentRedirectingChannel*>(this));
97 3 : }
98 :
99 6 : HttpChannelParent::~HttpChannelParent()
100 : {
101 2 : LOG(("Destroying HttpChannelParent [this=%p]\n", this));
102 2 : CleanupBackgroundChannel();
103 6 : }
104 :
105 : void
106 2 : HttpChannelParent::ActorDestroy(ActorDestroyReason why)
107 : {
108 : // We may still have refcount>0 if nsHttpChannel hasn't called OnStopRequest
109 : // yet, but child process has crashed. We must not try to send any more msgs
110 : // to child, or IPDL will kill chrome process, too.
111 2 : mIPCClosed = true;
112 :
113 : // If this is an intercepted channel, we need to make sure that any resources are
114 : // cleaned up to avoid leaks.
115 2 : if (mParentListener) {
116 2 : mParentListener->ClearInterceptedChannel();
117 : }
118 :
119 2 : CleanupBackgroundChannel();
120 2 : }
121 :
122 : bool
123 3 : HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs)
124 : {
125 3 : LOG(("HttpChannelParent::Init [this=%p]\n", this));
126 3 : switch (aArgs.type()) {
127 : case HttpChannelCreationArgs::THttpChannelOpenArgs:
128 : {
129 3 : const HttpChannelOpenArgs& a = aArgs.get_HttpChannelOpenArgs();
130 15 : return DoAsyncOpen(a.uri(), a.original(), a.doc(), a.referrer(),
131 3 : a.referrerPolicy(), a.apiRedirectTo(), a.topWindowURI(),
132 : a.loadFlags(), a.requestHeaders(),
133 3 : a.requestMethod(), a.uploadStream(),
134 : a.uploadStreamHasHeaders(), a.priority(), a.classOfService(),
135 : a.redirectionLimit(), a.allowSTS(),
136 : a.thirdPartyFlags(), a.resumeAt(), a.startPos(),
137 : a.entityID(), a.chooseApplicationCache(),
138 : a.appCacheClientID(), a.allowSpdy(), a.allowAltSvc(), a.beConservative(),
139 3 : a.loadInfo(), a.synthesizedResponseHead(),
140 : a.synthesizedSecurityInfoSerialization(),
141 3 : a.cacheKey(), a.requestContextID(), a.preflightArgs(),
142 : a.initialRwin(), a.blockAuthPrompt(),
143 : a.suspendAfterSynthesizeResponse(),
144 : a.allowStaleCacheContent(), a.contentTypeHint(),
145 : a.channelId(), a.contentWindowId(), a.preferredAlternativeType(),
146 : a.topLevelOuterContentWindowId(),
147 3 : a.launchServiceWorkerStart(),
148 3 : a.launchServiceWorkerEnd(),
149 3 : a.dispatchFetchEventStart(),
150 3 : a.dispatchFetchEventEnd(),
151 3 : a.handleFetchEventStart(),
152 6 : a.handleFetchEventEnd());
153 : }
154 : case HttpChannelCreationArgs::THttpChannelConnectArgs:
155 : {
156 0 : const HttpChannelConnectArgs& cArgs = aArgs.get_HttpChannelConnectArgs();
157 0 : return ConnectChannel(cArgs.registrarId(), cArgs.shouldIntercept());
158 : }
159 : default:
160 0 : NS_NOTREACHED("unknown open type");
161 0 : return false;
162 : }
163 : }
164 :
165 : void
166 3 : HttpChannelParent::TryInvokeAsyncOpen(nsresult aRv)
167 : {
168 3 : LOG(("HttpChannelParent::TryInvokeAsyncOpen [this=%p barrier=%u rv=%" PRIx32
169 : "]\n", this, mAsyncOpenBarrier, static_cast<uint32_t>(aRv)));
170 3 : MOZ_ASSERT(NS_IsMainThread());
171 :
172 : // TryInvokeAsyncOpen is called more than we expected.
173 : // Assert in nightly build but ignore it in release channel.
174 3 : MOZ_DIAGNOSTIC_ASSERT(mAsyncOpenBarrier > 0);
175 3 : if (NS_WARN_IF(!mAsyncOpenBarrier)) {
176 0 : return;
177 : }
178 :
179 3 : if (--mAsyncOpenBarrier > 0 && NS_SUCCEEDED(aRv)) {
180 : // Need to wait for more events.
181 0 : return;
182 : }
183 :
184 3 : InvokeAsyncOpen(aRv);
185 : }
186 :
187 : void
188 3 : HttpChannelParent::OnBackgroundParentReady(
189 : HttpBackgroundChannelParent* aBgParent)
190 : {
191 3 : LOG(("HttpChannelParent::OnBackgroundParentReady [this=%p bgParent=%p]\n",
192 : this, aBgParent));
193 3 : MOZ_ASSERT(NS_IsMainThread());
194 3 : MOZ_ASSERT(!mBgParent);
195 :
196 3 : mBgParent = aBgParent;
197 :
198 3 : mPromise.ResolveIfExists(true, __func__);
199 3 : }
200 :
201 : void
202 3 : HttpChannelParent::OnBackgroundParentDestroyed()
203 : {
204 3 : LOG(("HttpChannelParent::OnBackgroundParentDestroyed [this=%p]\n", this));
205 3 : MOZ_ASSERT(NS_IsMainThread());
206 :
207 3 : if (!mPromise.IsEmpty()) {
208 0 : MOZ_ASSERT(!mBgParent);
209 0 : mPromise.Reject(NS_ERROR_FAILURE, __func__);
210 0 : return;
211 : }
212 :
213 3 : if (!mBgParent) {
214 3 : return;
215 : }
216 :
217 : // Background channel is closed unexpectly, abort PHttpChannel operation.
218 0 : mBgParent = nullptr;
219 0 : Delete();
220 : }
221 :
222 : void
223 7 : HttpChannelParent::CleanupBackgroundChannel()
224 : {
225 7 : LOG(("HttpChannelParent::CleanupBackgroundChannel [this=%p bgParent=%p]\n",
226 : this, mBgParent.get()));
227 7 : MOZ_ASSERT(NS_IsMainThread());
228 :
229 7 : if (mBgParent) {
230 6 : RefPtr<HttpBackgroundChannelParent> bgParent = mBgParent.forget();
231 3 : bgParent->OnChannelClosed();
232 3 : return;
233 : }
234 :
235 4 : if (!mPromise.IsEmpty()) {
236 0 : mRequest.DisconnectIfExists();
237 0 : mPromise.Reject(NS_ERROR_FAILURE, __func__);
238 :
239 0 : if (!mChannel) {
240 0 : return;
241 : }
242 :
243 : // This HttpChannelParent might still have a reference from
244 : // BackgroundChannelRegistrar.
245 : nsCOMPtr<nsIBackgroundChannelRegistrar> registrar =
246 0 : do_GetService(NS_BACKGROUNDCHANNELREGISTRAR_CONTRACTID);
247 0 : MOZ_ASSERT(registrar);
248 :
249 0 : registrar->DeleteChannel(mChannel->ChannelId());
250 :
251 : // If mAsyncOpenBarrier is greater than zero, it means AsyncOpen procedure
252 : // is still on going. we need to abort AsyncOpen with failure to destroy
253 : // PHttpChannel actor.
254 0 : if (mAsyncOpenBarrier) {
255 0 : TryInvokeAsyncOpen(NS_ERROR_FAILURE);
256 : }
257 : }
258 : }
259 :
260 : //-----------------------------------------------------------------------------
261 : // HttpChannelParent::nsISupports
262 : //-----------------------------------------------------------------------------
263 :
264 101 : NS_IMPL_ADDREF(HttpChannelParent)
265 100 : NS_IMPL_RELEASE(HttpChannelParent)
266 84 : NS_INTERFACE_MAP_BEGIN(HttpChannelParent)
267 84 : NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
268 16 : NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)
269 10 : NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
270 10 : NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
271 7 : NS_INTERFACE_MAP_ENTRY(nsIParentChannel)
272 5 : NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)
273 5 : NS_INTERFACE_MAP_ENTRY(nsIParentRedirectingChannel)
274 5 : NS_INTERFACE_MAP_ENTRY(nsIDeprecationWarner)
275 5 : NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectReadyCallback)
276 5 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIParentRedirectingChannel)
277 5 : if (aIID.Equals(NS_GET_IID(HttpChannelParent))) {
278 1 : foundInterface = static_cast<nsIInterfaceRequestor*>(this);
279 : } else
280 4 : NS_INTERFACE_MAP_END
281 :
282 : //-----------------------------------------------------------------------------
283 : // HttpChannelParent::nsIInterfaceRequestor
284 : //-----------------------------------------------------------------------------
285 :
286 : NS_IMETHODIMP
287 34 : HttpChannelParent::GetInterface(const nsIID& aIID, void **result)
288 : {
289 68 : if (aIID.Equals(NS_GET_IID(nsIAuthPromptProvider)) ||
290 34 : aIID.Equals(NS_GET_IID(nsISecureBrowserUI))) {
291 0 : if (mTabParent) {
292 0 : return mTabParent->QueryInterface(aIID, result);
293 : }
294 : }
295 :
296 : // Only support nsIAuthPromptProvider in Content process
297 68 : if (XRE_IsParentProcess() &&
298 34 : aIID.Equals(NS_GET_IID(nsIAuthPromptProvider))) {
299 0 : *result = nullptr;
300 0 : return NS_OK;
301 : }
302 :
303 : // Only support nsILoadContext if child channel's callbacks did too
304 34 : if (aIID.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
305 52 : nsCOMPtr<nsILoadContext> copy = mLoadContext;
306 26 : copy.forget(result);
307 26 : return NS_OK;
308 : }
309 :
310 8 : if (mTabParent && aIID.Equals(NS_GET_IID(nsIPrompt))) {
311 0 : nsCOMPtr<Element> frameElement = mTabParent->GetOwnerElement();
312 0 : if (frameElement) {
313 0 : nsCOMPtr<nsPIDOMWindowOuter> win =frameElement->OwnerDoc()->GetWindow();
314 0 : NS_ENSURE_TRUE(win, NS_ERROR_UNEXPECTED);
315 :
316 : nsresult rv;
317 : nsCOMPtr<nsIWindowWatcher> wwatch =
318 0 : do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
319 :
320 0 : if (NS_WARN_IF(!NS_SUCCEEDED(rv))) {
321 0 : return rv;
322 : }
323 :
324 0 : nsCOMPtr<nsIPrompt> prompt;
325 0 : rv = wwatch->GetNewPrompter(win, getter_AddRefs(prompt));
326 0 : if (NS_WARN_IF(!NS_SUCCEEDED(rv))) {
327 0 : return rv;
328 : }
329 :
330 0 : prompt.forget(result);
331 0 : return NS_OK;
332 : }
333 : }
334 :
335 8 : return QueryInterface(aIID, result);
336 : }
337 :
338 : //-----------------------------------------------------------------------------
339 : // HttpChannelParent::PHttpChannelParent
340 : //-----------------------------------------------------------------------------
341 :
342 : void
343 0 : HttpChannelParent::AsyncOpenFailed(nsresult aRv)
344 : {
345 0 : MOZ_ASSERT(NS_IsMainThread());
346 0 : MOZ_ASSERT(NS_FAILED(aRv));
347 :
348 : // Break the reference cycle among HttpChannelParent,
349 : // HttpChannelParentListener, and nsHttpChannel to avoid memory leakage.
350 0 : mChannel = nullptr;
351 0 : mParentListener = nullptr;
352 :
353 0 : if (!mIPCClosed) {
354 0 : Unused << SendFailedAsyncOpen(aRv);
355 : }
356 0 : }
357 :
358 : void
359 3 : HttpChannelParent::InvokeAsyncOpen(nsresult rv)
360 : {
361 3 : LOG(("HttpChannelParent::InvokeAsyncOpen [this=%p rv=%" PRIx32 "]\n",
362 : this, static_cast<uint32_t>(rv)));
363 3 : MOZ_ASSERT(NS_IsMainThread());
364 :
365 3 : if (NS_FAILED(rv)) {
366 0 : AsyncOpenFailed(rv);
367 0 : return;
368 : }
369 :
370 6 : nsCOMPtr<nsILoadInfo> loadInfo;
371 3 : rv = mChannel->GetLoadInfo(getter_AddRefs(loadInfo));
372 3 : if (NS_FAILED(rv)) {
373 0 : AsyncOpenFailed(rv);
374 0 : return;
375 : }
376 3 : if (loadInfo && loadInfo->GetEnforceSecurity()) {
377 3 : rv = mChannel->AsyncOpen2(mParentListener);
378 : }
379 : else {
380 0 : rv = mChannel->AsyncOpen(mParentListener, nullptr);
381 : }
382 3 : if (NS_FAILED(rv)) {
383 0 : AsyncOpenFailed(rv);
384 : }
385 : }
386 :
387 : namespace {
388 0 : class InvokeAsyncOpen : public Runnable
389 : {
390 : nsMainThreadPtrHandle<nsIInterfaceRequestor> mChannel;
391 : nsresult mStatus;
392 : public:
393 0 : InvokeAsyncOpen(const nsMainThreadPtrHandle<nsIInterfaceRequestor>& aChannel,
394 : nsresult aStatus)
395 0 : : Runnable("net::InvokeAsyncOpen")
396 : , mChannel(aChannel)
397 0 : , mStatus(aStatus)
398 : {
399 0 : }
400 :
401 0 : NS_IMETHOD Run()
402 : {
403 0 : RefPtr<HttpChannelParent> channel = do_QueryObject(mChannel.get());
404 0 : channel->TryInvokeAsyncOpen(mStatus);
405 0 : return NS_OK;
406 : }
407 : };
408 :
409 0 : struct UploadStreamClosure {
410 : nsMainThreadPtrHandle<nsIInterfaceRequestor> mChannel;
411 :
412 0 : explicit UploadStreamClosure(const nsMainThreadPtrHandle<nsIInterfaceRequestor>& aChannel)
413 0 : : mChannel(aChannel)
414 : {
415 0 : }
416 : };
417 :
418 : void
419 0 : UploadCopyComplete(void* aClosure, nsresult aStatus) {
420 : // Called on the Stream Transport Service thread by NS_AsyncCopy
421 0 : MOZ_ASSERT(!NS_IsMainThread());
422 0 : UniquePtr<UploadStreamClosure> closure(static_cast<UploadStreamClosure*>(aClosure));
423 0 : nsCOMPtr<nsIRunnable> event = new InvokeAsyncOpen(closure->mChannel, aStatus);
424 0 : NS_DispatchToMainThread(event);
425 0 : }
426 : } // anonymous namespace
427 :
428 : bool
429 3 : HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
430 : const OptionalURIParams& aOriginalURI,
431 : const OptionalURIParams& aDocURI,
432 : const OptionalURIParams& aReferrerURI,
433 : const uint32_t& aReferrerPolicy,
434 : const OptionalURIParams& aAPIRedirectToURI,
435 : const OptionalURIParams& aTopWindowURI,
436 : const uint32_t& aLoadFlags,
437 : const RequestHeaderTuples& requestHeaders,
438 : const nsCString& requestMethod,
439 : const OptionalIPCStream& uploadStream,
440 : const bool& uploadStreamHasHeaders,
441 : const int16_t& priority,
442 : const uint32_t& classOfService,
443 : const uint8_t& redirectionLimit,
444 : const bool& allowSTS,
445 : const uint32_t& thirdPartyFlags,
446 : const bool& doResumeAt,
447 : const uint64_t& startPos,
448 : const nsCString& entityID,
449 : const bool& chooseApplicationCache,
450 : const nsCString& appCacheClientID,
451 : const bool& allowSpdy,
452 : const bool& allowAltSvc,
453 : const bool& beConservative,
454 : const OptionalLoadInfoArgs& aLoadInfoArgs,
455 : const OptionalHttpResponseHead& aSynthesizedResponseHead,
456 : const nsCString& aSecurityInfoSerialization,
457 : const uint32_t& aCacheKey,
458 : const uint64_t& aRequestContextID,
459 : const OptionalCorsPreflightArgs& aCorsPreflightArgs,
460 : const uint32_t& aInitialRwin,
461 : const bool& aBlockAuthPrompt,
462 : const bool& aSuspendAfterSynthesizeResponse,
463 : const bool& aAllowStaleCacheContent,
464 : const nsCString& aContentTypeHint,
465 : const uint64_t& aChannelId,
466 : const uint64_t& aContentWindowId,
467 : const nsCString& aPreferredAlternativeType,
468 : const uint64_t& aTopLevelOuterContentWindowId,
469 : const TimeStamp& aLaunchServiceWorkerStart,
470 : const TimeStamp& aLaunchServiceWorkerEnd,
471 : const TimeStamp& aDispatchFetchEventStart,
472 : const TimeStamp& aDispatchFetchEventEnd,
473 : const TimeStamp& aHandleFetchEventStart,
474 : const TimeStamp& aHandleFetchEventEnd)
475 : {
476 6 : nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
477 3 : if (!uri) {
478 : // URIParams does MOZ_ASSERT if null, but we need to protect opt builds from
479 : // null deref here.
480 0 : return false;
481 : }
482 6 : nsCOMPtr<nsIURI> originalUri = DeserializeURI(aOriginalURI);
483 6 : nsCOMPtr<nsIURI> docUri = DeserializeURI(aDocURI);
484 6 : nsCOMPtr<nsIURI> referrerUri = DeserializeURI(aReferrerURI);
485 6 : nsCOMPtr<nsIURI> apiRedirectToUri = DeserializeURI(aAPIRedirectToURI);
486 6 : nsCOMPtr<nsIURI> topWindowUri = DeserializeURI(aTopWindowURI);
487 :
488 3 : LOG(("HttpChannelParent RecvAsyncOpen [this=%p uri=%s]\n",
489 : this, uri->GetSpecOrDefault().get()));
490 :
491 : nsresult rv;
492 :
493 6 : nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
494 3 : if (NS_FAILED(rv))
495 0 : return SendFailedAsyncOpen(rv);
496 :
497 6 : nsCOMPtr<nsILoadInfo> loadInfo;
498 3 : rv = mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfoArgs,
499 6 : getter_AddRefs(loadInfo));
500 3 : if (NS_FAILED(rv)) {
501 0 : return SendFailedAsyncOpen(rv);
502 : }
503 :
504 3 : if (!loadInfo) {
505 0 : return SendFailedAsyncOpen(NS_ERROR_UNEXPECTED);
506 : }
507 :
508 6 : nsCOMPtr<nsIChannel> channel;
509 3 : rv = NS_NewChannelInternal(getter_AddRefs(channel), uri, loadInfo,
510 : nullptr, nullptr, aLoadFlags, ios);
511 3 : if (NS_FAILED(rv)) {
512 0 : return SendFailedAsyncOpen(rv);
513 : }
514 :
515 6 : RefPtr<nsHttpChannel> httpChannel = do_QueryObject(channel, &rv);
516 3 : if (NS_FAILED(rv)) {
517 0 : return SendFailedAsyncOpen(rv);
518 : }
519 :
520 : // Set the channelId allocated in child to the parent instance
521 3 : httpChannel->SetChannelId(aChannelId);
522 3 : httpChannel->SetTopLevelContentWindowId(aContentWindowId);
523 3 : httpChannel->SetTopLevelOuterContentWindowId(aTopLevelOuterContentWindowId);
524 :
525 3 : httpChannel->SetWarningReporter(this);
526 3 : httpChannel->SetTimingEnabled(true);
527 3 : if (mPBOverride != kPBOverride_Unset) {
528 0 : httpChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
529 : }
530 :
531 3 : if (doResumeAt)
532 0 : httpChannel->ResumeAt(startPos, entityID);
533 :
534 3 : if (originalUri)
535 3 : httpChannel->SetOriginalURI(originalUri);
536 3 : if (docUri)
537 1 : httpChannel->SetDocumentURI(docUri);
538 3 : if (referrerUri) {
539 2 : rv = httpChannel->SetReferrerWithPolicyInternal(referrerUri, aReferrerPolicy);
540 2 : MOZ_ASSERT(NS_SUCCEEDED(rv));
541 : }
542 3 : if (apiRedirectToUri)
543 0 : httpChannel->RedirectTo(apiRedirectToUri);
544 3 : if (topWindowUri) {
545 2 : rv = httpChannel->SetTopWindowURI(topWindowUri);
546 2 : MOZ_ASSERT(NS_SUCCEEDED(rv));
547 : }
548 3 : if (aLoadFlags != nsIRequest::LOAD_NORMAL)
549 3 : httpChannel->SetLoadFlags(aLoadFlags);
550 :
551 10 : for (uint32_t i = 0; i < requestHeaders.Length(); i++) {
552 7 : if (requestHeaders[i].mEmpty) {
553 0 : httpChannel->SetEmptyRequestHeader(requestHeaders[i].mHeader);
554 : } else {
555 21 : httpChannel->SetRequestHeader(requestHeaders[i].mHeader,
556 7 : requestHeaders[i].mValue,
557 14 : requestHeaders[i].mMerge);
558 : }
559 : }
560 :
561 : RefPtr<HttpChannelParentListener> parentListener
562 6 : = new HttpChannelParentListener(this);
563 :
564 3 : httpChannel->SetRequestMethod(nsDependentCString(requestMethod.get()));
565 :
566 3 : if (aCorsPreflightArgs.type() == OptionalCorsPreflightArgs::TCorsPreflightArgs) {
567 0 : const CorsPreflightArgs& args = aCorsPreflightArgs.get_CorsPreflightArgs();
568 0 : httpChannel->SetCorsPreflightParameters(args.unsafeHeaders());
569 : }
570 :
571 6 : nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(uploadStream);
572 3 : if (stream) {
573 : // FIXME: The fast path of using the existing stream currently only applies to streams
574 : // that have had their entire contents serialized from the child at this point.
575 : // Once bug 1294446 and bug 1294450 are fixed it is worth revisiting this heuristic.
576 0 : nsCOMPtr<nsIIPCSerializableInputStream> completeStream = do_QueryInterface(stream);
577 0 : if (!completeStream) {
578 : // Wait for completion of async copying IPC upload stream to a local input stream.
579 0 : ++mAsyncOpenBarrier;
580 :
581 : // buffer size matches PChildToParentStream transfer size.
582 0 : const uint32_t kBufferSize = 32768;
583 :
584 0 : nsCOMPtr<nsIStorageStream> storageStream;
585 0 : nsresult rv = NS_NewStorageStream(kBufferSize, UINT32_MAX,
586 0 : getter_AddRefs(storageStream));
587 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
588 0 : return SendFailedAsyncOpen(rv);
589 : }
590 :
591 0 : nsCOMPtr<nsIInputStream> newUploadStream;
592 0 : rv = storageStream->NewInputStream(0, getter_AddRefs(newUploadStream));
593 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
594 0 : return SendFailedAsyncOpen(rv);
595 : }
596 :
597 0 : nsCOMPtr<nsIOutputStream> sink;
598 0 : rv = storageStream->GetOutputStream(0, getter_AddRefs(sink));
599 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
600 0 : return SendFailedAsyncOpen(rv);
601 : }
602 :
603 : nsCOMPtr<nsIEventTarget> target =
604 0 : do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
605 0 : if (NS_FAILED(rv) || !target) {
606 0 : return SendFailedAsyncOpen(rv);
607 : }
608 :
609 0 : nsCOMPtr<nsIInterfaceRequestor> iir = static_cast<nsIInterfaceRequestor*>(this);
610 : nsMainThreadPtrHandle<nsIInterfaceRequestor> handle =
611 : nsMainThreadPtrHandle<nsIInterfaceRequestor>(
612 : new nsMainThreadPtrHolder<nsIInterfaceRequestor>(
613 0 : "nsIInterfaceRequestor", iir));
614 0 : UniquePtr<UploadStreamClosure> closure(new UploadStreamClosure(handle));
615 :
616 : // Accumulate the stream contents as the child sends it. We will continue with
617 : // the AsyncOpen process once the full stream has been received.
618 0 : rv = NS_AsyncCopy(stream, sink, target, NS_ASYNCCOPY_VIA_READSEGMENTS,
619 : kBufferSize, // copy segment size
620 0 : UploadCopyComplete, closure.release());
621 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
622 0 : return SendFailedAsyncOpen(rv);
623 : }
624 :
625 0 : httpChannel->InternalSetUploadStream(newUploadStream);
626 : } else {
627 0 : httpChannel->InternalSetUploadStream(stream);
628 : }
629 0 : httpChannel->SetUploadStreamHasHeaders(uploadStreamHasHeaders);
630 : }
631 :
632 3 : if (aSynthesizedResponseHead.type() == OptionalHttpResponseHead::TnsHttpResponseHead) {
633 0 : parentListener->SetupInterception(aSynthesizedResponseHead.get_nsHttpResponseHead());
634 0 : mWillSynthesizeResponse = true;
635 0 : httpChannel->SetCouldBeSynthesized();
636 :
637 0 : if (!aSecurityInfoSerialization.IsEmpty()) {
638 0 : nsCOMPtr<nsISupports> secInfo;
639 0 : NS_DeserializeObject(aSecurityInfoSerialization, getter_AddRefs(secInfo));
640 0 : rv = httpChannel->OverrideSecurityInfo(secInfo);
641 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
642 : }
643 : } else {
644 : nsLoadFlags newLoadFlags;
645 3 : httpChannel->GetLoadFlags(&newLoadFlags);
646 3 : newLoadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
647 3 : httpChannel->SetLoadFlags(newLoadFlags);
648 : }
649 :
650 : nsCOMPtr<nsISupportsPRUint32> cacheKey =
651 6 : do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
652 3 : if (NS_FAILED(rv)) {
653 0 : return SendFailedAsyncOpen(rv);
654 : }
655 :
656 3 : rv = cacheKey->SetData(aCacheKey);
657 3 : if (NS_FAILED(rv)) {
658 0 : return SendFailedAsyncOpen(rv);
659 : }
660 :
661 3 : httpChannel->SetCacheKey(cacheKey);
662 3 : httpChannel->PreferAlternativeDataType(aPreferredAlternativeType);
663 :
664 3 : httpChannel->SetAllowStaleCacheContent(aAllowStaleCacheContent);
665 :
666 3 : httpChannel->SetContentType(aContentTypeHint);
667 :
668 3 : if (priority != nsISupportsPriority::PRIORITY_NORMAL) {
669 0 : httpChannel->SetPriority(priority);
670 : }
671 3 : if (classOfService) {
672 3 : httpChannel->SetClassFlags(classOfService);
673 : }
674 3 : httpChannel->SetRedirectionLimit(redirectionLimit);
675 3 : httpChannel->SetAllowSTS(allowSTS);
676 3 : httpChannel->SetThirdPartyFlags(thirdPartyFlags);
677 3 : httpChannel->SetAllowSpdy(allowSpdy);
678 3 : httpChannel->SetAllowAltSvc(allowAltSvc);
679 3 : httpChannel->SetBeConservative(beConservative);
680 3 : httpChannel->SetInitialRwin(aInitialRwin);
681 3 : httpChannel->SetBlockAuthPrompt(aBlockAuthPrompt);
682 :
683 3 : httpChannel->SetLaunchServiceWorkerStart(aLaunchServiceWorkerStart);
684 3 : httpChannel->SetLaunchServiceWorkerEnd(aLaunchServiceWorkerEnd);
685 3 : httpChannel->SetDispatchFetchEventStart(aDispatchFetchEventStart);
686 3 : httpChannel->SetDispatchFetchEventEnd(aDispatchFetchEventEnd);
687 3 : httpChannel->SetHandleFetchEventStart(aHandleFetchEventStart);
688 3 : httpChannel->SetHandleFetchEventEnd(aHandleFetchEventEnd);
689 :
690 : nsCOMPtr<nsIApplicationCacheChannel> appCacheChan =
691 6 : do_QueryObject(httpChannel);
692 : nsCOMPtr<nsIApplicationCacheService> appCacheService =
693 6 : do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
694 :
695 3 : bool setChooseApplicationCache = chooseApplicationCache;
696 3 : if (appCacheChan && appCacheService) {
697 : // We might potentially want to drop this flag (that is TRUE by default)
698 : // after we successfully associate the channel with an application cache
699 : // reported by the channel child. Dropping it here may be too early.
700 3 : appCacheChan->SetInheritApplicationCache(false);
701 3 : if (!appCacheClientID.IsEmpty()) {
702 0 : nsCOMPtr<nsIApplicationCache> appCache;
703 0 : rv = appCacheService->GetApplicationCache(appCacheClientID,
704 0 : getter_AddRefs(appCache));
705 0 : if (NS_SUCCEEDED(rv)) {
706 0 : appCacheChan->SetApplicationCache(appCache);
707 0 : setChooseApplicationCache = false;
708 : }
709 : }
710 :
711 3 : if (setChooseApplicationCache) {
712 2 : OriginAttributes attrs;
713 1 : NS_GetOriginAttributes(httpChannel, attrs);
714 :
715 : nsCOMPtr<nsIPrincipal> principal =
716 2 : BasePrincipal::CreateCodebasePrincipal(uri, attrs);
717 :
718 1 : bool chooseAppCache = false;
719 : // This works because we've already called SetNotificationCallbacks and
720 : // done mPBOverride logic by this point.
721 1 : chooseAppCache = NS_ShouldCheckAppCache(principal);
722 :
723 1 : appCacheChan->SetChooseApplicationCache(chooseAppCache);
724 : }
725 : }
726 :
727 3 : httpChannel->SetRequestContextID(aRequestContextID);
728 :
729 : // Store the strong reference of channel and parent listener object until
730 : // all the initialization procedure is complete without failure, to remove
731 : // cycle reference in fail case and to avoid memory leakage.
732 3 : mChannel = httpChannel.forget();
733 3 : mParentListener = parentListener.forget();
734 3 : mChannel->SetNotificationCallbacks(mParentListener);
735 :
736 :
737 3 : mSuspendAfterSynthesizeResponse = aSuspendAfterSynthesizeResponse;
738 :
739 3 : MOZ_ASSERT(!mBgParent);
740 3 : MOZ_ASSERT(mPromise.IsEmpty());
741 : // Wait for HttpBackgrounChannel to continue the async open procedure.
742 3 : ++mAsyncOpenBarrier;
743 6 : RefPtr<GenericPromise> promise = WaitForBgParent();
744 6 : RefPtr<HttpChannelParent> self = this;
745 6 : promise->Then(GetMainThreadSerialEventTarget(), __func__,
746 12 : [self]() {
747 3 : self->mRequest.Complete();
748 3 : self->TryInvokeAsyncOpen(NS_OK);
749 3 : },
750 9 : [self](nsresult aStatus) {
751 0 : self->mRequest.Complete();
752 0 : self->TryInvokeAsyncOpen(aStatus);
753 0 : })
754 6 : ->Track(mRequest);
755 :
756 3 : return true;
757 : }
758 :
759 : already_AddRefed<GenericPromise>
760 3 : HttpChannelParent::WaitForBgParent()
761 : {
762 3 : LOG(("HttpChannelParent::WaitForBgParent [this=%p]\n", this));
763 3 : MOZ_ASSERT(!mBgParent);
764 3 : MOZ_ASSERT(mChannel);
765 :
766 :
767 : nsCOMPtr<nsIBackgroundChannelRegistrar> registrar =
768 6 : do_GetService(NS_BACKGROUNDCHANNELREGISTRAR_CONTRACTID);
769 3 : MOZ_ASSERT(registrar);
770 3 : registrar->LinkHttpChannel(mChannel->ChannelId(), this);
771 :
772 3 : if (mBgParent) {
773 0 : already_AddRefed<GenericPromise> promise = mPromise.Ensure(__func__);
774 : // resolve promise immediatedly if bg channel is ready.
775 0 : mPromise.Resolve(true, __func__);
776 0 : return promise;
777 : }
778 :
779 3 : return mPromise.Ensure(__func__);;
780 : }
781 :
782 : bool
783 0 : HttpChannelParent::ConnectChannel(const uint32_t& registrarId, const bool& shouldIntercept)
784 : {
785 : nsresult rv;
786 :
787 0 : LOG(("HttpChannelParent::ConnectChannel: Looking for a registered channel "
788 : "[this=%p, id=%" PRIu32 "]\n", this, registrarId));
789 0 : nsCOMPtr<nsIChannel> channel;
790 0 : rv = NS_LinkRedirectChannels(registrarId, this, getter_AddRefs(channel));
791 0 : if (NS_FAILED(rv)) {
792 0 : NS_ERROR("Could not find the http channel to connect its IPC parent");
793 : // This makes the channel delete itself safely. It's the only thing
794 : // we can do now, since this parent channel cannot be used and there is
795 : // no other way to tell the child side there were something wrong.
796 0 : Delete();
797 0 : return true;
798 : }
799 :
800 0 : LOG((" found channel %p, rv=%08" PRIx32, channel.get(), static_cast<uint32_t>(rv)));
801 0 : mChannel = do_QueryObject(channel);
802 0 : if (!mChannel) {
803 0 : LOG((" but it's not nsHttpChannel"));
804 0 : Delete();
805 0 : return true;
806 : }
807 :
808 0 : nsCOMPtr<nsINetworkInterceptController> controller;
809 0 : NS_QueryNotificationCallbacks(channel, controller);
810 0 : RefPtr<HttpChannelParentListener> parentListener = do_QueryObject(controller);
811 0 : MOZ_ASSERT(parentListener);
812 0 : parentListener->SetupInterceptionAfterRedirect(shouldIntercept);
813 :
814 0 : if (mPBOverride != kPBOverride_Unset) {
815 : // redirected-to channel may not support PB
816 0 : nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryObject(mChannel);
817 0 : if (pbChannel) {
818 0 : pbChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
819 : }
820 : }
821 :
822 0 : MOZ_ASSERT(!mBgParent);
823 0 : MOZ_ASSERT(mPromise.IsEmpty());
824 : // Waiting for background channel
825 0 : RefPtr<GenericPromise> promise = WaitForBgParent();
826 0 : RefPtr<HttpChannelParent> self = this;
827 0 : promise->Then(GetMainThreadSerialEventTarget(), __func__,
828 0 : [self]() {
829 0 : self->mRequest.Complete();
830 0 : },
831 0 : [self](const nsresult& aResult) {
832 0 : NS_ERROR("failed to establish the background channel");
833 0 : self->mRequest.Complete();
834 0 : })
835 0 : ->Track(mRequest);
836 0 : return true;
837 : }
838 :
839 : mozilla::ipc::IPCResult
840 0 : HttpChannelParent::RecvSetPriority(const int16_t& priority)
841 : {
842 0 : LOG(("HttpChannelParent::RecvSetPriority [this=%p, priority=%d]\n",
843 : this, priority));
844 :
845 0 : if (mChannel) {
846 0 : mChannel->SetPriority(priority);
847 : }
848 :
849 : nsCOMPtr<nsISupportsPriority> priorityRedirectChannel =
850 0 : do_QueryInterface(mRedirectChannel);
851 0 : if (priorityRedirectChannel)
852 0 : priorityRedirectChannel->SetPriority(priority);
853 :
854 0 : return IPC_OK();
855 : }
856 :
857 : mozilla::ipc::IPCResult
858 0 : HttpChannelParent::RecvSetClassOfService(const uint32_t& cos)
859 : {
860 0 : if (mChannel) {
861 0 : mChannel->SetClassFlags(cos);
862 : }
863 0 : return IPC_OK();
864 : }
865 :
866 : mozilla::ipc::IPCResult
867 0 : HttpChannelParent::RecvSuspend()
868 : {
869 0 : LOG(("HttpChannelParent::RecvSuspend [this=%p]\n", this));
870 :
871 0 : if (mChannel) {
872 0 : mChannel->Suspend();
873 : }
874 0 : return IPC_OK();
875 : }
876 :
877 : mozilla::ipc::IPCResult
878 0 : HttpChannelParent::RecvResume()
879 : {
880 0 : LOG(("HttpChannelParent::RecvResume [this=%p]\n", this));
881 :
882 0 : if (mChannel) {
883 0 : mChannel->Resume();
884 : }
885 0 : return IPC_OK();
886 : }
887 :
888 : mozilla::ipc::IPCResult
889 0 : HttpChannelParent::RecvCancel(const nsresult& status)
890 : {
891 0 : LOG(("HttpChannelParent::RecvCancel [this=%p]\n", this));
892 :
893 : // May receive cancel before channel has been constructed!
894 0 : if (mChannel) {
895 0 : mChannel->Cancel(status);
896 : }
897 0 : return IPC_OK();
898 : }
899 :
900 :
901 : mozilla::ipc::IPCResult
902 0 : HttpChannelParent::RecvSetCacheTokenCachedCharset(const nsCString& charset)
903 : {
904 0 : if (mCacheEntry)
905 0 : mCacheEntry->SetMetaDataElement("charset", charset.get());
906 0 : return IPC_OK();
907 : }
908 :
909 : mozilla::ipc::IPCResult
910 0 : HttpChannelParent::RecvUpdateAssociatedContentSecurity(const int32_t& broken,
911 : const int32_t& no)
912 : {
913 0 : if (mAssociatedContentSecurity) {
914 0 : mAssociatedContentSecurity->SetCountSubRequestsBrokenSecurity(broken);
915 0 : mAssociatedContentSecurity->SetCountSubRequestsNoSecurity(no);
916 : }
917 0 : return IPC_OK();
918 : }
919 :
920 : mozilla::ipc::IPCResult
921 0 : HttpChannelParent::RecvRedirect2Verify(const nsresult& result,
922 : const RequestHeaderTuples& changedHeaders,
923 : const uint32_t& loadFlags,
924 : const uint32_t& referrerPolicy,
925 : const OptionalURIParams& aReferrerURI,
926 : const OptionalURIParams& aAPIRedirectURI,
927 : const OptionalCorsPreflightArgs& aCorsPreflightArgs,
928 : const bool& aForceHSTSPriming,
929 : const bool& aMixedContentWouldBlock,
930 : const bool& aChooseAppcache)
931 : {
932 0 : LOG(("HttpChannelParent::RecvRedirect2Verify [this=%p result=%" PRIx32 "]\n",
933 : this, static_cast<uint32_t>(result)));
934 : nsresult rv;
935 0 : if (NS_SUCCEEDED(result)) {
936 : nsCOMPtr<nsIHttpChannel> newHttpChannel =
937 0 : do_QueryInterface(mRedirectChannel);
938 :
939 0 : if (newHttpChannel) {
940 0 : nsCOMPtr<nsIURI> apiRedirectUri = DeserializeURI(aAPIRedirectURI);
941 :
942 0 : if (apiRedirectUri) {
943 0 : rv = newHttpChannel->RedirectTo(apiRedirectUri);
944 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
945 : }
946 :
947 0 : for (uint32_t i = 0; i < changedHeaders.Length(); i++) {
948 0 : if (changedHeaders[i].mEmpty) {
949 0 : rv = newHttpChannel->SetEmptyRequestHeader(changedHeaders[i].mHeader);
950 : } else {
951 0 : rv = newHttpChannel->SetRequestHeader(changedHeaders[i].mHeader,
952 0 : changedHeaders[i].mValue,
953 0 : changedHeaders[i].mMerge);
954 : }
955 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
956 : }
957 :
958 : // A successfully redirected channel must have the LOAD_REPLACE flag.
959 0 : MOZ_ASSERT(loadFlags & nsIChannel::LOAD_REPLACE);
960 0 : if (loadFlags & nsIChannel::LOAD_REPLACE) {
961 0 : newHttpChannel->SetLoadFlags(loadFlags);
962 : }
963 :
964 0 : if (aCorsPreflightArgs.type() == OptionalCorsPreflightArgs::TCorsPreflightArgs) {
965 : nsCOMPtr<nsIHttpChannelInternal> newInternalChannel =
966 0 : do_QueryInterface(newHttpChannel);
967 0 : MOZ_RELEASE_ASSERT(newInternalChannel);
968 0 : const CorsPreflightArgs& args = aCorsPreflightArgs.get_CorsPreflightArgs();
969 0 : newInternalChannel->SetCorsPreflightParameters(args.unsafeHeaders());
970 : }
971 :
972 0 : if (aForceHSTSPriming) {
973 0 : nsCOMPtr<nsILoadInfo> newLoadInfo;
974 0 : rv = newHttpChannel->GetLoadInfo(getter_AddRefs(newLoadInfo));
975 0 : if (NS_SUCCEEDED(rv) && newLoadInfo) {
976 0 : newLoadInfo->SetHSTSPriming(aMixedContentWouldBlock);
977 : }
978 : }
979 :
980 0 : nsCOMPtr<nsIURI> referrerUri = DeserializeURI(aReferrerURI);
981 0 : rv = newHttpChannel->SetReferrerWithPolicy(referrerUri, referrerPolicy);
982 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
983 :
984 : nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
985 0 : do_QueryInterface(newHttpChannel);
986 0 : if (appCacheChannel) {
987 0 : appCacheChannel->SetChooseApplicationCache(aChooseAppcache);
988 : }
989 : }
990 : }
991 :
992 : // Continue the verification procedure if child has veto the redirection.
993 0 : if (NS_FAILED(result)) {
994 0 : ContinueRedirect2Verify(result);
995 0 : return IPC_OK();
996 : }
997 :
998 : // Wait for background channel ready on target channel
999 : nsCOMPtr<nsIRedirectChannelRegistrar> redirectReg =
1000 0 : do_GetService(NS_REDIRECTCHANNELREGISTRAR_CONTRACTID);
1001 0 : MOZ_ASSERT(redirectReg);
1002 :
1003 0 : nsCOMPtr<nsIParentChannel> redirectParentChannel;
1004 0 : rv = redirectReg->GetParentChannel(mRedirectRegistrarId,
1005 0 : getter_AddRefs(redirectParentChannel));
1006 0 : MOZ_ASSERT(redirectParentChannel);
1007 0 : if (!redirectParentChannel) {
1008 0 : ContinueRedirect2Verify(rv);
1009 0 : return IPC_OK();
1010 : }
1011 :
1012 : nsCOMPtr<nsIParentRedirectingChannel> redirectedParent =
1013 0 : do_QueryInterface(redirectParentChannel);
1014 0 : if (!redirectedParent) {
1015 : // Continue verification procedure if redirecting to non-Http protocol
1016 0 : ContinueRedirect2Verify(result);
1017 0 : return IPC_OK();
1018 : }
1019 :
1020 : // Ask redirected channel if verification can proceed.
1021 : // ContinueRedirect2Verify will be invoked when redirected channel is ready.
1022 0 : redirectedParent->ContinueVerification(this);
1023 :
1024 0 : return IPC_OK();
1025 : }
1026 :
1027 : // from nsIParentRedirectingChannel
1028 : NS_IMETHODIMP
1029 0 : HttpChannelParent::ContinueVerification(nsIAsyncVerifyRedirectReadyCallback* aCallback)
1030 : {
1031 0 : LOG(("HttpChannelParent::ContinueVerification [this=%p callback=%p]\n",
1032 : this, aCallback));
1033 :
1034 0 : MOZ_ASSERT(NS_IsMainThread());
1035 0 : MOZ_ASSERT(aCallback);
1036 :
1037 : // Continue the verification procedure if background channel is ready.
1038 0 : if (mBgParent) {
1039 0 : aCallback->ReadyToVerify(NS_OK);
1040 0 : return NS_OK;
1041 : }
1042 :
1043 : // ConnectChannel must be received before Redirect2Verify.
1044 0 : MOZ_ASSERT(!mPromise.IsEmpty());
1045 :
1046 : // Otherwise, wait for the background channel.
1047 0 : RefPtr<GenericPromise> promise = WaitForBgParent();
1048 0 : nsCOMPtr<nsIAsyncVerifyRedirectReadyCallback> callback = aCallback;
1049 : promise->Then(GetMainThreadSerialEventTarget(), __func__,
1050 0 : [callback]() {
1051 0 : callback->ReadyToVerify(NS_OK);
1052 0 : },
1053 0 : [callback](const nsresult& aResult) {
1054 0 : NS_ERROR("failed to establish the background channel");
1055 0 : callback->ReadyToVerify(aResult);
1056 0 : });
1057 0 : return NS_OK;
1058 : }
1059 :
1060 : void
1061 0 : HttpChannelParent::ContinueRedirect2Verify(const nsresult& aResult)
1062 : {
1063 0 : LOG(("HttpChannelParent::ContinueRedirect2Verify [this=%p result=%" PRIx32 "]\n",
1064 : this, static_cast<uint32_t>(aResult)));
1065 :
1066 0 : if (!mRedirectCallback) {
1067 : // This should according the logic never happen, log the situation.
1068 0 : if (mReceivedRedirect2Verify)
1069 0 : LOG(("RecvRedirect2Verify[%p]: Duplicate fire", this));
1070 0 : if (mSentRedirect1BeginFailed)
1071 0 : LOG(("RecvRedirect2Verify[%p]: Send to child failed", this));
1072 0 : if ((mRedirectRegistrarId > 0) && NS_FAILED(aResult))
1073 0 : LOG(("RecvRedirect2Verify[%p]: Redirect failed", this));
1074 0 : if ((mRedirectRegistrarId > 0) && NS_SUCCEEDED(aResult))
1075 0 : LOG(("RecvRedirect2Verify[%p]: Redirect succeeded", this));
1076 0 : if (!mRedirectChannel)
1077 0 : LOG(("RecvRedirect2Verify[%p]: Missing redirect channel", this));
1078 :
1079 0 : NS_ERROR("Unexpcted call to HttpChannelParent::RecvRedirect2Verify, "
1080 : "mRedirectCallback null");
1081 : }
1082 :
1083 0 : mReceivedRedirect2Verify = true;
1084 :
1085 0 : if (mRedirectCallback) {
1086 0 : LOG(("HttpChannelParent::ContinueRedirect2Verify call OnRedirectVerifyCallback"
1087 : " [this=%p result=%" PRIx32 ", mRedirectCallback=%p]\n",
1088 : this, static_cast<uint32_t>(aResult), mRedirectCallback.get()));
1089 0 : mRedirectCallback->OnRedirectVerifyCallback(aResult);
1090 0 : mRedirectCallback = nullptr;
1091 : }
1092 0 : }
1093 :
1094 : mozilla::ipc::IPCResult
1095 1 : HttpChannelParent::RecvDocumentChannelCleanup()
1096 : {
1097 : // From now on only using mAssociatedContentSecurity. Free everything else.
1098 1 : CleanupBackgroundChannel(); // Background channel can be closed.
1099 1 : mChannel = nullptr; // Reclaim some memory sooner.
1100 1 : mCacheEntry = nullptr; // Else we'll block other channels reading same URI
1101 1 : return IPC_OK();
1102 : }
1103 :
1104 : mozilla::ipc::IPCResult
1105 0 : HttpChannelParent::RecvMarkOfflineCacheEntryAsForeign()
1106 : {
1107 0 : if (mOfflineForeignMarker) {
1108 0 : mOfflineForeignMarker->MarkAsForeign();
1109 0 : mOfflineForeignMarker = 0;
1110 : }
1111 :
1112 0 : return IPC_OK();
1113 : }
1114 :
1115 0 : class DivertDataAvailableEvent : public MainThreadChannelEvent
1116 : {
1117 : public:
1118 0 : DivertDataAvailableEvent(HttpChannelParent* aParent,
1119 : const nsCString& data,
1120 : const uint64_t& offset,
1121 : const uint32_t& count)
1122 0 : : mParent(aParent)
1123 : , mData(data)
1124 0 : , mOffset(offset)
1125 0 : , mCount(count)
1126 : {
1127 0 : }
1128 :
1129 0 : void Run()
1130 : {
1131 0 : mParent->DivertOnDataAvailable(mData, mOffset, mCount);
1132 0 : }
1133 :
1134 : private:
1135 : HttpChannelParent* mParent;
1136 : nsCString mData;
1137 : uint64_t mOffset;
1138 : uint32_t mCount;
1139 : };
1140 :
1141 : mozilla::ipc::IPCResult
1142 0 : HttpChannelParent::RecvDivertOnDataAvailable(const nsCString& data,
1143 : const uint64_t& offset,
1144 : const uint32_t& count)
1145 : {
1146 0 : LOG(("HttpChannelParent::RecvDivertOnDataAvailable [this=%p]\n", this));
1147 :
1148 0 : MOZ_ASSERT(mParentListener);
1149 0 : if (NS_WARN_IF(!mDivertingFromChild)) {
1150 0 : MOZ_ASSERT(mDivertingFromChild,
1151 : "Cannot RecvDivertOnDataAvailable if diverting is not set!");
1152 0 : FailDiversion(NS_ERROR_UNEXPECTED);
1153 0 : return IPC_FAIL_NO_REASON(this);
1154 : }
1155 :
1156 : // Drop OnDataAvailables if the parent was canceled already.
1157 0 : if (NS_FAILED(mStatus)) {
1158 0 : return IPC_OK();
1159 : }
1160 :
1161 0 : mEventQ->RunOrEnqueue(new DivertDataAvailableEvent(this, data, offset,
1162 0 : count));
1163 0 : return IPC_OK();
1164 : }
1165 :
1166 : void
1167 0 : HttpChannelParent::DivertOnDataAvailable(const nsCString& data,
1168 : const uint64_t& offset,
1169 : const uint32_t& count)
1170 : {
1171 0 : LOG(("HttpChannelParent::DivertOnDataAvailable [this=%p]\n", this));
1172 :
1173 0 : MOZ_ASSERT(mParentListener);
1174 0 : if (NS_WARN_IF(!mDivertingFromChild)) {
1175 0 : MOZ_ASSERT(mDivertingFromChild,
1176 : "Cannot DivertOnDataAvailable if diverting is not set!");
1177 0 : FailDiversion(NS_ERROR_UNEXPECTED);
1178 0 : return;
1179 : }
1180 :
1181 : // Drop OnDataAvailables if the parent was canceled already.
1182 0 : if (NS_FAILED(mStatus)) {
1183 0 : return;
1184 : }
1185 :
1186 0 : nsCOMPtr<nsIInputStream> stringStream;
1187 0 : nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), data.get(),
1188 0 : count, NS_ASSIGNMENT_DEPEND);
1189 0 : if (NS_FAILED(rv)) {
1190 0 : if (mChannel) {
1191 0 : mChannel->Cancel(rv);
1192 : }
1193 0 : mStatus = rv;
1194 0 : return;
1195 : }
1196 :
1197 0 : AutoEventEnqueuer ensureSerialDispatch(mEventQ);
1198 :
1199 0 : rv = mParentListener->OnDataAvailable(mChannel, nullptr, stringStream,
1200 0 : offset, count);
1201 0 : stringStream->Close();
1202 0 : if (NS_FAILED(rv)) {
1203 0 : if (mChannel) {
1204 0 : mChannel->Cancel(rv);
1205 : }
1206 0 : mStatus = rv;
1207 : }
1208 : }
1209 :
1210 0 : class DivertStopRequestEvent : public MainThreadChannelEvent
1211 : {
1212 : public:
1213 0 : DivertStopRequestEvent(HttpChannelParent* aParent,
1214 : const nsresult& statusCode)
1215 0 : : mParent(aParent)
1216 0 : , mStatusCode(statusCode)
1217 : {
1218 0 : }
1219 :
1220 0 : void Run() {
1221 0 : mParent->DivertOnStopRequest(mStatusCode);
1222 0 : }
1223 :
1224 : private:
1225 : HttpChannelParent* mParent;
1226 : nsresult mStatusCode;
1227 : };
1228 :
1229 : mozilla::ipc::IPCResult
1230 0 : HttpChannelParent::RecvDivertOnStopRequest(const nsresult& statusCode)
1231 : {
1232 0 : LOG(("HttpChannelParent::RecvDivertOnStopRequest [this=%p]\n", this));
1233 :
1234 0 : MOZ_ASSERT(mParentListener);
1235 0 : if (NS_WARN_IF(!mDivertingFromChild)) {
1236 0 : MOZ_ASSERT(mDivertingFromChild,
1237 : "Cannot RecvDivertOnStopRequest if diverting is not set!");
1238 0 : FailDiversion(NS_ERROR_UNEXPECTED);
1239 0 : return IPC_FAIL_NO_REASON(this);
1240 : }
1241 :
1242 0 : mEventQ->RunOrEnqueue(new DivertStopRequestEvent(this, statusCode));
1243 0 : return IPC_OK();
1244 : }
1245 :
1246 : void
1247 0 : HttpChannelParent::DivertOnStopRequest(const nsresult& statusCode)
1248 : {
1249 0 : LOG(("HttpChannelParent::DivertOnStopRequest [this=%p]\n", this));
1250 :
1251 0 : MOZ_ASSERT(mParentListener);
1252 0 : if (NS_WARN_IF(!mDivertingFromChild)) {
1253 0 : MOZ_ASSERT(mDivertingFromChild,
1254 : "Cannot DivertOnStopRequest if diverting is not set!");
1255 0 : FailDiversion(NS_ERROR_UNEXPECTED);
1256 0 : return;
1257 : }
1258 :
1259 : // Honor the channel's status even if the underlying transaction completed.
1260 0 : nsresult status = NS_FAILED(mStatus) ? mStatus : statusCode;
1261 :
1262 : // Reset fake pending status in case OnStopRequest has already been called.
1263 0 : if (mChannel) {
1264 0 : mChannel->ForcePending(false);
1265 : }
1266 :
1267 0 : AutoEventEnqueuer ensureSerialDispatch(mEventQ);
1268 0 : mParentListener->OnStopRequest(mChannel, nullptr, status);
1269 : }
1270 :
1271 0 : class DivertCompleteEvent : public MainThreadChannelEvent
1272 : {
1273 : public:
1274 0 : explicit DivertCompleteEvent(HttpChannelParent* aParent)
1275 0 : : mParent(aParent)
1276 : {
1277 0 : }
1278 :
1279 0 : void Run() {
1280 0 : mParent->DivertComplete();
1281 0 : }
1282 :
1283 : private:
1284 : HttpChannelParent* mParent;
1285 : };
1286 :
1287 : mozilla::ipc::IPCResult
1288 0 : HttpChannelParent::RecvDivertComplete()
1289 : {
1290 0 : LOG(("HttpChannelParent::RecvDivertComplete [this=%p]\n", this));
1291 :
1292 0 : MOZ_ASSERT(mParentListener);
1293 0 : if (NS_WARN_IF(!mDivertingFromChild)) {
1294 0 : MOZ_ASSERT(mDivertingFromChild,
1295 : "Cannot RecvDivertComplete if diverting is not set!");
1296 0 : FailDiversion(NS_ERROR_UNEXPECTED);
1297 0 : return IPC_FAIL_NO_REASON(this);
1298 : }
1299 :
1300 0 : mEventQ->RunOrEnqueue(new DivertCompleteEvent(this));
1301 0 : return IPC_OK();
1302 : }
1303 :
1304 : void
1305 0 : HttpChannelParent::DivertComplete()
1306 : {
1307 0 : LOG(("HttpChannelParent::DivertComplete [this=%p]\n", this));
1308 :
1309 0 : MOZ_ASSERT(mParentListener);
1310 0 : if (NS_WARN_IF(!mDivertingFromChild)) {
1311 0 : MOZ_ASSERT(mDivertingFromChild,
1312 : "Cannot DivertComplete if diverting is not set!");
1313 0 : FailDiversion(NS_ERROR_UNEXPECTED);
1314 0 : return;
1315 : }
1316 :
1317 0 : nsresult rv = ResumeForDiversion();
1318 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
1319 0 : FailDiversion(NS_ERROR_UNEXPECTED);
1320 0 : return;
1321 : }
1322 :
1323 0 : mParentListener = nullptr;
1324 : }
1325 :
1326 : void
1327 0 : HttpChannelParent::MaybeFlushPendingDiversion()
1328 : {
1329 0 : if (!mPendingDiversion) {
1330 0 : return;
1331 : }
1332 :
1333 0 : mPendingDiversion = false;
1334 :
1335 0 : nsresult rv = SuspendForDiversion();
1336 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
1337 0 : return;
1338 : }
1339 :
1340 0 : if (mDivertListener) {
1341 0 : DivertTo(mDivertListener);
1342 : }
1343 :
1344 0 : return;
1345 : }
1346 :
1347 : void
1348 0 : HttpChannelParent::ResponseSynthesized()
1349 : {
1350 : // Suspend now even though the FinishSynthesizeResponse runnable has
1351 : // not executed. We want to suspend after we get far enough to trigger
1352 : // the synthesis, but not actually allow the nsHttpChannel to trigger
1353 : // any OnStartRequests().
1354 0 : if (mSuspendAfterSynthesizeResponse) {
1355 0 : mChannel->Suspend();
1356 : }
1357 :
1358 0 : mWillSynthesizeResponse = false;
1359 :
1360 0 : MaybeFlushPendingDiversion();
1361 0 : }
1362 :
1363 : mozilla::ipc::IPCResult
1364 0 : HttpChannelParent::RecvRemoveCorsPreflightCacheEntry(const URIParams& uri,
1365 : const mozilla::ipc::PrincipalInfo& requestingPrincipal)
1366 : {
1367 0 : nsCOMPtr<nsIURI> deserializedURI = DeserializeURI(uri);
1368 0 : if (!deserializedURI) {
1369 0 : return IPC_FAIL_NO_REASON(this);
1370 : }
1371 : nsCOMPtr<nsIPrincipal> principal =
1372 0 : PrincipalInfoToPrincipal(requestingPrincipal);
1373 0 : if (!principal) {
1374 0 : return IPC_FAIL_NO_REASON(this);
1375 : }
1376 0 : nsCORSListenerProxy::RemoveFromCorsPreflightCache(deserializedURI,
1377 0 : principal);
1378 0 : return IPC_OK();
1379 : }
1380 :
1381 : //-----------------------------------------------------------------------------
1382 : // HttpChannelParent::nsIRequestObserver
1383 : //-----------------------------------------------------------------------------
1384 :
1385 : NS_IMETHODIMP
1386 3 : HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
1387 : {
1388 3 : LOG(("HttpChannelParent::OnStartRequest [this=%p, aRequest=%p]\n",
1389 : this, aRequest));
1390 3 : MOZ_ASSERT(NS_IsMainThread());
1391 :
1392 3 : MOZ_RELEASE_ASSERT(!mDivertingFromChild,
1393 : "Cannot call OnStartRequest if diverting is set!");
1394 :
1395 6 : RefPtr<nsHttpChannel> chan = do_QueryObject(aRequest);
1396 3 : if (!chan) {
1397 0 : LOG((" aRequest is not nsHttpChannel"));
1398 0 : NS_ERROR("Expecting only nsHttpChannel as aRequest in HttpChannelParent::OnStartRequest");
1399 0 : return NS_ERROR_UNEXPECTED;
1400 : }
1401 :
1402 3 : MOZ_ASSERT(mChannel == chan,
1403 : "HttpChannelParent getting OnStartRequest from a different nsHttpChannel instance");
1404 :
1405 : // Send down any permissions which are relevant to this URL if we are
1406 : // performing a document load. We can't do that is mIPCClosed is set.
1407 3 : if (!mIPCClosed) {
1408 3 : PContentParent* pcp = Manager()->Manager();
1409 3 : MOZ_ASSERT(pcp, "We should have a manager if our IPC isn't closed");
1410 : DebugOnly<nsresult> rv =
1411 6 : static_cast<ContentParent*>(pcp)->AboutToLoadHttpFtpWyciwygDocumentForChild(chan);
1412 3 : MOZ_ASSERT(NS_SUCCEEDED(rv));
1413 : }
1414 :
1415 3 : nsHttpResponseHead *responseHead = chan->GetResponseHead();
1416 3 : nsHttpRequestHead *requestHead = chan->GetRequestHead();
1417 3 : bool isFromCache = false;
1418 3 : chan->IsFromCache(&isFromCache);
1419 3 : int32_t fetchCount = 0;
1420 3 : chan->GetCacheTokenFetchCount(&fetchCount);
1421 3 : uint32_t lastFetchedTime = 0;
1422 3 : chan->GetCacheTokenLastFetched(&lastFetchedTime);
1423 3 : uint32_t expirationTime = nsICacheEntry::NO_EXPIRATION_TIME;
1424 3 : chan->GetCacheTokenExpirationTime(&expirationTime);
1425 6 : nsCString cachedCharset;
1426 3 : chan->GetCacheTokenCachedCharset(cachedCharset);
1427 :
1428 : bool loadedFromApplicationCache;
1429 3 : chan->GetLoadedFromApplicationCache(&loadedFromApplicationCache);
1430 3 : if (loadedFromApplicationCache) {
1431 0 : mOfflineForeignMarker = chan->GetOfflineCacheEntryAsForeignMarker();
1432 0 : nsCOMPtr<nsIApplicationCache> appCache;
1433 0 : chan->GetApplicationCache(getter_AddRefs(appCache));
1434 0 : nsCString appCacheGroupId;
1435 0 : nsCString appCacheClientId;
1436 0 : appCache->GetGroupID(appCacheGroupId);
1437 0 : appCache->GetClientID(appCacheClientId);
1438 0 : if (mIPCClosed ||
1439 0 : !SendAssociateApplicationCache(appCacheGroupId, appCacheClientId))
1440 : {
1441 0 : return NS_ERROR_UNEXPECTED;
1442 : }
1443 : }
1444 :
1445 6 : nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(aRequest);
1446 3 : if (encodedChannel)
1447 3 : encodedChannel->SetApplyConversion(false);
1448 :
1449 : // Keep the cache entry for future use in RecvSetCacheTokenCachedCharset().
1450 : // It could be already released by nsHttpChannel at that time.
1451 6 : nsCOMPtr<nsISupports> cacheEntry;
1452 3 : chan->GetCacheToken(getter_AddRefs(cacheEntry));
1453 3 : mCacheEntry = do_QueryInterface(cacheEntry);
1454 :
1455 3 : nsresult channelStatus = NS_OK;
1456 3 : chan->GetStatus(&channelStatus);
1457 :
1458 6 : nsCString secInfoSerialization;
1459 3 : UpdateAndSerializeSecurityInfo(secInfoSerialization);
1460 :
1461 3 : uint16_t redirectCount = 0;
1462 3 : chan->GetRedirectCount(&redirectCount);
1463 :
1464 6 : nsCOMPtr<nsISupports> cacheKey;
1465 3 : chan->GetCacheKey(getter_AddRefs(cacheKey));
1466 3 : uint32_t cacheKeyValue = 0;
1467 3 : if (cacheKey) {
1468 6 : nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(cacheKey);
1469 3 : if (!container) {
1470 0 : return NS_ERROR_ILLEGAL_VALUE;
1471 : }
1472 :
1473 3 : nsresult rv = container->GetData(&cacheKeyValue);
1474 3 : if (NS_FAILED(rv)) {
1475 0 : return rv;
1476 : }
1477 : }
1478 :
1479 6 : nsAutoCString altDataType;
1480 3 : chan->GetAlternativeDataType(altDataType);
1481 3 : int64_t altDataLen = chan->GetAltDataLength();
1482 :
1483 : // !!! We need to lock headers and please don't forget to unlock them !!!
1484 3 : requestHead->Enter();
1485 3 : nsresult rv = NS_OK;
1486 21 : if (mIPCClosed ||
1487 15 : !SendOnStartRequest(channelStatus,
1488 6 : responseHead ? *responseHead : nsHttpResponseHead(),
1489 6 : !!responseHead,
1490 : requestHead->Headers(),
1491 : isFromCache,
1492 6 : mCacheEntry ? true : false,
1493 : fetchCount, lastFetchedTime, expirationTime,
1494 : cachedCharset, secInfoSerialization,
1495 3 : chan->GetSelfAddr(), chan->GetPeerAddr(),
1496 : redirectCount,
1497 : cacheKeyValue,
1498 : altDataType,
1499 : altDataLen))
1500 : {
1501 0 : rv = NS_ERROR_UNEXPECTED;
1502 : }
1503 3 : requestHead->Exit();
1504 :
1505 : // OnStartRequest is sent to content process successfully.
1506 : // Notify PHttpBackgroundChannelChild that all following IPC mesasges
1507 : // should be run after OnStartRequest is handled.
1508 3 : if (NS_SUCCEEDED(rv)) {
1509 3 : MOZ_ASSERT(mBgParent);
1510 3 : if (!mBgParent->OnStartRequestSent()) {
1511 0 : rv = NS_ERROR_UNEXPECTED;
1512 : }
1513 : }
1514 :
1515 3 : return rv;
1516 : }
1517 :
1518 : NS_IMETHODIMP
1519 3 : HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
1520 : nsISupports *aContext,
1521 : nsresult aStatusCode)
1522 : {
1523 3 : LOG(("HttpChannelParent::OnStopRequest: [this=%p aRequest=%p status=%" PRIx32 "]\n",
1524 : this, aRequest, static_cast<uint32_t>(aStatusCode)));
1525 3 : MOZ_ASSERT(NS_IsMainThread());
1526 :
1527 3 : MOZ_RELEASE_ASSERT(!mDivertingFromChild,
1528 : "Cannot call OnStopRequest if diverting is set!");
1529 6 : ResourceTimingStruct timing;
1530 3 : mChannel->GetDomainLookupStart(&timing.domainLookupStart);
1531 3 : mChannel->GetDomainLookupEnd(&timing.domainLookupEnd);
1532 3 : mChannel->GetConnectStart(&timing.connectStart);
1533 3 : mChannel->GetConnectEnd(&timing.connectEnd);
1534 3 : mChannel->GetRequestStart(&timing.requestStart);
1535 3 : mChannel->GetResponseStart(&timing.responseStart);
1536 3 : mChannel->GetResponseEnd(&timing.responseEnd);
1537 3 : mChannel->GetAsyncOpen(&timing.fetchStart);
1538 3 : mChannel->GetRedirectStart(&timing.redirectStart);
1539 3 : mChannel->GetRedirectEnd(&timing.redirectEnd);
1540 3 : mChannel->GetTransferSize(&timing.transferSize);
1541 3 : mChannel->GetEncodedBodySize(&timing.encodedBodySize);
1542 : // decodedBodySize can be computed in the child process so it doesn't need
1543 : // to be passed down.
1544 3 : mChannel->GetProtocolVersion(timing.protocolVersion);
1545 :
1546 3 : mChannel->GetCacheReadStart(&timing.cacheReadStart);
1547 3 : mChannel->GetCacheReadEnd(&timing.cacheReadEnd);
1548 :
1549 : // Either IPC channel is closed or background channel
1550 : // is ready to send OnStopRequest.
1551 3 : MOZ_ASSERT(mIPCClosed || mBgParent);
1552 :
1553 9 : if (mIPCClosed ||
1554 6 : !mBgParent || !mBgParent->OnStopRequest(aStatusCode, timing)) {
1555 0 : return NS_ERROR_UNEXPECTED;
1556 : }
1557 :
1558 3 : return NS_OK;
1559 : }
1560 :
1561 : //-----------------------------------------------------------------------------
1562 : // HttpChannelParent::nsIStreamListener
1563 : //-----------------------------------------------------------------------------
1564 :
1565 : NS_IMETHODIMP
1566 3 : HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
1567 : nsISupports *aContext,
1568 : nsIInputStream *aInputStream,
1569 : uint64_t aOffset,
1570 : uint32_t aCount)
1571 : {
1572 3 : LOG(("HttpChannelParent::OnDataAvailable [this=%p aRequest=%p offset=%" PRIu64
1573 : " count=%" PRIu32 "]\n", this, aRequest, aOffset, aCount));
1574 3 : MOZ_ASSERT(NS_IsMainThread());
1575 :
1576 3 : MOZ_RELEASE_ASSERT(!mDivertingFromChild,
1577 : "Cannot call OnDataAvailable if diverting is set!");
1578 :
1579 3 : nsresult channelStatus = NS_OK;
1580 3 : mChannel->GetStatus(&channelStatus);
1581 :
1582 : nsresult transportStatus =
1583 3 : (mChannel->IsReadingFromCache()) ? NS_NET_STATUS_READING
1584 3 : : NS_NET_STATUS_RECEIVING_FROM;
1585 :
1586 : static uint32_t const kCopyChunkSize = 128 * 1024;
1587 3 : uint32_t toRead = std::min<uint32_t>(aCount, kCopyChunkSize);
1588 :
1589 6 : nsCString data;
1590 3 : if (!data.SetCapacity(toRead, fallible)) {
1591 0 : LOG((" out of memory!"));
1592 0 : return NS_ERROR_OUT_OF_MEMORY;
1593 : }
1594 :
1595 9 : while (aCount) {
1596 3 : nsresult rv = NS_ReadInputStreamToString(aInputStream, data, toRead);
1597 3 : if (NS_FAILED(rv)) {
1598 0 : return rv;
1599 : }
1600 :
1601 : // Either IPC channel is closed or background channel
1602 : // is ready to send OnTransportAndData.
1603 3 : MOZ_ASSERT(mIPCClosed || mBgParent);
1604 :
1605 6 : if (mIPCClosed || !mBgParent ||
1606 3 : !mBgParent->OnTransportAndData(channelStatus, transportStatus,
1607 : aOffset, toRead, data)) {
1608 0 : return NS_ERROR_UNEXPECTED;
1609 : }
1610 :
1611 3 : aOffset += toRead;
1612 3 : aCount -= toRead;
1613 3 : toRead = std::min<uint32_t>(aCount, kCopyChunkSize);
1614 : }
1615 :
1616 3 : return NS_OK;
1617 : }
1618 :
1619 : //-----------------------------------------------------------------------------
1620 : // HttpChannelParent::nsIProgressEventSink
1621 : //-----------------------------------------------------------------------------
1622 :
1623 : NS_IMETHODIMP
1624 3 : HttpChannelParent::OnProgress(nsIRequest *aRequest,
1625 : nsISupports *aContext,
1626 : int64_t aProgress,
1627 : int64_t aProgressMax)
1628 : {
1629 3 : LOG(("HttpChannelParent::OnStatus [this=%p progress=%" PRId64 "max=%" PRId64
1630 : "]\n", this, aProgress, aProgressMax));
1631 3 : MOZ_ASSERT(NS_IsMainThread());
1632 :
1633 : // If it indicates this precedes OnDataAvailable, child can derive the value in ODA.
1634 3 : if (mIgnoreProgress) {
1635 3 : mIgnoreProgress = false;
1636 3 : return NS_OK;
1637 : }
1638 :
1639 : // Either IPC channel is closed or background channel
1640 : // is ready to send OnProgress.
1641 0 : MOZ_ASSERT(mIPCClosed || mBgParent);
1642 :
1643 : // Send OnProgress events to the child for data upload progress notifications
1644 : // (i.e. status == NS_NET_STATUS_SENDING_TO) or if the channel has
1645 : // LOAD_BACKGROUND set.
1646 0 : if (mIPCClosed || !mBgParent
1647 0 : || !mBgParent->OnProgress(aProgress, aProgressMax)) {
1648 0 : return NS_ERROR_UNEXPECTED;
1649 : }
1650 :
1651 0 : return NS_OK;
1652 : }
1653 :
1654 : NS_IMETHODIMP
1655 8 : HttpChannelParent::OnStatus(nsIRequest *aRequest,
1656 : nsISupports *aContext,
1657 : nsresult aStatus,
1658 : const char16_t *aStatusArg)
1659 : {
1660 8 : LOG(("HttpChannelParent::OnStatus [this=%p status=%" PRIx32 "]\n",
1661 : this, static_cast<uint32_t>(aStatus)));
1662 8 : MOZ_ASSERT(NS_IsMainThread());
1663 :
1664 : // If this precedes OnDataAvailable, transportStatus will be derived in ODA.
1665 15 : if (aStatus == NS_NET_STATUS_RECEIVING_FROM ||
1666 7 : aStatus == NS_NET_STATUS_READING) {
1667 : // The transport status and progress generated by ODA will be coalesced
1668 : // into one IPC message. Therefore, we can ignore the next OnProgress event
1669 : // since it is generated by ODA as well.
1670 3 : mIgnoreProgress = true;
1671 3 : return NS_OK;
1672 : }
1673 :
1674 : // Either IPC channel is closed or background channel
1675 : // is ready to send OnStatus.
1676 5 : MOZ_ASSERT(mIPCClosed || mBgParent);
1677 :
1678 : // Otherwise, send to child now
1679 5 : if (mIPCClosed || !mBgParent || !mBgParent->OnStatus(aStatus)) {
1680 0 : return NS_ERROR_UNEXPECTED;
1681 : }
1682 :
1683 5 : return NS_OK;
1684 : }
1685 :
1686 : //-----------------------------------------------------------------------------
1687 : // HttpChannelParent::nsIParentChannel
1688 : //-----------------------------------------------------------------------------
1689 :
1690 : NS_IMETHODIMP
1691 0 : HttpChannelParent::SetParentListener(HttpChannelParentListener* aListener)
1692 : {
1693 0 : LOG(("HttpChannelParent::SetParentListener [this=%p aListener=%p]\n",
1694 : this, aListener));
1695 0 : MOZ_ASSERT(aListener);
1696 0 : MOZ_ASSERT(!mParentListener, "SetParentListener should only be called for "
1697 : "new HttpChannelParents after a redirect, when "
1698 : "mParentListener is null.");
1699 0 : mParentListener = aListener;
1700 0 : return NS_OK;
1701 : }
1702 :
1703 : NS_IMETHODIMP
1704 0 : HttpChannelParent::NotifyTrackingProtectionDisabled()
1705 : {
1706 0 : LOG(("HttpChannelParent::NotifyTrackingProtectionDisabled [this=%p]\n", this));
1707 0 : if (!mIPCClosed) {
1708 0 : MOZ_ASSERT(mBgParent);
1709 0 : Unused << mBgParent->OnNotifyTrackingProtectionDisabled();
1710 : }
1711 0 : return NS_OK;
1712 : }
1713 :
1714 : NS_IMETHODIMP
1715 0 : HttpChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
1716 : const nsACString& aProvider,
1717 : const nsACString& aPrefix)
1718 : {
1719 0 : LOG(("HttpChannelParent::SetClassifierMatchedInfo [this=%p]\n", this));
1720 0 : if (!mIPCClosed) {
1721 0 : MOZ_ASSERT(mBgParent);
1722 0 : Unused << mBgParent->OnSetClassifierMatchedInfo(aList, aProvider, aPrefix);
1723 : }
1724 0 : return NS_OK;
1725 : }
1726 :
1727 : NS_IMETHODIMP
1728 0 : HttpChannelParent::NotifyTrackingResource()
1729 : {
1730 0 : LOG(("HttpChannelParent::NotifyTrackingResource [this=%p]\n", this));
1731 0 : if (!mIPCClosed) {
1732 0 : MOZ_ASSERT(mBgParent);
1733 0 : Unused << mBgParent->OnNotifyTrackingResource();
1734 : }
1735 0 : return NS_OK;
1736 : }
1737 :
1738 : NS_IMETHODIMP
1739 0 : HttpChannelParent::Delete()
1740 : {
1741 0 : if (!mIPCClosed)
1742 0 : Unused << DoSendDeleteSelf();
1743 :
1744 0 : return NS_OK;
1745 : }
1746 :
1747 : //-----------------------------------------------------------------------------
1748 : // HttpChannelParent::nsIParentRedirectingChannel
1749 : //-----------------------------------------------------------------------------
1750 :
1751 : NS_IMETHODIMP
1752 0 : HttpChannelParent::StartRedirect(uint32_t registrarId,
1753 : nsIChannel* newChannel,
1754 : uint32_t redirectFlags,
1755 : nsIAsyncVerifyRedirectCallback* callback)
1756 : {
1757 : nsresult rv;
1758 :
1759 0 : LOG(("HttpChannelParent::StartRedirect [this=%p, registrarId=%" PRIu32 " "
1760 : "newChannel=%p callback=%p]\n", this, registrarId, newChannel,
1761 : callback));
1762 :
1763 0 : if (mIPCClosed)
1764 0 : return NS_BINDING_ABORTED;
1765 :
1766 : // Sending down the original URI, because that is the URI we have
1767 : // to construct the channel from - this is the URI we've been actually
1768 : // redirected to. URI of the channel may be an inner channel URI.
1769 : // URI of the channel will be reconstructed by the protocol handler
1770 : // on the child process, no need to send it then.
1771 0 : nsCOMPtr<nsIURI> newOriginalURI;
1772 0 : newChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
1773 :
1774 0 : URIParams uriParams;
1775 0 : SerializeURI(newOriginalURI, uriParams);
1776 :
1777 0 : nsCString secInfoSerialization;
1778 0 : UpdateAndSerializeSecurityInfo(secInfoSerialization);
1779 :
1780 : // If the channel is a HTTP channel, we also want to inform the child
1781 : // about the parent's channelId attribute, so that both parent and child
1782 : // share the same ID. Useful for monitoring channel activity in devtools.
1783 : uint64_t channelId;
1784 0 : nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
1785 0 : if (httpChannel) {
1786 0 : rv = httpChannel->GetChannelId(&channelId);
1787 0 : NS_ENSURE_SUCCESS(rv, NS_BINDING_ABORTED);
1788 : }
1789 :
1790 0 : nsHttpResponseHead *responseHead = mChannel->GetResponseHead();
1791 0 : bool result = false;
1792 0 : if (!mIPCClosed) {
1793 0 : result = SendRedirect1Begin(registrarId, uriParams, redirectFlags,
1794 0 : responseHead ? *responseHead
1795 : : nsHttpResponseHead(),
1796 : secInfoSerialization,
1797 : channelId,
1798 0 : mChannel->GetPeerAddr());
1799 : }
1800 0 : if (!result) {
1801 : // Bug 621446 investigation
1802 0 : mSentRedirect1BeginFailed = true;
1803 0 : return NS_BINDING_ABORTED;
1804 : }
1805 :
1806 : // Bug 621446 investigation
1807 : // Store registrar Id of the new channel to find the redirect
1808 : // HttpChannelParent later in verification phase.
1809 0 : mRedirectRegistrarId = registrarId;
1810 :
1811 : // Result is handled in RecvRedirect2Verify above
1812 :
1813 0 : mRedirectChannel = newChannel;
1814 0 : mRedirectCallback = callback;
1815 0 : return NS_OK;
1816 : }
1817 :
1818 : NS_IMETHODIMP
1819 0 : HttpChannelParent::CompleteRedirect(bool succeeded)
1820 : {
1821 0 : LOG(("HttpChannelParent::CompleteRedirect [this=%p succeeded=%d]\n",
1822 : this, succeeded));
1823 :
1824 0 : if (succeeded && !mIPCClosed) {
1825 : // TODO: check return value: assume child dead if failed
1826 0 : Unused << SendRedirect3Complete();
1827 : }
1828 :
1829 0 : mRedirectChannel = nullptr;
1830 0 : return NS_OK;
1831 : }
1832 :
1833 : //-----------------------------------------------------------------------------
1834 : // HttpChannelParent::ADivertableParentChannel
1835 : //-----------------------------------------------------------------------------
1836 : nsresult
1837 0 : HttpChannelParent::SuspendForDiversion()
1838 : {
1839 0 : LOG(("HttpChannelParent::SuspendForDiversion [this=%p]\n", this));
1840 0 : MOZ_ASSERT(mChannel);
1841 0 : MOZ_ASSERT(mParentListener);
1842 :
1843 : // If we're in the process of opening a synthesized response, we must wait
1844 : // to perform the diversion. Some of our diversion listeners clear callbacks
1845 : // which breaks the synthesis process.
1846 0 : if (mWillSynthesizeResponse) {
1847 0 : mPendingDiversion = true;
1848 0 : return NS_OK;
1849 : }
1850 :
1851 0 : if (NS_WARN_IF(mDivertingFromChild)) {
1852 0 : MOZ_ASSERT(!mDivertingFromChild, "Already suspended for diversion!");
1853 0 : return NS_ERROR_UNEXPECTED;
1854 : }
1855 :
1856 : // MessageDiversionStarted call will suspend mEventQ as many times as the
1857 : // channel has been suspended, so that channel and this queue are in sync.
1858 0 : mChannel->MessageDiversionStarted(this);
1859 :
1860 0 : nsresult rv = NS_OK;
1861 :
1862 : // Try suspending the channel. Allow it to fail, since OnStopRequest may have
1863 : // been called and thus the channel may not be pending. If we've already
1864 : // automatically suspended after synthesizing the response, then we don't
1865 : // need to suspend again here.
1866 0 : if (!mSuspendAfterSynthesizeResponse) {
1867 : // We need to suspend only nsHttpChannel (i.e. we should not suspend
1868 : // mEventQ). Therefore we call mChannel->SuspendInternal() and not
1869 : // mChannel->Suspend().
1870 : // We are suspending only nsHttpChannel here because we want to stop
1871 : // OnDataAvailable until diversion is over. At the same time we should
1872 : // send the diverted OnDataAvailable-s to the listeners and not queue them
1873 : // in mEventQ.
1874 0 : rv = mChannel->SuspendInternal();
1875 0 : MOZ_ASSERT(NS_SUCCEEDED(rv) || rv == NS_ERROR_NOT_AVAILABLE);
1876 0 : mSuspendedForDiversion = NS_SUCCEEDED(rv);
1877 : } else {
1878 : // Take ownership of the automatic suspend that occurred after synthesizing
1879 : // the response.
1880 0 : mSuspendedForDiversion = true;
1881 :
1882 : // If mSuspendAfterSynthesizeResponse is true channel has been already
1883 : // suspended. From comment above mSuspendedForDiversion takes the ownership
1884 : // of this suspend, therefore mEventQ should not be suspened so we need to
1885 : // resume it once.
1886 0 : mEventQ->Resume();
1887 : }
1888 :
1889 0 : rv = mParentListener->SuspendForDiversion();
1890 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
1891 :
1892 : // Once this is set, no more OnStart/OnData/OnStop callbacks should be sent
1893 : // to the child.
1894 0 : mDivertingFromChild = true;
1895 :
1896 0 : return NS_OK;
1897 : }
1898 :
1899 : nsresult
1900 0 : HttpChannelParent::SuspendMessageDiversion()
1901 : {
1902 0 : LOG(("HttpChannelParent::SuspendMessageDiversion [this=%p]", this));
1903 : // This only needs to suspend message queue.
1904 0 : mEventQ->Suspend();
1905 0 : return NS_OK;
1906 : }
1907 :
1908 : nsresult
1909 0 : HttpChannelParent::ResumeMessageDiversion()
1910 : {
1911 0 : LOG(("HttpChannelParent::SuspendMessageDiversion [this=%p]", this));
1912 : // This only needs to resumes message queue.
1913 0 : mEventQ->Resume();
1914 0 : return NS_OK;
1915 : }
1916 :
1917 : /* private, supporting function for ADivertableParentChannel */
1918 : nsresult
1919 0 : HttpChannelParent::ResumeForDiversion()
1920 : {
1921 0 : LOG(("HttpChannelParent::ResumeForDiversion [this=%p]\n", this));
1922 0 : MOZ_ASSERT(mChannel);
1923 0 : if (NS_WARN_IF(!mDivertingFromChild)) {
1924 0 : MOZ_ASSERT(mDivertingFromChild,
1925 : "Cannot ResumeForDiversion if not diverting!");
1926 0 : return NS_ERROR_UNEXPECTED;
1927 : }
1928 :
1929 0 : mChannel->MessageDiversionStop();
1930 :
1931 0 : if (mSuspendedForDiversion) {
1932 : // The nsHttpChannel will deliver remaining OnData/OnStop for the transfer.
1933 0 : nsresult rv = mChannel->ResumeInternal();
1934 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
1935 0 : return rv;
1936 : }
1937 0 : mSuspendedForDiversion = false;
1938 : }
1939 :
1940 0 : if (NS_WARN_IF(mIPCClosed || !DoSendDeleteSelf())) {
1941 0 : return NS_ERROR_UNEXPECTED;
1942 : }
1943 0 : return NS_OK;
1944 : }
1945 :
1946 : void
1947 0 : HttpChannelParent::DivertTo(nsIStreamListener *aListener)
1948 : {
1949 0 : LOG(("HttpChannelParent::DivertTo [this=%p aListener=%p]\n",
1950 : this, aListener));
1951 0 : MOZ_ASSERT(mParentListener);
1952 :
1953 : // If we're in the process of opening a synthesized response, we must wait
1954 : // to perform the diversion. Some of our diversion listeners clear callbacks
1955 : // which breaks the synthesis process.
1956 0 : if (mWillSynthesizeResponse) {
1957 : // We should already have started pending the diversion when
1958 : // SuspendForDiversion() was called.
1959 0 : MOZ_ASSERT(mPendingDiversion);
1960 0 : mDivertListener = aListener;
1961 0 : return;
1962 : }
1963 :
1964 0 : if (NS_WARN_IF(!mDivertingFromChild)) {
1965 0 : MOZ_ASSERT(mDivertingFromChild,
1966 : "Cannot DivertTo new listener if diverting is not set!");
1967 0 : return;
1968 : }
1969 :
1970 0 : mDivertListener = aListener;
1971 :
1972 : // Call OnStartRequest and SendDivertMessages asynchronously to avoid
1973 : // reentering client context.
1974 0 : NS_DispatchToCurrentThread(
1975 0 : NewRunnableMethod("net::HttpChannelParent::StartDiversion",
1976 : this,
1977 0 : &HttpChannelParent::StartDiversion));
1978 0 : return;
1979 : }
1980 :
1981 : void
1982 0 : HttpChannelParent::StartDiversion()
1983 : {
1984 0 : LOG(("HttpChannelParent::StartDiversion [this=%p]\n", this));
1985 0 : if (NS_WARN_IF(!mDivertingFromChild)) {
1986 0 : MOZ_ASSERT(mDivertingFromChild,
1987 : "Cannot StartDiversion if diverting is not set!");
1988 0 : return;
1989 : }
1990 :
1991 : // Fake pending status in case OnStopRequest has already been called.
1992 0 : if (mChannel) {
1993 0 : mChannel->ForcePending(true);
1994 : }
1995 :
1996 : {
1997 0 : AutoEventEnqueuer ensureSerialDispatch(mEventQ);
1998 :
1999 : // Call OnStartRequest for the "DivertTo" listener.
2000 0 : nsresult rv = mDivertListener->OnStartRequest(mChannel, nullptr);
2001 0 : if (NS_FAILED(rv)) {
2002 0 : if (mChannel) {
2003 0 : mChannel->Cancel(rv);
2004 : }
2005 0 : mStatus = rv;
2006 : }
2007 : }
2008 0 : mDivertedOnStartRequest = true;
2009 :
2010 : // After OnStartRequest has been called, setup content decoders if needed.
2011 : //
2012 : // Create a content conversion chain based on mDivertListener and update
2013 : // mDivertListener.
2014 0 : nsCOMPtr<nsIStreamListener> converterListener;
2015 0 : Unused << mChannel->DoApplyContentConversions(mDivertListener,
2016 0 : getter_AddRefs(converterListener));
2017 0 : if (converterListener) {
2018 0 : mDivertListener = converterListener.forget();
2019 : }
2020 :
2021 : // Now mParentListener can be diverted to mDivertListener.
2022 0 : DebugOnly<nsresult> rvdbg = mParentListener->DivertTo(mDivertListener);
2023 0 : MOZ_ASSERT(NS_SUCCEEDED(rvdbg));
2024 0 : mDivertListener = nullptr;
2025 :
2026 : // Either IPC channel is closed or background channel
2027 : // is ready to send FlushedForDiversion and DivertMessages.
2028 0 : MOZ_ASSERT(mIPCClosed || mBgParent);
2029 :
2030 0 : if (NS_WARN_IF(mIPCClosed || !mBgParent || !mBgParent->OnDiversion())) {
2031 0 : FailDiversion(NS_ERROR_UNEXPECTED);
2032 0 : return;
2033 : }
2034 : }
2035 :
2036 0 : class HTTPFailDiversionEvent : public Runnable
2037 : {
2038 : public:
2039 0 : HTTPFailDiversionEvent(HttpChannelParent *aChannelParent,
2040 : nsresult aErrorCode)
2041 0 : : Runnable("net::HTTPFailDiversionEvent")
2042 : , mChannelParent(aChannelParent)
2043 0 : , mErrorCode(aErrorCode)
2044 : {
2045 0 : MOZ_RELEASE_ASSERT(aChannelParent);
2046 0 : MOZ_RELEASE_ASSERT(NS_FAILED(aErrorCode));
2047 0 : }
2048 0 : NS_IMETHOD Run() override
2049 : {
2050 0 : mChannelParent->NotifyDiversionFailed(mErrorCode);
2051 0 : return NS_OK;
2052 : }
2053 : private:
2054 : RefPtr<HttpChannelParent> mChannelParent;
2055 : nsresult mErrorCode;
2056 : };
2057 :
2058 : void
2059 0 : HttpChannelParent::FailDiversion(nsresult aErrorCode)
2060 : {
2061 0 : MOZ_RELEASE_ASSERT(NS_FAILED(aErrorCode));
2062 0 : MOZ_RELEASE_ASSERT(mDivertingFromChild);
2063 0 : MOZ_RELEASE_ASSERT(mParentListener);
2064 0 : MOZ_RELEASE_ASSERT(mChannel);
2065 :
2066 : NS_DispatchToCurrentThread(
2067 0 : new HTTPFailDiversionEvent(this, aErrorCode));
2068 0 : }
2069 :
2070 : void
2071 0 : HttpChannelParent::NotifyDiversionFailed(nsresult aErrorCode)
2072 : {
2073 0 : LOG(("HttpChannelParent::NotifyDiversionFailed [this=%p aErrorCode=%" PRIx32 "]\n",
2074 : this, static_cast<uint32_t>(aErrorCode)));
2075 0 : MOZ_RELEASE_ASSERT(NS_FAILED(aErrorCode));
2076 0 : MOZ_RELEASE_ASSERT(mDivertingFromChild);
2077 0 : MOZ_RELEASE_ASSERT(mParentListener);
2078 0 : MOZ_RELEASE_ASSERT(mChannel);
2079 :
2080 0 : mChannel->Cancel(aErrorCode);
2081 :
2082 0 : mChannel->ForcePending(false);
2083 :
2084 0 : bool isPending = false;
2085 0 : nsresult rv = mChannel->IsPending(&isPending);
2086 0 : MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
2087 :
2088 : // Resume only if we suspended earlier.
2089 0 : if (mSuspendedForDiversion) {
2090 0 : mChannel->ResumeInternal();
2091 : }
2092 : // Channel has already sent OnStartRequest to the child, so ensure that we
2093 : // call it here if it hasn't already been called.
2094 0 : if (!mDivertedOnStartRequest) {
2095 0 : mChannel->ForcePending(true);
2096 0 : mParentListener->OnStartRequest(mChannel, nullptr);
2097 0 : mChannel->ForcePending(false);
2098 : }
2099 : // If the channel is pending, it will call OnStopRequest itself; otherwise, do
2100 : // it here.
2101 0 : if (!isPending) {
2102 0 : mParentListener->OnStopRequest(mChannel, nullptr, aErrorCode);
2103 : }
2104 :
2105 0 : if (!mIPCClosed) {
2106 0 : Unused << DoSendDeleteSelf();
2107 : }
2108 :
2109 : // DoSendDeleteSelf will need channel Id to remove the strong reference in
2110 : // BackgroundChannelRegistrar if channel pairing is aborted.
2111 : // Thus we need to keep mChannel until DoSendDeleteSelf is done.
2112 0 : mParentListener = nullptr;
2113 0 : mChannel = nullptr;
2114 0 : }
2115 :
2116 : nsresult
2117 0 : HttpChannelParent::OpenAlternativeOutputStream(const nsACString & type, nsIOutputStream * *_retval)
2118 : {
2119 : // We need to make sure the child does not call SendDocumentChannelCleanup()
2120 : // before opening the altOutputStream, because that clears mCacheEntry.
2121 0 : if (!mCacheEntry) {
2122 0 : return NS_ERROR_NOT_AVAILABLE;
2123 : }
2124 0 : return mCacheEntry->OpenAlternativeOutputStream(type, _retval);
2125 : }
2126 :
2127 : NS_IMETHODIMP
2128 0 : HttpChannelParent::GetAuthPrompt(uint32_t aPromptReason, const nsIID& iid,
2129 : void** aResult)
2130 : {
2131 : nsCOMPtr<nsIAuthPrompt2> prompt =
2132 0 : new NeckoParent::NestedFrameAuthPrompt(Manager(), mNestedFrameId);
2133 0 : prompt.forget(aResult);
2134 0 : return NS_OK;
2135 : }
2136 :
2137 : void
2138 3 : HttpChannelParent::UpdateAndSerializeSecurityInfo(nsACString& aSerializedSecurityInfoOut)
2139 : {
2140 6 : nsCOMPtr<nsISupports> secInfoSupp;
2141 3 : mChannel->GetSecurityInfo(getter_AddRefs(secInfoSupp));
2142 3 : if (secInfoSupp) {
2143 0 : mAssociatedContentSecurity = do_QueryInterface(secInfoSupp);
2144 0 : nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(secInfoSupp);
2145 0 : if (secInfoSer) {
2146 0 : NS_SerializeToString(secInfoSer, aSerializedSecurityInfoOut);
2147 : }
2148 : }
2149 3 : }
2150 :
2151 : bool
2152 2 : HttpChannelParent::DoSendDeleteSelf()
2153 : {
2154 2 : bool rv = SendDeleteSelf();
2155 2 : mIPCClosed = true;
2156 :
2157 2 : CleanupBackgroundChannel();
2158 :
2159 2 : return rv;
2160 : }
2161 :
2162 : mozilla::ipc::IPCResult
2163 2 : HttpChannelParent::RecvDeletingChannel()
2164 : {
2165 : // We need to ensure that the parent channel will not be sending any more IPC
2166 : // messages after this, as the child is going away. DoSendDeleteSelf will
2167 : // set mIPCClosed = true;
2168 2 : if (!DoSendDeleteSelf()) {
2169 0 : return IPC_FAIL_NO_REASON(this);
2170 : }
2171 2 : return IPC_OK();
2172 : }
2173 :
2174 : mozilla::ipc::IPCResult
2175 0 : HttpChannelParent::RecvFinishInterceptedRedirect()
2176 : {
2177 : // We make sure not to send any more messages until the IPC channel is torn
2178 : // down by the child.
2179 0 : mIPCClosed = true;
2180 0 : if (!SendFinishInterceptedRedirect()) {
2181 0 : return IPC_FAIL_NO_REASON(this);
2182 : }
2183 0 : return IPC_OK();
2184 : }
2185 :
2186 : //-----------------------------------------------------------------------------
2187 : // HttpChannelSecurityWarningReporter
2188 : //-----------------------------------------------------------------------------
2189 :
2190 : nsresult
2191 0 : HttpChannelParent::ReportSecurityMessage(const nsAString& aMessageTag,
2192 : const nsAString& aMessageCategory)
2193 : {
2194 0 : if (mIPCClosed ||
2195 0 : NS_WARN_IF(!SendReportSecurityMessage(nsString(aMessageTag),
2196 : nsString(aMessageCategory)))) {
2197 0 : return NS_ERROR_UNEXPECTED;
2198 : }
2199 0 : return NS_OK;
2200 : }
2201 :
2202 : NS_IMETHODIMP
2203 0 : HttpChannelParent::IssueWarning(uint32_t aWarning, bool aAsError)
2204 : {
2205 0 : Unused << SendIssueDeprecationWarning(aWarning, aAsError);
2206 0 : return NS_OK;
2207 : }
2208 :
2209 : //-----------------------------------------------------------------------------
2210 : // nsIAsyncVerifyRedirectReadyCallback
2211 : //-----------------------------------------------------------------------------
2212 :
2213 : NS_IMETHODIMP
2214 0 : HttpChannelParent::ReadyToVerify(nsresult aResult)
2215 : {
2216 0 : LOG(("HttpChannelParent::RecvRedirect2Verify [this=%p result=%" PRIx32 "]\n",
2217 : this, static_cast<uint32_t>(aResult)));
2218 0 : MOZ_ASSERT(NS_IsMainThread());
2219 :
2220 0 : ContinueRedirect2Verify(aResult);
2221 :
2222 0 : return NS_OK;
2223 : }
2224 :
2225 : void
2226 1 : HttpChannelParent::DoSendSetPriority(int16_t aValue)
2227 : {
2228 1 : if (!mIPCClosed) {
2229 1 : Unused << SendSetPriority(aValue);
2230 : }
2231 1 : }
2232 :
2233 : } // namespace net
2234 : } // namespace mozilla
|