LCOV - code coverage report
Current view: top level - netwerk/protocol/http - HttpChannelParent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 366 1047 35.0 %
Date: 2017-07-14 16:53:18 Functions: 31 110 28.2 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.13