LCOV - code coverage report
Current view: top level - netwerk/protocol/http - HttpChannelChild.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 604 1611 37.5 %
Date: 2017-07-14 16:53:18 Functions: 77 214 36.0 %
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             : 
       4             : /* This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       7             : 
       8             : // HttpLog.h should generally be included first
       9             : #include "HttpLog.h"
      10             : 
      11             : #include "nsHttp.h"
      12             : #include "nsICacheEntry.h"
      13             : #include "mozilla/Unused.h"
      14             : #include "mozilla/dom/ContentChild.h"
      15             : #include "mozilla/dom/DocGroup.h"
      16             : #include "mozilla/dom/TabChild.h"
      17             : #include "mozilla/dom/TabGroup.h"
      18             : #include "mozilla/ipc/FileDescriptorSetChild.h"
      19             : #include "mozilla/ipc/IPCStreamUtils.h"
      20             : #include "mozilla/net/NeckoChild.h"
      21             : #include "mozilla/net/HttpChannelChild.h"
      22             : 
      23             : #include "AltDataOutputStreamChild.h"
      24             : #include "HttpBackgroundChannelChild.h"
      25             : #include "nsCOMPtr.h"
      26             : #include "nsISupportsPrimitives.h"
      27             : #include "nsChannelClassifier.h"
      28             : #include "nsGlobalWindow.h"
      29             : #include "nsStringStream.h"
      30             : #include "nsHttpChannel.h"
      31             : #include "nsHttpHandler.h"
      32             : #include "nsNetUtil.h"
      33             : #include "nsSerializationHelper.h"
      34             : #include "mozilla/Attributes.h"
      35             : #include "mozilla/dom/Performance.h"
      36             : #include "mozilla/ipc/InputStreamUtils.h"
      37             : #include "mozilla/ipc/URIUtils.h"
      38             : #include "mozilla/ipc/BackgroundUtils.h"
      39             : #include "mozilla/net/ChannelDiverterChild.h"
      40             : #include "mozilla/net/DNS.h"
      41             : #include "SerializedLoadContext.h"
      42             : #include "nsInputStreamPump.h"
      43             : #include "InterceptedChannel.h"
      44             : #include "mozIThirdPartyUtil.h"
      45             : #include "nsContentSecurityManager.h"
      46             : #include "nsIDeprecationWarner.h"
      47             : #include "nsICompressConvStats.h"
      48             : #include "nsIDocument.h"
      49             : #include "nsIDOMDocument.h"
      50             : #include "nsIDOMWindowUtils.h"
      51             : #include "nsIEventTarget.h"
      52             : #include "nsRedirectHistoryEntry.h"
      53             : #include "nsSocketTransportService2.h"
      54             : #include "nsStreamUtils.h"
      55             : #include "nsThreadUtils.h"
      56             : 
      57             : #ifdef MOZ_TASK_TRACER
      58             : #include "GeckoTaskTracer.h"
      59             : #endif
      60             : 
      61             : using namespace mozilla::dom;
      62             : using namespace mozilla::ipc;
      63             : 
      64             : namespace mozilla {
      65             : namespace net {
      66             : 
      67             : #if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION) || defined(DEBUG)
      68             : static bool gIPCSecurityDisabled = false;
      69             : #endif
      70             : 
      71           0 : NS_IMPL_ISUPPORTS(InterceptStreamListener,
      72             :                   nsIStreamListener,
      73             :                   nsIRequestObserver,
      74             :                   nsIProgressEventSink)
      75             : 
      76             : NS_IMETHODIMP
      77           0 : InterceptStreamListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
      78             : {
      79           0 :   if (mOwner) {
      80           0 :     mOwner->DoOnStartRequest(mOwner, mContext);
      81             :   }
      82           0 :   return NS_OK;
      83             : }
      84             : 
      85             : NS_IMETHODIMP
      86           0 : InterceptStreamListener::OnStatus(nsIRequest* aRequest, nsISupports* aContext,
      87             :                                   nsresult status, const char16_t* aStatusArg)
      88             : {
      89           0 :   if (mOwner) {
      90           0 :     mOwner->DoOnStatus(mOwner, status);
      91             :   }
      92           0 :   return NS_OK;
      93             : }
      94             : 
      95             : NS_IMETHODIMP
      96           0 : InterceptStreamListener::OnProgress(nsIRequest* aRequest, nsISupports* aContext,
      97             :                                     int64_t aProgress, int64_t aProgressMax)
      98             : {
      99           0 :   if (mOwner) {
     100           0 :     mOwner->DoOnProgress(mOwner, aProgress, aProgressMax);
     101             :   }
     102           0 :   return NS_OK;
     103             : }
     104             : 
     105             : NS_IMETHODIMP
     106           0 : InterceptStreamListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
     107             :                                          nsIInputStream* aInputStream, uint64_t aOffset,
     108             :                                          uint32_t aCount)
     109             : {
     110           0 :   if (!mOwner) {
     111           0 :     return NS_OK;
     112             :   }
     113             : 
     114             :   uint32_t loadFlags;
     115           0 :   mOwner->GetLoadFlags(&loadFlags);
     116             : 
     117           0 :   if (!(loadFlags & HttpBaseChannel::LOAD_BACKGROUND)) {
     118           0 :     nsCOMPtr<nsIURI> uri;
     119           0 :     mOwner->GetURI(getter_AddRefs(uri));
     120             : 
     121           0 :     nsAutoCString host;
     122           0 :     uri->GetHost(host);
     123             : 
     124           0 :     OnStatus(mOwner, aContext, NS_NET_STATUS_READING, NS_ConvertUTF8toUTF16(host).get());
     125             : 
     126           0 :     int64_t progress = aOffset + aCount;
     127           0 :     OnProgress(mOwner, aContext, progress, mOwner->mSynthesizedStreamLength);
     128             :   }
     129             : 
     130           0 :   mOwner->DoOnDataAvailable(mOwner, mContext, aInputStream, aOffset, aCount);
     131           0 :   return NS_OK;
     132             : }
     133             : 
     134             : NS_IMETHODIMP
     135           0 : InterceptStreamListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatusCode)
     136             : {
     137           0 :   if (mOwner) {
     138           0 :     mOwner->DoPreOnStopRequest(aStatusCode);
     139           0 :     mOwner->DoOnStopRequest(mOwner, aStatusCode, mContext);
     140             :   }
     141           0 :   Cleanup();
     142           0 :   return NS_OK;
     143             : }
     144             : 
     145             : void
     146           0 : InterceptStreamListener::Cleanup()
     147             : {
     148           0 :   mOwner = nullptr;
     149           0 :   mContext = nullptr;
     150           0 : }
     151             : 
     152             : //-----------------------------------------------------------------------------
     153             : // HttpChannelChild
     154             : //-----------------------------------------------------------------------------
     155             : 
     156           3 : HttpChannelChild::HttpChannelChild()
     157             :   : HttpAsyncAborter<HttpChannelChild>(this)
     158             :   , NeckoTargetHolder(nullptr)
     159             :   , mSynthesizedStreamLength(0)
     160             :   , mIsFromCache(false)
     161             :   , mCacheEntryAvailable(false)
     162             :   , mAltDataCacheEntryAvailable(false)
     163             :   , mCacheFetchCount(0)
     164             :   , mCacheLastFetched(0)
     165             :   , mCacheExpirationTime(nsICacheEntry::NO_EXPIRATION_TIME)
     166             :   , mSendResumeAt(false)
     167             :   , mDeletingChannelSent(false)
     168             :   , mIPCOpen(false)
     169             :   , mKeptAlive(false)
     170             :   , mUnknownDecoderInvolved(false)
     171             :   , mDivertingToParent(false)
     172             :   , mFlushedForDiversion(false)
     173             :   , mSuspendSent(false)
     174             :   , mSynthesizedResponse(false)
     175             :   , mShouldInterceptSubsequentRedirect(false)
     176             :   , mRedirectingForSubsequentSynthesizedResponse(false)
     177             :   , mPostRedirectChannelShouldIntercept(false)
     178             :   , mPostRedirectChannelShouldUpgrade(false)
     179             :   , mShouldParentIntercept(false)
     180             :   , mSuspendParentAfterSynthesizeResponse(false)
     181             :   , mBgChildMutex("HttpChannelChild::BgChildMutex")
     182           3 :   , mEventTargetMutex("HttpChannelChild::EventTargetMutex")
     183             : {
     184           3 :   LOG(("Creating HttpChannelChild @%p\n", this));
     185             : 
     186           3 :   mChannelCreationTime = PR_Now();
     187           3 :   mChannelCreationTimestamp = TimeStamp::Now();
     188           3 :   mAsyncOpenTime = TimeStamp::Now();
     189           3 :   mEventQ = new ChannelEventQueue(static_cast<nsIHttpChannel*>(this));
     190             : 
     191             : #if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION) || defined(DEBUG)
     192             :   static bool sSecurityPrefChecked = false;
     193           3 :   if (!sSecurityPrefChecked) {
     194             :     Preferences::AddBoolVarCache(&gIPCSecurityDisabled,
     195           1 :                                  "network.disable.ipc.security");
     196           1 :     sSecurityPrefChecked = true;
     197             :   }
     198             : #endif
     199           3 : }
     200             : 
     201           6 : HttpChannelChild::~HttpChannelChild()
     202             : {
     203           2 :   LOG(("Destroying HttpChannelChild @%p\n", this));
     204             : 
     205           2 :   ReleaseMainThreadOnlyReferences();
     206           6 : }
     207             : 
     208             : void
     209           2 : HttpChannelChild::ReleaseMainThreadOnlyReferences()
     210             : {
     211           2 :   if (NS_IsMainThread()) {
     212             :       // Already on main thread, let dtor to
     213             :       // take care of releasing references
     214           2 :       return;
     215             :   }
     216             : 
     217           0 :   nsTArray<nsCOMPtr<nsISupports>> arrayToRelease;
     218           0 :   arrayToRelease.AppendElement(mCacheKey.forget());
     219             : 
     220           0 :   NS_DispatchToMainThread(new ProxyReleaseRunnable(Move(arrayToRelease)));
     221             : }
     222             : //-----------------------------------------------------------------------------
     223             : // HttpChannelChild::nsISupports
     224             : //-----------------------------------------------------------------------------
     225             : 
     226         318 : NS_IMPL_ADDREF(HttpChannelChild)
     227             : 
     228         308 : NS_IMETHODIMP_(MozExternalRefCountType) HttpChannelChild::Release()
     229             : {
     230         308 :   nsrefcnt count = --mRefCnt;
     231         308 :   MOZ_ASSERT(int32_t(count) >= 0, "dup release");
     232         308 :   NS_LOG_RELEASE(this, count, "HttpChannelChild");
     233             : 
     234             :   // Normally we Send_delete in OnStopRequest, but when we need to retain the
     235             :   // remote channel for security info IPDL itself holds 1 reference, so we
     236             :   // Send_delete when refCnt==1.  But if !mIPCOpen, then there's nobody to send
     237             :   // to, so we fall through.
     238         308 :   if (mKeptAlive && count == 1 && mIPCOpen) {
     239           0 :     mKeptAlive = false;
     240             :     // We send a message to the parent, which calls SendDelete, and then the
     241             :     // child calling Send__delete__() to finally drop the refcount to 0.
     242           0 :     TrySendDeletingChannel();
     243           0 :     return 1;
     244             :   }
     245             : 
     246         308 :   if (count == 0) {
     247           2 :     mRefCnt = 1; /* stabilize */
     248           2 :     delete this;
     249           2 :     return 0;
     250             :   }
     251         306 :   return count;
     252             : }
     253             : 
     254         305 : NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
     255         305 :   NS_INTERFACE_MAP_ENTRY(nsIRequest)
     256         277 :   NS_INTERFACE_MAP_ENTRY(nsIChannel)
     257         202 :   NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
     258         160 :   NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
     259         156 :   NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)
     260         148 :   NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
     261         148 :   NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
     262         148 :   NS_INTERFACE_MAP_ENTRY(nsIClassOfService)
     263         145 :   NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
     264         145 :   NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
     265         145 :   NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
     266         145 :   NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
     267         143 :   NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
     268         143 :   NS_INTERFACE_MAP_ENTRY(nsIChildChannel)
     269         143 :   NS_INTERFACE_MAP_ENTRY(nsIHttpChannelChild)
     270         143 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAssociatedContentSecurity, GetAssociatedContentSecurity())
     271         143 :   NS_INTERFACE_MAP_ENTRY(nsIDivertableChannel)
     272         143 :   NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)
     273         142 : NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel)
     274             : 
     275             : //-----------------------------------------------------------------------------
     276             : // HttpChannelChild::PHttpChannelChild
     277             : //-----------------------------------------------------------------------------
     278             : 
     279             : void
     280           3 : HttpChannelChild::AddIPDLReference()
     281             : {
     282           3 :   MOZ_ASSERT(!mIPCOpen, "Attempt to retain more than one IPDL reference");
     283           3 :   mIPCOpen = true;
     284           3 :   AddRef();
     285           3 : }
     286             : 
     287             : void
     288           2 : HttpChannelChild::ReleaseIPDLReference()
     289             : {
     290           2 :   MOZ_ASSERT(mIPCOpen, "Attempt to release nonexistent IPDL reference");
     291           2 :   mIPCOpen = false;
     292           2 :   Release();
     293           2 : }
     294             : 
     295             : void
     296           3 : HttpChannelChild::OnBackgroundChildReady(HttpBackgroundChannelChild* aBgChild)
     297             : {
     298           3 :   LOG(("HttpChannelChild::OnBackgroundChildReady [this=%p, bgChild=%p]\n",
     299             :        this, aBgChild));
     300           3 :   MOZ_ASSERT(OnSocketThread());
     301             : 
     302             :   {
     303           6 :     MutexAutoLock lock(mBgChildMutex);
     304             : 
     305             :     // mBgChild might be removed or replaced while the original background
     306             :     // channel is inited on STS thread.
     307           3 :     if (mBgChild != aBgChild) {
     308           0 :       return;
     309             :     }
     310             : 
     311           3 :     MOZ_ASSERT(mBgInitFailCallback);
     312           3 :     mBgInitFailCallback = nullptr;
     313             :   }
     314             : }
     315             : 
     316             : void
     317           0 : HttpChannelChild::OnBackgroundChildDestroyed(HttpBackgroundChannelChild* aBgChild)
     318             : {
     319           0 :   LOG(("HttpChannelChild::OnBackgroundChildDestroyed [this=%p]\n", this));
     320             :   // This function might be called during shutdown phase, so OnSocketThread()
     321             :   // might return false even on STS thread. Use IsOnCurrentThreadInfallible()
     322             :   // to get correct information.
     323           0 :   MOZ_ASSERT(gSocketTransportService);
     324           0 :   MOZ_ASSERT(gSocketTransportService->IsOnCurrentThreadInfallible());
     325             : 
     326           0 :   nsCOMPtr<nsIRunnable> callback;
     327             :   {
     328           0 :     MutexAutoLock lock(mBgChildMutex);
     329             : 
     330             :     // mBgChild might be removed or replaced while the original background
     331             :     // channel is destroyed on STS thread.
     332           0 :     if (aBgChild != mBgChild) {
     333           0 :       return;
     334             :     }
     335             : 
     336           0 :     mBgChild = nullptr;
     337           0 :     callback = mBgInitFailCallback.forget();
     338             :   }
     339             : 
     340           0 :   if (callback) {
     341           0 :     nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
     342           0 :     neckoTarget->Dispatch(callback, NS_DISPATCH_NORMAL);
     343             :   }
     344             : }
     345             : 
     346           0 : class AssociateApplicationCacheEvent : public NeckoTargetChannelEvent<HttpChannelChild>
     347             : {
     348             :   public:
     349           0 :     AssociateApplicationCacheEvent(HttpChannelChild* aChild,
     350             :                                    const nsCString &aGroupID,
     351             :                                    const nsCString &aClientID)
     352           0 :     : NeckoTargetChannelEvent<HttpChannelChild>(aChild)
     353             :     , groupID(aGroupID)
     354           0 :     , clientID(aClientID) {}
     355             : 
     356           0 :     void Run() { mChild->AssociateApplicationCache(groupID, clientID); }
     357             : 
     358             :   private:
     359             :     nsCString groupID;
     360             :     nsCString clientID;
     361             : };
     362             : 
     363             : mozilla::ipc::IPCResult
     364           0 : HttpChannelChild::RecvAssociateApplicationCache(const nsCString &groupID,
     365             :                                                 const nsCString &clientID)
     366             : {
     367           0 :   LOG(("HttpChannelChild::RecvAssociateApplicationCache [this=%p]\n", this));
     368           0 :   mEventQ->RunOrEnqueue(new AssociateApplicationCacheEvent(this, groupID,
     369           0 :                                                            clientID));
     370           0 :   return IPC_OK();
     371             : }
     372             : 
     373             : void
     374           0 : HttpChannelChild::AssociateApplicationCache(const nsCString &groupID,
     375             :                                             const nsCString &clientID)
     376             : {
     377           0 :   LOG(("HttpChannelChild::AssociateApplicationCache [this=%p]\n", this));
     378             :   nsresult rv;
     379           0 :   mApplicationCache = do_CreateInstance(NS_APPLICATIONCACHE_CONTRACTID, &rv);
     380           0 :   if (NS_FAILED(rv))
     381           0 :     return;
     382             : 
     383           0 :   mLoadedFromApplicationCache = true;
     384           0 :   mApplicationCache->InitAsHandle(groupID, clientID);
     385             : }
     386             : 
     387           9 : class StartRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild>
     388             : {
     389             :  public:
     390           3 :   StartRequestEvent(HttpChannelChild* aChild,
     391             :                     const nsresult& aChannelStatus,
     392             :                     const nsHttpResponseHead& aResponseHead,
     393             :                     const bool& aUseResponseHead,
     394             :                     const nsHttpHeaderArray& aRequestHeaders,
     395             :                     const bool& aIsFromCache,
     396             :                     const bool& aCacheEntryAvailable,
     397             :                     const int32_t& aCacheFetchCount,
     398             :                     const uint32_t& aCacheLastFetched,
     399             :                     const uint32_t& aCacheExpirationTime,
     400             :                     const nsCString& aCachedCharset,
     401             :                     const nsCString& aSecurityInfoSerialization,
     402             :                     const NetAddr& aSelfAddr,
     403             :                     const NetAddr& aPeerAddr,
     404             :                     const uint32_t& aCacheKey,
     405             :                     const nsCString& altDataType,
     406             :                     const int64_t& altDataLen)
     407           3 :   : NeckoTargetChannelEvent<HttpChannelChild>(aChild)
     408           3 :   , mChannelStatus(aChannelStatus)
     409             :   , mResponseHead(aResponseHead)
     410             :   , mRequestHeaders(aRequestHeaders)
     411           3 :   , mUseResponseHead(aUseResponseHead)
     412           3 :   , mIsFromCache(aIsFromCache)
     413           3 :   , mCacheEntryAvailable(aCacheEntryAvailable)
     414           3 :   , mCacheFetchCount(aCacheFetchCount)
     415           3 :   , mCacheLastFetched(aCacheLastFetched)
     416           3 :   , mCacheExpirationTime(aCacheExpirationTime)
     417             :   , mCachedCharset(aCachedCharset)
     418             :   , mSecurityInfoSerialization(aSecurityInfoSerialization)
     419             :   , mSelfAddr(aSelfAddr)
     420             :   , mPeerAddr(aPeerAddr)
     421           3 :   , mCacheKey(aCacheKey)
     422             :   , mAltDataType(altDataType)
     423          27 :   , mAltDataLen(altDataLen)
     424           3 :   {}
     425             : 
     426           3 :   void Run()
     427             :   {
     428           3 :     LOG(("StartRequestEvent [this=%p]\n", mChild));
     429           3 :     mChild->OnStartRequest(mChannelStatus, mResponseHead, mUseResponseHead,
     430             :                            mRequestHeaders, mIsFromCache, mCacheEntryAvailable,
     431             :                            mCacheFetchCount, mCacheLastFetched,
     432             :                            mCacheExpirationTime, mCachedCharset,
     433             :                            mSecurityInfoSerialization, mSelfAddr, mPeerAddr,
     434           3 :                            mCacheKey, mAltDataType, mAltDataLen);
     435           3 :   }
     436             : 
     437             :  private:
     438             :   nsresult mChannelStatus;
     439             :   nsHttpResponseHead mResponseHead;
     440             :   nsHttpHeaderArray mRequestHeaders;
     441             :   bool mUseResponseHead;
     442             :   bool mIsFromCache;
     443             :   bool mCacheEntryAvailable;
     444             :   int32_t mCacheFetchCount;
     445             :   uint32_t mCacheLastFetched;
     446             :   uint32_t mCacheExpirationTime;
     447             :   nsCString mCachedCharset;
     448             :   nsCString mSecurityInfoSerialization;
     449             :   NetAddr mSelfAddr;
     450             :   NetAddr mPeerAddr;
     451             :   uint32_t mCacheKey;
     452             :   nsCString mAltDataType;
     453             :   int64_t mAltDataLen;
     454             : };
     455             : 
     456             : mozilla::ipc::IPCResult
     457           3 : HttpChannelChild::RecvOnStartRequest(const nsresult& channelStatus,
     458             :                                      const nsHttpResponseHead& responseHead,
     459             :                                      const bool& useResponseHead,
     460             :                                      const nsHttpHeaderArray& requestHeaders,
     461             :                                      const bool& isFromCache,
     462             :                                      const bool& cacheEntryAvailable,
     463             :                                      const int32_t& cacheFetchCount,
     464             :                                      const uint32_t& cacheLastFetched,
     465             :                                      const uint32_t& cacheExpirationTime,
     466             :                                      const nsCString& cachedCharset,
     467             :                                      const nsCString& securityInfoSerialization,
     468             :                                      const NetAddr& selfAddr,
     469             :                                      const NetAddr& peerAddr,
     470             :                                      const int16_t& redirectCount,
     471             :                                      const uint32_t& cacheKey,
     472             :                                      const nsCString& altDataType,
     473             :                                      const int64_t& altDataLen)
     474             : {
     475           3 :   LOG(("HttpChannelChild::RecvOnStartRequest [this=%p]\n", this));
     476             :   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
     477             :   // stage, as they are set in the listener's OnStartRequest.
     478           3 :   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     479             :     "mFlushedForDiversion should be unset before OnStartRequest!");
     480           3 :   MOZ_RELEASE_ASSERT(!mDivertingToParent,
     481             :     "mDivertingToParent should be unset before OnStartRequest!");
     482             : 
     483             : 
     484           3 :   mRedirectCount = redirectCount;
     485             : 
     486           3 :   mEventQ->RunOrEnqueue(new StartRequestEvent(this, channelStatus, responseHead,
     487             :                                               useResponseHead, requestHeaders,
     488             :                                               isFromCache, cacheEntryAvailable,
     489             :                                               cacheFetchCount, cacheLastFetched,
     490             :                                               cacheExpirationTime, cachedCharset,
     491             :                                               securityInfoSerialization,
     492             :                                               selfAddr, peerAddr, cacheKey,
     493           6 :                                               altDataType, altDataLen));
     494             : 
     495             :   {
     496             :     // Child's mEventQ is to control the execution order of the IPC messages
     497             :     // from both main thread IPDL and PBackground IPDL.
     498             :     // To guarantee the ordering, PBackground IPC messages that are sent after
     499             :     // OnStartRequest will be throttled until OnStartRequest hits the Child's
     500             :     // mEventQ.
     501           6 :     MutexAutoLock lock(mBgChildMutex);
     502             : 
     503           3 :     if (mBgChild) {
     504           3 :       MOZ_RELEASE_ASSERT(gSocketTransportService);
     505             :       DebugOnly<nsresult> rv =
     506           6 :         gSocketTransportService->Dispatch(
     507           6 :           NewRunnableMethod(
     508             :             "HttpBackgroundChannelChild::OnStartRequestReceived",
     509             :             mBgChild, &HttpBackgroundChannelChild::OnStartRequestReceived),
     510           9 :         NS_DISPATCH_NORMAL);
     511             :     }
     512             :   }
     513             : 
     514           3 :   return IPC_OK();
     515             : }
     516             : 
     517             : void
     518           3 : HttpChannelChild::OnStartRequest(const nsresult& channelStatus,
     519             :                                  const nsHttpResponseHead& responseHead,
     520             :                                  const bool& useResponseHead,
     521             :                                  const nsHttpHeaderArray& requestHeaders,
     522             :                                  const bool& isFromCache,
     523             :                                  const bool& cacheEntryAvailable,
     524             :                                  const int32_t& cacheFetchCount,
     525             :                                  const uint32_t& cacheLastFetched,
     526             :                                  const uint32_t& cacheExpirationTime,
     527             :                                  const nsCString& cachedCharset,
     528             :                                  const nsCString& securityInfoSerialization,
     529             :                                  const NetAddr& selfAddr,
     530             :                                  const NetAddr& peerAddr,
     531             :                                  const uint32_t& cacheKey,
     532             :                                  const nsCString& altDataType,
     533             :                                  const int64_t& altDataLen)
     534             : {
     535           3 :   LOG(("HttpChannelChild::OnStartRequest [this=%p]\n", this));
     536             : 
     537             :   // mFlushedForDiversion and mDivertingToParent should NEVER be set at this
     538             :   // stage, as they are set in the listener's OnStartRequest.
     539           3 :   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     540             :     "mFlushedForDiversion should be unset before OnStartRequest!");
     541           3 :   MOZ_RELEASE_ASSERT(!mDivertingToParent,
     542             :     "mDivertingToParent should be unset before OnStartRequest!");
     543             : 
     544           3 :   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
     545           3 :     mStatus = channelStatus;
     546             :   }
     547             : 
     548           3 :   if (useResponseHead && !mCanceled)
     549           3 :     mResponseHead = new nsHttpResponseHead(responseHead);
     550             : 
     551           3 :   if (!securityInfoSerialization.IsEmpty()) {
     552           0 :     NS_DeserializeObject(securityInfoSerialization,
     553           0 :                          getter_AddRefs(mSecurityInfo));
     554             :   }
     555             : 
     556           3 :   mIsFromCache = isFromCache;
     557           3 :   mCacheEntryAvailable = cacheEntryAvailable;
     558           3 :   mCacheFetchCount = cacheFetchCount;
     559           3 :   mCacheLastFetched = cacheLastFetched;
     560           3 :   mCacheExpirationTime = cacheExpirationTime;
     561           3 :   mCachedCharset = cachedCharset;
     562           3 :   mSelfAddr = selfAddr;
     563           3 :   mPeerAddr = peerAddr;
     564             : 
     565           3 :   mAvailableCachedAltDataType = altDataType;
     566           3 :   mAltDataLength = altDataLen;
     567             : 
     568           3 :   mAfterOnStartRequestBegun = true;
     569             : 
     570           6 :   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     571             : 
     572             :   nsresult rv;
     573             :   nsCOMPtr<nsISupportsPRUint32> container =
     574           6 :     do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
     575           3 :   if (NS_FAILED(rv)) {
     576           0 :     Cancel(rv);
     577           0 :     return;
     578             :   }
     579             : 
     580           3 :   rv = container->SetData(cacheKey);
     581           3 :   if (NS_FAILED(rv)) {
     582           0 :     Cancel(rv);
     583           0 :     return;
     584             :   }
     585           3 :   mCacheKey = container;
     586             : 
     587             :   // replace our request headers with what actually got sent in the parent
     588           3 :   mRequestHead.SetHeaders(requestHeaders);
     589             : 
     590             :   // Note: this is where we would notify "http-on-examine-response" observers.
     591             :   // We have deliberately disabled this for child processes (see bug 806753)
     592             :   //
     593             :   // gHttpHandler->OnExamineResponse(this);
     594             : 
     595           3 :   mTracingEnabled = false;
     596             : 
     597           3 :   DoOnStartRequest(this, mListenerContext);
     598             : }
     599             : 
     600             : namespace {
     601             : 
     602             : class SyntheticDiversionListener final : public nsIStreamListener
     603             : {
     604             :   RefPtr<HttpChannelChild> mChannel;
     605             : 
     606           0 :   ~SyntheticDiversionListener()
     607           0 :   {
     608           0 :   }
     609             : 
     610             : public:
     611           0 :   explicit SyntheticDiversionListener(HttpChannelChild* aChannel)
     612           0 :     : mChannel(aChannel)
     613             :   {
     614           0 :     MOZ_ASSERT(mChannel);
     615           0 :   }
     616             : 
     617             :   NS_IMETHOD
     618           0 :   OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) override
     619             :   {
     620           0 :     MOZ_ASSERT_UNREACHABLE("SyntheticDiversionListener should never see OnStartRequest");
     621             :     return NS_OK;
     622             :   }
     623             : 
     624             :   NS_IMETHOD
     625           0 :   OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
     626             :                 nsresult aStatus) override
     627             :   {
     628           0 :     mChannel->SendDivertOnStopRequest(aStatus);
     629           0 :     return NS_OK;
     630             :   }
     631             : 
     632             :   NS_IMETHOD
     633           0 :   OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
     634             :                   nsIInputStream* aInputStream, uint64_t aOffset,
     635             :                   uint32_t aCount) override
     636             :   {
     637           0 :     nsAutoCString data;
     638           0 :     nsresult rv = NS_ConsumeStream(aInputStream, aCount, data);
     639           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     640           0 :       aRequest->Cancel(rv);
     641           0 :       return rv;
     642             :     }
     643             : 
     644           0 :     mChannel->SendDivertOnDataAvailable(data, aOffset, aCount);
     645           0 :     return NS_OK;
     646             :   }
     647             : 
     648             :   NS_DECL_ISUPPORTS
     649             : };
     650             : 
     651           0 : NS_IMPL_ISUPPORTS(SyntheticDiversionListener, nsIStreamListener);
     652             : 
     653             : } // anonymous namespace
     654             : 
     655             : void
     656           3 : HttpChannelChild::DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
     657             : {
     658           3 :   LOG(("HttpChannelChild::DoOnStartRequest [this=%p]\n", this));
     659             : 
     660             :   // In theory mListener should not be null, but in practice sometimes it is.
     661           3 :   MOZ_ASSERT(mListener);
     662           3 :   if (!mListener) {
     663           0 :     Cancel(NS_ERROR_FAILURE);
     664           0 :     return;
     665             :   }
     666           3 :   nsresult rv = mListener->OnStartRequest(aRequest, aContext);
     667           3 :   if (NS_FAILED(rv)) {
     668           0 :     Cancel(rv);
     669           0 :     return;
     670             :   }
     671             : 
     672           3 :   if (mDivertingToParent) {
     673           0 :     mListener = nullptr;
     674           0 :     mListenerContext = nullptr;
     675           0 :     mCompressListener = nullptr;
     676           0 :     if (mLoadGroup) {
     677           0 :       mLoadGroup->RemoveRequest(this, nullptr, mStatus);
     678             :     }
     679             : 
     680             :     // If the response has been synthesized in the child, then we are going
     681             :     // be getting OnDataAvailable and OnStopRequest from the synthetic
     682             :     // stream pump.  We need to forward these back to the parent diversion
     683             :     // listener.
     684           0 :     if (mSynthesizedResponse) {
     685           0 :       mListener = new SyntheticDiversionListener(this);
     686             :     }
     687             : 
     688           0 :     return;
     689             :   }
     690             : 
     691           6 :   nsCOMPtr<nsIStreamListener> listener;
     692           9 :   rv = DoApplyContentConversions(mListener, getter_AddRefs(listener),
     693           6 :                                  mListenerContext);
     694           3 :   if (NS_FAILED(rv)) {
     695           0 :     Cancel(rv);
     696           3 :   } else if (listener) {
     697           0 :     mListener = listener;
     698           0 :     mCompressListener = listener;
     699             :   }
     700             : }
     701             : 
     702           9 : class TransportAndDataEvent : public ChannelEvent
     703             : {
     704             :  public:
     705           3 :   TransportAndDataEvent(HttpChannelChild* child,
     706             :                         const nsresult& channelStatus,
     707             :                         const nsresult& transportStatus,
     708             :                         const nsCString& data,
     709             :                         const uint64_t& offset,
     710             :                         const uint32_t& count)
     711           3 :   : mChild(child)
     712           3 :   , mChannelStatus(channelStatus)
     713           3 :   , mTransportStatus(transportStatus)
     714             :   , mData(data)
     715           3 :   , mOffset(offset)
     716          12 :   , mCount(count) {}
     717             : 
     718           3 :   void Run()
     719             :   {
     720           3 :     mChild->OnTransportAndData(mChannelStatus, mTransportStatus,
     721           3 :                                mOffset, mCount, mData);
     722           3 :   }
     723             : 
     724           9 :   already_AddRefed<nsIEventTarget> GetEventTarget()
     725             :   {
     726           9 :     MOZ_ASSERT(mChild);
     727          18 :     nsCOMPtr<nsIEventTarget> target = mChild->GetODATarget();
     728          18 :     return target.forget();
     729             :   }
     730             :  private:
     731             :   HttpChannelChild* mChild;
     732             :   nsresult mChannelStatus;
     733             :   nsresult mTransportStatus;
     734             :   nsCString mData;
     735             :   uint64_t mOffset;
     736             :   uint32_t mCount;
     737             : };
     738             : 
     739             : void
     740           3 : HttpChannelChild::ProcessOnTransportAndData(const nsresult& aChannelStatus,
     741             :                                             const nsresult& aTransportStatus,
     742             :                                             const uint64_t& aOffset,
     743             :                                             const uint32_t& aCount,
     744             :                                             const nsCString& aData)
     745             : {
     746           3 :   LOG(("HttpChannelChild::ProcessOnTransportAndData [this=%p]\n", this));
     747           3 :   MOZ_ASSERT(OnSocketThread());
     748           3 :   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     749             :                      "Should not be receiving any more callbacks from parent!");
     750           6 :   mEventQ->RunOrEnqueue(new TransportAndDataEvent(this, aChannelStatus,
     751             :                                                   aTransportStatus, aData,
     752           3 :                                                   aOffset, aCount),
     753           6 :                         mDivertingToParent);
     754           3 : }
     755             : 
     756           0 : class MaybeDivertOnDataHttpEvent : public NeckoTargetChannelEvent<HttpChannelChild>
     757             : {
     758             :  public:
     759           0 :   MaybeDivertOnDataHttpEvent(HttpChannelChild* child,
     760             :                              const nsCString& data,
     761             :                              const uint64_t& offset,
     762             :                              const uint32_t& count)
     763           0 :   : NeckoTargetChannelEvent<HttpChannelChild>(child)
     764             :   , mData(data)
     765           0 :   , mOffset(offset)
     766           0 :   , mCount(count) {}
     767             : 
     768           0 :   void Run()
     769             :   {
     770           0 :     mChild->MaybeDivertOnData(mData, mOffset, mCount);
     771           0 :   }
     772             : 
     773             :  private:
     774             :   nsCString mData;
     775             :   uint64_t mOffset;
     776             :   uint32_t mCount;
     777             : };
     778             : 
     779             : void
     780           0 : HttpChannelChild::MaybeDivertOnData(const nsCString& data,
     781             :                                     const uint64_t& offset,
     782             :                                     const uint32_t& count)
     783             : {
     784           0 :   LOG(("HttpChannelChild::MaybeDivertOnData [this=%p]", this));
     785             : 
     786           0 :   if (mDivertingToParent) {
     787           0 :     SendDivertOnDataAvailable(data, offset, count);
     788             :   }
     789           0 : }
     790             : 
     791             : void
     792           3 : HttpChannelChild::OnTransportAndData(const nsresult& channelStatus,
     793             :                                      const nsresult& transportStatus,
     794             :                                      const uint64_t& offset,
     795             :                                      const uint32_t& count,
     796             :                                      const nsCString& data)
     797             : {
     798           3 :   LOG(("HttpChannelChild::OnTransportAndData [this=%p]\n", this));
     799             : 
     800           3 :   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
     801           3 :     mStatus = channelStatus;
     802             :   }
     803             : 
     804             :   // For diversion to parent, just SendDivertOnDataAvailable.
     805           3 :   if (mDivertingToParent) {
     806           0 :     MOZ_ASSERT(NS_IsMainThread());
     807           0 :     MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     808             :       "Should not be processing any more callbacks from parent!");
     809             : 
     810           0 :     SendDivertOnDataAvailable(data, offset, count);
     811           0 :     return;
     812             :   }
     813             : 
     814           3 :   if (mCanceled)
     815           0 :     return;
     816             : 
     817           3 :   if (mUnknownDecoderInvolved) {
     818           0 :     LOG(("UnknownDecoder is involved queue OnDataAvailable call. [this=%p]",
     819             :          this));
     820           0 :     MOZ_ASSERT(NS_IsMainThread());
     821           0 :     mUnknownDecoderEventQ.AppendElement(
     822           0 :       MakeUnique<MaybeDivertOnDataHttpEvent>(this, data, offset, count));
     823             :   }
     824             : 
     825             :   // Hold queue lock throughout all three calls, else we might process a later
     826             :   // necko msg in between them.
     827           6 :   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
     828             : 
     829             :   int64_t progressMax;
     830           3 :   if (NS_FAILED(GetContentLength(&progressMax))) {
     831           0 :     progressMax = -1;
     832             :   }
     833             : 
     834           3 :   const int64_t progress = offset + count;
     835             : 
     836             :   // OnTransportAndData will be run on retargeted thread if applicable, however
     837             :   // OnStatus/OnProgress event can only be fired on main thread. We need to
     838             :   // dispatch the status/progress event handling back to main thread with the
     839             :   // appropriate event target for networking.
     840           3 :   if (NS_IsMainThread()) {
     841           2 :     DoOnStatus(this, transportStatus);
     842           2 :     DoOnProgress(this, progress, progressMax);
     843             :   } else {
     844           2 :     RefPtr<HttpChannelChild> self = this;
     845           2 :     nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
     846           1 :     MOZ_ASSERT(neckoTarget);
     847             : 
     848           3 :     DebugOnly<nsresult> rv = neckoTarget->Dispatch(
     849           3 :       NS_NewRunnableFunction("net::HttpChannelChild::OnTransportAndData",
     850           5 :                              [self, transportStatus, progress, progressMax]() {
     851           1 :                                self->DoOnStatus(self, transportStatus);
     852           1 :                                self->DoOnProgress(self, progress, progressMax);
     853           1 :                              }),
     854           4 :       NS_DISPATCH_NORMAL);
     855           1 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
     856             :   }
     857             : 
     858             :   // OnDataAvailable
     859             :   //
     860             :   // NOTE: the OnDataAvailable contract requires the client to read all the data
     861             :   // in the inputstream.  This code relies on that ('data' will go away after
     862             :   // this function).  Apparently the previous, non-e10s behavior was to actually
     863             :   // support only reading part of the data, allowing later calls to read the
     864             :   // rest.
     865           6 :   nsCOMPtr<nsIInputStream> stringStream;
     866           6 :   nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), data.get(),
     867           6 :                                       count, NS_ASSIGNMENT_DEPEND);
     868           3 :   if (NS_FAILED(rv)) {
     869           0 :     Cancel(rv);
     870           0 :     return;
     871             :   }
     872             : 
     873           3 :   DoOnDataAvailable(this, mListenerContext, stringStream, offset, count);
     874           3 :   stringStream->Close();
     875             : }
     876             : 
     877             : void
     878           3 : HttpChannelChild::DoOnStatus(nsIRequest* aRequest, nsresult status)
     879             : {
     880           3 :   LOG(("HttpChannelChild::DoOnStatus [this=%p]\n", this));
     881           3 :   MOZ_ASSERT(NS_IsMainThread());
     882             : 
     883           3 :   if (mCanceled)
     884           0 :     return;
     885             : 
     886             :   // cache the progress sink so we don't have to query for it each time.
     887           3 :   if (!mProgressSink)
     888           2 :     GetCallback(mProgressSink);
     889             : 
     890             :   // Temporary fix for bug 1116124
     891             :   // See 1124971 - Child removes LOAD_BACKGROUND flag from channel
     892           3 :   if (status == NS_OK)
     893           0 :     return;
     894             : 
     895             :   // block status/progress after Cancel or OnStopRequest has been called,
     896             :   // or if channel has LOAD_BACKGROUND set.
     897           6 :   if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
     898           3 :       !(mLoadFlags & LOAD_BACKGROUND))
     899             :   {
     900             :     // OnStatus
     901             :     //
     902           3 :     MOZ_ASSERT(status == NS_NET_STATUS_RECEIVING_FROM ||
     903             :                status == NS_NET_STATUS_READING);
     904             : 
     905           6 :     nsAutoCString host;
     906           3 :     mURI->GetHost(host);
     907           6 :     mProgressSink->OnStatus(aRequest, nullptr, status,
     908           6 :                             NS_ConvertUTF8toUTF16(host).get());
     909             :   }
     910             : }
     911             : 
     912             : void
     913           3 : HttpChannelChild::DoOnProgress(nsIRequest* aRequest, int64_t progress, int64_t progressMax)
     914             : {
     915           3 :   LOG(("HttpChannelChild::DoOnProgress [this=%p]\n", this));
     916           3 :   MOZ_ASSERT(NS_IsMainThread());
     917             : 
     918           3 :   if (mCanceled)
     919           0 :     return;
     920             : 
     921             :   // cache the progress sink so we don't have to query for it each time.
     922           3 :   if (!mProgressSink)
     923           0 :     GetCallback(mProgressSink);
     924             : 
     925             :   // block status/progress after Cancel or OnStopRequest has been called,
     926             :   // or if channel has LOAD_BACKGROUND set.
     927           6 :   if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
     928           3 :       !(mLoadFlags & LOAD_BACKGROUND))
     929             :   {
     930             :     // OnProgress
     931             :     //
     932           3 :     if (progress > 0) {
     933           3 :       mProgressSink->OnProgress(aRequest, nullptr, progress, progressMax);
     934             :     }
     935             :   }
     936             : }
     937             : 
     938             : void
     939           3 : HttpChannelChild::DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
     940             :                                     nsIInputStream* aStream,
     941             :                                     uint64_t offset, uint32_t count)
     942             : {
     943           3 :   LOG(("HttpChannelChild::DoOnDataAvailable [this=%p]\n", this));
     944           3 :   if (mCanceled)
     945           0 :     return;
     946             : 
     947           3 :   nsresult rv = mListener->OnDataAvailable(aRequest, aContext, aStream, offset, count);
     948           3 :   if (NS_FAILED(rv)) {
     949           0 :     CancelOnMainThread(rv);
     950             :   }
     951             : }
     952             : 
     953           9 : class StopRequestEvent : public NeckoTargetChannelEvent<HttpChannelChild>
     954             : {
     955             :  public:
     956           3 :   StopRequestEvent(HttpChannelChild* child,
     957             :                    const nsresult& channelStatus,
     958             :                    const ResourceTimingStruct& timing)
     959           3 :   : NeckoTargetChannelEvent<HttpChannelChild>(child)
     960           3 :   , mChannelStatus(channelStatus)
     961           6 :   , mTiming(timing) {}
     962             : 
     963           3 :   void Run() { mChild->OnStopRequest(mChannelStatus, mTiming); }
     964             : 
     965             :  private:
     966             :   nsresult mChannelStatus;
     967             :   ResourceTimingStruct mTiming;
     968             : };
     969             : 
     970             : void
     971           3 : HttpChannelChild::ProcessOnStopRequest(const nsresult& aChannelStatus,
     972             :                                        const ResourceTimingStruct& aTiming)
     973             : {
     974           3 :   LOG(("HttpChannelChild::ProcessOnStopRequest [this=%p]\n", this));
     975           3 :   MOZ_ASSERT(OnSocketThread());
     976           3 :   MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
     977             :     "Should not be receiving any more callbacks from parent!");
     978             : 
     979           6 :   mEventQ->RunOrEnqueue(new StopRequestEvent(this, aChannelStatus, aTiming),
     980           6 :                         mDivertingToParent);
     981           3 : }
     982             : 
     983           0 : class MaybeDivertOnStopHttpEvent : public NeckoTargetChannelEvent<HttpChannelChild>
     984             : {
     985             :  public:
     986           0 :   MaybeDivertOnStopHttpEvent(HttpChannelChild* child,
     987             :                              const nsresult& channelStatus)
     988           0 :   : NeckoTargetChannelEvent<HttpChannelChild>(child)
     989           0 :   , mChannelStatus(channelStatus)
     990           0 :   {}
     991             : 
     992           0 :   void Run()
     993             :   {
     994           0 :     mChild->MaybeDivertOnStop(mChannelStatus);
     995           0 :   }
     996             : 
     997             :  private:
     998             :   nsresult mChannelStatus;
     999             : };
    1000             : 
    1001             : void
    1002           0 : HttpChannelChild::MaybeDivertOnStop(const nsresult& aChannelStatus)
    1003             : {
    1004           0 :   LOG(("HttpChannelChild::MaybeDivertOnStop [this=%p, "
    1005             :        "mDivertingToParent=%d status=%" PRIx32 "]", this,
    1006             :        static_cast<bool>(mDivertingToParent),
    1007             :        static_cast<uint32_t>(aChannelStatus)));
    1008           0 :   if (mDivertingToParent) {
    1009           0 :     SendDivertOnStopRequest(aChannelStatus);
    1010             :   }
    1011           0 : }
    1012             : 
    1013             : void
    1014           3 : HttpChannelChild::OnStopRequest(const nsresult& channelStatus,
    1015             :                                 const ResourceTimingStruct& timing)
    1016             : {
    1017           3 :   LOG(("HttpChannelChild::OnStopRequest [this=%p status=%" PRIx32 "]\n",
    1018             :        this, static_cast<uint32_t>(channelStatus)));
    1019           3 :   MOZ_ASSERT(NS_IsMainThread());
    1020             : 
    1021           3 :   if (mDivertingToParent) {
    1022           0 :     MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
    1023             :       "Should not be processing any more callbacks from parent!");
    1024             : 
    1025           0 :     SendDivertOnStopRequest(channelStatus);
    1026           0 :     return;
    1027             :   }
    1028             : 
    1029           3 :   if (mUnknownDecoderInvolved) {
    1030           0 :    LOG(("UnknownDecoder is involved queue OnStopRequest call. [this=%p]",
    1031             :         this));
    1032           0 :     MOZ_ASSERT(NS_IsMainThread());
    1033           0 :     mUnknownDecoderEventQ.AppendElement(
    1034           0 :       MakeUnique<MaybeDivertOnStopHttpEvent>(this, channelStatus));
    1035             :   }
    1036             : 
    1037           6 :   nsCOMPtr<nsICompressConvStats> conv = do_QueryInterface(mCompressListener);
    1038           3 :   if (conv) {
    1039           0 :       conv->GetDecodedDataLength(&mDecodedBodySize);
    1040             :   }
    1041             : 
    1042           3 :   mTransactionTimings.domainLookupStart = timing.domainLookupStart;
    1043           3 :   mTransactionTimings.domainLookupEnd = timing.domainLookupEnd;
    1044           3 :   mTransactionTimings.connectStart = timing.connectStart;
    1045           3 :   mTransactionTimings.connectEnd = timing.connectEnd;
    1046           3 :   mTransactionTimings.requestStart = timing.requestStart;
    1047           3 :   mTransactionTimings.responseStart = timing.responseStart;
    1048           3 :   mTransactionTimings.responseEnd = timing.responseEnd;
    1049             : 
    1050             :   // Do not overwrite or adjust the original mAsyncOpenTime by timing.fetchStart
    1051             :   // We must use the original child process time in order to account for child
    1052             :   // side work and IPC transit overhead.
    1053             :   // XXX: This depends on TimeStamp being equivalent across processes.
    1054             :   // This is true for modern hardware but for older platforms it is not always
    1055             :   // true.
    1056             : 
    1057           3 :   mRedirectStartTimeStamp = timing.redirectStart;
    1058           3 :   mRedirectEndTimeStamp = timing.redirectEnd;
    1059           3 :   mTransferSize = timing.transferSize;
    1060           3 :   mEncodedBodySize = timing.encodedBodySize;
    1061           3 :   mProtocolVersion = timing.protocolVersion;
    1062             : 
    1063           3 :   mCacheReadStart = timing.cacheReadStart;
    1064           3 :   mCacheReadEnd = timing.cacheReadEnd;
    1065             : 
    1066           3 :   Performance* documentPerformance = GetPerformance();
    1067           3 :   if (documentPerformance) {
    1068           2 :       documentPerformance->AddEntry(this, this);
    1069             :   }
    1070             : 
    1071           3 :   DoPreOnStopRequest(channelStatus);
    1072             : 
    1073             :   { // We must flush the queue before we Send__delete__
    1074             :     // (although we really shouldn't receive any msgs after OnStop),
    1075             :     // so make sure this goes out of scope before then.
    1076           6 :     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
    1077             : 
    1078           3 :     DoOnStopRequest(this, channelStatus, mListenerContext);
    1079             :     // DoOnStopRequest() calls ReleaseListeners()
    1080             :   }
    1081             : 
    1082           3 :   CleanupBackgroundChannel();
    1083             : 
    1084             :   // DocumentChannelCleanup actually nulls out mCacheEntry in the parent, which
    1085             :   // we might need later to open the Alt-Data output stream, so just return here
    1086           3 :   if (!mPreferredCachedAltDataType.IsEmpty()) {
    1087           0 :     mKeptAlive = true;
    1088           0 :     return;
    1089             :   }
    1090             : 
    1091           3 :   if (mLoadFlags & LOAD_DOCUMENT_URI) {
    1092             :     // Keep IPDL channel open, but only for updating security info.
    1093             :     // If IPDL is already closed, then do nothing.
    1094           1 :     if (mIPCOpen) {
    1095           1 :       mKeptAlive = true;
    1096           1 :       SendDocumentChannelCleanup();
    1097             :     }
    1098             :   } else {
    1099             :     // The parent process will respond by sending a DeleteSelf message and
    1100             :     // making sure not to send any more messages after that.
    1101           2 :     TrySendDeletingChannel();
    1102             :   }
    1103             : }
    1104             : 
    1105             : void
    1106           3 : HttpChannelChild::DoPreOnStopRequest(nsresult aStatus)
    1107             : {
    1108           3 :   LOG(("HttpChannelChild::DoPreOnStopRequest [this=%p status=%" PRIx32 "]\n",
    1109             :        this, static_cast<uint32_t>(aStatus)));
    1110           3 :   mIsPending = false;
    1111             : 
    1112           3 :   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
    1113           3 :     mStatus = aStatus;
    1114             :   }
    1115           3 : }
    1116             : 
    1117             : void
    1118           3 : HttpChannelChild::DoOnStopRequest(nsIRequest* aRequest, nsresult aChannelStatus, nsISupports* aContext)
    1119             : {
    1120           3 :   LOG(("HttpChannelChild::DoOnStopRequest [this=%p]\n", this));
    1121           3 :   MOZ_ASSERT(NS_IsMainThread());
    1122           3 :   MOZ_ASSERT(!mIsPending);
    1123             : 
    1124             :   // NB: We use aChannelStatus here instead of mStatus because if there was an
    1125             :   // nsCORSListenerProxy on this request, it will override the tracking
    1126             :   // protection's return value.
    1127           3 :   if (aChannelStatus == NS_ERROR_TRACKING_URI ||
    1128           3 :       aChannelStatus == NS_ERROR_MALWARE_URI ||
    1129           3 :       aChannelStatus == NS_ERROR_UNWANTED_URI ||
    1130           3 :       aChannelStatus == NS_ERROR_BLOCKED_URI ||
    1131             :       aChannelStatus == NS_ERROR_PHISHING_URI) {
    1132           0 :     nsCString list, provider, prefix;
    1133             : 
    1134           0 :     nsresult rv = GetMatchedList(list);
    1135           0 :     NS_ENSURE_SUCCESS_VOID(rv);
    1136             : 
    1137           0 :     rv = GetMatchedProvider(provider);
    1138           0 :     NS_ENSURE_SUCCESS_VOID(rv);
    1139             : 
    1140           0 :     rv = GetMatchedPrefix(prefix);
    1141           0 :     NS_ENSURE_SUCCESS_VOID(rv);
    1142             : 
    1143           0 :     nsChannelClassifier::SetBlockedContent(this, aChannelStatus, list, provider, prefix);
    1144             :   }
    1145             : 
    1146           3 :   MOZ_ASSERT(!mOnStopRequestCalled,
    1147             :              "We should not call OnStopRequest twice");
    1148             : 
    1149             :   // In theory mListener should not be null, but in practice sometimes it is.
    1150           3 :   MOZ_ASSERT(mListener);
    1151           3 :   if (mListener) {
    1152           3 :     mListener->OnStopRequest(aRequest, aContext, mStatus);
    1153             :   }
    1154           3 :   mOnStopRequestCalled = true;
    1155             : 
    1156           3 :   ReleaseListeners();
    1157             : 
    1158             :   // If a preferred alt-data type was set, the parent would hold a reference to
    1159             :   // the cache entry in case the child calls openAlternativeOutputStream().
    1160             :   // (see nsHttpChannel::OnStopRequest)
    1161           3 :   if (!mPreferredCachedAltDataType.IsEmpty()) {
    1162           0 :     mAltDataCacheEntryAvailable = mCacheEntryAvailable;
    1163             :   }
    1164           3 :   mCacheEntryAvailable = false;
    1165             : 
    1166           3 :   if (mLoadGroup)
    1167           3 :     mLoadGroup->RemoveRequest(this, nullptr, mStatus);
    1168             : }
    1169             : 
    1170           0 : class ProgressEvent : public NeckoTargetChannelEvent<HttpChannelChild>
    1171             : {
    1172             :  public:
    1173           0 :   ProgressEvent(HttpChannelChild* child,
    1174             :                 const int64_t& progress,
    1175             :                 const int64_t& progressMax)
    1176           0 :   : NeckoTargetChannelEvent<HttpChannelChild>(child)
    1177           0 :   , mProgress(progress)
    1178           0 :   , mProgressMax(progressMax) {}
    1179             : 
    1180           0 :   void Run() { mChild->OnProgress(mProgress, mProgressMax); }
    1181             : 
    1182             :  private:
    1183             :   int64_t mProgress, mProgressMax;
    1184             : };
    1185             : 
    1186             : void
    1187           0 : HttpChannelChild::ProcessOnProgress(const int64_t& aProgress,
    1188             :                                     const int64_t& aProgressMax)
    1189             : {
    1190           0 :   LOG(("HttpChannelChild::ProcessOnProgress [this=%p]\n", this));
    1191           0 :   MOZ_ASSERT(OnSocketThread());
    1192           0 :   mEventQ->RunOrEnqueue(new ProgressEvent(this, aProgress, aProgressMax));
    1193           0 : }
    1194             : 
    1195             : void
    1196           0 : HttpChannelChild::OnProgress(const int64_t& progress,
    1197             :                              const int64_t& progressMax)
    1198             : {
    1199           0 :   LOG(("HttpChannelChild::OnProgress [this=%p progress=%" PRId64 "/%" PRId64 "]\n",
    1200             :        this, progress, progressMax));
    1201             : 
    1202           0 :   if (mCanceled)
    1203           0 :     return;
    1204             : 
    1205             :   // cache the progress sink so we don't have to query for it each time.
    1206           0 :   if (!mProgressSink) {
    1207           0 :     GetCallback(mProgressSink);
    1208             :   }
    1209             : 
    1210           0 :   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
    1211             : 
    1212             :   // Block socket status event after Cancel or OnStopRequest has been called.
    1213           0 :   if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending)
    1214             :   {
    1215           0 :     if (progress > 0) {
    1216           0 :       mProgressSink->OnProgress(this, nullptr, progress, progressMax);
    1217             :     }
    1218             :   }
    1219             : }
    1220             : 
    1221          15 : class StatusEvent : public NeckoTargetChannelEvent<HttpChannelChild>
    1222             : {
    1223             :  public:
    1224           5 :   StatusEvent(HttpChannelChild* child,
    1225             :               const nsresult& status)
    1226           5 :   : NeckoTargetChannelEvent<HttpChannelChild>(child)
    1227           5 :   , mStatus(status) {}
    1228             : 
    1229           5 :   void Run() { mChild->OnStatus(mStatus); }
    1230             : 
    1231             :  private:
    1232             :   nsresult mStatus;
    1233             : };
    1234             : 
    1235             : void
    1236           5 : HttpChannelChild::ProcessOnStatus(const nsresult& aStatus)
    1237             : {
    1238           5 :   LOG(("HttpChannelChild::ProcessOnStatus [this=%p]\n", this));
    1239           5 :   MOZ_ASSERT(OnSocketThread());
    1240           5 :   mEventQ->RunOrEnqueue(new StatusEvent(this, aStatus));
    1241           5 : }
    1242             : 
    1243             : void
    1244           5 : HttpChannelChild::OnStatus(const nsresult& status)
    1245             : {
    1246           5 :   LOG(("HttpChannelChild::OnStatus [this=%p status=%" PRIx32 "]\n",
    1247             :        this, static_cast<uint32_t>(status)));
    1248             : 
    1249           5 :   if (mCanceled)
    1250           0 :     return;
    1251             : 
    1252             :   // cache the progress sink so we don't have to query for it each time.
    1253           5 :   if (!mProgressSink)
    1254           1 :     GetCallback(mProgressSink);
    1255             : 
    1256          10 :   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
    1257             : 
    1258             :   // block socket status event after Cancel or OnStopRequest has been called,
    1259             :   // or if channel has LOAD_BACKGROUND set
    1260          10 :   if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
    1261           5 :       !(mLoadFlags & LOAD_BACKGROUND))
    1262             :   {
    1263          10 :     nsAutoCString host;
    1264           5 :     mURI->GetHost(host);
    1265          10 :     mProgressSink->OnStatus(this, nullptr, status,
    1266          10 :                             NS_ConvertUTF8toUTF16(host).get());
    1267             :   }
    1268             : }
    1269             : 
    1270           0 : class FailedAsyncOpenEvent : public NeckoTargetChannelEvent<HttpChannelChild>
    1271             : {
    1272             :  public:
    1273           0 :   FailedAsyncOpenEvent(HttpChannelChild* child, const nsresult& status)
    1274           0 :   : NeckoTargetChannelEvent<HttpChannelChild>(child)
    1275           0 :   , mStatus(status) {}
    1276             : 
    1277           0 :   void Run() { mChild->FailedAsyncOpen(mStatus); }
    1278             : 
    1279             :  private:
    1280             :   nsresult mStatus;
    1281             : };
    1282             : 
    1283             : mozilla::ipc::IPCResult
    1284           0 : HttpChannelChild::RecvFailedAsyncOpen(const nsresult& status)
    1285             : {
    1286           0 :   LOG(("HttpChannelChild::RecvFailedAsyncOpen [this=%p]\n", this));
    1287           0 :   mEventQ->RunOrEnqueue(new FailedAsyncOpenEvent(this, status));
    1288           0 :   return IPC_OK();
    1289             : }
    1290             : 
    1291             : // We need to have an implementation of this function just so that we can keep
    1292             : // all references to mCallOnResume of type HttpChannelChild:  it's not OK in C++
    1293             : // to set a member function ptr to a base class function.
    1294             : void
    1295           0 : HttpChannelChild::HandleAsyncAbort()
    1296             : {
    1297           0 :   HttpAsyncAborter<HttpChannelChild>::HandleAsyncAbort();
    1298             : 
    1299             :   // Ignore all the messages from background channel after channel aborted.
    1300           0 :   CleanupBackgroundChannel();
    1301           0 : }
    1302             : 
    1303             : void
    1304           0 : HttpChannelChild::FailedAsyncOpen(const nsresult& status)
    1305             : {
    1306           0 :   LOG(("HttpChannelChild::FailedAsyncOpen [this=%p status=%" PRIx32 "]\n",
    1307             :        this, static_cast<uint32_t>(status)));
    1308           0 :   MOZ_ASSERT(NS_IsMainThread());
    1309             : 
    1310             :   // Might be called twice in race condition in theory.
    1311             :   // (one by RecvFailedAsyncOpen, another by
    1312             :   // HttpBackgroundChannelChild::ActorFailed)
    1313           0 :   if (NS_WARN_IF(NS_FAILED(mStatus))) {
    1314           0 :     return;
    1315             :   }
    1316             : 
    1317           0 :   mStatus = status;
    1318             : 
    1319             :   // We're already being called from IPDL, therefore already "async"
    1320           0 :   HandleAsyncAbort();
    1321             : 
    1322           0 :   if (mIPCOpen) {
    1323           0 :     TrySendDeletingChannel();
    1324             :   }
    1325             : }
    1326             : 
    1327             : void
    1328           3 : HttpChannelChild::CleanupBackgroundChannel()
    1329             : {
    1330           6 :   MutexAutoLock lock(mBgChildMutex);
    1331             : 
    1332           3 :   LOG(("HttpChannelChild::CleanupBackgroundChannel [this=%p bgChild=%p]\n",
    1333             :        this, mBgChild.get()));
    1334             : 
    1335           3 :   mBgInitFailCallback = nullptr;
    1336             : 
    1337           3 :   if (!mBgChild) {
    1338           0 :     return;
    1339             :   }
    1340             : 
    1341           6 :   RefPtr<HttpBackgroundChannelChild> bgChild = mBgChild.forget();
    1342             : 
    1343           3 :   MOZ_RELEASE_ASSERT(gSocketTransportService);
    1344           3 :   if (!OnSocketThread()) {
    1345           6 :     gSocketTransportService->Dispatch(
    1346           6 :       NewRunnableMethod(
    1347             :         "HttpBackgroundChannelChild::OnChannelClosed",
    1348             :         bgChild, &HttpBackgroundChannelChild::OnChannelClosed),
    1349           3 :       NS_DISPATCH_NORMAL);
    1350             :   } else {
    1351           0 :     bgChild->OnChannelClosed();
    1352             :   }
    1353             : }
    1354             : 
    1355             : void
    1356           0 : HttpChannelChild::DoNotifyListenerCleanup()
    1357             : {
    1358           0 :   LOG(("HttpChannelChild::DoNotifyListenerCleanup [this=%p]\n", this));
    1359             : 
    1360           0 :   if (mInterceptListener) {
    1361           0 :     mInterceptListener->Cleanup();
    1362           0 :     mInterceptListener = nullptr;
    1363             :   }
    1364           0 : }
    1365             : 
    1366           6 : class DeleteSelfEvent : public NeckoTargetChannelEvent<HttpChannelChild>
    1367             : {
    1368             :  public:
    1369           2 :   explicit DeleteSelfEvent(HttpChannelChild* child)
    1370           2 :   : NeckoTargetChannelEvent<HttpChannelChild>(child) {}
    1371           2 :   void Run() { mChild->DeleteSelf(); }
    1372             : };
    1373             : 
    1374             : mozilla::ipc::IPCResult
    1375           2 : HttpChannelChild::RecvDeleteSelf()
    1376             : {
    1377           2 :   LOG(("HttpChannelChild::RecvDeleteSelf [this=%p]\n", this));
    1378           2 :   mEventQ->RunOrEnqueue(new DeleteSelfEvent(this));
    1379           2 :   return IPC_OK();
    1380             : }
    1381             : 
    1382           0 : HttpChannelChild::OverrideRunnable::OverrideRunnable(
    1383             :   HttpChannelChild* aChannel,
    1384             :   HttpChannelChild* aNewChannel,
    1385             :   InterceptStreamListener* aListener,
    1386             :   nsIInputStream* aInput,
    1387           0 :   nsAutoPtr<nsHttpResponseHead>& aHead)
    1388           0 :   : Runnable("net::HttpChannelChild::OverrideRunnable")
    1389             : {
    1390           0 :   mChannel = aChannel;
    1391           0 :   mNewChannel = aNewChannel;
    1392           0 :   mListener = aListener;
    1393           0 :   mInput = aInput;
    1394           0 :   mHead = aHead;
    1395           0 : }
    1396             : 
    1397             : void
    1398           0 : HttpChannelChild::OverrideRunnable::OverrideWithSynthesizedResponse()
    1399             : {
    1400           0 :   if (mNewChannel) {
    1401           0 :     mNewChannel->OverrideWithSynthesizedResponse(mHead, mInput, mListener);
    1402             :   }
    1403           0 : }
    1404             : 
    1405             : NS_IMETHODIMP
    1406           0 : HttpChannelChild::OverrideRunnable::Run()
    1407             : {
    1408           0 :   bool ret = mChannel->Redirect3Complete(this);
    1409             : 
    1410             :   // If the method returns false, it means the IPDL connection is being
    1411             :   // asyncly torn down and reopened, and OverrideWithSynthesizedResponse
    1412             :   // will be called later from FinishInterceptedRedirect. This object will
    1413             :   // be assigned to HttpChannelChild::mOverrideRunnable in order to do so.
    1414             :   // If it is true, we can call the method right now.
    1415           0 :   if (ret) {
    1416           0 :     OverrideWithSynthesizedResponse();
    1417             :   }
    1418             : 
    1419           0 :   return NS_OK;
    1420             : }
    1421             : 
    1422             : mozilla::ipc::IPCResult
    1423           0 : HttpChannelChild::RecvFinishInterceptedRedirect()
    1424             : {
    1425             :   // Hold a ref to this to keep it from being deleted by Send__delete__()
    1426           0 :   RefPtr<HttpChannelChild> self(this);
    1427           0 :   Send__delete__(this);
    1428             : 
    1429             :   {
    1430             :     // Reset the event target since the IPC actor is about to be destroyed.
    1431             :     // Following channel event should be handled on main thread.
    1432           0 :     MutexAutoLock lock(mEventTargetMutex);
    1433           0 :     mNeckoTarget = nullptr;
    1434             :   }
    1435             : 
    1436             :   // The IPDL connection was torn down by a interception logic in
    1437             :   // CompleteRedirectSetup, and we need to call FinishInterceptedRedirect.
    1438           0 :   nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
    1439           0 :   MOZ_ASSERT(neckoTarget);
    1440             : 
    1441           0 :   Unused << neckoTarget->Dispatch(
    1442           0 :     NewRunnableMethod("net::HttpChannelChild::FinishInterceptedRedirect",
    1443             :                       this,
    1444             :                       &HttpChannelChild::FinishInterceptedRedirect),
    1445           0 :     NS_DISPATCH_NORMAL);
    1446             : 
    1447           0 :   return IPC_OK();
    1448             : }
    1449             : 
    1450             : void
    1451           2 : HttpChannelChild::DeleteSelf()
    1452             : {
    1453           2 :   Send__delete__(this);
    1454           2 : }
    1455             : 
    1456           0 : void HttpChannelChild::FinishInterceptedRedirect()
    1457             : {
    1458             :   nsresult rv;
    1459           0 :   if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
    1460           0 :     MOZ_ASSERT(!mInterceptedRedirectContext, "the context should be null!");
    1461           0 :     rv = AsyncOpen2(mInterceptedRedirectListener);
    1462             :   } else {
    1463           0 :     rv = AsyncOpen(mInterceptedRedirectListener, mInterceptedRedirectContext);
    1464             :   }
    1465           0 :   mInterceptedRedirectListener = nullptr;
    1466           0 :   mInterceptedRedirectContext = nullptr;
    1467             : 
    1468           0 :   if (mInterceptingChannel) {
    1469           0 :     mInterceptingChannel->CleanupRedirectingChannel(rv);
    1470           0 :     mInterceptingChannel = nullptr;
    1471             :   }
    1472             : 
    1473           0 :   if (mOverrideRunnable) {
    1474           0 :     mOverrideRunnable->OverrideWithSynthesizedResponse();
    1475           0 :     mOverrideRunnable = nullptr;
    1476             :   }
    1477           0 : }
    1478             : 
    1479             : mozilla::ipc::IPCResult
    1480           0 : HttpChannelChild::RecvReportSecurityMessage(const nsString& messageTag,
    1481             :                                             const nsString& messageCategory)
    1482             : {
    1483           0 :   DebugOnly<nsresult> rv = AddSecurityMessage(messageTag, messageCategory);
    1484           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    1485           0 :   return IPC_OK();
    1486             : }
    1487             : 
    1488           0 : class Redirect1Event : public NeckoTargetChannelEvent<HttpChannelChild>
    1489             : {
    1490             :  public:
    1491           0 :   Redirect1Event(HttpChannelChild* child,
    1492             :                  const uint32_t& registrarId,
    1493             :                  const URIParams& newURI,
    1494             :                  const uint32_t& redirectFlags,
    1495             :                  const nsHttpResponseHead& responseHead,
    1496             :                  const nsACString& securityInfoSerialization,
    1497             :                  const uint64_t& channelId)
    1498           0 :   : NeckoTargetChannelEvent<HttpChannelChild>(child)
    1499           0 :   , mRegistrarId(registrarId)
    1500             :   , mNewURI(newURI)
    1501           0 :   , mRedirectFlags(redirectFlags)
    1502             :   , mResponseHead(responseHead)
    1503             :   , mSecurityInfoSerialization(securityInfoSerialization)
    1504           0 :   , mChannelId(channelId) {}
    1505             : 
    1506           0 :   void Run()
    1507             :   {
    1508           0 :     mChild->Redirect1Begin(mRegistrarId, mNewURI, mRedirectFlags,
    1509             :                            mResponseHead, mSecurityInfoSerialization,
    1510           0 :                            mChannelId);
    1511           0 :   }
    1512             : 
    1513             :  private:
    1514             :   uint32_t            mRegistrarId;
    1515             :   URIParams           mNewURI;
    1516             :   uint32_t            mRedirectFlags;
    1517             :   nsHttpResponseHead  mResponseHead;
    1518             :   nsCString           mSecurityInfoSerialization;
    1519             :   uint64_t            mChannelId;
    1520             : };
    1521             : 
    1522             : mozilla::ipc::IPCResult
    1523           0 : HttpChannelChild::RecvRedirect1Begin(const uint32_t& registrarId,
    1524             :                                      const URIParams& newUri,
    1525             :                                      const uint32_t& redirectFlags,
    1526             :                                      const nsHttpResponseHead& responseHead,
    1527             :                                      const nsCString& securityInfoSerialization,
    1528             :                                      const uint64_t& channelId,
    1529             :                                      const NetAddr& oldPeerAddr)
    1530             : {
    1531             :   // TODO: handle security info
    1532           0 :   LOG(("HttpChannelChild::RecvRedirect1Begin [this=%p]\n", this));
    1533             :   // We set peer address of child to the old peer,
    1534             :   // Then it will be updated to new peer in OnStartRequest
    1535           0 :   mPeerAddr = oldPeerAddr;
    1536             : 
    1537           0 :   mEventQ->RunOrEnqueue(new Redirect1Event(this, registrarId, newUri,
    1538             :                                            redirectFlags, responseHead,
    1539             :                                            securityInfoSerialization,
    1540           0 :                                            channelId));
    1541           0 :   return IPC_OK();
    1542             : }
    1543             : 
    1544             : nsresult
    1545           0 : HttpChannelChild::SetupRedirect(nsIURI* uri,
    1546             :                                 const nsHttpResponseHead* responseHead,
    1547             :                                 const uint32_t& redirectFlags,
    1548             :                                 nsIChannel** outChannel)
    1549             : {
    1550           0 :   LOG(("HttpChannelChild::SetupRedirect [this=%p]\n", this));
    1551             : 
    1552             :   nsresult rv;
    1553           0 :   nsCOMPtr<nsIIOService> ioService;
    1554           0 :   rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
    1555           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1556             : 
    1557           0 :   nsCOMPtr<nsIChannel> newChannel;
    1558           0 :   nsCOMPtr<nsILoadInfo> redirectLoadInfo = CloneLoadInfoForRedirect(uri, redirectFlags);
    1559           0 :   rv = NS_NewChannelInternal(getter_AddRefs(newChannel),
    1560             :                              uri,
    1561             :                              redirectLoadInfo,
    1562             :                              nullptr, // aLoadGroup
    1563             :                              nullptr, // aCallbacks
    1564             :                              nsIRequest::LOAD_NORMAL,
    1565           0 :                              ioService);
    1566           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1567             : 
    1568             :   // We won't get OnStartRequest, set cookies here.
    1569           0 :   mResponseHead = new nsHttpResponseHead(*responseHead);
    1570             : 
    1571           0 :   bool rewriteToGET = HttpBaseChannel::ShouldRewriteRedirectToGET(mResponseHead->Status(),
    1572           0 :                                                                   mRequestHead.ParsedMethod());
    1573             : 
    1574           0 :   rv = SetupReplacementChannel(uri, newChannel, !rewriteToGET, redirectFlags);
    1575           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1576             : 
    1577           0 :   nsCOMPtr<nsIHttpChannelChild> httpChannelChild = do_QueryInterface(newChannel);
    1578           0 :   if (httpChannelChild) {
    1579           0 :     bool shouldUpgrade = false;
    1580           0 :     auto channelChild = static_cast<HttpChannelChild*>(httpChannelChild.get());
    1581           0 :     if (mShouldInterceptSubsequentRedirect) {
    1582             :       // In the case where there was a synthesized response that caused a redirection,
    1583             :       // we must force the new channel to intercept the request in the parent before a
    1584             :       // network transaction is initiated.
    1585           0 :       rv = httpChannelChild->ForceIntercepted(false, false);
    1586           0 :     } else if (mRedirectMode == nsIHttpChannelInternal::REDIRECT_MODE_MANUAL &&
    1587           0 :                ((redirectFlags & (nsIChannelEventSink::REDIRECT_TEMPORARY |
    1588           0 :                                   nsIChannelEventSink::REDIRECT_PERMANENT)) != 0) &&
    1589           0 :                channelChild->ShouldInterceptURI(uri, shouldUpgrade)) {
    1590             :       // In the case where the redirect mode is manual, we need to check whether
    1591             :       // the post-redirect channel needs to be intercepted.  If that is the
    1592             :       // case, force the new channel to intercept the request in the parent
    1593             :       // similar to the case above, but also remember that ShouldInterceptURI()
    1594             :       // returned true to avoid calling it a second time.
    1595           0 :       rv = httpChannelChild->ForceIntercepted(true, shouldUpgrade);
    1596             :     }
    1597           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    1598             :   }
    1599             : 
    1600           0 :   mRedirectChannelChild = do_QueryInterface(newChannel);
    1601           0 :   newChannel.forget(outChannel);
    1602             : 
    1603           0 :   return NS_OK;
    1604             : }
    1605             : 
    1606             : void
    1607           0 : HttpChannelChild::Redirect1Begin(const uint32_t& registrarId,
    1608             :                                  const URIParams& newOriginalURI,
    1609             :                                  const uint32_t& redirectFlags,
    1610             :                                  const nsHttpResponseHead& responseHead,
    1611             :                                  const nsACString& securityInfoSerialization,
    1612             :                                  const uint64_t& channelId)
    1613             : {
    1614             :   nsresult rv;
    1615             : 
    1616           0 :   LOG(("HttpChannelChild::Redirect1Begin [this=%p]\n", this));
    1617             : 
    1618           0 :   nsCOMPtr<nsIURI> uri = DeserializeURI(newOriginalURI);
    1619             : 
    1620           0 :   if (!securityInfoSerialization.IsEmpty()) {
    1621           0 :     NS_DeserializeObject(securityInfoSerialization,
    1622           0 :                          getter_AddRefs(mSecurityInfo));
    1623             :   }
    1624             : 
    1625           0 :   nsCOMPtr<nsIChannel> newChannel;
    1626           0 :   rv = SetupRedirect(uri,
    1627             :                       &responseHead,
    1628             :                       redirectFlags,
    1629           0 :                       getter_AddRefs(newChannel));
    1630             : 
    1631           0 :   if (NS_SUCCEEDED(rv)) {
    1632           0 :     if (mRedirectChannelChild) {
    1633             :       // Set the channelId allocated in parent to the child instance
    1634           0 :       nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mRedirectChannelChild);
    1635           0 :       if (httpChannel) {
    1636           0 :         rv = httpChannel->SetChannelId(channelId);
    1637           0 :         MOZ_ASSERT(NS_SUCCEEDED(rv));
    1638             :       }
    1639           0 :       mRedirectChannelChild->ConnectParent(registrarId);
    1640             :     }
    1641             : 
    1642           0 :     nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
    1643           0 :     MOZ_ASSERT(target);
    1644             : 
    1645           0 :     rv = gHttpHandler->AsyncOnChannelRedirect(this,
    1646             :                                               newChannel,
    1647             :                                               redirectFlags,
    1648           0 :                                               target);
    1649             :   }
    1650             : 
    1651           0 :   if (NS_FAILED(rv))
    1652           0 :     OnRedirectVerifyCallback(rv);
    1653           0 : }
    1654             : 
    1655             : void
    1656           0 : HttpChannelChild::BeginNonIPCRedirect(nsIURI* responseURI,
    1657             :                                       const nsHttpResponseHead* responseHead)
    1658             : {
    1659           0 :   LOG(("HttpChannelChild::BeginNonIPCRedirect [this=%p]\n", this));
    1660             : 
    1661           0 :   nsCOMPtr<nsIChannel> newChannel;
    1662           0 :   nsresult rv = SetupRedirect(responseURI,
    1663             :                               responseHead,
    1664             :                               nsIChannelEventSink::REDIRECT_INTERNAL,
    1665           0 :                               getter_AddRefs(newChannel));
    1666             : 
    1667           0 :   if (NS_SUCCEEDED(rv)) {
    1668             :     // Ensure that the new channel shares the original channel's security information,
    1669             :     // since it won't be provided via IPC. In particular, if the target of this redirect
    1670             :     // is a synthesized response that has its own security info, the pre-redirect channel
    1671             :     // has already received it and it must be propagated to the post-redirect channel.
    1672           0 :     nsCOMPtr<nsIHttpChannelChild> channelChild = do_QueryInterface(newChannel);
    1673           0 :     if (mSecurityInfo && channelChild) {
    1674           0 :       HttpChannelChild* httpChannelChild = static_cast<HttpChannelChild*>(channelChild.get());
    1675           0 :       httpChannelChild->OverrideSecurityInfoForNonIPCRedirect(mSecurityInfo);
    1676             :     }
    1677             : 
    1678           0 :     nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
    1679           0 :     MOZ_ASSERT(target);
    1680             : 
    1681           0 :     rv = gHttpHandler->AsyncOnChannelRedirect(this,
    1682             :                                               newChannel,
    1683             :                                               nsIChannelEventSink::REDIRECT_INTERNAL,
    1684           0 :                                               target);
    1685             :   }
    1686             : 
    1687           0 :   if (NS_FAILED(rv))
    1688           0 :     OnRedirectVerifyCallback(rv);
    1689           0 : }
    1690             : 
    1691             : void
    1692           0 : HttpChannelChild::OverrideSecurityInfoForNonIPCRedirect(nsISupports* securityInfo)
    1693             : {
    1694           0 :   mResponseCouldBeSynthesized = true;
    1695           0 :   DebugOnly<nsresult> rv = OverrideSecurityInfo(securityInfo);
    1696           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    1697           0 : }
    1698             : 
    1699           0 : class Redirect3Event : public NeckoTargetChannelEvent<HttpChannelChild>
    1700             : {
    1701             :  public:
    1702           0 :   explicit Redirect3Event(HttpChannelChild* child)
    1703           0 :   : NeckoTargetChannelEvent<HttpChannelChild>(child) {}
    1704           0 :   void Run() { mChild->Redirect3Complete(nullptr); }
    1705             : };
    1706             : 
    1707             : mozilla::ipc::IPCResult
    1708           0 : HttpChannelChild::RecvRedirect3Complete()
    1709             : {
    1710           0 :   LOG(("HttpChannelChild::RecvRedirect3Complete [this=%p]\n", this));
    1711           0 :   mEventQ->RunOrEnqueue(new Redirect3Event(this));
    1712           0 :   return IPC_OK();
    1713             : }
    1714             : 
    1715           0 : class HttpFlushedForDiversionEvent : public NeckoTargetChannelEvent<HttpChannelChild>
    1716             : {
    1717             :  public:
    1718           0 :   explicit HttpFlushedForDiversionEvent(HttpChannelChild* aChild)
    1719           0 :   : NeckoTargetChannelEvent<HttpChannelChild>(aChild)
    1720             :   {
    1721           0 :     MOZ_RELEASE_ASSERT(aChild);
    1722           0 :   }
    1723             : 
    1724           0 :   void Run()
    1725             :   {
    1726           0 :     mChild->FlushedForDiversion();
    1727           0 :   }
    1728             : };
    1729             : 
    1730             : void
    1731           0 : HttpChannelChild::ProcessFlushedForDiversion()
    1732             : {
    1733           0 :   LOG(("HttpChannelChild::ProcessFlushedForDiversion [this=%p]\n", this));
    1734           0 :   MOZ_ASSERT(OnSocketThread());
    1735           0 :   MOZ_RELEASE_ASSERT(mDivertingToParent);
    1736             : 
    1737           0 :   mEventQ->RunOrEnqueue(new HttpFlushedForDiversionEvent(this), true);
    1738           0 : }
    1739             : 
    1740             : void
    1741           0 : HttpChannelChild::ProcessNotifyTrackingProtectionDisabled()
    1742             : {
    1743           0 :   LOG(("HttpChannelChild::ProcessNotifyTrackingProtectionDisabled [this=%p]\n", this));
    1744           0 :   MOZ_ASSERT(OnSocketThread());
    1745             : 
    1746           0 :   RefPtr<HttpChannelChild> self = this;
    1747           0 :   nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
    1748           0 :   mainTarget->Dispatch(
    1749           0 :     NS_NewRunnableFunction(
    1750             :       "nsChannelClassifier::NotifyTrackingProtectionDisabled",
    1751           0 :       [self]() {
    1752           0 :         nsChannelClassifier::NotifyTrackingProtectionDisabled(self);
    1753           0 :       }),
    1754           0 :     NS_DISPATCH_NORMAL);
    1755           0 : }
    1756             : 
    1757             : void
    1758           0 : HttpChannelChild::ProcessNotifyTrackingResource()
    1759             : {
    1760           0 :   LOG(("HttpChannelChild::ProcessNotifyTrackingResource [this=%p]\n", this));
    1761           0 :   MOZ_ASSERT(OnSocketThread());
    1762             : 
    1763           0 :   nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
    1764           0 :   mainTarget->Dispatch(
    1765           0 :     NewRunnableMethod(
    1766             :       "HttpChannelChild::SetIsTrackingResource",
    1767             :       this, &HttpChannelChild::SetIsTrackingResource),
    1768           0 :     NS_DISPATCH_NORMAL);
    1769           0 : }
    1770             : 
    1771             : void
    1772           0 : HttpChannelChild::FlushedForDiversion()
    1773             : {
    1774           0 :   LOG(("HttpChannelChild::FlushedForDiversion [this=%p]\n", this));
    1775           0 :   MOZ_RELEASE_ASSERT(mDivertingToParent);
    1776             : 
    1777             :   // Once this is set, it should not be unset before HttpChannelChild is taken
    1778             :   // down. After it is set, no OnStart/OnData/OnStop callbacks should be
    1779             :   // received from the parent channel, nor dequeued from the ChannelEventQueue.
    1780           0 :   mFlushedForDiversion = true;
    1781             : 
    1782           0 :   SendDivertComplete();
    1783           0 : }
    1784             : 
    1785             : void
    1786           0 : HttpChannelChild::ProcessSetClassifierMatchedInfo(const nsCString& aList,
    1787             :                                                   const nsCString& aProvider,
    1788             :                                                   const nsCString& aPrefix)
    1789             : {
    1790           0 :   LOG(("HttpChannelChild::ProcessSetClassifierMatchedInfo [this=%p]\n", this));
    1791           0 :   MOZ_ASSERT(OnSocketThread());
    1792             : 
    1793           0 :   nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
    1794           0 :   mainTarget->Dispatch(
    1795             :     NewRunnableMethod<const nsCString, const nsCString, const nsCString>
    1796           0 :       ("HttpChannelChild::SetMatchedInfo",
    1797             :        this, &HttpChannelChild::SetMatchedInfo,
    1798             :        aList, aProvider, aPrefix),
    1799           0 :     NS_DISPATCH_NORMAL);
    1800           0 : }
    1801             : 
    1802             : void
    1803           0 : HttpChannelChild::ProcessDivertMessages()
    1804             : {
    1805           0 :   LOG(("HttpChannelChild::ProcessDivertMessages [this=%p]\n", this));
    1806           0 :   MOZ_ASSERT(OnSocketThread());
    1807           0 :   MOZ_RELEASE_ASSERT(mDivertingToParent);
    1808             : 
    1809             :   // DivertTo() has been called on parent, so we can now start sending queued
    1810             :   // IPDL messages back to parent listener.
    1811           0 :   nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
    1812           0 :   MOZ_ASSERT(neckoTarget);
    1813             :   nsresult rv =
    1814           0 :     neckoTarget->Dispatch(
    1815           0 :       NewRunnableMethod(
    1816             :         "HttpChannelChild::Resume",
    1817             :         this, &HttpChannelChild::Resume),
    1818           0 :       NS_DISPATCH_NORMAL);
    1819             : 
    1820           0 :   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
    1821           0 : }
    1822             : 
    1823             : // Returns true if has actually completed the redirect and cleaned up the
    1824             : // channel, or false the interception logic kicked in and we need to asyncly
    1825             : // call FinishInterceptedRedirect and CleanupRedirectingChannel.
    1826             : // The argument is an optional OverrideRunnable that we pass to the redirected
    1827             : // channel.
    1828             : bool
    1829           0 : HttpChannelChild::Redirect3Complete(OverrideRunnable* aRunnable)
    1830             : {
    1831           0 :   LOG(("HttpChannelChild::Redirect3Complete [this=%p]\n", this));
    1832           0 :   nsresult rv = NS_OK;
    1833             : 
    1834           0 :   nsCOMPtr<nsIHttpChannelChild> chan = do_QueryInterface(mRedirectChannelChild);
    1835           0 :   RefPtr<HttpChannelChild> httpChannelChild = static_cast<HttpChannelChild*>(chan.get());
    1836             :   // Chrome channel has been AsyncOpen'd.  Reflect this in child.
    1837           0 :   if (mRedirectChannelChild) {
    1838           0 :     if (httpChannelChild) {
    1839           0 :       httpChannelChild->mOverrideRunnable = aRunnable;
    1840           0 :       httpChannelChild->mInterceptingChannel = this;
    1841             :     }
    1842           0 :     rv = mRedirectChannelChild->CompleteRedirectSetup(mListener,
    1843           0 :                                                       mListenerContext);
    1844             :   }
    1845             : 
    1846           0 :   if (!httpChannelChild || !httpChannelChild->mShouldParentIntercept) {
    1847             :     // The redirect channel either isn't a HttpChannelChild, or the interception
    1848             :     // logic wasn't triggered, so we can clean it up right here.
    1849           0 :     CleanupRedirectingChannel(rv);
    1850           0 :     if (httpChannelChild) {
    1851           0 :       httpChannelChild->mOverrideRunnable = nullptr;
    1852           0 :       httpChannelChild->mInterceptingChannel = nullptr;
    1853             :     }
    1854           0 :     return true;
    1855             :   }
    1856           0 :   return false;
    1857             : }
    1858             : 
    1859             : void
    1860           0 : HttpChannelChild::CleanupRedirectingChannel(nsresult rv)
    1861             : {
    1862             :   // Redirecting to new channel: shut this down and init new channel
    1863           0 :   if (mLoadGroup)
    1864           0 :     mLoadGroup->RemoveRequest(this, nullptr, NS_BINDING_ABORTED);
    1865             : 
    1866           0 :   if (NS_SUCCEEDED(rv)) {
    1867           0 :     if (mLoadInfo) {
    1868           0 :       nsCString remoteAddress;
    1869           0 :       Unused << GetRemoteAddress(remoteAddress);
    1870             :       nsCOMPtr<nsIRedirectHistoryEntry> entry =
    1871           0 :         new nsRedirectHistoryEntry(GetURIPrincipal(), mReferrer, remoteAddress);
    1872             : 
    1873           0 :       mLoadInfo->AppendRedirectHistoryEntry(entry, false);
    1874             :     }
    1875             :   }
    1876             :   else {
    1877           0 :     NS_WARNING("CompleteRedirectSetup failed, HttpChannelChild already open?");
    1878             :   }
    1879             : 
    1880             :   // Release ref to new channel.
    1881           0 :   mRedirectChannelChild = nullptr;
    1882             : 
    1883           0 :   if (mInterceptListener) {
    1884           0 :     mInterceptListener->Cleanup();
    1885           0 :     mInterceptListener = nullptr;
    1886             :   }
    1887           0 :   ReleaseListeners();
    1888           0 : }
    1889             : 
    1890             : //-----------------------------------------------------------------------------
    1891             : // HttpChannelChild::nsIChildChannel
    1892             : //-----------------------------------------------------------------------------
    1893             : 
    1894             : NS_IMETHODIMP
    1895           0 : HttpChannelChild::ConnectParent(uint32_t registrarId)
    1896             : {
    1897           0 :   LOG(("HttpChannelChild::ConnectParent [this=%p]\n", this));
    1898           0 :   mozilla::dom::TabChild* tabChild = nullptr;
    1899           0 :   nsCOMPtr<nsITabChild> iTabChild;
    1900           0 :   GetCallback(iTabChild);
    1901           0 :   if (iTabChild) {
    1902           0 :     tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
    1903             :   }
    1904           0 :   if (MissingRequiredTabChild(tabChild, "http")) {
    1905           0 :     return NS_ERROR_ILLEGAL_VALUE;
    1906             :   }
    1907             : 
    1908           0 :   if (tabChild && !tabChild->IPCOpen()) {
    1909           0 :     return NS_ERROR_FAILURE;
    1910             :   }
    1911             : 
    1912           0 :   ContentChild* cc = static_cast<ContentChild*>(gNeckoChild->Manager());
    1913           0 :   if (cc->IsShuttingDown()) {
    1914           0 :     return NS_ERROR_FAILURE;
    1915             :   }
    1916             : 
    1917           0 :   HttpBaseChannel::SetDocshellUserAgentOverride();
    1918             : 
    1919             :   // The socket transport in the chrome process now holds a logical ref to us
    1920             :   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
    1921           0 :   AddIPDLReference();
    1922             : 
    1923             :   // This must happen before the constructor message is sent. Otherwise messages
    1924             :   // from the parent could arrive quickly and be delivered to the wrong event
    1925             :   // target.
    1926           0 :   SetEventTarget();
    1927             : 
    1928           0 :   HttpChannelConnectArgs connectArgs(registrarId, mShouldParentIntercept);
    1929           0 :   PBrowserOrId browser = static_cast<ContentChild*>(gNeckoChild->Manager())
    1930           0 :                          ->GetBrowserOrId(tabChild);
    1931           0 :   IPC::SerializedLoadContext slc(this);
    1932           0 :   MOZ_DIAGNOSTIC_ASSERT(gIPCSecurityDisabled || slc.IsNotNull(),
    1933             :                         "SerializedLoadContext should not be null");
    1934           0 :   if (!gNeckoChild->
    1935           0 :         SendPHttpChannelConstructor(this, browser,
    1936             :                                     slc,
    1937             :                                     connectArgs)) {
    1938           0 :     return NS_ERROR_FAILURE;
    1939             :   }
    1940             : 
    1941             :   {
    1942           0 :     MutexAutoLock lock(mBgChildMutex);
    1943             : 
    1944           0 :     MOZ_ASSERT(!mBgChild);
    1945           0 :     MOZ_ASSERT(!mBgInitFailCallback);
    1946             : 
    1947           0 :     mBgInitFailCallback = NewRunnableMethod<nsresult>(
    1948             :         "HttpChannelChild::OnRedirectVerifyCallback",
    1949             :         this, &HttpChannelChild::OnRedirectVerifyCallback,
    1950           0 :         NS_ERROR_FAILURE);
    1951             : 
    1952             :     RefPtr<HttpBackgroundChannelChild> bgChild =
    1953           0 :       new HttpBackgroundChannelChild();
    1954             : 
    1955           0 :     MOZ_RELEASE_ASSERT(gSocketTransportService);
    1956             : 
    1957           0 :     RefPtr<HttpChannelChild> self = this;
    1958             :     nsresult rv =
    1959           0 :       gSocketTransportService->Dispatch(
    1960           0 :         NewRunnableMethod<RefPtr<HttpChannelChild>>(
    1961             :           "HttpBackgroundChannelChild::Init",
    1962           0 :           bgChild, &HttpBackgroundChannelChild::Init, Move(self)),
    1963           0 :         NS_DISPATCH_NORMAL);
    1964             : 
    1965           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
    1966           0 :       return rv;
    1967             :     }
    1968             : 
    1969           0 :     mBgChild = bgChild.forget();
    1970             :   }
    1971             : 
    1972           0 :   return NS_OK;
    1973             : }
    1974             : 
    1975             : NS_IMETHODIMP
    1976           0 : HttpChannelChild::CompleteRedirectSetup(nsIStreamListener *listener,
    1977             :                                         nsISupports *aContext)
    1978             : {
    1979           0 :   LOG(("HttpChannelChild::FinishRedirectSetup [this=%p]\n", this));
    1980             : 
    1981           0 :   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
    1982           0 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
    1983             : 
    1984           0 :   if (mShouldParentIntercept) {
    1985             :     // This is a redirected channel, and the corresponding parent channel has started
    1986             :     // AsyncOpen but was intercepted and suspended. We must tear it down and start
    1987             :     // fresh - we will intercept the child channel this time, before creating a new
    1988             :     // parent channel unnecessarily.
    1989             : 
    1990             :     // Since this method is called from RecvRedirect3Complete which itself is
    1991             :     // called from either OnRedirectVerifyCallback via OverrideRunnable, or from
    1992             :     // RecvRedirect3Complete. The order of events must always be:
    1993             :     //  1. Teardown the IPDL connection
    1994             :     //  2. AsyncOpen the connection again
    1995             :     //  3. Cleanup the redirecting channel (the one calling Redirect3Complete)
    1996             :     //  4. [optional] Call OverrideWithSynthesizedResponse on the redirected
    1997             :     //  channel if the call came from OverrideRunnable.
    1998           0 :     mInterceptedRedirectListener = listener;
    1999           0 :     mInterceptedRedirectContext = aContext;
    2000             : 
    2001             :     // This will send a message to the parent notifying it that we are closing
    2002             :     // down. After closing the IPC channel, we will proceed to execute
    2003             :     // FinishInterceptedRedirect() which AsyncOpen's the channel again.
    2004           0 :     SendFinishInterceptedRedirect();
    2005             : 
    2006             :     // XXX valentin: The interception logic should be rewritten to avoid
    2007             :     // calling AsyncOpen on the channel _after_ we call Send__delete__()
    2008           0 :     return NS_OK;
    2009             :   }
    2010             : 
    2011             :   /*
    2012             :    * No need to check for cancel: we don't get here if nsHttpChannel canceled
    2013             :    * before AsyncOpen(); if it's canceled after that, OnStart/Stop will just
    2014             :    * get called with error code as usual.  So just setup mListener and make the
    2015             :    * channel reflect AsyncOpen'ed state.
    2016             :    */
    2017             : 
    2018           0 :   mIsPending = true;
    2019           0 :   mWasOpened = true;
    2020           0 :   mListener = listener;
    2021           0 :   mListenerContext = aContext;
    2022             : 
    2023             :   // add ourselves to the load group.
    2024           0 :   if (mLoadGroup)
    2025           0 :     mLoadGroup->AddRequest(this, nullptr);
    2026             : 
    2027             :   // We already have an open IPDL connection to the parent. If on-modify-request
    2028             :   // listeners or load group observers canceled us, let the parent handle it
    2029             :   // and send it back to us naturally.
    2030           0 :   return NS_OK;
    2031             : }
    2032             : 
    2033             : //-----------------------------------------------------------------------------
    2034             : // HttpChannelChild::nsIAsyncVerifyRedirectCallback
    2035             : //-----------------------------------------------------------------------------
    2036             : 
    2037             : NS_IMETHODIMP
    2038           0 : HttpChannelChild::OnRedirectVerifyCallback(nsresult result)
    2039             : {
    2040           0 :   LOG(("HttpChannelChild::OnRedirectVerifyCallback [this=%p]\n", this));
    2041             :   nsresult rv;
    2042           0 :   OptionalURIParams redirectURI;
    2043             : 
    2044           0 :   uint32_t referrerPolicy = REFERRER_POLICY_UNSET;
    2045           0 :   OptionalURIParams referrerURI;
    2046           0 :   SerializeURI(nullptr, referrerURI);
    2047             : 
    2048             :   nsCOMPtr<nsIHttpChannel> newHttpChannel =
    2049           0 :       do_QueryInterface(mRedirectChannelChild);
    2050             : 
    2051           0 :   if (NS_SUCCEEDED(result) && !mRedirectChannelChild) {
    2052             :     // mRedirectChannelChild doesn't exist means we're redirecting to a protocol
    2053             :     // that doesn't implement nsIChildChannel. The redirect result should be set
    2054             :     // as failed by veto listeners and shouldn't enter this condition. As the
    2055             :     // last resort, we synthesize the error result as NS_ERROR_DOM_BAD_URI here
    2056             :     // to let nsHttpChannel::ContinueProcessResponse2 know it's redirecting to
    2057             :     // another protocol and throw an error.
    2058           0 :     LOG(("  redirecting to a protocol that doesn't implement nsIChildChannel"));
    2059           0 :     result = NS_ERROR_DOM_BAD_URI;
    2060             :   }
    2061             : 
    2062           0 :   bool forceHSTSPriming = false;
    2063           0 :   bool mixedContentWouldBlock = false;
    2064           0 :   if (newHttpChannel) {
    2065             :     // Must not be called until after redirect observers called.
    2066           0 :     newHttpChannel->SetOriginalURI(mOriginalURI);
    2067             : 
    2068           0 :     nsCOMPtr<nsILoadInfo> newLoadInfo;
    2069           0 :     rv = newHttpChannel->GetLoadInfo(getter_AddRefs(newLoadInfo));
    2070           0 :     if (NS_SUCCEEDED(rv) && newLoadInfo) {
    2071           0 :       forceHSTSPriming = newLoadInfo->GetForceHSTSPriming();
    2072           0 :       mixedContentWouldBlock = newLoadInfo->GetMixedContentWouldBlock();
    2073             :     }
    2074             : 
    2075           0 :     rv = newHttpChannel->GetReferrerPolicy(&referrerPolicy);
    2076           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    2077           0 :     nsCOMPtr<nsIURI> newChannelReferrerURI;
    2078           0 :     rv = newHttpChannel->GetReferrer(getter_AddRefs(newChannelReferrerURI));
    2079           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    2080             : 
    2081           0 :     SerializeURI(newChannelReferrerURI, referrerURI);
    2082             :   }
    2083             : 
    2084           0 :   if (mRedirectingForSubsequentSynthesizedResponse) {
    2085           0 :     nsCOMPtr<nsIHttpChannelChild> httpChannelChild = do_QueryInterface(mRedirectChannelChild);
    2086             :     RefPtr<HttpChannelChild> redirectedChannel =
    2087           0 :         static_cast<HttpChannelChild*>(httpChannelChild.get());
    2088             :     // redirectChannel will be NULL if mRedirectChannelChild isn't a
    2089             :     // nsIHttpChannelChild (it could be a DataChannelChild).
    2090             : 
    2091             :     RefPtr<InterceptStreamListener> streamListener =
    2092           0 :         new InterceptStreamListener(redirectedChannel, mListenerContext);
    2093             : 
    2094           0 :     nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
    2095           0 :     MOZ_ASSERT(neckoTarget);
    2096             : 
    2097           0 :     Unused << neckoTarget->Dispatch(
    2098             :       new OverrideRunnable(this, redirectedChannel, streamListener,
    2099           0 :                            mSynthesizedInput, mResponseHead),
    2100             :       NS_DISPATCH_NORMAL);
    2101             : 
    2102           0 :     return NS_OK;
    2103             :   }
    2104             : 
    2105           0 :   RequestHeaderTuples emptyHeaders;
    2106           0 :   RequestHeaderTuples* headerTuples = &emptyHeaders;
    2107           0 :   nsLoadFlags loadFlags = 0;
    2108           0 :   OptionalCorsPreflightArgs corsPreflightArgs = mozilla::void_t();
    2109             : 
    2110             :   nsCOMPtr<nsIHttpChannelChild> newHttpChannelChild =
    2111           0 :       do_QueryInterface(mRedirectChannelChild);
    2112           0 :   if (newHttpChannelChild && NS_SUCCEEDED(result)) {
    2113           0 :     rv = newHttpChannelChild->AddCookiesToRequest();
    2114           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    2115           0 :     rv = newHttpChannelChild->GetClientSetRequestHeaders(&headerTuples);
    2116           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    2117           0 :     newHttpChannelChild->GetClientSetCorsPreflightParameters(corsPreflightArgs);
    2118             :   }
    2119             : 
    2120             :   /* If the redirect was canceled, bypass OMR and send an empty API
    2121             :    * redirect URI */
    2122           0 :   SerializeURI(nullptr, redirectURI);
    2123             : 
    2124           0 :   if (NS_SUCCEEDED(result)) {
    2125             :     // Note: this is where we would notify "http-on-modify-response" observers.
    2126             :     // We have deliberately disabled this for child processes (see bug 806753)
    2127             :     //
    2128             :     // After we verify redirect, nsHttpChannel may hit the network: must give
    2129             :     // "http-on-modify-request" observers the chance to cancel before that.
    2130             :     //base->CallOnModifyRequestObservers();
    2131             : 
    2132             :     nsCOMPtr<nsIHttpChannelInternal> newHttpChannelInternal =
    2133           0 :       do_QueryInterface(mRedirectChannelChild);
    2134           0 :     if (newHttpChannelInternal) {
    2135           0 :       nsCOMPtr<nsIURI> apiRedirectURI;
    2136           0 :       nsresult rv = newHttpChannelInternal->GetApiRedirectToURI(
    2137           0 :         getter_AddRefs(apiRedirectURI));
    2138           0 :       if (NS_SUCCEEDED(rv) && apiRedirectURI) {
    2139             :         /* If there was an API redirect of this channel, we need to send it
    2140             :          * up here, since it can't be sent via SendAsyncOpen. */
    2141           0 :         SerializeURI(apiRedirectURI, redirectURI);
    2142             :       }
    2143             :     }
    2144             : 
    2145           0 :     nsCOMPtr<nsIRequest> request = do_QueryInterface(mRedirectChannelChild);
    2146           0 :     if (request) {
    2147           0 :       request->GetLoadFlags(&loadFlags);
    2148             :     }
    2149             :   }
    2150             : 
    2151           0 :   bool chooseAppcache = false;
    2152             :   nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
    2153           0 :     do_QueryInterface(newHttpChannel);
    2154           0 :   if (appCacheChannel) {
    2155           0 :     appCacheChannel->GetChooseApplicationCache(&chooseAppcache);
    2156             :   }
    2157             : 
    2158           0 :   if (mIPCOpen)
    2159           0 :     SendRedirect2Verify(result, *headerTuples, loadFlags, referrerPolicy,
    2160             :                         referrerURI, redirectURI, corsPreflightArgs,
    2161           0 :                         forceHSTSPriming, mixedContentWouldBlock, chooseAppcache);
    2162             : 
    2163           0 :   return NS_OK;
    2164             : }
    2165             : 
    2166             : //-----------------------------------------------------------------------------
    2167             : // HttpChannelChild::nsIRequest
    2168             : //-----------------------------------------------------------------------------
    2169             : 
    2170             : NS_IMETHODIMP
    2171           0 : HttpChannelChild::Cancel(nsresult status)
    2172             : {
    2173           0 :   LOG(("HttpChannelChild::Cancel [this=%p]\n", this));
    2174           0 :   MOZ_ASSERT(NS_IsMainThread());
    2175             : 
    2176           0 :   if (!mCanceled) {
    2177             :     // If this cancel occurs before nsHttpChannel has been set up, AsyncOpen
    2178             :     // is responsible for cleaning up.
    2179           0 :     mCanceled = true;
    2180           0 :     mStatus = status;
    2181           0 :     if (RemoteChannelExists())
    2182           0 :       SendCancel(status);
    2183           0 :     if (mSynthesizedResponsePump) {
    2184           0 :       mSynthesizedResponsePump->Cancel(status);
    2185             :     }
    2186           0 :     mInterceptListener = nullptr;
    2187             :   }
    2188           0 :   return NS_OK;
    2189             : }
    2190             : 
    2191             : NS_IMETHODIMP
    2192           0 : HttpChannelChild::Suspend()
    2193             : {
    2194           0 :   LOG(("HttpChannelChild::Suspend [this=%p, mSuspendCount=%" PRIu32 ", "
    2195             :        "mDivertingToParent=%d]\n", this, mSuspendCount + 1,
    2196             :        static_cast<bool>(mDivertingToParent)));
    2197           0 :   NS_ENSURE_TRUE(RemoteChannelExists() || mInterceptListener,
    2198             :                  NS_ERROR_NOT_AVAILABLE);
    2199             : 
    2200             :   // SendSuspend only once, when suspend goes from 0 to 1.
    2201             :   // Don't SendSuspend at all if we're diverting callbacks to the parent;
    2202             :   // suspend will be called at the correct time in the parent itself.
    2203           0 :   if (!mSuspendCount++ && !mDivertingToParent) {
    2204           0 :     if (RemoteChannelExists()) {
    2205           0 :       SendSuspend();
    2206           0 :       mSuspendSent = true;
    2207             :     }
    2208             :   }
    2209           0 :   if (mSynthesizedResponsePump) {
    2210           0 :     mSynthesizedResponsePump->Suspend();
    2211             :   }
    2212           0 :   mEventQ->Suspend();
    2213             : 
    2214           0 :   return NS_OK;
    2215             : }
    2216             : 
    2217             : NS_IMETHODIMP
    2218           0 : HttpChannelChild::Resume()
    2219             : {
    2220           0 :   LOG(("HttpChannelChild::Resume [this=%p, mSuspendCount=%" PRIu32 ", "
    2221             :        "mDivertingToParent=%d]\n", this, mSuspendCount - 1,
    2222             :        static_cast<bool>(mDivertingToParent)));
    2223           0 :   NS_ENSURE_TRUE(RemoteChannelExists() || mInterceptListener,
    2224             :                  NS_ERROR_NOT_AVAILABLE);
    2225           0 :   NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
    2226             : 
    2227           0 :   nsresult rv = NS_OK;
    2228             : 
    2229             :   // SendResume only once, when suspend count drops to 0.
    2230             :   // Don't SendResume at all if we're diverting callbacks to the parent (unless
    2231             :   // suspend was sent earlier); otherwise, resume will be called at the correct
    2232             :   // time in the parent itself.
    2233           0 :   if (!--mSuspendCount && (!mDivertingToParent || mSuspendSent)) {
    2234           0 :     if (RemoteChannelExists()) {
    2235           0 :       SendResume();
    2236             :     }
    2237           0 :     if (mCallOnResume) {
    2238           0 :       rv = AsyncCall(mCallOnResume);
    2239           0 :       NS_ENSURE_SUCCESS(rv, rv);
    2240           0 :       mCallOnResume = nullptr;
    2241             :     }
    2242             :   }
    2243           0 :   if (mSynthesizedResponsePump) {
    2244           0 :     mSynthesizedResponsePump->Resume();
    2245             :   }
    2246           0 :   mEventQ->Resume();
    2247             : 
    2248           0 :   return rv;
    2249             : }
    2250             : 
    2251             : //-----------------------------------------------------------------------------
    2252             : // HttpChannelChild::nsIChannel
    2253             : //-----------------------------------------------------------------------------
    2254             : 
    2255             : NS_IMETHODIMP
    2256          13 : HttpChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
    2257             : {
    2258          13 :   NS_ENSURE_ARG_POINTER(aSecurityInfo);
    2259          13 :   NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
    2260          13 :   return NS_OK;
    2261             : }
    2262             : 
    2263             : NS_IMETHODIMP
    2264           3 : HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
    2265             : {
    2266           3 :   MOZ_ASSERT(!mLoadInfo ||
    2267             :              mLoadInfo->GetSecurityMode() == 0 ||
    2268             :              mLoadInfo->GetInitialSecurityCheckDone() ||
    2269             :              (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
    2270             :               nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
    2271             :              "security flags in loadInfo but asyncOpen2() not called");
    2272             : 
    2273           3 :   LOG(("HttpChannelChild::AsyncOpen [this=%p uri=%s]\n", this, mSpec.get()));
    2274             : 
    2275             : #ifdef DEBUG
    2276           3 :   AssertPrivateBrowsingId();
    2277             : #endif
    2278             : 
    2279           3 :   if (mCanceled)
    2280           0 :     return mStatus;
    2281             : 
    2282           3 :   NS_ENSURE_TRUE(gNeckoChild != nullptr, NS_ERROR_FAILURE);
    2283           3 :   NS_ENSURE_ARG_POINTER(listener);
    2284           3 :   NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
    2285           3 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
    2286             : 
    2287           3 :   mAsyncOpenTime = TimeStamp::Now();
    2288             : #ifdef MOZ_TASK_TRACER
    2289             :   if (tasktracer::IsStartLogging()) {
    2290             :     nsCOMPtr<nsIURI> uri;
    2291             :     GetURI(getter_AddRefs(uri));
    2292             :     nsAutoCString urispec;
    2293             :     uri->GetSpec(urispec);
    2294             :     tasktracer::AddLabel("HttpChannelChild::AsyncOpen %s", urispec.get());
    2295             :   }
    2296             : #endif
    2297             : 
    2298             : 
    2299             :   // Port checked in parent, but duplicate here so we can return with error
    2300             :   // immediately
    2301             :   nsresult rv;
    2302           3 :   rv = NS_CheckPortSafety(mURI);
    2303           3 :   if (NS_FAILED(rv))
    2304           0 :     return rv;
    2305             : 
    2306           6 :   nsAutoCString cookie;
    2307           3 :   if (NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::Cookie, cookie))) {
    2308           0 :     mUserSetCookieHeader = cookie;
    2309             :   }
    2310             : 
    2311           3 :   rv = AddCookiesToRequest();
    2312           3 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    2313             : 
    2314             :   //
    2315             :   // NOTE: From now on we must return NS_OK; all errors must be handled via
    2316             :   // OnStart/OnStopRequest
    2317             :   //
    2318             : 
    2319             :   // We notify "http-on-opening-request" observers in the child
    2320             :   // process so that devtools can capture a stack trace at the
    2321             :   // appropriate spot.  See bug 806753 for some information about why
    2322             :   // other http-* notifications are disabled in child processes.
    2323           3 :   gHttpHandler->OnOpeningRequest(this);
    2324             : 
    2325           3 :   mIsPending = true;
    2326           3 :   mWasOpened = true;
    2327           3 :   mListener = listener;
    2328           3 :   mListenerContext = aContext;
    2329             : 
    2330             :   // add ourselves to the load group.
    2331           3 :   if (mLoadGroup)
    2332           3 :     mLoadGroup->AddRequest(this, nullptr);
    2333             : 
    2334           3 :   if (mCanceled) {
    2335             :     // We may have been canceled already, either by on-modify-request
    2336             :     // listeners or by load group observers; in that case, don't create IPDL
    2337             :     // connection. See nsHttpChannel::AsyncOpen().
    2338           0 :     Unused << AsyncAbort(mStatus);
    2339           0 :     return NS_OK;
    2340             :   }
    2341             : 
    2342             :   // Set user agent override from docshell
    2343           3 :   HttpBaseChannel::SetDocshellUserAgentOverride();
    2344             : 
    2345           3 :   MOZ_ASSERT_IF(mPostRedirectChannelShouldUpgrade,
    2346             :                 mPostRedirectChannelShouldIntercept);
    2347           3 :   bool shouldUpgrade = mPostRedirectChannelShouldUpgrade;
    2348           6 :   if (mPostRedirectChannelShouldIntercept ||
    2349           3 :       ShouldInterceptURI(mURI, shouldUpgrade)) {
    2350           0 :     mResponseCouldBeSynthesized = true;
    2351             : 
    2352           0 :     nsCOMPtr<nsINetworkInterceptController> controller;
    2353           0 :     GetCallback(controller);
    2354             : 
    2355           0 :     mInterceptListener = new InterceptStreamListener(this, mListenerContext);
    2356             : 
    2357             :     RefPtr<InterceptedChannelContent> intercepted =
    2358             :         new InterceptedChannelContent(this, controller,
    2359           0 :                                       mInterceptListener, shouldUpgrade);
    2360           0 :     intercepted->NotifyController();
    2361           0 :     return NS_OK;
    2362             :   }
    2363             : 
    2364           3 :   return ContinueAsyncOpen();
    2365             : }
    2366             : 
    2367             : NS_IMETHODIMP
    2368           3 : HttpChannelChild::AsyncOpen2(nsIStreamListener *aListener)
    2369             : {
    2370           6 :   nsCOMPtr<nsIStreamListener> listener = aListener;
    2371           3 :   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
    2372           3 :   if (NS_WARN_IF(NS_FAILED(rv))) {
    2373           0 :     ReleaseListeners();
    2374           0 :     return rv;
    2375             :   }
    2376           3 :   return AsyncOpen(listener, nullptr);
    2377             : }
    2378             : 
    2379             : // Assigns an nsIEventTarget to our IPDL actor so that IPC messages are sent to
    2380             : // the correct DocGroup/TabGroup.
    2381             : void
    2382           3 : HttpChannelChild::SetEventTarget()
    2383             : {
    2384           6 :   nsCOMPtr<nsILoadInfo> loadInfo;
    2385           3 :   GetLoadInfo(getter_AddRefs(loadInfo));
    2386             : 
    2387             :   nsCOMPtr<nsIEventTarget> target =
    2388           6 :     nsContentUtils::GetEventTargetByLoadInfo(loadInfo, TaskCategory::Network);
    2389             : 
    2390           3 :   if (!target) {
    2391           0 :     return;
    2392             :   }
    2393             : 
    2394           3 :   gNeckoChild->SetEventTargetForActor(this, target);
    2395             : 
    2396             :   {
    2397           6 :     MutexAutoLock lock(mEventTargetMutex);
    2398           3 :     mNeckoTarget = target;
    2399             :   }
    2400             : }
    2401             : 
    2402             : already_AddRefed<nsIEventTarget>
    2403          18 : HttpChannelChild::GetNeckoTarget()
    2404             : {
    2405          36 :   nsCOMPtr<nsIEventTarget> target;
    2406             :   {
    2407          36 :     MutexAutoLock lock(mEventTargetMutex);
    2408          18 :     target = mNeckoTarget;
    2409             :   }
    2410             : 
    2411          18 :   if (!target) {
    2412           0 :     target = GetMainThreadEventTarget();
    2413             :   }
    2414          36 :   return target.forget();
    2415             : }
    2416             : 
    2417             : already_AddRefed<nsIEventTarget>
    2418           9 : HttpChannelChild::GetODATarget()
    2419             : {
    2420          18 :   nsCOMPtr<nsIEventTarget> target;
    2421             :   {
    2422          18 :     MutexAutoLock lock(mEventTargetMutex);
    2423           9 :     target = mODATarget ? mODATarget : mNeckoTarget;
    2424             :   }
    2425             : 
    2426           9 :   if (!target) {
    2427           0 :     target = GetMainThreadEventTarget();
    2428             :   }
    2429          18 :   return target.forget();
    2430             : }
    2431             : 
    2432             : nsresult
    2433           3 : HttpChannelChild::ContinueAsyncOpen()
    2434             : {
    2435           6 :   nsCString appCacheClientId;
    2436           3 :   if (mInheritApplicationCache) {
    2437             :     // Pick up an application cache from the notification
    2438             :     // callbacks if available
    2439           4 :     nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer;
    2440           2 :     GetCallback(appCacheContainer);
    2441             : 
    2442           2 :     if (appCacheContainer) {
    2443           4 :       nsCOMPtr<nsIApplicationCache> appCache;
    2444           2 :       nsresult rv = appCacheContainer->GetApplicationCache(getter_AddRefs(appCache));
    2445           2 :       if (NS_SUCCEEDED(rv) && appCache) {
    2446           0 :         appCache->GetClientID(appCacheClientId);
    2447             :       }
    2448             :     }
    2449             :   }
    2450             : 
    2451             :   //
    2452             :   // Send request to the chrome process...
    2453             :   //
    2454             : 
    2455           3 :   mozilla::dom::TabChild* tabChild = nullptr;
    2456           6 :   nsCOMPtr<nsITabChild> iTabChild;
    2457           3 :   GetCallback(iTabChild);
    2458           3 :   if (iTabChild) {
    2459           3 :     tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
    2460             :   }
    2461           3 :   if (MissingRequiredTabChild(tabChild, "http")) {
    2462           0 :     return NS_ERROR_ILLEGAL_VALUE;
    2463             :   }
    2464             : 
    2465             :   // This id identifies the inner window's top-level document,
    2466             :   // which changes on every new load or navigation.
    2467           3 :   uint64_t contentWindowId = 0;
    2468           3 :   if (tabChild) {
    2469           3 :     MOZ_ASSERT(tabChild->WebNavigation());
    2470           6 :     nsCOMPtr<nsIDocument> document = tabChild->GetDocument();
    2471           3 :     if (document) {
    2472           3 :       contentWindowId = document->InnerWindowID();
    2473           3 :       mTopLevelOuterContentWindowId = document->OuterWindowID();
    2474             :     }
    2475             :   }
    2476           3 :   SetTopLevelContentWindowId(contentWindowId);
    2477             : 
    2478           6 :   HttpChannelOpenArgs openArgs;
    2479             :   // No access to HttpChannelOpenArgs members, but they each have a
    2480             :   // function with the struct name that returns a ref.
    2481           3 :   SerializeURI(mURI, openArgs.uri());
    2482           3 :   SerializeURI(mOriginalURI, openArgs.original());
    2483           3 :   SerializeURI(mDocumentURI, openArgs.doc());
    2484           3 :   SerializeURI(mReferrer, openArgs.referrer());
    2485           3 :   openArgs.referrerPolicy() = mReferrerPolicy;
    2486           3 :   SerializeURI(mAPIRedirectToURI, openArgs.apiRedirectTo());
    2487           3 :   openArgs.loadFlags() = mLoadFlags;
    2488           3 :   openArgs.requestHeaders() = mClientSetRequestHeaders;
    2489           3 :   mRequestHead.Method(openArgs.requestMethod());
    2490           3 :   openArgs.preferredAlternativeType() = mPreferredCachedAltDataType;
    2491             : 
    2492           6 :   AutoIPCStream autoStream(openArgs.uploadStream());
    2493           3 :   if (mUploadStream) {
    2494           0 :     autoStream.Serialize(mUploadStream, ContentChild::GetSingleton());
    2495           0 :     autoStream.TakeOptionalValue();
    2496             :   }
    2497             : 
    2498           3 :   if (mResponseHead) {
    2499           0 :     openArgs.synthesizedResponseHead() = *mResponseHead;
    2500           0 :     openArgs.suspendAfterSynthesizeResponse() =
    2501           0 :       mSuspendParentAfterSynthesizeResponse;
    2502             :   } else {
    2503           3 :     openArgs.synthesizedResponseHead() = mozilla::void_t();
    2504           3 :     openArgs.suspendAfterSynthesizeResponse() = false;
    2505             :   }
    2506             : 
    2507           6 :   nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(mSecurityInfo);
    2508           3 :   if (secInfoSer) {
    2509           0 :     NS_SerializeToString(secInfoSer, openArgs.synthesizedSecurityInfoSerialization());
    2510             :   }
    2511             : 
    2512           6 :   OptionalCorsPreflightArgs optionalCorsPreflightArgs;
    2513           3 :   GetClientSetCorsPreflightParameters(optionalCorsPreflightArgs);
    2514             : 
    2515             :   // NB: This call forces us to cache mTopWindowURI if we haven't already.
    2516           6 :   nsCOMPtr<nsIURI> uri;
    2517           3 :   GetTopWindowURI(getter_AddRefs(uri));
    2518             : 
    2519           3 :   SerializeURI(mTopWindowURI, openArgs.topWindowURI());
    2520             : 
    2521           3 :   openArgs.preflightArgs() = optionalCorsPreflightArgs;
    2522             : 
    2523           3 :   openArgs.uploadStreamHasHeaders() = mUploadStreamHasHeaders;
    2524           3 :   openArgs.priority() = mPriority;
    2525           3 :   openArgs.classOfService() = mClassOfService;
    2526           3 :   openArgs.redirectionLimit() = mRedirectionLimit;
    2527           3 :   openArgs.allowSTS() = mAllowSTS;
    2528           3 :   openArgs.thirdPartyFlags() = mThirdPartyFlags;
    2529           3 :   openArgs.resumeAt() = mSendResumeAt;
    2530           3 :   openArgs.startPos() = mStartPos;
    2531           3 :   openArgs.entityID() = mEntityID;
    2532           3 :   openArgs.chooseApplicationCache() = mChooseApplicationCache;
    2533           3 :   openArgs.appCacheClientID() = appCacheClientId;
    2534           3 :   openArgs.allowSpdy() = mAllowSpdy;
    2535           3 :   openArgs.allowAltSvc() = mAllowAltSvc;
    2536           3 :   openArgs.beConservative() = mBeConservative;
    2537           3 :   openArgs.initialRwin() = mInitialRwin;
    2538             : 
    2539           3 :   uint32_t cacheKey = 0;
    2540           3 :   if (mCacheKey) {
    2541           0 :     nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(mCacheKey);
    2542           0 :     if (!container) {
    2543           0 :       return NS_ERROR_ILLEGAL_VALUE;
    2544             :     }
    2545             : 
    2546           0 :     nsresult rv = container->GetData(&cacheKey);
    2547           0 :     if (NS_FAILED(rv)) {
    2548           0 :       return rv;
    2549             :     }
    2550             :   }
    2551           3 :   openArgs.cacheKey() = cacheKey;
    2552             : 
    2553           3 :   openArgs.blockAuthPrompt() = mBlockAuthPrompt;
    2554             : 
    2555           3 :   openArgs.allowStaleCacheContent() = mAllowStaleCacheContent;
    2556             : 
    2557           3 :   openArgs.contentTypeHint() = mContentTypeHint;
    2558             : 
    2559           3 :   nsresult rv = mozilla::ipc::LoadInfoToLoadInfoArgs(mLoadInfo, &openArgs.loadInfo());
    2560           3 :   NS_ENSURE_SUCCESS(rv, rv);
    2561             : 
    2562           3 :   EnsureRequestContextID();
    2563           3 :   openArgs.requestContextID() = mRequestContextID;
    2564             : 
    2565           3 :   openArgs.channelId() = mChannelId;
    2566             : 
    2567           3 :   openArgs.contentWindowId() = contentWindowId;
    2568           3 :   openArgs.topLevelOuterContentWindowId() = mTopLevelOuterContentWindowId;
    2569             : 
    2570           3 :   if (tabChild && !tabChild->IPCOpen()) {
    2571           0 :     return NS_ERROR_FAILURE;
    2572             :   }
    2573             : 
    2574           3 :   ContentChild* cc = static_cast<ContentChild*>(gNeckoChild->Manager());
    2575           3 :   if (cc->IsShuttingDown()) {
    2576           0 :     return NS_ERROR_FAILURE;
    2577             :   }
    2578             : 
    2579           3 :   openArgs.launchServiceWorkerStart() = mLaunchServiceWorkerStart;
    2580           3 :   openArgs.launchServiceWorkerEnd()   = mLaunchServiceWorkerEnd;
    2581           3 :   openArgs.dispatchFetchEventStart()  = mDispatchFetchEventStart;
    2582           3 :   openArgs.dispatchFetchEventEnd()    = mDispatchFetchEventEnd;
    2583           3 :   openArgs.handleFetchEventStart()    = mHandleFetchEventStart;
    2584           3 :   openArgs.handleFetchEventEnd()      = mHandleFetchEventEnd;
    2585             : 
    2586             :   // This must happen before the constructor message is sent. Otherwise messages
    2587             :   // from the parent could arrive quickly and be delivered to the wrong event
    2588             :   // target.
    2589           3 :   SetEventTarget();
    2590             : 
    2591             :   // The socket transport in the chrome process now holds a logical ref to us
    2592             :   // until OnStopRequest, or we do a redirect, or we hit an IPDL error.
    2593           3 :   AddIPDLReference();
    2594             : 
    2595           6 :   PBrowserOrId browser = cc->GetBrowserOrId(tabChild);
    2596           6 :   IPC::SerializedLoadContext slc(this);
    2597           3 :   MOZ_DIAGNOSTIC_ASSERT(gIPCSecurityDisabled || slc.IsNotNull(),
    2598             :                         "SerializedLoadContext should not be null");
    2599           3 :   if (!gNeckoChild->SendPHttpChannelConstructor(this, browser,
    2600             :                                                 slc,
    2601             :                                                 openArgs)) {
    2602           0 :     return NS_ERROR_FAILURE;
    2603             :   }
    2604             : 
    2605             :   {
    2606           6 :     MutexAutoLock lock(mBgChildMutex);
    2607             : 
    2608           3 :     MOZ_RELEASE_ASSERT(gSocketTransportService);
    2609             : 
    2610             :     // Service worker might use the same HttpChannelChild to do async open
    2611             :     // twice. Need to disconnect with previous background channel before
    2612             :     // creating the new one, to prevent receiving further notification
    2613             :     // from it.
    2614           3 :     if (mBgChild) {
    2615           0 :       RefPtr<HttpBackgroundChannelChild> prevBgChild = mBgChild.forget();
    2616           0 :       gSocketTransportService->Dispatch(
    2617           0 :         NewRunnableMethod(
    2618             :           "HttpBackgroundChannelChild::OnChannelClosed",
    2619             :           prevBgChild, &HttpBackgroundChannelChild::OnChannelClosed),
    2620           0 :         NS_DISPATCH_NORMAL);
    2621             :     }
    2622             : 
    2623           3 :     MOZ_ASSERT(!mBgInitFailCallback);
    2624             : 
    2625           6 :     mBgInitFailCallback = NewRunnableMethod<nsresult>(
    2626             :         "HttpChannelChild::FailedAsyncOpen",
    2627             :         this, &HttpChannelChild::FailedAsyncOpen,
    2628           3 :         NS_ERROR_FAILURE);
    2629             : 
    2630             :     RefPtr<HttpBackgroundChannelChild> bgChild =
    2631           6 :       new HttpBackgroundChannelChild();
    2632             : 
    2633           6 :     RefPtr<HttpChannelChild> self = this;
    2634             :     nsresult rv =
    2635           6 :       gSocketTransportService->Dispatch(
    2636           6 :         NewRunnableMethod<RefPtr<HttpChannelChild>>(
    2637             :           "HttpBackgroundChannelChild::Init",
    2638             :           bgChild, &HttpBackgroundChannelChild::Init, self),
    2639           3 :         NS_DISPATCH_NORMAL);
    2640             : 
    2641           3 :     if (NS_WARN_IF(NS_FAILED(rv))) {
    2642           0 :       return rv;
    2643             :     }
    2644             : 
    2645           3 :     mBgChild = bgChild.forget();
    2646             :   }
    2647             : 
    2648           3 :   return NS_OK;
    2649             : }
    2650             : 
    2651             : //-----------------------------------------------------------------------------
    2652             : // HttpChannelChild::nsIHttpChannel
    2653             : //-----------------------------------------------------------------------------
    2654             : 
    2655             : NS_IMETHODIMP
    2656           2 : HttpChannelChild::SetReferrerWithPolicy(nsIURI *referrer,
    2657             :                                        uint32_t referrerPolicy)
    2658             : {
    2659           2 :   ENSURE_CALLED_BEFORE_CONNECT();
    2660             : 
    2661             :   // remove old referrer if any, loop backwards
    2662           4 :   for (int i = mClientSetRequestHeaders.Length() - 1; i >= 0; --i) {
    2663           2 :     if (NS_LITERAL_CSTRING("Referer").Equals(mClientSetRequestHeaders[i].mHeader)) {
    2664           0 :       mClientSetRequestHeaders.RemoveElementAt(i);
    2665             :     }
    2666             :   }
    2667             : 
    2668           2 :   nsresult rv = HttpBaseChannel::SetReferrerWithPolicy(referrer, referrerPolicy);
    2669           2 :   if (NS_FAILED(rv))
    2670           0 :     return rv;
    2671           2 :   return NS_OK;
    2672             : 
    2673             : }
    2674             : NS_IMETHODIMP
    2675           7 : HttpChannelChild::SetRequestHeader(const nsACString& aHeader,
    2676             :                                    const nsACString& aValue,
    2677             :                                    bool aMerge)
    2678             : {
    2679           7 :   LOG(("HttpChannelChild::SetRequestHeader [this=%p]\n", this));
    2680           7 :   nsresult rv = HttpBaseChannel::SetRequestHeader(aHeader, aValue, aMerge);
    2681           7 :   if (NS_FAILED(rv))
    2682           0 :     return rv;
    2683             : 
    2684           7 :   RequestHeaderTuple* tuple = mClientSetRequestHeaders.AppendElement();
    2685           7 :   if (!tuple)
    2686           0 :     return NS_ERROR_OUT_OF_MEMORY;
    2687             : 
    2688           7 :   tuple->mHeader = aHeader;
    2689           7 :   tuple->mValue = aValue;
    2690           7 :   tuple->mMerge = aMerge;
    2691           7 :   tuple->mEmpty = false;
    2692           7 :   return NS_OK;
    2693             : }
    2694             : 
    2695             : NS_IMETHODIMP
    2696           0 : HttpChannelChild::SetEmptyRequestHeader(const nsACString& aHeader)
    2697             : {
    2698           0 :   LOG(("HttpChannelChild::SetEmptyRequestHeader [this=%p]\n", this));
    2699           0 :   nsresult rv = HttpBaseChannel::SetEmptyRequestHeader(aHeader);
    2700           0 :   if (NS_FAILED(rv))
    2701           0 :     return rv;
    2702             : 
    2703           0 :   RequestHeaderTuple* tuple = mClientSetRequestHeaders.AppendElement();
    2704           0 :   if (!tuple)
    2705           0 :     return NS_ERROR_OUT_OF_MEMORY;
    2706             : 
    2707           0 :   tuple->mHeader = aHeader;
    2708           0 :   tuple->mMerge = false;
    2709           0 :   tuple->mEmpty = true;
    2710           0 :   return NS_OK;
    2711             : }
    2712             : 
    2713             : NS_IMETHODIMP
    2714           0 : HttpChannelChild::RedirectTo(nsIURI *newURI)
    2715             : {
    2716             :   // disabled until/unless addons run in child or something else needs this
    2717           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    2718             : }
    2719             : 
    2720             : NS_IMETHODIMP
    2721           2 : HttpChannelChild::GetProtocolVersion(nsACString& aProtocolVersion)
    2722             : {
    2723           2 :   aProtocolVersion = mProtocolVersion;
    2724           2 :   return NS_OK;
    2725             : }
    2726             : 
    2727             : //-----------------------------------------------------------------------------
    2728             : // HttpChannelChild::nsIHttpChannelInternal
    2729             : //-----------------------------------------------------------------------------
    2730             : 
    2731             : NS_IMETHODIMP
    2732           0 : HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey)
    2733             : {
    2734           0 :   DROP_DEAD();
    2735             : }
    2736             : 
    2737             : //-----------------------------------------------------------------------------
    2738             : // HttpChannelChild::nsICacheInfoChannel
    2739             : //-----------------------------------------------------------------------------
    2740             : 
    2741             : NS_IMETHODIMP
    2742           0 : HttpChannelChild::GetCacheTokenFetchCount(int32_t *_retval)
    2743             : {
    2744           0 :   NS_ENSURE_ARG_POINTER(_retval);
    2745           0 :   if (!mCacheEntryAvailable && !mAltDataCacheEntryAvailable) {
    2746           0 :     return NS_ERROR_NOT_AVAILABLE;
    2747             :   }
    2748             : 
    2749           0 :   *_retval = mCacheFetchCount;
    2750           0 :   return NS_OK;
    2751             : }
    2752             : 
    2753             : NS_IMETHODIMP
    2754           0 : HttpChannelChild::GetCacheTokenLastFetched(uint32_t *_retval)
    2755             : {
    2756           0 :   NS_ENSURE_ARG_POINTER(_retval);
    2757           0 :   if (!mCacheEntryAvailable && !mAltDataCacheEntryAvailable) {
    2758           0 :     return NS_ERROR_NOT_AVAILABLE;
    2759             :   }
    2760             : 
    2761           0 :   *_retval = mCacheLastFetched;
    2762           0 :   return NS_OK;
    2763             : }
    2764             : 
    2765             : NS_IMETHODIMP
    2766           1 : HttpChannelChild::GetCacheTokenExpirationTime(uint32_t *_retval)
    2767             : {
    2768           1 :   NS_ENSURE_ARG_POINTER(_retval);
    2769           1 :   if (!mCacheEntryAvailable)
    2770           0 :     return NS_ERROR_NOT_AVAILABLE;
    2771             : 
    2772           1 :   *_retval = mCacheExpirationTime;
    2773           1 :   return NS_OK;
    2774             : }
    2775             : 
    2776             : NS_IMETHODIMP
    2777           0 : HttpChannelChild::GetCacheTokenCachedCharset(nsACString &_retval)
    2778             : {
    2779           0 :   if (!mCacheEntryAvailable)
    2780           0 :     return NS_ERROR_NOT_AVAILABLE;
    2781             : 
    2782           0 :   _retval = mCachedCharset;
    2783           0 :   return NS_OK;
    2784             : }
    2785             : NS_IMETHODIMP
    2786           0 : HttpChannelChild::SetCacheTokenCachedCharset(const nsACString &aCharset)
    2787             : {
    2788           0 :   if (!mCacheEntryAvailable || !RemoteChannelExists())
    2789           0 :     return NS_ERROR_NOT_AVAILABLE;
    2790             : 
    2791           0 :   mCachedCharset = aCharset;
    2792           0 :   if (!SendSetCacheTokenCachedCharset(PromiseFlatCString(aCharset))) {
    2793           0 :     return NS_ERROR_FAILURE;
    2794             :   }
    2795           0 :   return NS_OK;
    2796             : }
    2797             : 
    2798             : NS_IMETHODIMP
    2799           2 : HttpChannelChild::IsFromCache(bool *value)
    2800             : {
    2801           2 :   if (!mIsPending)
    2802           0 :     return NS_ERROR_NOT_AVAILABLE;
    2803             : 
    2804           2 :   *value = mIsFromCache;
    2805           2 :   return NS_OK;
    2806             : }
    2807             : 
    2808             : NS_IMETHODIMP
    2809           1 : HttpChannelChild::GetCacheKey(nsISupports **cacheKey)
    2810             : {
    2811           1 :   NS_IF_ADDREF(*cacheKey = mCacheKey);
    2812           1 :   return NS_OK;
    2813             : }
    2814             : NS_IMETHODIMP
    2815           0 : HttpChannelChild::SetCacheKey(nsISupports *cacheKey)
    2816             : {
    2817           0 :   ENSURE_CALLED_BEFORE_ASYNC_OPEN();
    2818             : 
    2819           0 :   mCacheKey = cacheKey;
    2820           0 :   return NS_OK;
    2821             : }
    2822             : 
    2823             : NS_IMETHODIMP
    2824           0 : HttpChannelChild::SetAllowStaleCacheContent(bool aAllowStaleCacheContent)
    2825             : {
    2826           0 :   mAllowStaleCacheContent = aAllowStaleCacheContent;
    2827           0 :   return NS_OK;
    2828             : }
    2829             : NS_IMETHODIMP
    2830           0 : HttpChannelChild::GetAllowStaleCacheContent(bool *aAllowStaleCacheContent)
    2831             : {
    2832           0 :   NS_ENSURE_ARG(aAllowStaleCacheContent);
    2833           0 :   *aAllowStaleCacheContent = mAllowStaleCacheContent;
    2834           0 :   return NS_OK;
    2835             : }
    2836             : 
    2837             : NS_IMETHODIMP
    2838           0 : HttpChannelChild::PreferAlternativeDataType(const nsACString & aType)
    2839             : {
    2840           0 :   ENSURE_CALLED_BEFORE_ASYNC_OPEN();
    2841           0 :   mPreferredCachedAltDataType = aType;
    2842           0 :   return NS_OK;
    2843             : }
    2844             : 
    2845             : NS_IMETHODIMP
    2846           2 : HttpChannelChild::GetAlternativeDataType(nsACString & aType)
    2847             : {
    2848             :   // Must be called during or after OnStartRequest
    2849           2 :   if (!mAfterOnStartRequestBegun) {
    2850           0 :     return NS_ERROR_NOT_AVAILABLE;
    2851             :   }
    2852             : 
    2853           2 :   aType = mAvailableCachedAltDataType;
    2854           2 :   return NS_OK;
    2855             : }
    2856             : 
    2857             : NS_IMETHODIMP
    2858           0 : HttpChannelChild::OpenAlternativeOutputStream(const nsACString & aType, nsIOutputStream * *_retval)
    2859             : {
    2860           0 :   MOZ_ASSERT(NS_IsMainThread(), "Main thread only");
    2861             : 
    2862           0 :   if (!mIPCOpen) {
    2863           0 :     return NS_ERROR_NOT_AVAILABLE;
    2864             :   }
    2865           0 :   if (static_cast<ContentChild*>(gNeckoChild->Manager())->IsShuttingDown()) {
    2866           0 :     return NS_ERROR_NOT_AVAILABLE;
    2867             :   }
    2868             : 
    2869           0 :   nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
    2870           0 :   MOZ_ASSERT(neckoTarget);
    2871             : 
    2872           0 :   RefPtr<AltDataOutputStreamChild> stream = new AltDataOutputStreamChild();
    2873           0 :   stream->AddIPDLReference();
    2874             : 
    2875           0 :   gNeckoChild->SetEventTargetForActor(stream, neckoTarget);
    2876             : 
    2877           0 :   if (!gNeckoChild->SendPAltDataOutputStreamConstructor(stream,
    2878           0 :                                                         nsCString(aType),
    2879           0 :                                                         this)) {
    2880           0 :     return NS_ERROR_FAILURE;
    2881             :   }
    2882             : 
    2883           0 :   stream.forget(_retval);
    2884           0 :   return NS_OK;
    2885             : }
    2886             : 
    2887             : //-----------------------------------------------------------------------------
    2888             : // HttpChannelChild::nsIResumableChannel
    2889             : //-----------------------------------------------------------------------------
    2890             : 
    2891             : NS_IMETHODIMP
    2892           0 : HttpChannelChild::ResumeAt(uint64_t startPos, const nsACString& entityID)
    2893             : {
    2894           0 :   LOG(("HttpChannelChild::ResumeAt [this=%p]\n", this));
    2895           0 :   ENSURE_CALLED_BEFORE_CONNECT();
    2896           0 :   mStartPos = startPos;
    2897           0 :   mEntityID = entityID;
    2898           0 :   mSendResumeAt = true;
    2899           0 :   return NS_OK;
    2900             : }
    2901             : 
    2902             : // GetEntityID is shared in HttpBaseChannel
    2903             : 
    2904             : //-----------------------------------------------------------------------------
    2905             : // HttpChannelChild::nsISupportsPriority
    2906             : //-----------------------------------------------------------------------------
    2907             : 
    2908             : NS_IMETHODIMP
    2909           0 : HttpChannelChild::SetPriority(int32_t aPriority)
    2910             : {
    2911           0 :   int16_t newValue = clamped<int32_t>(aPriority, INT16_MIN, INT16_MAX);
    2912           0 :   if (mPriority == newValue)
    2913           0 :     return NS_OK;
    2914           0 :   mPriority = newValue;
    2915           0 :   if (RemoteChannelExists())
    2916           0 :     SendSetPriority(mPriority);
    2917           0 :   return NS_OK;
    2918             : }
    2919             : 
    2920             : //-----------------------------------------------------------------------------
    2921             : // HttpChannelChild::nsIClassOfService
    2922             : //-----------------------------------------------------------------------------
    2923             : NS_IMETHODIMP
    2924           0 : HttpChannelChild::SetClassFlags(uint32_t inFlags)
    2925             : {
    2926           0 :   if (mClassOfService == inFlags) {
    2927           0 :     return NS_OK;
    2928             :   }
    2929             : 
    2930           0 :   mClassOfService = inFlags;
    2931           0 :   if (RemoteChannelExists()) {
    2932           0 :     SendSetClassOfService(mClassOfService);
    2933             :   }
    2934           0 :   return NS_OK;
    2935             : }
    2936             : 
    2937             : NS_IMETHODIMP
    2938           3 : HttpChannelChild::AddClassFlags(uint32_t inFlags)
    2939             : {
    2940           3 :   mClassOfService |= inFlags;
    2941           3 :   if (RemoteChannelExists()) {
    2942           0 :     SendSetClassOfService(mClassOfService);
    2943             :   }
    2944           3 :   return NS_OK;
    2945             : }
    2946             : 
    2947             : NS_IMETHODIMP
    2948           0 : HttpChannelChild::ClearClassFlags(uint32_t inFlags)
    2949             : {
    2950           0 :   mClassOfService &= ~inFlags;
    2951           0 :   if (RemoteChannelExists()) {
    2952           0 :     SendSetClassOfService(mClassOfService);
    2953             :   }
    2954           0 :   return NS_OK;
    2955             : }
    2956             : 
    2957             : //-----------------------------------------------------------------------------
    2958             : // HttpChannelChild::nsIProxiedChannel
    2959             : //-----------------------------------------------------------------------------
    2960             : 
    2961             : NS_IMETHODIMP
    2962           0 : HttpChannelChild::GetProxyInfo(nsIProxyInfo **aProxyInfo)
    2963             : {
    2964           0 :   DROP_DEAD();
    2965             : }
    2966             : 
    2967             : //-----------------------------------------------------------------------------
    2968             : // HttpChannelChild::nsIApplicationCacheContainer
    2969             : //-----------------------------------------------------------------------------
    2970             : 
    2971             : NS_IMETHODIMP
    2972           0 : HttpChannelChild::GetApplicationCache(nsIApplicationCache **aApplicationCache)
    2973             : {
    2974           0 :   NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
    2975           0 :   return NS_OK;
    2976             : }
    2977             : NS_IMETHODIMP
    2978           0 : HttpChannelChild::SetApplicationCache(nsIApplicationCache *aApplicationCache)
    2979             : {
    2980           0 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
    2981             : 
    2982           0 :   mApplicationCache = aApplicationCache;
    2983           0 :   return NS_OK;
    2984             : }
    2985             : 
    2986             : //-----------------------------------------------------------------------------
    2987             : // HttpChannelChild::nsIApplicationCacheChannel
    2988             : //-----------------------------------------------------------------------------
    2989             : 
    2990             : NS_IMETHODIMP
    2991           0 : HttpChannelChild::GetApplicationCacheForWrite(nsIApplicationCache **aApplicationCache)
    2992             : {
    2993           0 :   *aApplicationCache = nullptr;
    2994           0 :   return NS_OK;
    2995             : }
    2996             : NS_IMETHODIMP
    2997           0 : HttpChannelChild::SetApplicationCacheForWrite(nsIApplicationCache *aApplicationCache)
    2998             : {
    2999           0 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
    3000             : 
    3001             :   // Child channels are not intended to be used for cache writes
    3002           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    3003             : }
    3004             : 
    3005             : NS_IMETHODIMP
    3006           1 : HttpChannelChild::GetLoadedFromApplicationCache(bool *aLoadedFromApplicationCache)
    3007             : {
    3008           1 :   *aLoadedFromApplicationCache = mLoadedFromApplicationCache;
    3009           1 :   return NS_OK;
    3010             : }
    3011             : 
    3012             : NS_IMETHODIMP
    3013           0 : HttpChannelChild::GetInheritApplicationCache(bool *aInherit)
    3014             : {
    3015           0 :   *aInherit = mInheritApplicationCache;
    3016           0 :   return NS_OK;
    3017             : }
    3018             : NS_IMETHODIMP
    3019           1 : HttpChannelChild::SetInheritApplicationCache(bool aInherit)
    3020             : {
    3021           1 :   mInheritApplicationCache = aInherit;
    3022           1 :   return NS_OK;
    3023             : }
    3024             : 
    3025             : NS_IMETHODIMP
    3026           0 : HttpChannelChild::GetChooseApplicationCache(bool *aChoose)
    3027             : {
    3028           0 :   *aChoose = mChooseApplicationCache;
    3029           0 :   return NS_OK;
    3030             : }
    3031             : 
    3032             : NS_IMETHODIMP
    3033           1 : HttpChannelChild::SetChooseApplicationCache(bool aChoose)
    3034             : {
    3035           1 :   mChooseApplicationCache = aChoose;
    3036           1 :   return NS_OK;
    3037             : }
    3038             : 
    3039             : NS_IMETHODIMP
    3040           0 : HttpChannelChild::MarkOfflineCacheEntryAsForeign()
    3041             : {
    3042           0 :   SendMarkOfflineCacheEntryAsForeign();
    3043           0 :   return NS_OK;
    3044             : }
    3045             : 
    3046             : //-----------------------------------------------------------------------------
    3047             : // HttpChannelChild::nsIAssociatedContentSecurity
    3048             : //-----------------------------------------------------------------------------
    3049             : 
    3050             : bool
    3051         143 : HttpChannelChild::GetAssociatedContentSecurity(
    3052             :                     nsIAssociatedContentSecurity** _result)
    3053             : {
    3054         143 :   if (!mSecurityInfo)
    3055         143 :     return false;
    3056             : 
    3057             :   nsCOMPtr<nsIAssociatedContentSecurity> assoc =
    3058           0 :       do_QueryInterface(mSecurityInfo);
    3059           0 :   if (!assoc)
    3060           0 :     return false;
    3061             : 
    3062           0 :   if (_result)
    3063           0 :     assoc.forget(_result);
    3064           0 :   return true;
    3065             : }
    3066             : 
    3067             : NS_IMETHODIMP
    3068           0 : HttpChannelChild::GetCountSubRequestsBrokenSecurity(
    3069             :                     int32_t *aSubRequestsBrokenSecurity)
    3070             : {
    3071           0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    3072           0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    3073           0 :     return NS_OK;
    3074             : 
    3075           0 :   return assoc->GetCountSubRequestsBrokenSecurity(aSubRequestsBrokenSecurity);
    3076             : }
    3077             : NS_IMETHODIMP
    3078           0 : HttpChannelChild::SetCountSubRequestsBrokenSecurity(
    3079             :                     int32_t aSubRequestsBrokenSecurity)
    3080             : {
    3081           0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    3082           0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    3083           0 :     return NS_OK;
    3084             : 
    3085           0 :   return assoc->SetCountSubRequestsBrokenSecurity(aSubRequestsBrokenSecurity);
    3086             : }
    3087             : 
    3088             : NS_IMETHODIMP
    3089           0 : HttpChannelChild::GetCountSubRequestsNoSecurity(int32_t *aSubRequestsNoSecurity)
    3090             : {
    3091           0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    3092           0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    3093           0 :     return NS_OK;
    3094             : 
    3095           0 :   return assoc->GetCountSubRequestsNoSecurity(aSubRequestsNoSecurity);
    3096             : }
    3097             : NS_IMETHODIMP
    3098           0 : HttpChannelChild::SetCountSubRequestsNoSecurity(int32_t aSubRequestsNoSecurity)
    3099             : {
    3100           0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    3101           0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    3102           0 :     return NS_OK;
    3103             : 
    3104           0 :   return assoc->SetCountSubRequestsNoSecurity(aSubRequestsNoSecurity);
    3105             : }
    3106             : 
    3107             : NS_IMETHODIMP
    3108           0 : HttpChannelChild::Flush()
    3109             : {
    3110           0 :   nsCOMPtr<nsIAssociatedContentSecurity> assoc;
    3111           0 :   if (!GetAssociatedContentSecurity(getter_AddRefs(assoc)))
    3112           0 :     return NS_OK;
    3113             : 
    3114             :   nsresult rv;
    3115             :   int32_t broken, no;
    3116             : 
    3117           0 :   rv = assoc->GetCountSubRequestsBrokenSecurity(&broken);
    3118           0 :   NS_ENSURE_SUCCESS(rv, rv);
    3119           0 :   rv = assoc->GetCountSubRequestsNoSecurity(&no);
    3120           0 :   NS_ENSURE_SUCCESS(rv, rv);
    3121             : 
    3122           0 :   if (mIPCOpen)
    3123           0 :     SendUpdateAssociatedContentSecurity(broken, no);
    3124             : 
    3125           0 :   return NS_OK;
    3126             : }
    3127             : 
    3128             : //-----------------------------------------------------------------------------
    3129             : // HttpChannelChild::nsIHttpChannelChild
    3130             : //-----------------------------------------------------------------------------
    3131             : 
    3132           3 : NS_IMETHODIMP HttpChannelChild::AddCookiesToRequest()
    3133             : {
    3134           3 :   HttpBaseChannel::AddCookiesToRequest();
    3135           3 :   return NS_OK;
    3136             : }
    3137             : 
    3138           0 : NS_IMETHODIMP HttpChannelChild::GetClientSetRequestHeaders(RequestHeaderTuples **aRequestHeaders)
    3139             : {
    3140           0 :   *aRequestHeaders = &mClientSetRequestHeaders;
    3141           0 :   return NS_OK;
    3142             : }
    3143             : 
    3144             : void
    3145           3 : HttpChannelChild::GetClientSetCorsPreflightParameters(OptionalCorsPreflightArgs& aArgs)
    3146             : {
    3147           3 :   if (mRequireCORSPreflight) {
    3148           0 :     CorsPreflightArgs args;
    3149           0 :     args.unsafeHeaders() = mUnsafeHeaders;
    3150           0 :     aArgs = args;
    3151             :   } else {
    3152           3 :     aArgs = mozilla::void_t();
    3153             :   }
    3154           3 : }
    3155             : 
    3156             : NS_IMETHODIMP
    3157           0 : HttpChannelChild::RemoveCorsPreflightCacheEntry(nsIURI* aURI,
    3158             :                                                 nsIPrincipal* aPrincipal)
    3159             : {
    3160           0 :   URIParams uri;
    3161           0 :   SerializeURI(aURI, uri);
    3162           0 :   PrincipalInfo principalInfo;
    3163           0 :   nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
    3164           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
    3165           0 :     return rv;
    3166             :   }
    3167           0 :   bool result = false;
    3168             :   // Be careful to not attempt to send a message to the parent after the
    3169             :   // actor has been destroyed.
    3170           0 :   if (mIPCOpen) {
    3171           0 :     result = SendRemoveCorsPreflightCacheEntry(uri, principalInfo);
    3172             :   }
    3173           0 :   return result ? NS_OK : NS_ERROR_FAILURE;
    3174             : }
    3175             : 
    3176             : //-----------------------------------------------------------------------------
    3177             : // HttpChannelChild::nsIDivertableChannel
    3178             : //-----------------------------------------------------------------------------
    3179             : NS_IMETHODIMP
    3180           0 : HttpChannelChild::DivertToParent(ChannelDiverterChild **aChild)
    3181             : {
    3182           0 :   LOG(("HttpChannelChild::DivertToParent [this=%p]\n", this));
    3183           0 :   MOZ_RELEASE_ASSERT(aChild);
    3184           0 :   MOZ_RELEASE_ASSERT(gNeckoChild);
    3185           0 :   MOZ_RELEASE_ASSERT(!mDivertingToParent);
    3186             : 
    3187           0 :   nsresult rv = NS_OK;
    3188             : 
    3189             :   // If the channel was intercepted, then we likely do not have an IPC actor
    3190             :   // yet.  We need one, though, in order to have a parent side to divert to.
    3191             :   // Therefore, create the actor just in time for us to suspend and divert it.
    3192           0 :   if (mSynthesizedResponse && !RemoteChannelExists()) {
    3193           0 :     mSuspendParentAfterSynthesizeResponse = true;
    3194           0 :     rv = ContinueAsyncOpen();
    3195           0 :     NS_ENSURE_SUCCESS(rv, rv);
    3196             :   }
    3197             : 
    3198             :   // We must fail DivertToParent() if there's no parent end of the channel (and
    3199             :   // won't be!) due to early failure.
    3200           0 :   if (NS_FAILED(mStatus) && !RemoteChannelExists()) {
    3201           0 :     return mStatus;
    3202             :   }
    3203             : 
    3204             :   // Once this is set, it should not be unset before the child is taken down.
    3205           0 :   mDivertingToParent = true;
    3206             : 
    3207           0 :   rv = Suspend();
    3208           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
    3209           0 :     return rv;
    3210             :   }
    3211           0 :   if (static_cast<ContentChild*>(gNeckoChild->Manager())->IsShuttingDown()) {
    3212           0 :     return NS_ERROR_FAILURE;
    3213             :   }
    3214             : 
    3215           0 :   HttpChannelDiverterArgs args;
    3216           0 :   args.mChannelChild() = this;
    3217           0 :   args.mApplyConversion() = mApplyConversion;
    3218             : 
    3219             :   PChannelDiverterChild* diverter =
    3220           0 :     gNeckoChild->SendPChannelDiverterConstructor(args);
    3221           0 :   MOZ_RELEASE_ASSERT(diverter);
    3222             : 
    3223           0 :   *aChild = static_cast<ChannelDiverterChild*>(diverter);
    3224             : 
    3225           0 :   return NS_OK;
    3226             : }
    3227             : 
    3228             : NS_IMETHODIMP
    3229           0 : HttpChannelChild::UnknownDecoderInvolvedKeepData()
    3230             : {
    3231           0 :   LOG(("HttpChannelChild::UnknownDecoderInvolvedKeepData [this=%p]",
    3232             :        this));
    3233           0 :   MOZ_ASSERT(NS_IsMainThread());
    3234             : 
    3235           0 :   mUnknownDecoderInvolved = true;
    3236           0 :   return NS_OK;
    3237             : }
    3238             : 
    3239             : NS_IMETHODIMP
    3240           0 : HttpChannelChild::UnknownDecoderInvolvedOnStartRequestCalled()
    3241             : {
    3242           0 :   LOG(("HttpChannelChild::UnknownDecoderInvolvedOnStartRequestCalled "
    3243             :        "[this=%p, mDivertingToParent=%d]", this,
    3244             :        static_cast<bool>(mDivertingToParent)));
    3245           0 :   MOZ_ASSERT(NS_IsMainThread());
    3246             : 
    3247           0 :   mUnknownDecoderInvolved = false;
    3248             : 
    3249           0 :   nsresult rv = NS_OK;
    3250             : 
    3251           0 :   if (mDivertingToParent) {
    3252           0 :     rv = mEventQ->PrependEvents(mUnknownDecoderEventQ);
    3253             :   }
    3254           0 :   mUnknownDecoderEventQ.Clear();
    3255             : 
    3256           0 :   return rv;
    3257             : }
    3258             : 
    3259             : NS_IMETHODIMP
    3260           0 : HttpChannelChild::GetDivertingToParent(bool* aDiverting)
    3261             : {
    3262           0 :   NS_ENSURE_ARG_POINTER(aDiverting);
    3263           0 :   *aDiverting = mDivertingToParent;
    3264           0 :   return NS_OK;
    3265             : }
    3266             : 
    3267             : //-----------------------------------------------------------------------------
    3268             : // HttpChannelChild::nsIThreadRetargetableRequest
    3269             : //-----------------------------------------------------------------------------
    3270             : 
    3271             : NS_IMETHODIMP
    3272           1 : HttpChannelChild::RetargetDeliveryTo(nsIEventTarget* aNewTarget)
    3273             : {
    3274           1 :   LOG(("HttpChannelChild::RetargetDeliveryTo [this=%p, aNewTarget=%p]",
    3275             :        this, aNewTarget));
    3276             : 
    3277           1 :   MOZ_ASSERT(NS_IsMainThread(), "Should be called on main thread only");
    3278           1 :   MOZ_ASSERT(!mODATarget);
    3279           1 :   MOZ_ASSERT(aNewTarget);
    3280             : 
    3281           1 :   NS_ENSURE_ARG(aNewTarget);
    3282           1 :   if (aNewTarget->IsOnCurrentThread()) {
    3283           0 :     NS_WARNING("Retargeting delivery to same thread");
    3284           0 :     return NS_OK;
    3285             :   }
    3286             : 
    3287             :   // Ensure that |mListener| and any subsequent listeners can be retargeted
    3288             :   // to another thread.
    3289           1 :   nsresult rv = NS_OK;
    3290             :   nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
    3291           2 :       do_QueryInterface(mListener, &rv);
    3292           1 :   if (!retargetableListener || NS_FAILED(rv)) {
    3293           0 :     NS_WARNING("Listener is not retargetable");
    3294           0 :     return NS_ERROR_NO_INTERFACE;
    3295             :   }
    3296             : 
    3297           1 :   rv = retargetableListener->CheckListenerChain();
    3298           1 :   if (NS_FAILED(rv)) {
    3299           0 :     NS_WARNING("Subsequent listeners are not retargetable");
    3300           0 :     return rv;
    3301             :   }
    3302             : 
    3303             :   {
    3304           2 :     MutexAutoLock lock(mEventTargetMutex);
    3305           1 :     mODATarget = aNewTarget;
    3306             :   }
    3307           1 :   return NS_OK;
    3308             : }
    3309             : 
    3310             : void
    3311           0 : HttpChannelChild::ResetInterception()
    3312             : {
    3313           0 :   NS_ENSURE_TRUE_VOID(gNeckoChild != nullptr);
    3314             : 
    3315           0 :   if (mInterceptListener) {
    3316           0 :     mInterceptListener->Cleanup();
    3317             :   }
    3318           0 :   mInterceptListener = nullptr;
    3319             : 
    3320             :   // The chance to intercept any further requests associated with this channel
    3321             :   // (such as redirects) has passed.
    3322           0 :   if (mRedirectMode != nsIHttpChannelInternal::REDIRECT_MODE_MANUAL) {
    3323           0 :     mLoadFlags |= LOAD_BYPASS_SERVICE_WORKER;
    3324             :   }
    3325             : 
    3326             :   // Continue with the original cross-process request
    3327           0 :   nsresult rv = ContinueAsyncOpen();
    3328           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
    3329           0 :     Unused << AsyncAbort(rv);
    3330             :   }
    3331             : }
    3332             : 
    3333             : NS_IMETHODIMP
    3334           5 : HttpChannelChild::GetResponseSynthesized(bool* aSynthesized)
    3335             : {
    3336           5 :   NS_ENSURE_ARG_POINTER(aSynthesized);
    3337           5 :   *aSynthesized = mSynthesizedResponse;
    3338           5 :   return NS_OK;
    3339             : }
    3340             : 
    3341             : void
    3342           2 : HttpChannelChild::TrySendDeletingChannel()
    3343             : {
    3344           2 :   if (!mDeletingChannelSent.compareExchange(false, true)) {
    3345             :     // SendDeletingChannel is already sent.
    3346           2 :     return;
    3347             :   }
    3348             : 
    3349           2 :   if (NS_IsMainThread()) {
    3350           2 :     if (NS_WARN_IF(!mIPCOpen)) {
    3351             :       // IPC actor is detroyed already, do not send more messages.
    3352           0 :       return;
    3353             :     }
    3354             : 
    3355           2 :     Unused << PHttpChannelChild::SendDeletingChannel();
    3356           2 :     return;
    3357             :   }
    3358             : 
    3359           0 :   nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
    3360           0 :   MOZ_ASSERT(neckoTarget);
    3361             : 
    3362           0 :   DebugOnly<nsresult> rv = neckoTarget->Dispatch(
    3363           0 :     NewNonOwningRunnableMethod("net::HttpChannelChild::TrySendDeletingChannel",
    3364             :                                this,
    3365             :                                &HttpChannelChild::TrySendDeletingChannel),
    3366           0 :     NS_DISPATCH_NORMAL);
    3367           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    3368             : }
    3369             : 
    3370             : void
    3371           0 : HttpChannelChild::OnCopyComplete(nsresult aStatus)
    3372             : {
    3373           0 :   nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod<nsresult>(
    3374             :     "net::HttpBaseChannel::EnsureUploadStreamIsCloneableComplete",
    3375             :     this,
    3376             :     &HttpChannelChild::EnsureUploadStreamIsCloneableComplete,
    3377           0 :     aStatus);
    3378           0 :   nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
    3379           0 :   MOZ_ASSERT(neckoTarget);
    3380             : 
    3381           0 :   Unused << neckoTarget->Dispatch(runnable, NS_DISPATCH_NORMAL);
    3382           0 : }
    3383             : 
    3384             : nsresult
    3385           0 : HttpChannelChild::AsyncCall(void (HttpChannelChild::*funcPtr)(),
    3386             :                             nsRunnableMethod<HttpChannelChild> **retval)
    3387             : {
    3388             :   nsresult rv;
    3389             : 
    3390             :   RefPtr<nsRunnableMethod<HttpChannelChild>> event =
    3391           0 :     NewRunnableMethod("net::HttpChannelChild::AsyncCall", this, funcPtr);
    3392           0 :   nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
    3393           0 :   MOZ_ASSERT(neckoTarget);
    3394             : 
    3395           0 :   rv = neckoTarget->Dispatch(event, NS_DISPATCH_NORMAL);
    3396             : 
    3397           0 :   if (NS_SUCCEEDED(rv) && retval) {
    3398           0 :     *retval = event;
    3399             :   }
    3400             : 
    3401           0 :   return rv;
    3402             : }
    3403             : 
    3404           0 : class CancelEvent final : public NeckoTargetChannelEvent<HttpChannelChild>
    3405             : {
    3406             : public:
    3407           0 :   CancelEvent(HttpChannelChild* aChild, nsresult aRv)
    3408           0 :   : NeckoTargetChannelEvent<HttpChannelChild>(aChild)
    3409           0 :   , mRv(aRv)
    3410             :   {
    3411           0 :     MOZ_ASSERT(!NS_IsMainThread());
    3412           0 :     MOZ_ASSERT(aChild);
    3413           0 :   }
    3414             : 
    3415           0 :   void Run() {
    3416           0 :     MOZ_ASSERT(NS_IsMainThread());
    3417           0 :     mChild->Cancel(mRv);
    3418           0 :   }
    3419             : 
    3420             : private:
    3421             :   const nsresult mRv;
    3422             : };
    3423             : 
    3424             : void
    3425           0 : HttpChannelChild::CancelOnMainThread(nsresult aRv)
    3426             : {
    3427           0 :   LOG(("HttpChannelChild::CancelOnMainThread [this=%p]", this));
    3428             : 
    3429           0 :   if (NS_IsMainThread()) {
    3430           0 :     Cancel(aRv);
    3431           0 :     return;
    3432             :   }
    3433             : 
    3434           0 :   mEventQ->Suspend();
    3435             :   // Cancel is expected to preempt any other channel events, thus we put this
    3436             :   // event in the front of mEventQ to make sure nsIStreamListener not receiving
    3437             :   // any ODA/OnStopRequest callbacks.
    3438           0 :   UniquePtr<ChannelEvent> cancelEvent = MakeUnique<CancelEvent>(this, aRv);
    3439           0 :   mEventQ->PrependEvent(cancelEvent);
    3440           0 :   mEventQ->Resume();
    3441             : }
    3442             : 
    3443             : void
    3444           0 : HttpChannelChild::OverrideWithSynthesizedResponse(nsAutoPtr<nsHttpResponseHead>& aResponseHead,
    3445             :                                                   nsIInputStream* aSynthesizedInput,
    3446             :                                                   InterceptStreamListener* aStreamListener)
    3447             : {
    3448           0 :   mInterceptListener = aStreamListener;
    3449             : 
    3450             :   // Intercepted responses should already be decoded.  If its a redirect,
    3451             :   // however, we want to respect the encoding of the final result instead.
    3452           0 :   if (!nsHttpChannel::WillRedirect(aResponseHead)) {
    3453           0 :     SetApplyConversion(false);
    3454             :   }
    3455             : 
    3456           0 :   mResponseHead = aResponseHead;
    3457           0 :   mSynthesizedResponse = true;
    3458             : 
    3459           0 :   if (nsHttpChannel::WillRedirect(mResponseHead)) {
    3460           0 :     mShouldInterceptSubsequentRedirect = true;
    3461             :     // Continue with the original cross-process request
    3462           0 :     nsresult rv = ContinueAsyncOpen();
    3463           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
    3464           0 :       rv = AsyncAbort(rv);
    3465           0 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
    3466             :     }
    3467           0 :     return;
    3468             :   }
    3469             : 
    3470             :   // In our current implementation, the FetchEvent handler will copy the
    3471             :   // response stream completely into the pipe backing the input stream so we
    3472             :   // can treat the available as the length of the stream.
    3473             :   uint64_t available;
    3474           0 :   nsresult rv = aSynthesizedInput->Available(&available);
    3475           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
    3476           0 :     mSynthesizedStreamLength = -1;
    3477             :   } else {
    3478           0 :     mSynthesizedStreamLength = int64_t(available);
    3479             :   }
    3480             : 
    3481           0 :   nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
    3482           0 :   MOZ_ASSERT(neckoTarget);
    3483             : 
    3484           0 :   rv = nsInputStreamPump::Create(getter_AddRefs(mSynthesizedResponsePump),
    3485             :                                  aSynthesizedInput,
    3486             :                                  int64_t(-1), int64_t(-1), 0, 0, true,
    3487           0 :                                  neckoTarget);
    3488           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
    3489           0 :     aSynthesizedInput->Close();
    3490           0 :     return;
    3491             :   }
    3492             : 
    3493           0 :   rv = mSynthesizedResponsePump->AsyncRead(aStreamListener, nullptr);
    3494           0 :   NS_ENSURE_SUCCESS_VOID(rv);
    3495             : 
    3496             :   // if this channel has been suspended previously, the pump needs to be
    3497             :   // correspondingly suspended now that it exists.
    3498           0 :   for (uint32_t i = 0; i < mSuspendCount; i++) {
    3499           0 :     rv = mSynthesizedResponsePump->Suspend();
    3500           0 :     NS_ENSURE_SUCCESS_VOID(rv);
    3501             :   }
    3502             : 
    3503           0 :   if (mCanceled) {
    3504           0 :     mSynthesizedResponsePump->Cancel(mStatus);
    3505             :   }
    3506             : }
    3507             : 
    3508             : NS_IMETHODIMP
    3509           0 : HttpChannelChild::ForceIntercepted(bool aPostRedirectChannelShouldIntercept,
    3510             :                                    bool aPostRedirectChannelShouldUpgrade)
    3511             : {
    3512           0 :   mShouldParentIntercept = true;
    3513           0 :   mPostRedirectChannelShouldIntercept = aPostRedirectChannelShouldIntercept;
    3514           0 :   mPostRedirectChannelShouldUpgrade = aPostRedirectChannelShouldUpgrade;
    3515           0 :   return NS_OK;
    3516             : }
    3517             : 
    3518             : NS_IMETHODIMP
    3519           0 : HttpChannelChild::ForceIntercepted(uint64_t aInterceptionID)
    3520             : {
    3521           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    3522             : }
    3523             : 
    3524             : void
    3525           0 : HttpChannelChild::ForceIntercepted(nsIInputStream* aSynthesizedInput)
    3526             : {
    3527           0 :   mSynthesizedInput = aSynthesizedInput;
    3528           0 :   mSynthesizedResponse = true;
    3529           0 :   mRedirectingForSubsequentSynthesizedResponse = true;
    3530           0 : }
    3531             : 
    3532             : mozilla::ipc::IPCResult
    3533           0 : HttpChannelChild::RecvIssueDeprecationWarning(const uint32_t& warning,
    3534             :                                               const bool& asError)
    3535             : {
    3536           0 :   nsCOMPtr<nsIDeprecationWarner> warner;
    3537           0 :   GetCallback(warner);
    3538           0 :   if (warner) {
    3539           0 :     warner->IssueWarning(warning, asError);
    3540             :   }
    3541           0 :   return IPC_OK();
    3542             : }
    3543             : 
    3544             : bool
    3545           3 : HttpChannelChild::ShouldInterceptURI(nsIURI* aURI,
    3546             :                                      bool& aShouldUpgrade)
    3547             : {
    3548           3 :   bool isHttps = false;
    3549           3 :   nsresult rv = aURI->SchemeIs("https", &isHttps);
    3550           3 :   NS_ENSURE_SUCCESS(rv, false);
    3551           6 :   nsCOMPtr<nsIPrincipal> resultPrincipal;
    3552           3 :   if (!isHttps && mLoadInfo) {
    3553           3 :       nsContentUtils::GetSecurityManager()->
    3554           3 :         GetChannelResultPrincipal(this, getter_AddRefs(resultPrincipal));
    3555             :   }
    3556           6 :   OriginAttributes originAttributes;
    3557           3 :   NS_ENSURE_TRUE(NS_GetOriginAttributes(this, originAttributes), false);
    3558           6 :   rv = NS_ShouldSecureUpgrade(aURI,
    3559             :                               mLoadInfo,
    3560             :                               resultPrincipal,
    3561           3 :                               mPrivateBrowsing,
    3562             :                               mAllowSTS,
    3563             :                               originAttributes,
    3564           6 :                               aShouldUpgrade);
    3565           3 :   NS_ENSURE_SUCCESS(rv, false);
    3566             : 
    3567           6 :   nsCOMPtr<nsIURI> upgradedURI;
    3568           3 :   if (aShouldUpgrade) {
    3569           0 :     rv = NS_GetSecureUpgradedURI(aURI, getter_AddRefs(upgradedURI));
    3570           0 :     NS_ENSURE_SUCCESS(rv, false);
    3571             :   }
    3572             : 
    3573           3 :   return ShouldIntercept(upgradedURI ? upgradedURI.get() : aURI);
    3574             : }
    3575             : 
    3576             : mozilla::ipc::IPCResult
    3577           1 : HttpChannelChild::RecvSetPriority(const int16_t& aPriority)
    3578             : {
    3579           1 :   mPriority = aPriority;
    3580           1 :   return IPC_OK();
    3581             : }
    3582             : 
    3583             : } // namespace net
    3584             : } // namespace mozilla

Generated by: LCOV version 1.13