LCOV - code coverage report
Current view: top level - netwerk/protocol/http - HttpBaseChannel.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 672 1916 35.1 %
Date: 2017-07-14 16:53:18 Functions: 114 272 41.9 %
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 "mozilla/net/HttpBaseChannel.h"
      12             : 
      13             : #include "nsHttpHandler.h"
      14             : #include "nsMimeTypes.h"
      15             : #include "nsNetCID.h"
      16             : #include "nsNetUtil.h"
      17             : #include "nsReadableUtils.h"
      18             : 
      19             : #include "nsICachingChannel.h"
      20             : #include "nsIDOMDocument.h"
      21             : #include "nsIPrincipal.h"
      22             : #include "nsIScriptError.h"
      23             : #include "nsISeekableStream.h"
      24             : #include "nsIStorageStream.h"
      25             : #include "nsITimedChannel.h"
      26             : #include "nsIEncodedChannel.h"
      27             : #include "nsIApplicationCacheChannel.h"
      28             : #include "nsIMutableArray.h"
      29             : #include "nsEscape.h"
      30             : #include "nsStreamListenerWrapper.h"
      31             : #include "nsISecurityConsoleMessage.h"
      32             : #include "nsURLHelper.h"
      33             : #include "nsICookieService.h"
      34             : #include "nsIStreamConverterService.h"
      35             : #include "nsCRT.h"
      36             : #include "nsContentUtils.h"
      37             : #include "nsIScriptSecurityManager.h"
      38             : #include "nsIObserverService.h"
      39             : #include "nsProxyRelease.h"
      40             : #include "nsPIDOMWindow.h"
      41             : #include "nsIDocShell.h"
      42             : #include "nsINetworkInterceptController.h"
      43             : #include "mozilla/dom/Performance.h"
      44             : #include "mozIThirdPartyUtil.h"
      45             : #include "nsStreamUtils.h"
      46             : #include "nsThreadUtils.h"
      47             : #include "nsContentSecurityManager.h"
      48             : #include "nsIChannelEventSink.h"
      49             : #include "nsILoadGroupChild.h"
      50             : #include "mozilla/ConsoleReportCollector.h"
      51             : #include "LoadInfo.h"
      52             : #include "NullPrincipal.h"
      53             : #include "nsISSLSocketControl.h"
      54             : #include "mozilla/Telemetry.h"
      55             : #include "nsIURL.h"
      56             : #include "nsIConsoleService.h"
      57             : #include "mozilla/BinarySearch.h"
      58             : #include "mozilla/DebugOnly.h"
      59             : #include "mozilla/Move.h"
      60             : #include "nsIHttpHeaderVisitor.h"
      61             : #include "nsIMIMEInputStream.h"
      62             : #include "nsIXULRuntime.h"
      63             : #include "nsICacheInfoChannel.h"
      64             : #include "nsIDOMWindowUtils.h"
      65             : #include "nsHttpChannel.h"
      66             : #include "nsRedirectHistoryEntry.h"
      67             : 
      68             : #include <algorithm>
      69             : #include "HttpBaseChannel.h"
      70             : 
      71             : namespace mozilla {
      72             : namespace net {
      73             : 
      74             : static
      75           0 : bool IsHeaderBlacklistedForRedirectCopy(nsHttpAtom const& aHeader)
      76             : {
      77             :   // IMPORTANT: keep this list ASCII-code sorted
      78             :   static nsHttpAtom const* blackList[] = {
      79             :     &nsHttp::Accept,
      80             :     &nsHttp::Accept_Encoding,
      81             :     &nsHttp::Accept_Language,
      82             :     &nsHttp::Authentication,
      83             :     &nsHttp::Authorization,
      84             :     &nsHttp::Connection,
      85             :     &nsHttp::Content_Length,
      86             :     &nsHttp::Cookie,
      87             :     &nsHttp::Host,
      88             :     &nsHttp::If,
      89             :     &nsHttp::If_Match,
      90             :     &nsHttp::If_Modified_Since,
      91             :     &nsHttp::If_None_Match,
      92             :     &nsHttp::If_None_Match_Any,
      93             :     &nsHttp::If_Range,
      94             :     &nsHttp::If_Unmodified_Since,
      95             :     &nsHttp::Proxy_Authenticate,
      96             :     &nsHttp::Proxy_Authorization,
      97             :     &nsHttp::Range,
      98             :     &nsHttp::TE,
      99             :     &nsHttp::Transfer_Encoding,
     100             :     &nsHttp::Upgrade,
     101             :     &nsHttp::User_Agent,
     102             :     &nsHttp::WWW_Authenticate
     103             :   };
     104             : 
     105             :   class HttpAtomComparator
     106             :   {
     107             :     nsHttpAtom const& mTarget;
     108             :   public:
     109           0 :     explicit HttpAtomComparator(nsHttpAtom const& aTarget)
     110           0 :       : mTarget(aTarget) {}
     111           0 :     int operator()(nsHttpAtom const* aVal) const {
     112           0 :       if (mTarget == *aVal) {
     113           0 :         return 0;
     114             :       }
     115           0 :       return strcmp(mTarget._val, aVal->_val);
     116             :     }
     117             :   };
     118             : 
     119             :   size_t unused;
     120           0 :   return BinarySearchIf(blackList, 0, ArrayLength(blackList),
     121           0 :                         HttpAtomComparator(aHeader), &unused);
     122             : }
     123             : 
     124             : class AddHeadersToChannelVisitor final : public nsIHttpHeaderVisitor
     125             : {
     126             : public:
     127             :   NS_DECL_ISUPPORTS
     128             : 
     129           0 :   explicit AddHeadersToChannelVisitor(nsIHttpChannel *aChannel)
     130           0 :     : mChannel(aChannel)
     131             :   {
     132           0 :   }
     133             : 
     134           0 :   NS_IMETHOD VisitHeader(const nsACString& aHeader,
     135             :                          const nsACString& aValue) override
     136             :   {
     137           0 :     nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
     138           0 :     if (!IsHeaderBlacklistedForRedirectCopy(atom)) {
     139           0 :       DebugOnly<nsresult> rv = mChannel->SetRequestHeader(aHeader, aValue, false);
     140           0 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
     141             :     }
     142           0 :     return NS_OK;
     143             :   }
     144             : private:
     145           0 :   ~AddHeadersToChannelVisitor()
     146           0 :   {
     147           0 :   }
     148             : 
     149             :   nsCOMPtr<nsIHttpChannel> mChannel;
     150             : };
     151             : 
     152           0 : NS_IMPL_ISUPPORTS(AddHeadersToChannelVisitor, nsIHttpHeaderVisitor)
     153             : 
     154          10 : HttpBaseChannel::HttpBaseChannel()
     155             :   : mCanceled(false)
     156             :   , mStartPos(UINT64_MAX)
     157             :   , mStatus(NS_OK)
     158             :   , mLoadFlags(LOAD_NORMAL)
     159             :   , mCaps(0)
     160             :   , mClassOfService(0)
     161             :   , mPriority(PRIORITY_NORMAL)
     162          10 :   , mRedirectionLimit(gHttpHandler->RedirectionLimit())
     163             :   , mApplyConversion(true)
     164             :   , mIsPending(false)
     165             :   , mWasOpened(false)
     166             :   , mRequestObserversCalled(false)
     167             :   , mResponseHeadersModified(false)
     168             :   , mAllowSTS(true)
     169             :   , mThirdPartyFlags(0)
     170             :   , mUploadStreamHasHeaders(false)
     171             :   , mInheritApplicationCache(true)
     172             :   , mChooseApplicationCache(false)
     173             :   , mLoadedFromApplicationCache(false)
     174             :   , mChannelIsForDownload(false)
     175             :   , mTracingEnabled(true)
     176             :   , mTimingEnabled(false)
     177             :   , mAllowSpdy(true)
     178             :   , mAllowAltSvc(true)
     179             :   , mBeConservative(false)
     180             :   , mResponseTimeoutEnabled(true)
     181             :   , mAllRedirectsSameOrigin(true)
     182             :   , mAllRedirectsPassTimingAllowCheck(true)
     183             :   , mResponseCouldBeSynthesized(false)
     184             :   , mBlockAuthPrompt(false)
     185             :   , mAllowStaleCacheContent(false)
     186             :   , mSuspendCount(0)
     187             :   , mInitialRwin(0)
     188             :   , mProxyResolveFlags(0)
     189             :   , mContentDispositionHint(UINT32_MAX)
     190             :   , mHttpHandler(gHttpHandler)
     191          10 :   , mReferrerPolicy(NS_GetDefaultReferrerPolicy())
     192             :   , mRedirectCount(0)
     193             :   , mForcePending(false)
     194             :   , mCorsIncludeCredentials(false)
     195             :   , mCorsMode(nsIHttpChannelInternal::CORS_MODE_NO_CORS)
     196             :   , mRedirectMode(nsIHttpChannelInternal::REDIRECT_MODE_FOLLOW)
     197             :   , mFetchCacheMode(nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT)
     198             :   , mOnStartRequestCalled(false)
     199             :   , mOnStopRequestCalled(false)
     200             :   , mAfterOnStartRequestBegun(false)
     201             :   , mTransferSize(0)
     202             :   , mDecodedBodySize(0)
     203             :   , mEncodedBodySize(0)
     204             :   , mRequestContextID(0)
     205             :   , mContentWindowId(0)
     206             :   , mTopLevelOuterContentWindowId(0)
     207             :   , mRequireCORSPreflight(false)
     208          10 :   , mReportCollector(new ConsoleReportCollector())
     209             :   , mAltDataLength(0)
     210             :   , mForceMainDocumentChannel(false)
     211             :   , mIsTrackingResource(false)
     212          40 :   , mLastRedirectFlags(0)
     213             : {
     214          10 :   LOG(("Creating HttpBaseChannel @%p\n", this));
     215             : 
     216             :   // Subfields of unions cannot be targeted in an initializer list.
     217             : #ifdef MOZ_VALGRIND
     218             :   // Zero the entire unions so that Valgrind doesn't complain when we send them
     219             :   // to another process.
     220             :   memset(&mSelfAddr, 0, sizeof(NetAddr));
     221             :   memset(&mPeerAddr, 0, sizeof(NetAddr));
     222             : #endif
     223          10 :   mSelfAddr.raw.family = PR_AF_UNSPEC;
     224          10 :   mPeerAddr.raw.family = PR_AF_UNSPEC;
     225          10 : }
     226             : 
     227          14 : HttpBaseChannel::~HttpBaseChannel()
     228             : {
     229           7 :   LOG(("Destroying HttpBaseChannel @%p\n", this));
     230             : 
     231             :   // Make sure we don't leak
     232           7 :   CleanRedirectCacheChainIfNecessary();
     233             : 
     234           7 :   ReleaseMainThreadOnlyReferences();
     235           7 : }
     236             : 
     237             : void
     238           7 : HttpBaseChannel::ReleaseMainThreadOnlyReferences()
     239             : {
     240           7 :   if (NS_IsMainThread()) {
     241             :     // Already on main thread, let dtor to
     242             :     // take care of releasing references
     243           7 :     return;
     244             :   }
     245             : 
     246           0 :   nsTArray<nsCOMPtr<nsISupports>> arrayToRelease;
     247           0 :   arrayToRelease.AppendElement(mURI.forget());
     248           0 :   arrayToRelease.AppendElement(mOriginalURI.forget());
     249           0 :   arrayToRelease.AppendElement(mDocumentURI.forget());
     250           0 :   arrayToRelease.AppendElement(mLoadGroup.forget());
     251           0 :   arrayToRelease.AppendElement(mLoadInfo.forget());
     252           0 :   arrayToRelease.AppendElement(mCallbacks.forget());
     253           0 :   arrayToRelease.AppendElement(mProgressSink.forget());
     254           0 :   arrayToRelease.AppendElement(mReferrer.forget());
     255           0 :   arrayToRelease.AppendElement(mApplicationCache.forget());
     256           0 :   arrayToRelease.AppendElement(mAPIRedirectToURI.forget());
     257           0 :   arrayToRelease.AppendElement(mProxyURI.forget());
     258           0 :   arrayToRelease.AppendElement(mPrincipal.forget());
     259           0 :   arrayToRelease.AppendElement(mTopWindowURI.forget());
     260             : 
     261           0 :   NS_DispatchToMainThread(new ProxyReleaseRunnable(Move(arrayToRelease)));
     262             : }
     263             : 
     264             : nsresult
     265          10 : HttpBaseChannel::Init(nsIURI *aURI,
     266             :                       uint32_t aCaps,
     267             :                       nsProxyInfo *aProxyInfo,
     268             :                       uint32_t aProxyResolveFlags,
     269             :                       nsIURI *aProxyURI,
     270             :                       uint64_t aChannelId)
     271             : {
     272          10 :   LOG(("HttpBaseChannel::Init [this=%p]\n", this));
     273             : 
     274          10 :   NS_PRECONDITION(aURI, "null uri");
     275             : 
     276          10 :   mURI = aURI;
     277          10 :   mOriginalURI = aURI;
     278          10 :   mDocumentURI = nullptr;
     279          10 :   mCaps = aCaps;
     280          10 :   mProxyResolveFlags = aProxyResolveFlags;
     281          10 :   mProxyURI = aProxyURI;
     282          10 :   mChannelId = aChannelId;
     283             : 
     284             :   // Construct connection info object
     285          20 :   nsAutoCString host;
     286          10 :   int32_t port = -1;
     287          10 :   bool isHTTPS = false;
     288             : 
     289          10 :   nsresult rv = mURI->SchemeIs("https", &isHTTPS);
     290          10 :   if (NS_FAILED(rv)) return rv;
     291             : 
     292          10 :   rv = mURI->GetAsciiHost(host);
     293          10 :   if (NS_FAILED(rv)) return rv;
     294             : 
     295             :   // Reject the URL if it doesn't specify a host
     296          10 :   if (host.IsEmpty())
     297           0 :     return NS_ERROR_MALFORMED_URI;
     298             : 
     299          10 :   rv = mURI->GetPort(&port);
     300          10 :   if (NS_FAILED(rv)) return rv;
     301             : 
     302          10 :   LOG(("host=%s port=%d\n", host.get(), port));
     303             : 
     304          10 :   rv = mURI->GetAsciiSpec(mSpec);
     305          10 :   if (NS_FAILED(rv)) return rv;
     306          10 :   LOG(("uri=%s\n", mSpec.get()));
     307             : 
     308             :   // Assert default request method
     309          10 :   MOZ_ASSERT(mRequestHead.EqualsMethod(nsHttpRequestHead::kMethod_Get));
     310             : 
     311             :   // Set request headers
     312          20 :   nsAutoCString hostLine;
     313          10 :   rv = nsHttpHandler::GenerateHostPort(host, port, hostLine);
     314          10 :   if (NS_FAILED(rv)) return rv;
     315             : 
     316          10 :   rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
     317          10 :   if (NS_FAILED(rv)) return rv;
     318             : 
     319          10 :   rv = gHttpHandler->AddStandardRequestHeaders(&mRequestHead, isHTTPS);
     320          10 :   if (NS_FAILED(rv)) return rv;
     321             : 
     322          20 :   nsAutoCString type;
     323          10 :   if (aProxyInfo && NS_SUCCEEDED(aProxyInfo->GetType(type)) &&
     324           0 :       !type.EqualsLiteral("unknown"))
     325           0 :     mProxyInfo = aProxyInfo;
     326             : 
     327          10 :   return rv;
     328             : }
     329             : 
     330             : //-----------------------------------------------------------------------------
     331             : // HttpBaseChannel::nsISupports
     332             : //-----------------------------------------------------------------------------
     333             : 
     334         321 : NS_IMPL_ADDREF(HttpBaseChannel)
     335         307 : NS_IMPL_RELEASE(HttpBaseChannel)
     336             : 
     337         259 : NS_INTERFACE_MAP_BEGIN(HttpBaseChannel)
     338         259 :   NS_INTERFACE_MAP_ENTRY(nsIRequest)
     339         259 :   NS_INTERFACE_MAP_ENTRY(nsIChannel)
     340         259 :   NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)
     341         256 :   NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
     342         256 :   NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
     343         256 :   NS_INTERFACE_MAP_ENTRY(nsIForcePendingChannel)
     344         256 :   NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)
     345         254 :   NS_INTERFACE_MAP_ENTRY(nsIFormPOSTActionChannel)
     346         254 :   NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)
     347         251 :   NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
     348         251 :   NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
     349         251 :   NS_INTERFACE_MAP_ENTRY(nsIPrivateBrowsingChannel)
     350         197 :   NS_INTERFACE_MAP_ENTRY(nsITimedChannel)
     351         179 :   NS_INTERFACE_MAP_ENTRY(nsIConsoleReportCollector)
     352         178 :   NS_INTERFACE_MAP_ENTRY(nsIThrottledInputChannel)
     353         175 :   NS_INTERFACE_MAP_ENTRY(nsIClassifiedChannel)
     354         175 :   if (aIID.Equals(NS_GET_IID(HttpBaseChannel))) {
     355           0 :     foundInterface = static_cast<nsIWritablePropertyBag*>(this);
     356             :   } else
     357         175 : NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
     358             : 
     359             : //-----------------------------------------------------------------------------
     360             : // HttpBaseChannel::nsIRequest
     361             : //-----------------------------------------------------------------------------
     362             : 
     363             : NS_IMETHODIMP
     364          35 : HttpBaseChannel::GetName(nsACString& aName)
     365             : {
     366          35 :   aName = mSpec;
     367          35 :   return NS_OK;
     368             : }
     369             : 
     370             : NS_IMETHODIMP
     371           0 : HttpBaseChannel::IsPending(bool *aIsPending)
     372             : {
     373           0 :   NS_ENSURE_ARG_POINTER(aIsPending);
     374           0 :   *aIsPending = mIsPending || mForcePending;
     375           0 :   return NS_OK;
     376             : }
     377             : 
     378             : NS_IMETHODIMP
     379          14 : HttpBaseChannel::GetStatus(nsresult *aStatus)
     380             : {
     381          14 :   NS_ENSURE_ARG_POINTER(aStatus);
     382          14 :   *aStatus = mStatus;
     383          14 :   return NS_OK;
     384             : }
     385             : 
     386             : NS_IMETHODIMP
     387          23 : HttpBaseChannel::GetLoadGroup(nsILoadGroup **aLoadGroup)
     388             : {
     389          23 :   NS_ENSURE_ARG_POINTER(aLoadGroup);
     390          23 :   *aLoadGroup = mLoadGroup;
     391          23 :   NS_IF_ADDREF(*aLoadGroup);
     392          23 :   return NS_OK;
     393             : }
     394             : 
     395             : NS_IMETHODIMP
     396           4 : HttpBaseChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
     397             : {
     398           4 :   MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
     399             : 
     400           4 :   if (!CanSetLoadGroup(aLoadGroup)) {
     401           0 :     return NS_ERROR_FAILURE;
     402             :   }
     403             : 
     404           4 :   mLoadGroup = aLoadGroup;
     405           4 :   mProgressSink = nullptr;
     406           4 :   UpdatePrivateBrowsing();
     407           4 :   return NS_OK;
     408             : }
     409             : 
     410             : NS_IMETHODIMP
     411          75 : HttpBaseChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
     412             : {
     413          75 :   NS_ENSURE_ARG_POINTER(aLoadFlags);
     414          75 :   *aLoadFlags = mLoadFlags;
     415          75 :   return NS_OK;
     416             : }
     417             : 
     418             : NS_IMETHODIMP
     419          16 : HttpBaseChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
     420             : {
     421          16 :   bool synthesized = false;
     422          16 :   nsresult rv = GetResponseSynthesized(&synthesized);
     423          16 :   NS_ENSURE_SUCCESS(rv, rv);
     424             : 
     425             :   // If this channel is marked as awaiting a synthesized response,
     426             :   // modifying certain load flags can interfere with the implementation
     427             :   // of the network interception logic. This takes care of a couple
     428             :   // known cases that attempt to mark channels as anonymous due
     429             :   // to cross-origin redirects; since the response is entirely synthesized
     430             :   // this is an unnecessary precaution.
     431             :   // This should be removed when bug 1201683 is fixed.
     432          16 :   if (synthesized && aLoadFlags != mLoadFlags) {
     433           0 :     aLoadFlags &= ~LOAD_ANONYMOUS;
     434             :   }
     435             : 
     436          16 :   mLoadFlags = aLoadFlags;
     437          16 :   mForceMainDocumentChannel = (aLoadFlags & LOAD_DOCUMENT_URI);
     438          16 :   return NS_OK;
     439             : }
     440             : 
     441             : NS_IMETHODIMP
     442           9 : HttpBaseChannel::SetDocshellUserAgentOverride()
     443             : {
     444             :   // This sets the docshell specific user agent override, it will be overwritten
     445             :   // by UserAgentOverrides.jsm if site-specific user agent overrides are set.
     446             :   nsresult rv;
     447          18 :   nsCOMPtr<nsILoadContext> loadContext;
     448           9 :   NS_QueryNotificationCallbacks(this, loadContext);
     449           9 :   if (!loadContext) {
     450           2 :     return NS_OK;
     451             :   }
     452             : 
     453          14 :   nsCOMPtr<mozIDOMWindowProxy> domWindow;
     454           7 :   loadContext->GetAssociatedWindow(getter_AddRefs(domWindow));
     455           7 :   if (!domWindow) {
     456           3 :     return NS_OK;
     457             :   }
     458             : 
     459           4 :   auto* pDomWindow = nsPIDOMWindowOuter::From(domWindow);
     460           4 :   nsIDocShell* docshell = pDomWindow->GetDocShell();
     461           4 :   if (!docshell) {
     462           0 :     return NS_OK;
     463             :   }
     464             : 
     465           8 :   nsString customUserAgent;
     466           4 :   docshell->GetCustomUserAgent(customUserAgent);
     467           4 :   if (customUserAgent.IsEmpty()) {
     468           4 :     return NS_OK;
     469             :   }
     470             : 
     471           0 :   NS_ConvertUTF16toUTF8 utf8CustomUserAgent(customUserAgent);
     472           0 :   rv = SetRequestHeader(NS_LITERAL_CSTRING("User-Agent"), utf8CustomUserAgent, false);
     473           0 :   if (NS_FAILED(rv)) return rv;
     474             : 
     475           0 :   return NS_OK;
     476             : }
     477             : 
     478             : //-----------------------------------------------------------------------------
     479             : // HttpBaseChannel::nsIChannel
     480             : //-----------------------------------------------------------------------------
     481             : 
     482             : NS_IMETHODIMP
     483          60 : HttpBaseChannel::GetOriginalURI(nsIURI **aOriginalURI)
     484             : {
     485          60 :   NS_ENSURE_ARG_POINTER(aOriginalURI);
     486          60 :   *aOriginalURI = mOriginalURI;
     487          60 :   NS_ADDREF(*aOriginalURI);
     488          60 :   return NS_OK;
     489             : }
     490             : 
     491             : NS_IMETHODIMP
     492           4 : HttpBaseChannel::SetOriginalURI(nsIURI *aOriginalURI)
     493             : {
     494           4 :   ENSURE_CALLED_BEFORE_CONNECT();
     495             : 
     496           4 :   NS_ENSURE_ARG_POINTER(aOriginalURI);
     497           4 :   mOriginalURI = aOriginalURI;
     498           4 :   return NS_OK;
     499             : }
     500             : 
     501             : NS_IMETHODIMP
     502          57 : HttpBaseChannel::GetURI(nsIURI **aURI)
     503             : {
     504          57 :   NS_ENSURE_ARG_POINTER(aURI);
     505          57 :   *aURI = mURI;
     506          57 :   NS_ADDREF(*aURI);
     507          57 :   return NS_OK;
     508             : }
     509             : 
     510             : NS_IMETHODIMP
     511          14 : HttpBaseChannel::GetOwner(nsISupports **aOwner)
     512             : {
     513          14 :   NS_ENSURE_ARG_POINTER(aOwner);
     514          14 :   *aOwner = mOwner;
     515          14 :   NS_IF_ADDREF(*aOwner);
     516          14 :   return NS_OK;
     517             : }
     518             : 
     519             : NS_IMETHODIMP
     520           0 : HttpBaseChannel::SetOwner(nsISupports *aOwner)
     521             : {
     522           0 :   mOwner = aOwner;
     523           0 :   return NS_OK;
     524             : }
     525             : 
     526             : NS_IMETHODIMP
     527          10 : HttpBaseChannel::SetLoadInfo(nsILoadInfo *aLoadInfo)
     528             : {
     529          10 :   mLoadInfo = aLoadInfo;
     530          10 :   return NS_OK;
     531             : }
     532             : 
     533             : NS_IMETHODIMP
     534         214 : HttpBaseChannel::GetLoadInfo(nsILoadInfo **aLoadInfo)
     535             : {
     536         214 :   NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
     537         214 :   return NS_OK;
     538             : }
     539             : 
     540             : NS_IMETHODIMP
     541           3 : HttpBaseChannel::GetIsDocument(bool *aIsDocument)
     542             : {
     543           3 :   return NS_GetIsDocumentChannel(this, aIsDocument);
     544             : }
     545             : 
     546             : NS_IMETHODIMP
     547          71 : HttpBaseChannel::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks)
     548             : {
     549          71 :   *aCallbacks = mCallbacks;
     550          71 :   NS_IF_ADDREF(*aCallbacks);
     551          71 :   return NS_OK;
     552             : }
     553             : 
     554             : NS_IMETHODIMP
     555          12 : HttpBaseChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
     556             : {
     557          12 :   MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
     558             : 
     559          12 :   if (!CanSetCallbacks(aCallbacks)) {
     560           0 :     return NS_ERROR_FAILURE;
     561             :   }
     562             : 
     563          12 :   mCallbacks = aCallbacks;
     564          12 :   mProgressSink = nullptr;
     565             : 
     566          12 :   UpdatePrivateBrowsing();
     567          12 :   return NS_OK;
     568             : }
     569             : 
     570             : NS_IMETHODIMP
     571          12 : HttpBaseChannel::GetContentType(nsACString& aContentType)
     572             : {
     573          12 :   if (!mResponseHead) {
     574           0 :     aContentType.Truncate();
     575           0 :     return NS_ERROR_NOT_AVAILABLE;
     576             :   }
     577             : 
     578          12 :   mResponseHead->ContentType(aContentType);
     579          12 :   if (!aContentType.IsEmpty()) {
     580          12 :     return NS_OK;
     581             :   }
     582             : 
     583           0 :   aContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
     584           0 :   return NS_OK;
     585             : }
     586             : 
     587             : NS_IMETHODIMP
     588           3 : HttpBaseChannel::SetContentType(const nsACString& aContentType)
     589             : {
     590           3 :   if (mListener || mWasOpened) {
     591           0 :     if (!mResponseHead)
     592           0 :       return NS_ERROR_NOT_AVAILABLE;
     593             : 
     594           0 :     nsAutoCString contentTypeBuf, charsetBuf;
     595             :     bool hadCharset;
     596           0 :     net_ParseContentType(aContentType, contentTypeBuf, charsetBuf, &hadCharset);
     597             : 
     598           0 :     mResponseHead->SetContentType(contentTypeBuf);
     599             : 
     600             :     // take care not to stomp on an existing charset
     601           0 :     if (hadCharset)
     602           0 :       mResponseHead->SetContentCharset(charsetBuf);
     603             : 
     604             :   } else {
     605             :     // We are being given a content-type hint.
     606             :     bool dummy;
     607           3 :     net_ParseContentType(aContentType, mContentTypeHint, mContentCharsetHint,
     608           3 :                          &dummy);
     609             :   }
     610             : 
     611           3 :   return NS_OK;
     612             : }
     613             : 
     614             : NS_IMETHODIMP
     615           3 : HttpBaseChannel::GetContentCharset(nsACString& aContentCharset)
     616             : {
     617           3 :   if (!mResponseHead)
     618           0 :     return NS_ERROR_NOT_AVAILABLE;
     619             : 
     620           3 :   mResponseHead->ContentCharset(aContentCharset);
     621           3 :   return NS_OK;
     622             : }
     623             : 
     624             : NS_IMETHODIMP
     625           0 : HttpBaseChannel::SetContentCharset(const nsACString& aContentCharset)
     626             : {
     627           0 :   if (mListener) {
     628           0 :     if (!mResponseHead)
     629           0 :       return NS_ERROR_NOT_AVAILABLE;
     630             : 
     631           0 :     mResponseHead->SetContentCharset(aContentCharset);
     632             :   } else {
     633             :     // Charset hint
     634           0 :     mContentCharsetHint = aContentCharset;
     635             :   }
     636           0 :   return NS_OK;
     637             : }
     638             : 
     639             : NS_IMETHODIMP
     640           2 : HttpBaseChannel::GetContentDisposition(uint32_t *aContentDisposition)
     641             : {
     642             :   nsresult rv;
     643           4 :   nsCString header;
     644             : 
     645           2 :   rv = GetContentDispositionHeader(header);
     646           2 :   if (NS_FAILED(rv)) {
     647           2 :     if (mContentDispositionHint == UINT32_MAX)
     648           2 :       return rv;
     649             : 
     650           0 :     *aContentDisposition = mContentDispositionHint;
     651           0 :     return NS_OK;
     652             :   }
     653             : 
     654           0 :   *aContentDisposition = NS_GetContentDispositionFromHeader(header, this);
     655           0 :   return NS_OK;
     656             : }
     657             : 
     658             : NS_IMETHODIMP
     659           0 : HttpBaseChannel::SetContentDisposition(uint32_t aContentDisposition)
     660             : {
     661           0 :   mContentDispositionHint = aContentDisposition;
     662           0 :   return NS_OK;
     663             : }
     664             : 
     665             : NS_IMETHODIMP
     666           0 : HttpBaseChannel::GetContentDispositionFilename(nsAString& aContentDispositionFilename)
     667             : {
     668           0 :   aContentDispositionFilename.Truncate();
     669             :   nsresult rv;
     670           0 :   nsCString header;
     671             : 
     672           0 :   rv = GetContentDispositionHeader(header);
     673           0 :   if (NS_FAILED(rv)) {
     674           0 :     if (!mContentDispositionFilename)
     675           0 :       return rv;
     676             : 
     677           0 :     aContentDispositionFilename = *mContentDispositionFilename;
     678           0 :     return NS_OK;
     679             :   }
     680             : 
     681           0 :   return NS_GetFilenameFromDisposition(aContentDispositionFilename,
     682           0 :                                        header, mURI);
     683             : }
     684             : 
     685             : NS_IMETHODIMP
     686           0 : HttpBaseChannel::SetContentDispositionFilename(const nsAString& aContentDispositionFilename)
     687             : {
     688           0 :   mContentDispositionFilename = new nsString(aContentDispositionFilename);
     689           0 :   return NS_OK;
     690             : }
     691             : 
     692             : NS_IMETHODIMP
     693           3 : HttpBaseChannel::GetContentDispositionHeader(nsACString& aContentDispositionHeader)
     694             : {
     695           3 :   if (!mResponseHead)
     696           0 :     return NS_ERROR_NOT_AVAILABLE;
     697             : 
     698           3 :   nsresult rv = mResponseHead->GetHeader(nsHttp::Content_Disposition,
     699           3 :                                          aContentDispositionHeader);
     700           3 :   if (NS_FAILED(rv) || aContentDispositionHeader.IsEmpty())
     701           3 :     return NS_ERROR_NOT_AVAILABLE;
     702             : 
     703           0 :   return NS_OK;
     704             : }
     705             : 
     706             : NS_IMETHODIMP
     707          10 : HttpBaseChannel::GetContentLength(int64_t *aContentLength)
     708             : {
     709          10 :   NS_ENSURE_ARG_POINTER(aContentLength);
     710             : 
     711          10 :   if (!mResponseHead)
     712           0 :     return NS_ERROR_NOT_AVAILABLE;
     713             : 
     714          10 :   if (!mAvailableCachedAltDataType.IsEmpty()) {
     715           0 :     *aContentLength = mAltDataLength;
     716           0 :     return NS_OK;
     717             :   }
     718             : 
     719          10 :   *aContentLength = mResponseHead->ContentLength();
     720          10 :   return NS_OK;
     721             : }
     722             : 
     723             : NS_IMETHODIMP
     724           0 : HttpBaseChannel::SetContentLength(int64_t value)
     725             : {
     726           0 :   NS_NOTYETIMPLEMENTED("HttpBaseChannel::SetContentLength");
     727           0 :   return NS_ERROR_NOT_IMPLEMENTED;
     728             : }
     729             : 
     730             : NS_IMETHODIMP
     731           0 : HttpBaseChannel::Open(nsIInputStream **aResult)
     732             : {
     733           0 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_IN_PROGRESS);
     734             : 
     735           0 :   if (!gHttpHandler->Active()) {
     736           0 :     LOG(("HttpBaseChannel::Open after HTTP shutdown..."));
     737           0 :     return NS_ERROR_NOT_AVAILABLE;
     738             :   }
     739             : 
     740           0 :   return NS_ImplementChannelOpen(this, aResult);
     741             : }
     742             : 
     743             : NS_IMETHODIMP
     744           0 : HttpBaseChannel::Open2(nsIInputStream** aStream)
     745             : {
     746           0 :   if (!gHttpHandler->Active()) {
     747           0 :     LOG(("HttpBaseChannel::Open after HTTP shutdown..."));
     748           0 :     return NS_ERROR_NOT_AVAILABLE;
     749             :   }
     750             : 
     751           0 :   nsCOMPtr<nsIStreamListener> listener;
     752           0 :   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
     753           0 :   NS_ENSURE_SUCCESS(rv, rv);
     754           0 :   return Open(aStream);
     755             : }
     756             : 
     757             : //-----------------------------------------------------------------------------
     758             : // HttpBaseChannel::nsIUploadChannel
     759             : //-----------------------------------------------------------------------------
     760             : 
     761             : NS_IMETHODIMP
     762           2 : HttpBaseChannel::GetUploadStream(nsIInputStream **stream)
     763             : {
     764           2 :   NS_ENSURE_ARG_POINTER(stream);
     765           2 :   *stream = mUploadStream;
     766           2 :   NS_IF_ADDREF(*stream);
     767           2 :   return NS_OK;
     768             : }
     769             : 
     770             : NS_IMETHODIMP
     771           1 : HttpBaseChannel::SetUploadStream(nsIInputStream *stream,
     772             :                                  const nsACString &contentTypeArg,
     773             :                                  int64_t contentLength)
     774             : {
     775             :   // NOTE: for backwards compatibility and for compatibility with old style
     776             :   // plugins, |stream| may include headers, specifically Content-Type and
     777             :   // Content-Length headers.  in this case, |contentType| and |contentLength|
     778             :   // would be unspecified.  this is traditionally the case of a POST request,
     779             :   // and so we select POST as the request method if contentType and
     780             :   // contentLength are unspecified.
     781             : 
     782           1 :   if (stream) {
     783           2 :     nsAutoCString method;
     784           1 :     bool hasHeaders = false;
     785             : 
     786             :     // This method and ExplicitSetUploadStream mean different things by "empty
     787             :     // content type string".  This method means "no header", but
     788             :     // ExplicitSetUploadStream means "header with empty value".  So we have to
     789             :     // massage the contentType argument into the form ExplicitSetUploadStream
     790             :     // expects.
     791           2 :     nsCOMPtr<nsIMIMEInputStream> mimeStream;
     792           2 :     nsCString contentType(contentTypeArg);
     793           1 :     if (contentType.IsEmpty()) {
     794           0 :       contentType.SetIsVoid(true);
     795           0 :       method = NS_LITERAL_CSTRING("POST");
     796             : 
     797             :       // MIME streams are a special case, and include headers which need to be
     798             :       // copied to the channel.
     799           0 :       mimeStream = do_QueryInterface(stream);
     800           0 :       if (mimeStream) {
     801             :         // Copy non-origin related headers to the channel.
     802             :         nsCOMPtr<nsIHttpHeaderVisitor> visitor =
     803           0 :           new AddHeadersToChannelVisitor(this);
     804           0 :         mimeStream->VisitHeaders(visitor);
     805             : 
     806           0 :         return ExplicitSetUploadStream(stream, contentType, contentLength,
     807           0 :                                        method, hasHeaders);
     808             :       }
     809             : 
     810           0 :       hasHeaders = true;
     811             :     } else {
     812           1 :       method = NS_LITERAL_CSTRING("PUT");
     813             : 
     814           1 :       MOZ_ASSERT(NS_FAILED(CallQueryInterface(stream, getter_AddRefs(mimeStream))),
     815             :                  "nsIMIMEInputStream should not be set with an explicit content type");
     816             :     }
     817           1 :     return ExplicitSetUploadStream(stream, contentType, contentLength,
     818           2 :                                    method, hasHeaders);
     819             :   }
     820             : 
     821             :   // if stream is null, ExplicitSetUploadStream returns error.
     822             :   // So we need special case for GET method.
     823           0 :   mUploadStreamHasHeaders = false;
     824           0 :   mRequestHead.SetMethod(NS_LITERAL_CSTRING("GET")); // revert to GET request
     825           0 :   mUploadStream = stream;
     826           0 :   return NS_OK;
     827             : }
     828             : 
     829             : namespace {
     830             : 
     831             : void
     832           0 : CopyComplete(void* aClosure, nsresult aStatus) {
     833             : #ifdef DEBUG
     834             :   // Called on the STS thread by NS_AsyncCopy
     835             :   nsCOMPtr<nsIEventTarget> sts =
     836           0 :     do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
     837           0 :   bool result = false;
     838           0 :   sts->IsOnCurrentThread(&result);
     839           0 :   MOZ_ASSERT(result, "Should only be called on the STS thread.");
     840             : #endif
     841             : 
     842           0 :   auto channel = static_cast<HttpBaseChannel*>(aClosure);
     843           0 :   channel->OnCopyComplete(aStatus);
     844           0 : }
     845             : 
     846             : } // anonymous namespace
     847             : 
     848             : NS_IMETHODIMP
     849           0 : HttpBaseChannel::EnsureUploadStreamIsCloneable(nsIRunnable* aCallback)
     850             : {
     851           0 :   MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
     852           0 :   NS_ENSURE_ARG_POINTER(aCallback);
     853             : 
     854             :   // We could in theory allow multiple callers to use this method,
     855             :   // but the complexity does not seem worth it yet.  Just fail if
     856             :   // this is called more than once simultaneously.
     857           0 :   NS_ENSURE_FALSE(mUploadCloneableCallback, NS_ERROR_UNEXPECTED);
     858             : 
     859             :   // If the CloneUploadStream() will succeed, then synchronously invoke
     860             :   // the callback to indicate we're already cloneable.
     861           0 :   if (!mUploadStream || NS_InputStreamIsCloneable(mUploadStream)) {
     862           0 :     aCallback->Run();
     863           0 :     return NS_OK;
     864             :   }
     865             : 
     866           0 :   nsCOMPtr<nsIStorageStream> storageStream;
     867           0 :   nsresult rv = NS_NewStorageStream(4096, UINT32_MAX,
     868           0 :                                     getter_AddRefs(storageStream));
     869           0 :   NS_ENSURE_SUCCESS(rv, rv);
     870             : 
     871           0 :   nsCOMPtr<nsIInputStream> newUploadStream;
     872           0 :   rv = storageStream->NewInputStream(0, getter_AddRefs(newUploadStream));
     873           0 :   NS_ENSURE_SUCCESS(rv, rv);
     874             : 
     875           0 :   nsCOMPtr<nsIOutputStream> sink;
     876           0 :   rv = storageStream->GetOutputStream(0, getter_AddRefs(sink));
     877           0 :   NS_ENSURE_SUCCESS(rv, rv);
     878             : 
     879           0 :   nsCOMPtr<nsIInputStream> source;
     880           0 :   if (NS_InputStreamIsBuffered(mUploadStream)) {
     881           0 :     source = mUploadStream;
     882             :   } else {
     883           0 :     rv = NS_NewBufferedInputStream(getter_AddRefs(source), mUploadStream, 4096);
     884           0 :     NS_ENSURE_SUCCESS(rv, rv);
     885             :   }
     886             : 
     887             :   nsCOMPtr<nsIEventTarget> target =
     888           0 :     do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
     889             : 
     890           0 :   mUploadCloneableCallback = aCallback;
     891             : 
     892           0 :   rv = NS_AsyncCopy(source, sink, target, NS_ASYNCCOPY_VIA_READSEGMENTS,
     893             :                     4096, // copy segment size
     894           0 :                     CopyComplete, this);
     895           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     896           0 :     mUploadCloneableCallback = nullptr;
     897           0 :     return rv;
     898             :   }
     899             : 
     900             :   // Since we're consuming the old stream, replace it with the new
     901             :   // stream immediately.
     902           0 :   mUploadStream = newUploadStream;
     903             : 
     904             :   // Explicity hold the stream alive until copying is complete.  This will
     905             :   // be released in EnsureUploadStreamIsCloneableComplete().
     906           0 :   AddRef();
     907             : 
     908           0 :   return NS_OK;
     909             : }
     910             : 
     911             : void
     912           0 : HttpBaseChannel::OnCopyComplete(nsresult aStatus)
     913             : {
     914             :   // Assert in parent process because we don't have to label the runnable
     915             :   // in parent process.
     916           0 :   MOZ_ASSERT(XRE_IsParentProcess());
     917             : 
     918           0 :   nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod<nsresult>(
     919             :     "net::HttpBaseChannel::EnsureUploadStreamIsCloneableComplete",
     920             :     this,
     921             :     &HttpBaseChannel::EnsureUploadStreamIsCloneableComplete,
     922           0 :     aStatus);
     923           0 :   NS_DispatchToMainThread(runnable.forget());
     924           0 : }
     925             : 
     926             : void
     927           0 : HttpBaseChannel::EnsureUploadStreamIsCloneableComplete(nsresult aStatus)
     928             : {
     929           0 :   MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
     930           0 :   MOZ_ASSERT(mUploadCloneableCallback);
     931             : 
     932           0 :   if (NS_SUCCEEDED(mStatus)) {
     933           0 :     mStatus = aStatus;
     934             :   }
     935             : 
     936           0 :   mUploadCloneableCallback->Run();
     937           0 :   mUploadCloneableCallback = nullptr;
     938             : 
     939             :   // Release the reference we grabbed in EnsureUploadStreamIsCloneable() now
     940             :   // that the copying is complete.
     941           0 :   Release();
     942           0 : }
     943             : 
     944             : NS_IMETHODIMP
     945           0 : HttpBaseChannel::CloneUploadStream(nsIInputStream** aClonedStream)
     946             : {
     947           0 :   NS_ENSURE_ARG_POINTER(aClonedStream);
     948           0 :   *aClonedStream = nullptr;
     949             : 
     950           0 :   if (!mUploadStream) {
     951           0 :     return NS_OK;
     952             :   }
     953             : 
     954           0 :   nsCOMPtr<nsIInputStream> clonedStream;
     955           0 :   nsresult rv = NS_CloneInputStream(mUploadStream, getter_AddRefs(clonedStream));
     956           0 :   NS_ENSURE_SUCCESS(rv, rv);
     957             : 
     958           0 :   clonedStream.forget(aClonedStream);
     959             : 
     960           0 :   return NS_OK;
     961             : }
     962             : 
     963             : 
     964             : //-----------------------------------------------------------------------------
     965             : // HttpBaseChannel::nsIUploadChannel2
     966             : //-----------------------------------------------------------------------------
     967             : 
     968             : NS_IMETHODIMP
     969           1 : HttpBaseChannel::ExplicitSetUploadStream(nsIInputStream *aStream,
     970             :                                        const nsACString &aContentType,
     971             :                                        int64_t aContentLength,
     972             :                                        const nsACString &aMethod,
     973             :                                        bool aStreamHasHeaders)
     974             : {
     975             :   // Ensure stream is set and method is valid
     976           1 :   NS_ENSURE_TRUE(aStream, NS_ERROR_FAILURE);
     977             : 
     978             :   {
     979           2 :     DebugOnly<nsCOMPtr<nsIMIMEInputStream>> mimeStream;
     980           1 :     MOZ_ASSERT(!aStreamHasHeaders ||
     981             :                NS_FAILED(CallQueryInterface(aStream, getter_AddRefs(mimeStream.value))),
     982             :                "nsIMIMEInputStream should not include headers");
     983             :   }
     984             : 
     985           1 :   if (aContentLength < 0 && !aStreamHasHeaders) {
     986           1 :     nsresult rv = aStream->Available(reinterpret_cast<uint64_t*>(&aContentLength));
     987           1 :     if (NS_FAILED(rv) || aContentLength < 0) {
     988           0 :       NS_ERROR("unable to determine content length");
     989           0 :       return NS_ERROR_FAILURE;
     990             :     }
     991             :   }
     992             : 
     993           1 :   nsresult rv = SetRequestMethod(aMethod);
     994           1 :   NS_ENSURE_SUCCESS(rv, rv);
     995             : 
     996           1 :   if (!aStreamHasHeaders) {
     997             :     // SetRequestHeader propagates headers to chrome if HttpChannelChild
     998           2 :     nsAutoCString contentLengthStr;
     999           1 :     contentLengthStr.AppendInt(aContentLength);
    1000           3 :     SetRequestHeader(NS_LITERAL_CSTRING("Content-Length"), contentLengthStr,
    1001           3 :                      false);
    1002           1 :     if (!aContentType.IsVoid()) {
    1003           1 :       if (aContentType.IsEmpty()) {
    1004           0 :         SetEmptyRequestHeader(NS_LITERAL_CSTRING("Content-Type"));
    1005             :       } else {
    1006           3 :         SetRequestHeader(NS_LITERAL_CSTRING("Content-Type"), aContentType,
    1007           3 :                          false);
    1008             :       }
    1009             :     }
    1010             :   }
    1011             : 
    1012           1 :   mUploadStreamHasHeaders = aStreamHasHeaders;
    1013           1 :   mUploadStream = aStream;
    1014           1 :   return NS_OK;
    1015             : }
    1016             : 
    1017             : NS_IMETHODIMP
    1018           0 : HttpBaseChannel::GetUploadStreamHasHeaders(bool *hasHeaders)
    1019             : {
    1020           0 :   NS_ENSURE_ARG(hasHeaders);
    1021             : 
    1022           0 :   *hasHeaders = mUploadStreamHasHeaders;
    1023           0 :   return NS_OK;
    1024             : }
    1025             : 
    1026             : //-----------------------------------------------------------------------------
    1027             : // HttpBaseChannel::nsIEncodedChannel
    1028             : //-----------------------------------------------------------------------------
    1029             : 
    1030             : NS_IMETHODIMP
    1031           0 : HttpBaseChannel::GetApplyConversion(bool *value)
    1032             : {
    1033           0 :   *value = mApplyConversion;
    1034           0 :   return NS_OK;
    1035             : }
    1036             : 
    1037             : NS_IMETHODIMP
    1038           3 : HttpBaseChannel::SetApplyConversion(bool value)
    1039             : {
    1040           3 :   LOG(("HttpBaseChannel::SetApplyConversion [this=%p value=%d]\n", this, value));
    1041           3 :   mApplyConversion = value;
    1042           3 :   return NS_OK;
    1043             : }
    1044             : 
    1045             : nsresult
    1046           0 : HttpBaseChannel::DoApplyContentConversions(nsIStreamListener* aNextListener,
    1047             :                                            nsIStreamListener** aNewNextListener)
    1048             : {
    1049           0 :   return DoApplyContentConversions(aNextListener,
    1050             :                                    aNewNextListener,
    1051           0 :                                    mListenerContext);
    1052             : }
    1053             : 
    1054             : // create a listener chain that looks like this
    1055             : // http-channel -> decompressor (n times) -> InterceptFailedOnSTop -> channel-creator-listener
    1056             : //
    1057             : // we need to do this because not every decompressor has fully streamed output so
    1058             : // may need a call to OnStopRequest to identify its completion state.. and if it
    1059             : // creates an error there the channel status code needs to be updated before calling
    1060             : // the terminal listener. Having the decompress do it via cancel() means channels cannot
    1061             : // effectively be used in two contexts (specifically this one and a peek context for
    1062             : // sniffing)
    1063             : //
    1064             : class InterceptFailedOnStop : public nsIStreamListener
    1065             : {
    1066           0 :   virtual ~InterceptFailedOnStop() {}
    1067             :   nsCOMPtr<nsIStreamListener> mNext;
    1068             :   HttpBaseChannel *mChannel;
    1069             : 
    1070             : public:
    1071           0 :   InterceptFailedOnStop(nsIStreamListener *arg, HttpBaseChannel *chan)
    1072           0 :   : mNext(arg)
    1073           0 :   , mChannel(chan) {}
    1074             :   NS_DECL_THREADSAFE_ISUPPORTS
    1075             : 
    1076           0 :   NS_IMETHOD OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) override
    1077             :   {
    1078           0 :     return mNext->OnStartRequest(aRequest, aContext);
    1079             :   }
    1080             : 
    1081           0 :   NS_IMETHOD OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) override
    1082             :   {
    1083           0 :     if (NS_FAILED(aStatusCode) && NS_SUCCEEDED(mChannel->mStatus)) {
    1084           0 :       LOG(("HttpBaseChannel::InterceptFailedOnStop %p seting status %" PRIx32,
    1085             :            mChannel, static_cast<uint32_t>(aStatusCode)));
    1086           0 :       mChannel->mStatus = aStatusCode;
    1087             :     }
    1088           0 :     return mNext->OnStopRequest(aRequest, aContext, aStatusCode);
    1089             :   }
    1090             : 
    1091           0 :   NS_IMETHOD OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
    1092             :                            nsIInputStream *aInputStream, uint64_t aOffset,
    1093             :                            uint32_t aCount) override
    1094             :   {
    1095           0 :     return mNext->OnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
    1096             :   }
    1097             : };
    1098             : 
    1099           0 : NS_IMPL_ISUPPORTS(InterceptFailedOnStop, nsIStreamListener, nsIRequestObserver)
    1100             : 
    1101             : NS_IMETHODIMP
    1102           8 : HttpBaseChannel::DoApplyContentConversions(nsIStreamListener* aNextListener,
    1103             :                                            nsIStreamListener** aNewNextListener,
    1104             :                                            nsISupports *aCtxt)
    1105             : {
    1106           8 :   *aNewNextListener = nullptr;
    1107           8 :   if (!mResponseHead || ! aNextListener) {
    1108           0 :     return NS_OK;
    1109             :   }
    1110             : 
    1111           8 :   LOG(("HttpBaseChannel::DoApplyContentConversions [this=%p]\n", this));
    1112             : 
    1113           8 :   if (!mApplyConversion) {
    1114           3 :     LOG(("not applying conversion per mApplyConversion\n"));
    1115           3 :     return NS_OK;
    1116             :   }
    1117             : 
    1118           5 :   if (!mAvailableCachedAltDataType.IsEmpty()) {
    1119           0 :     LOG(("not applying conversion because delivering alt-data\n"));
    1120           0 :     return NS_OK;
    1121             :   }
    1122             : 
    1123          10 :   nsAutoCString contentEncoding;
    1124           5 :   nsresult rv = mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
    1125           5 :   if (NS_FAILED(rv) || contentEncoding.IsEmpty())
    1126           5 :     return NS_OK;
    1127             : 
    1128           0 :   nsCOMPtr<nsIStreamListener> nextListener = new InterceptFailedOnStop(aNextListener, this);
    1129             : 
    1130             :   // The encodings are listed in the order they were applied
    1131             :   // (see rfc 2616 section 14.11), so they need to removed in reverse
    1132             :   // order. This is accomplished because the converter chain ends up
    1133             :   // being a stack with the last converter created being the first one
    1134             :   // to accept the raw network data.
    1135             : 
    1136           0 :   char* cePtr = contentEncoding.BeginWriting();
    1137           0 :   uint32_t count = 0;
    1138           0 :   while (char* val = nsCRT::strtok(cePtr, HTTP_LWS ",", &cePtr)) {
    1139           0 :     if (++count > 16) {
    1140             :       // That's ridiculous. We only understand 2 different ones :)
    1141             :       // but for compatibility with old code, we will just carry on without
    1142             :       // removing the encodings
    1143           0 :       LOG(("Too many Content-Encodings. Ignoring remainder.\n"));
    1144           0 :       break;
    1145             :     }
    1146             : 
    1147           0 :     bool isHTTPS = false;
    1148           0 :     mURI->SchemeIs("https", &isHTTPS);
    1149           0 :     if (gHttpHandler->IsAcceptableEncoding(val, isHTTPS)) {
    1150           0 :       nsCOMPtr<nsIStreamConverterService> serv;
    1151           0 :       rv = gHttpHandler->GetStreamConverterService(getter_AddRefs(serv));
    1152             : 
    1153             :       // we won't fail to load the page just because we couldn't load the
    1154             :       // stream converter service.. carry on..
    1155           0 :       if (NS_FAILED(rv)) {
    1156           0 :         if (val)
    1157           0 :           LOG(("Unknown content encoding '%s', ignoring\n", val));
    1158           0 :         continue;
    1159             :       }
    1160             : 
    1161           0 :       nsCOMPtr<nsIStreamListener> converter;
    1162           0 :       nsAutoCString from(val);
    1163           0 :       ToLowerCase(from);
    1164           0 :       rv = serv->AsyncConvertData(from.get(),
    1165             :                                   "uncompressed",
    1166             :                                   nextListener,
    1167             :                                   aCtxt,
    1168           0 :                                   getter_AddRefs(converter));
    1169           0 :       if (NS_FAILED(rv)) {
    1170           0 :         LOG(("Unexpected failure of AsyncConvertData %s\n", val));
    1171           0 :         return rv;
    1172             :       }
    1173             : 
    1174           0 :       LOG(("converter removed '%s' content-encoding\n", val));
    1175           0 :       if (gHttpHandler->IsTelemetryEnabled()) {
    1176           0 :         int mode = 0;
    1177           0 :         if (from.Equals("gzip") || from.Equals("x-gzip")) {
    1178           0 :           mode = 1;
    1179           0 :         } else if (from.Equals("deflate") || from.Equals("x-deflate")) {
    1180           0 :           mode = 2;
    1181           0 :         } else if (from.Equals("br")) {
    1182           0 :           mode = 3;
    1183             :         }
    1184           0 :         Telemetry::Accumulate(Telemetry::HTTP_CONTENT_ENCODING, mode);
    1185             :       }
    1186           0 :       nextListener = converter;
    1187             :     }
    1188             :     else {
    1189           0 :       if (val)
    1190           0 :         LOG(("Unknown content encoding '%s', ignoring\n", val));
    1191             :     }
    1192           0 :   }
    1193           0 :   *aNewNextListener = nextListener;
    1194           0 :   NS_IF_ADDREF(*aNewNextListener);
    1195           0 :   return NS_OK;
    1196             : }
    1197             : 
    1198             : NS_IMETHODIMP
    1199           0 : HttpBaseChannel::GetContentEncodings(nsIUTF8StringEnumerator** aEncodings)
    1200             : {
    1201           0 :   if (!mResponseHead) {
    1202           0 :     *aEncodings = nullptr;
    1203           0 :     return NS_OK;
    1204             :   }
    1205             : 
    1206           0 :   nsAutoCString encoding;
    1207           0 :   Unused << mResponseHead->GetHeader(nsHttp::Content_Encoding, encoding);
    1208           0 :   if (encoding.IsEmpty()) {
    1209           0 :     *aEncodings = nullptr;
    1210           0 :     return NS_OK;
    1211             :   }
    1212             :   nsContentEncodings* enumerator = new nsContentEncodings(this,
    1213           0 :                                                           encoding.get());
    1214           0 :   NS_ADDREF(*aEncodings = enumerator);
    1215           0 :   return NS_OK;
    1216             : }
    1217             : 
    1218             : //-----------------------------------------------------------------------------
    1219             : // HttpBaseChannel::nsContentEncodings <public>
    1220             : //-----------------------------------------------------------------------------
    1221             : 
    1222           0 : HttpBaseChannel::nsContentEncodings::nsContentEncodings(nsIHttpChannel* aChannel,
    1223           0 :                                                         const char* aEncodingHeader)
    1224             :   : mEncodingHeader(aEncodingHeader)
    1225             :   , mChannel(aChannel)
    1226           0 :   , mReady(false)
    1227             : {
    1228           0 :   mCurEnd = aEncodingHeader + strlen(aEncodingHeader);
    1229           0 :   mCurStart = mCurEnd;
    1230           0 : }
    1231             : 
    1232           0 : HttpBaseChannel::nsContentEncodings::~nsContentEncodings()
    1233             : {
    1234           0 : }
    1235             : 
    1236             : //-----------------------------------------------------------------------------
    1237             : // HttpBaseChannel::nsContentEncodings::nsISimpleEnumerator
    1238             : //-----------------------------------------------------------------------------
    1239             : 
    1240             : NS_IMETHODIMP
    1241           0 : HttpBaseChannel::nsContentEncodings::HasMore(bool* aMoreEncodings)
    1242             : {
    1243           0 :   if (mReady) {
    1244           0 :     *aMoreEncodings = true;
    1245           0 :     return NS_OK;
    1246             :   }
    1247             : 
    1248           0 :   nsresult rv = PrepareForNext();
    1249           0 :   *aMoreEncodings = NS_SUCCEEDED(rv);
    1250           0 :   return NS_OK;
    1251             : }
    1252             : 
    1253             : NS_IMETHODIMP
    1254           0 : HttpBaseChannel::nsContentEncodings::GetNext(nsACString& aNextEncoding)
    1255             : {
    1256           0 :   aNextEncoding.Truncate();
    1257           0 :   if (!mReady) {
    1258           0 :     nsresult rv = PrepareForNext();
    1259           0 :     if (NS_FAILED(rv)) {
    1260           0 :       return NS_ERROR_FAILURE;
    1261             :     }
    1262             :   }
    1263             : 
    1264           0 :   const nsACString & encoding = Substring(mCurStart, mCurEnd);
    1265             : 
    1266           0 :   nsACString::const_iterator start, end;
    1267           0 :   encoding.BeginReading(start);
    1268           0 :   encoding.EndReading(end);
    1269             : 
    1270           0 :   bool haveType = false;
    1271           0 :   if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("gzip"), start, end)) {
    1272           0 :     aNextEncoding.AssignLiteral(APPLICATION_GZIP);
    1273           0 :     haveType = true;
    1274             :   }
    1275             : 
    1276           0 :   if (!haveType) {
    1277           0 :     encoding.BeginReading(start);
    1278           0 :     if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("compress"), start, end)) {
    1279           0 :       aNextEncoding.AssignLiteral(APPLICATION_COMPRESS);
    1280           0 :       haveType = true;
    1281             :     }
    1282             :   }
    1283             : 
    1284           0 :   if (!haveType) {
    1285           0 :     encoding.BeginReading(start);
    1286           0 :     if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("deflate"), start, end)) {
    1287           0 :       aNextEncoding.AssignLiteral(APPLICATION_ZIP);
    1288           0 :       haveType = true;
    1289             :     }
    1290             :   }
    1291             : 
    1292           0 :   if (!haveType) {
    1293           0 :     encoding.BeginReading(start);
    1294           0 :     if (CaseInsensitiveFindInReadable(NS_LITERAL_CSTRING("br"), start, end)) {
    1295           0 :       aNextEncoding.AssignLiteral(APPLICATION_BROTLI);
    1296           0 :       haveType = true;
    1297             :     }
    1298             :   }
    1299             : 
    1300             :   // Prepare to fetch the next encoding
    1301           0 :   mCurEnd = mCurStart;
    1302           0 :   mReady = false;
    1303             : 
    1304           0 :   if (haveType)
    1305           0 :     return NS_OK;
    1306             : 
    1307           0 :   NS_WARNING("Unknown encoding type");
    1308           0 :   return NS_ERROR_FAILURE;
    1309             : }
    1310             : 
    1311             : //-----------------------------------------------------------------------------
    1312             : // HttpBaseChannel::nsContentEncodings::nsISupports
    1313             : //-----------------------------------------------------------------------------
    1314             : 
    1315           0 : NS_IMPL_ISUPPORTS(HttpBaseChannel::nsContentEncodings, nsIUTF8StringEnumerator)
    1316             : 
    1317             : //-----------------------------------------------------------------------------
    1318             : // HttpBaseChannel::nsContentEncodings <private>
    1319             : //-----------------------------------------------------------------------------
    1320             : 
    1321             : nsresult
    1322           0 : HttpBaseChannel::nsContentEncodings::PrepareForNext(void)
    1323             : {
    1324           0 :   MOZ_ASSERT(mCurStart == mCurEnd, "Indeterminate state");
    1325             : 
    1326             :   // At this point both mCurStart and mCurEnd point to somewhere
    1327             :   // past the end of the next thing we want to return
    1328             : 
    1329           0 :   while (mCurEnd != mEncodingHeader) {
    1330           0 :     --mCurEnd;
    1331           0 :     if (*mCurEnd != ',' && !nsCRT::IsAsciiSpace(*mCurEnd))
    1332           0 :       break;
    1333             :   }
    1334           0 :   if (mCurEnd == mEncodingHeader)
    1335           0 :     return NS_ERROR_NOT_AVAILABLE; // no more encodings
    1336           0 :   ++mCurEnd;
    1337             : 
    1338             :   // At this point mCurEnd points to the first char _after_ the
    1339             :   // header we want.  Furthermore, mCurEnd - 1 != mEncodingHeader
    1340             : 
    1341           0 :   mCurStart = mCurEnd - 1;
    1342           0 :   while (mCurStart != mEncodingHeader &&
    1343           0 :          *mCurStart != ',' && !nsCRT::IsAsciiSpace(*mCurStart))
    1344           0 :     --mCurStart;
    1345           0 :   if (*mCurStart == ',' || nsCRT::IsAsciiSpace(*mCurStart))
    1346           0 :     ++mCurStart; // we stopped because of a weird char, so move up one
    1347             : 
    1348             :   // At this point mCurStart and mCurEnd bracket the encoding string
    1349             :   // we want.  Check that it's not "identity"
    1350           0 :   if (Substring(mCurStart, mCurEnd).Equals("identity",
    1351           0 :                                            nsCaseInsensitiveCStringComparator())) {
    1352           0 :     mCurEnd = mCurStart;
    1353           0 :     return PrepareForNext();
    1354             :   }
    1355             : 
    1356           0 :   mReady = true;
    1357           0 :   return NS_OK;
    1358             : }
    1359             : 
    1360             : 
    1361             : //-----------------------------------------------------------------------------
    1362             : // HttpBaseChannel::nsIHttpChannel
    1363             : //-----------------------------------------------------------------------------
    1364             : 
    1365             : NS_IMETHODIMP
    1366           0 : HttpBaseChannel::GetChannelId(uint64_t *aChannelId)
    1367             : {
    1368           0 :   NS_ENSURE_ARG_POINTER(aChannelId);
    1369           0 :   *aChannelId = mChannelId;
    1370           0 :   return NS_OK;
    1371             : }
    1372             : 
    1373             : NS_IMETHODIMP
    1374           3 : HttpBaseChannel::SetChannelId(uint64_t aChannelId)
    1375             : {
    1376           3 :   mChannelId = aChannelId;
    1377           3 :   return NS_OK;
    1378             : }
    1379             : 
    1380           0 : NS_IMETHODIMP HttpBaseChannel::GetTopLevelContentWindowId(uint64_t *aWindowId)
    1381             : {
    1382           0 :   if (!mContentWindowId) {
    1383           0 :     nsCOMPtr<nsILoadContext> loadContext;
    1384           0 :     GetCallback(loadContext);
    1385           0 :     if (loadContext) {
    1386           0 :       nsCOMPtr<mozIDOMWindowProxy> topWindow;
    1387           0 :       loadContext->GetTopWindow(getter_AddRefs(topWindow));
    1388           0 :       nsCOMPtr<nsIDOMWindowUtils> windowUtils = do_GetInterface(topWindow);
    1389           0 :       if (windowUtils) {
    1390           0 :         windowUtils->GetCurrentInnerWindowID(&mContentWindowId);
    1391             :       }
    1392             :     }
    1393             :   }
    1394           0 :   *aWindowId = mContentWindowId;
    1395           0 :   return NS_OK;
    1396             : }
    1397             : 
    1398           3 : NS_IMETHODIMP HttpBaseChannel::SetTopLevelOuterContentWindowId(uint64_t aWindowId)
    1399             : {
    1400           3 :   mTopLevelOuterContentWindowId = aWindowId;
    1401           3 :   return NS_OK;
    1402             : }
    1403             : 
    1404           0 : NS_IMETHODIMP HttpBaseChannel::GetTopLevelOuterContentWindowId(uint64_t *aWindowId)
    1405             : {
    1406           0 :   EnsureTopLevelOuterContentWindowId();
    1407           0 :   *aWindowId = mTopLevelOuterContentWindowId;
    1408           0 :   return NS_OK;
    1409             : }
    1410             : 
    1411           6 : NS_IMETHODIMP HttpBaseChannel::SetTopLevelContentWindowId(uint64_t aWindowId)
    1412             : {
    1413           6 :   mContentWindowId = aWindowId;
    1414           6 :   return NS_OK;
    1415             : }
    1416             : 
    1417             : NS_IMETHODIMP
    1418           2 : HttpBaseChannel::GetIsTrackingResource(bool* aIsTrackingResource)
    1419             : {
    1420           2 :   *aIsTrackingResource = mIsTrackingResource;
    1421           2 :   return NS_OK;
    1422             : }
    1423             : 
    1424             : NS_IMETHODIMP
    1425           5 : HttpBaseChannel::GetTransferSize(uint64_t *aTransferSize)
    1426             : {
    1427           5 :   *aTransferSize = mTransferSize;
    1428           5 :   return NS_OK;
    1429             : }
    1430             : 
    1431             : NS_IMETHODIMP
    1432           2 : HttpBaseChannel::GetDecodedBodySize(uint64_t *aDecodedBodySize)
    1433             : {
    1434           2 :   *aDecodedBodySize = mDecodedBodySize;
    1435           2 :   return NS_OK;
    1436             : }
    1437             : 
    1438             : NS_IMETHODIMP
    1439           2 : HttpBaseChannel::GetEncodedBodySize(uint64_t *aEncodedBodySize)
    1440             : {
    1441           2 :   *aEncodedBodySize = mEncodedBodySize;
    1442           2 :   return NS_OK;
    1443             : }
    1444             : 
    1445             : NS_IMETHODIMP
    1446           3 : HttpBaseChannel::GetRequestMethod(nsACString& aMethod)
    1447             : {
    1448           3 :   mRequestHead.Method(aMethod);
    1449           3 :   return NS_OK;
    1450             : }
    1451             : 
    1452             : NS_IMETHODIMP
    1453           5 : HttpBaseChannel::SetRequestMethod(const nsACString& aMethod)
    1454             : {
    1455           5 :   ENSURE_CALLED_BEFORE_CONNECT();
    1456             : 
    1457          10 :   const nsCString& flatMethod = PromiseFlatCString(aMethod);
    1458             : 
    1459             :   // Method names are restricted to valid HTTP tokens.
    1460           5 :   if (!nsHttp::IsValidToken(flatMethod))
    1461           0 :     return NS_ERROR_INVALID_ARG;
    1462             : 
    1463           5 :   mRequestHead.SetMethod(flatMethod);
    1464           5 :   return NS_OK;
    1465             : }
    1466             : 
    1467             : NS_IMETHODIMP
    1468           0 : HttpBaseChannel::GetNetworkInterfaceId(nsACString& aNetworkInterfaceId)
    1469             : {
    1470           0 :   aNetworkInterfaceId = mNetworkInterfaceId;
    1471           0 :   return NS_OK;
    1472             : }
    1473             : 
    1474             : NS_IMETHODIMP
    1475           0 : HttpBaseChannel::SetNetworkInterfaceId(const nsACString& aNetworkInterfaceId)
    1476             : {
    1477           0 :   ENSURE_CALLED_BEFORE_CONNECT();
    1478           0 :   mNetworkInterfaceId = aNetworkInterfaceId;
    1479           0 :   return NS_OK;
    1480             : }
    1481             : 
    1482             : NS_IMETHODIMP
    1483           4 : HttpBaseChannel::GetReferrer(nsIURI **referrer)
    1484             : {
    1485           4 :   NS_ENSURE_ARG_POINTER(referrer);
    1486           4 :   *referrer = mReferrer;
    1487           4 :   NS_IF_ADDREF(*referrer);
    1488           4 :   return NS_OK;
    1489             : }
    1490             : 
    1491             : NS_IMETHODIMP
    1492           0 : HttpBaseChannel::SetReferrer(nsIURI *referrer)
    1493             : {
    1494           0 :   return SetReferrerWithPolicy(referrer, NS_GetDefaultReferrerPolicy());
    1495             : }
    1496             : 
    1497             : NS_IMETHODIMP
    1498           2 : HttpBaseChannel::GetReferrerPolicy(uint32_t *referrerPolicy)
    1499             : {
    1500           2 :   NS_ENSURE_ARG_POINTER(referrerPolicy);
    1501           2 :   *referrerPolicy = mReferrerPolicy;
    1502           2 :   return NS_OK;
    1503             : }
    1504             : 
    1505             : NS_IMETHODIMP
    1506           3 : HttpBaseChannel::SetReferrerWithPolicy(nsIURI *referrer,
    1507             :                                        uint32_t referrerPolicy)
    1508             : {
    1509           3 :   ENSURE_CALLED_BEFORE_CONNECT();
    1510             : 
    1511           3 :   mReferrerPolicy = referrerPolicy;
    1512             : 
    1513             :   // clear existing referrer, if any
    1514           3 :   mReferrer = nullptr;
    1515           3 :   nsresult rv = mRequestHead.ClearHeader(nsHttp::Referer);
    1516           3 :   if(NS_FAILED(rv)) {
    1517           0 :     return rv;
    1518             :   }
    1519             : 
    1520           3 :   if (mReferrerPolicy == REFERRER_POLICY_UNSET) {
    1521           3 :     mReferrerPolicy = NS_GetDefaultReferrerPolicy();
    1522             :   }
    1523             : 
    1524           3 :   if (!referrer) {
    1525           0 :     return NS_OK;
    1526             :   }
    1527             : 
    1528             :   // Don't send referrer at all when the meta referrer setting is "no-referrer"
    1529           3 :   if (mReferrerPolicy == REFERRER_POLICY_NO_REFERRER) {
    1530           0 :     return NS_OK;
    1531             :   }
    1532             : 
    1533             :   // 0: never send referer
    1534             :   // 1: send referer for direct user action
    1535             :   // 2: always send referer
    1536           3 :   uint32_t userReferrerLevel = gHttpHandler->ReferrerLevel();
    1537             : 
    1538             :   // false: use real referrer
    1539             :   // true: spoof with URI of the current request
    1540           3 :   bool userSpoofReferrerSource = gHttpHandler->SpoofReferrerSource();
    1541             : 
    1542             :   // false: use real referrer when leaving .onion
    1543             :   // true: use an empty referrer
    1544           3 :   bool userHideOnionReferrerSource = gHttpHandler->HideOnionReferrerSource();
    1545             : 
    1546             :   // 0: full URI
    1547             :   // 1: scheme+host+port+path
    1548             :   // 2: scheme+host+port
    1549           3 :   int userReferrerTrimmingPolicy = gHttpHandler->ReferrerTrimmingPolicy();
    1550             : 
    1551             :   // 0: send referer no matter what
    1552             :   // 1: send referer ONLY when base domains match
    1553             :   // 2: send referer ONLY when hosts match
    1554           3 :   int userReferrerXOriginPolicy = gHttpHandler->ReferrerXOriginPolicy();
    1555             : 
    1556             :   // check referrer blocking pref
    1557             :   uint32_t referrerLevel;
    1558           3 :   if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
    1559           0 :     referrerLevel = 1; // user action
    1560             :   } else {
    1561           3 :     referrerLevel = 2; // inline content
    1562             :   }
    1563           3 :   if (userReferrerLevel < referrerLevel) {
    1564           0 :     return NS_OK;
    1565             :   }
    1566             : 
    1567           6 :   nsCOMPtr<nsIURI> referrerGrip;
    1568             :   bool match;
    1569             : 
    1570             :   //
    1571             :   // Strip off "wyciwyg://123/" from wyciwyg referrers.
    1572             :   //
    1573             :   // XXX this really belongs elsewhere since wyciwyg URLs aren't part of necko.
    1574             :   //   perhaps some sort of generic nsINestedURI could be used.  then, if an URI
    1575             :   //   fails the whitelist test, then we could check for an inner URI and try
    1576             :   //   that instead.  though, that might be too automatic.
    1577             :   //
    1578           3 :   rv = referrer->SchemeIs("wyciwyg", &match);
    1579           3 :   if (NS_FAILED(rv)) return rv;
    1580           3 :   if (match) {
    1581           0 :     nsAutoCString path;
    1582           0 :     rv = referrer->GetPath(path);
    1583           0 :     if (NS_FAILED(rv)) return rv;
    1584             : 
    1585           0 :     uint32_t pathLength = path.Length();
    1586           0 :     if (pathLength <= 2) return NS_ERROR_FAILURE;
    1587             : 
    1588             :     // Path is of the form "//123/http://foo/bar", with a variable number of
    1589             :     // digits. To figure out where the "real" URL starts, search path for a
    1590             :     // '/', starting at the third character.
    1591           0 :     int32_t slashIndex = path.FindChar('/', 2);
    1592           0 :     if (slashIndex == kNotFound) return NS_ERROR_FAILURE;
    1593             : 
    1594             :     // Get charset of the original URI so we can pass it to our fixed up URI.
    1595           0 :     nsAutoCString charset;
    1596           0 :     referrer->GetOriginCharset(charset);
    1597             : 
    1598             :     // Replace |referrer| with a URI without wyciwyg://123/.
    1599           0 :     rv = NS_NewURI(getter_AddRefs(referrerGrip),
    1600           0 :                    Substring(path, slashIndex + 1, pathLength - slashIndex - 1),
    1601           0 :                    charset.get());
    1602           0 :     if (NS_FAILED(rv)) return rv;
    1603             : 
    1604           0 :     referrer = referrerGrip.get();
    1605             :   }
    1606             : 
    1607             :   //
    1608             :   // block referrer if not on our white list...
    1609             :   //
    1610             :   static const char *const referrerWhiteList[] = {
    1611             :     "http",
    1612             :     "https",
    1613             :     "ftp",
    1614             :     nullptr
    1615             :   };
    1616           3 :   match = false;
    1617           3 :   const char *const *scheme = referrerWhiteList;
    1618          13 :   for (; *scheme && !match; ++scheme) {
    1619           5 :     rv = referrer->SchemeIs(*scheme, &match);
    1620           5 :     if (NS_FAILED(rv)) return rv;
    1621             :   }
    1622           3 :   if (!match) return NS_OK; // kick out....
    1623             : 
    1624             :   //
    1625             :   // Handle secure referrals.
    1626             :   //
    1627             :   // Support referrals from a secure server if this is a secure site
    1628             :   // and (optionally) if the host names are the same.
    1629             :   //
    1630           2 :   rv = referrer->SchemeIs("https", &match);
    1631           2 :   if (NS_FAILED(rv)) return rv;
    1632             : 
    1633           2 :   if (match) {
    1634           0 :     rv = mURI->SchemeIs("https", &match);
    1635           0 :     if (NS_FAILED(rv)) return rv;
    1636             : 
    1637             :     // It's ok to send referrer for https-to-http scenarios if the referrer
    1638             :     // policy is "unsafe-url", "origin", or "origin-when-cross-origin".
    1639           0 :     if (mReferrerPolicy != REFERRER_POLICY_UNSAFE_URL &&
    1640           0 :         mReferrerPolicy != REFERRER_POLICY_ORIGIN_WHEN_XORIGIN &&
    1641           0 :         mReferrerPolicy != REFERRER_POLICY_ORIGIN) {
    1642             : 
    1643             :       // in other referrer policies, https->http is not allowed...
    1644           0 :       if (!match) return NS_OK;
    1645             :     }
    1646             :   }
    1647             : 
    1648           4 :   nsCOMPtr<nsIURI> clone;
    1649             :   //
    1650             :   // we need to clone the referrer, so we can:
    1651             :   //  (1) modify it
    1652             :   //  (2) keep a reference to it after returning from this function
    1653             :   //
    1654             :   // Use CloneIgnoringRef to strip away any fragment per RFC 2616 section 14.36
    1655             :   // and Referrer Policy section 6.3.5.
    1656           2 :   rv = referrer->CloneIgnoringRef(getter_AddRefs(clone));
    1657           2 :   if (NS_FAILED(rv)) return rv;
    1658             : 
    1659           4 :   nsAutoCString currentHost;
    1660           4 :   nsAutoCString referrerHost;
    1661             : 
    1662           2 :   rv = mURI->GetAsciiHost(currentHost);
    1663           2 :   if (NS_FAILED(rv)) return rv;
    1664             : 
    1665           2 :   rv = clone->GetAsciiHost(referrerHost);
    1666           2 :   if (NS_FAILED(rv)) return rv;
    1667             : 
    1668             :   // Send an empty referrer if leaving a .onion domain.
    1669           6 :   if(userHideOnionReferrerSource &&
    1670           2 :      !currentHost.Equals(referrerHost) &&
    1671           2 :      StringEndsWith(referrerHost, NS_LITERAL_CSTRING(".onion"))) {
    1672           0 :     return NS_OK;
    1673             :   }
    1674             : 
    1675             :   // check policy for sending ref only when hosts match
    1676           2 :   if (userReferrerXOriginPolicy == 2 && !currentHost.Equals(referrerHost))
    1677           0 :     return NS_OK;
    1678             : 
    1679           2 :   if (userReferrerXOriginPolicy == 1) {
    1680           0 :     nsAutoCString currentDomain = currentHost;
    1681           0 :     nsAutoCString referrerDomain = referrerHost;
    1682           0 :     uint32_t extraDomains = 0;
    1683             :     nsCOMPtr<nsIEffectiveTLDService> eTLDService = do_GetService(
    1684           0 :       NS_EFFECTIVETLDSERVICE_CONTRACTID);
    1685           0 :     if (eTLDService) {
    1686           0 :       rv = eTLDService->GetBaseDomain(mURI, extraDomains, currentDomain);
    1687           0 :       if (NS_FAILED(rv)) return rv;
    1688           0 :       rv = eTLDService->GetBaseDomain(clone, extraDomains, referrerDomain);
    1689           0 :       if (NS_FAILED(rv)) return rv;
    1690             :     }
    1691             : 
    1692             :     // check policy for sending only when effective top level domain matches.
    1693             :     // this falls back on using host if eTLDService does not work
    1694           0 :     if (!currentDomain.Equals(referrerDomain))
    1695           0 :       return NS_OK;
    1696             :   }
    1697             : 
    1698             :   // send spoofed referrer if desired
    1699           2 :   if (userSpoofReferrerSource) {
    1700           0 :     nsCOMPtr<nsIURI> mURIclone;
    1701           0 :     rv = mURI->CloneIgnoringRef(getter_AddRefs(mURIclone));
    1702           0 :     if (NS_FAILED(rv)) return rv;
    1703           0 :     clone = mURIclone;
    1704           0 :     currentHost = referrerHost;
    1705             :   }
    1706             : 
    1707             :   // strip away any userpass; we don't want to be giving out passwords ;-)
    1708             :   // This is required by Referrer Policy stripping algorithm.
    1709           2 :   rv = clone->SetUserPass(EmptyCString());
    1710           2 :   if (NS_FAILED(rv)) return rv;
    1711             : 
    1712             :   // Computing whether our URI is cross-origin may be expensive, so we only do
    1713             :   // that in cases where we're going to use this information later on.  The if
    1714             :   // condition below encodes those cases.  isCrossOrigin.isNothing() will return
    1715             :   // true otherwise.
    1716           4 :   Maybe<bool> isCrossOrigin;
    1717           6 :   if ((mReferrerPolicy == REFERRER_POLICY_SAME_ORIGIN ||
    1718           4 :        mReferrerPolicy == REFERRER_POLICY_ORIGIN_WHEN_XORIGIN ||
    1719           4 :        mReferrerPolicy == REFERRER_POLICY_STRICT_ORIGIN_WHEN_XORIGIN ||
    1720             :        // If our referrer policy is origin-only or strict-origin, we will send
    1721             :        // the origin only no matter if we are cross origin, so in those cases we
    1722             :        // can also skip checking cross-origin-ness.
    1723           2 :        (gHttpHandler->ReferrerXOriginTrimmingPolicy() != 0 &&
    1724           0 :         mReferrerPolicy != REFERRER_POLICY_ORIGIN &&
    1725           2 :         mReferrerPolicy != REFERRER_POLICY_STRICT_ORIGIN)) &&
    1726             :       // 2 (origin-only) is already the strictest policy which we'd adopt if we
    1727             :       // were cross-origin, so there is no point to compute whether we are or
    1728             :       // not.
    1729           0 :       gHttpHandler->ReferrerTrimmingPolicy() != 2) {
    1730             :     // for cross-origin-based referrer changes (not just host-based), figure out
    1731             :     // if the referrer is being sent cross-origin.
    1732           0 :     nsCOMPtr<nsIURI> triggeringURI;
    1733           0 :     if (mLoadInfo) {
    1734           0 :       nsCOMPtr<nsIPrincipal> triggeringPrincipal = mLoadInfo->TriggeringPrincipal();
    1735           0 :       if (triggeringPrincipal) {
    1736           0 :         triggeringPrincipal->GetURI(getter_AddRefs(triggeringURI));
    1737             :       }
    1738             :     }
    1739           0 :     if (triggeringURI) {
    1740           0 :       if (LOG_ENABLED()) {
    1741           0 :         nsAutoCString triggeringURISpec;
    1742           0 :         rv = triggeringURI->GetAsciiSpec(triggeringURISpec);
    1743           0 :         if (!NS_FAILED(rv)) {
    1744           0 :           LOG(("triggeringURI=%s\n", triggeringURISpec.get()));
    1745             :         }
    1746             :       }
    1747           0 :       nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
    1748           0 :       rv = ssm->CheckSameOriginURI(triggeringURI, mURI, false);
    1749           0 :       isCrossOrigin.emplace(NS_FAILED(rv));
    1750             :     } else {
    1751           0 :       LOG(("no triggering principal available via loadInfo, assuming load is cross-origin"));
    1752           0 :       isCrossOrigin.emplace(true);
    1753             :     }
    1754             :   }
    1755             : 
    1756             :   // Don't send referrer when the request is cross-origin and policy is "same-origin".
    1757           2 :   if (mReferrerPolicy == REFERRER_POLICY_SAME_ORIGIN && *isCrossOrigin) {
    1758           0 :     return NS_OK;
    1759             :   }
    1760             : 
    1761           4 :   nsAutoCString spec;
    1762             : 
    1763             :   // Apply the user cross-origin trimming policy if it's more
    1764             :   // restrictive than the general one.
    1765             :   int userReferrerXOriginTrimmingPolicy =
    1766           2 :     gHttpHandler->ReferrerXOriginTrimmingPolicy();
    1767           2 :   if (userReferrerXOriginTrimmingPolicy != 0 && *isCrossOrigin) {
    1768           0 :     userReferrerTrimmingPolicy =
    1769           0 :       std::max(userReferrerTrimmingPolicy, userReferrerXOriginTrimmingPolicy);
    1770             :   }
    1771             : 
    1772             :   // site-specified referrer trimming may affect the trim level
    1773             :   // "unsafe-url" behaves like "origin" (send referrer in the same situations) but
    1774             :   // "unsafe-url" sends the whole referrer and origin removes the path.
    1775             :   // "origin-when-cross-origin" trims the referrer only when the request is
    1776             :   // cross-origin.
    1777             :   // "Strict" request from https->http case was bailed out, so here:
    1778             :   // "strict-origin" behaves the same as "origin".
    1779             :   // "strict-origin-when-cross-origin" behaves the same as "origin-when-cross-origin"
    1780           6 :   if (mReferrerPolicy == REFERRER_POLICY_ORIGIN ||
    1781           4 :       mReferrerPolicy == REFERRER_POLICY_STRICT_ORIGIN ||
    1782           4 :       ((mReferrerPolicy == REFERRER_POLICY_ORIGIN_WHEN_XORIGIN ||
    1783           2 :         mReferrerPolicy == REFERRER_POLICY_STRICT_ORIGIN_WHEN_XORIGIN) &&
    1784           0 :         *isCrossOrigin)) {
    1785             :     // We can override the user trimming preference because "origin"
    1786             :     // (network.http.referer.trimmingPolicy = 2) is the strictest
    1787             :     // trimming policy that users can specify.
    1788           0 :     userReferrerTrimmingPolicy = 2;
    1789             :   }
    1790             : 
    1791             :   // check how much referer to send
    1792           2 :   if (userReferrerTrimmingPolicy) {
    1793             :     // All output strings start with: scheme+host+port
    1794             :     // We want the IDN-normalized PrePath.  That's not something currently
    1795             :     // available and there doesn't yet seem to be justification for adding it to
    1796             :     // the interfaces, so just build it up ourselves from scheme+AsciiHostPort
    1797           0 :     nsAutoCString scheme, asciiHostPort;
    1798           0 :     rv = clone->GetScheme(scheme);
    1799           0 :     if (NS_FAILED(rv)) return rv;
    1800           0 :     spec = scheme;
    1801           0 :     spec.AppendLiteral("://");
    1802             :     // Note we explicitly cleared UserPass above, so do not need to build it.
    1803           0 :     rv = clone->GetAsciiHostPort(asciiHostPort);
    1804           0 :     if (NS_FAILED(rv)) return rv;
    1805           0 :     spec.Append(asciiHostPort);
    1806             : 
    1807           0 :     switch (userReferrerTrimmingPolicy) {
    1808             :       case 1: { // scheme+host+port+path
    1809           0 :         nsCOMPtr<nsIURL> url(do_QueryInterface(clone));
    1810           0 :         if (url) {
    1811           0 :           nsAutoCString path;
    1812           0 :           rv = url->GetFilePath(path);
    1813           0 :           if (NS_FAILED(rv)) return rv;
    1814           0 :           spec.Append(path);
    1815           0 :           rv = url->SetQuery(EmptyCString());
    1816           0 :           if (NS_FAILED(rv)) return rv;
    1817           0 :           rv = url->SetRef(EmptyCString());
    1818           0 :           if (NS_FAILED(rv)) return rv;
    1819           0 :           break;
    1820             :         }
    1821             :         // No URL, so fall through to truncating the path and any query/ref off
    1822             :         // as well.
    1823             :       }
    1824             :       MOZ_FALLTHROUGH;
    1825             :       default: // (Pref limited to [0,2] enforced by clamp, MOZ_CRASH overkill.)
    1826             :       case 2: // scheme+host+port+/
    1827           0 :         spec.AppendLiteral("/");
    1828             :         // This nukes any query/ref present as well in the case of nsStandardURL
    1829           0 :         rv = clone->SetPath(EmptyCString());
    1830           0 :         if (NS_FAILED(rv)) return rv;
    1831           0 :         break;
    1832             :     }
    1833             :   } else {
    1834             :     // use the full URI
    1835           2 :     rv = clone->GetAsciiSpec(spec);
    1836           2 :     if (NS_FAILED(rv)) return rv;
    1837             :   }
    1838             : 
    1839             :   // finally, remember the referrer URI and set the Referer header.
    1840           2 :   rv = SetRequestHeader(NS_LITERAL_CSTRING("Referer"), spec, false);
    1841           2 :   if (NS_FAILED(rv)) return rv;
    1842             : 
    1843           2 :   mReferrer = clone;
    1844           2 :   return NS_OK;
    1845             : }
    1846             : 
    1847             : // Return the channel's proxy URI, or if it doesn't exist, the
    1848             : // channel's main URI.
    1849             : NS_IMETHODIMP
    1850          12 : HttpBaseChannel::GetProxyURI(nsIURI **aOut)
    1851             : {
    1852          12 :   NS_ENSURE_ARG_POINTER(aOut);
    1853          24 :   nsCOMPtr<nsIURI> result(mProxyURI);
    1854          12 :   result.forget(aOut);
    1855          12 :   return NS_OK;
    1856             : }
    1857             : 
    1858             : NS_IMETHODIMP
    1859           8 : HttpBaseChannel::GetRequestHeader(const nsACString& aHeader,
    1860             :                                   nsACString& aValue)
    1861             : {
    1862           8 :   aValue.Truncate();
    1863             : 
    1864             :   // XXX might be better to search the header list directly instead of
    1865             :   // hitting the http atom hash table.
    1866           8 :   nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
    1867           8 :   if (!atom)
    1868           0 :     return NS_ERROR_NOT_AVAILABLE;
    1869             : 
    1870           8 :   return mRequestHead.GetHeader(atom, aValue);
    1871             : }
    1872             : 
    1873             : NS_IMETHODIMP
    1874          25 : HttpBaseChannel::SetRequestHeader(const nsACString& aHeader,
    1875             :                                   const nsACString& aValue,
    1876             :                                   bool aMerge)
    1877             : {
    1878          50 :   const nsCString &flatHeader = PromiseFlatCString(aHeader);
    1879          50 :   const nsCString &flatValue  = PromiseFlatCString(aValue);
    1880             : 
    1881          25 :   LOG(("HttpBaseChannel::SetRequestHeader [this=%p header=\"%s\" value=\"%s\" merge=%u]\n",
    1882             :       this, flatHeader.get(), flatValue.get(), aMerge));
    1883             : 
    1884             :   // Verify header names are valid HTTP tokens and header values are reasonably
    1885             :   // close to whats allowed in RFC 2616.
    1886          50 :   if (!nsHttp::IsValidToken(flatHeader) ||
    1887          25 :       !nsHttp::IsReasonableHeaderValue(flatValue)) {
    1888           0 :     return NS_ERROR_INVALID_ARG;
    1889             :   }
    1890             : 
    1891          25 :   return mRequestHead.SetHeader(aHeader, flatValue, aMerge);
    1892             : }
    1893             : 
    1894             : NS_IMETHODIMP
    1895           0 : HttpBaseChannel::SetEmptyRequestHeader(const nsACString& aHeader)
    1896             : {
    1897           0 :   const nsCString &flatHeader = PromiseFlatCString(aHeader);
    1898             : 
    1899           0 :   LOG(("HttpBaseChannel::SetEmptyRequestHeader [this=%p header=\"%s\"]\n",
    1900             :       this, flatHeader.get()));
    1901             : 
    1902             :   // Verify header names are valid HTTP tokens and header values are reasonably
    1903             :   // close to whats allowed in RFC 2616.
    1904           0 :   if (!nsHttp::IsValidToken(flatHeader)) {
    1905           0 :     return NS_ERROR_INVALID_ARG;
    1906             :   }
    1907             : 
    1908           0 :   return mRequestHead.SetEmptyHeader(aHeader);
    1909             : }
    1910             : 
    1911             : NS_IMETHODIMP
    1912           0 : HttpBaseChannel::VisitRequestHeaders(nsIHttpHeaderVisitor *visitor)
    1913             : {
    1914           0 :   return mRequestHead.VisitHeaders(visitor);
    1915             : }
    1916             : 
    1917             : NS_IMETHODIMP
    1918           0 : HttpBaseChannel::VisitNonDefaultRequestHeaders(nsIHttpHeaderVisitor *visitor)
    1919             : {
    1920           0 :   return mRequestHead.VisitHeaders(visitor,
    1921           0 :                                    nsHttpHeaderArray::eFilterSkipDefault);
    1922             : }
    1923             : 
    1924             : NS_IMETHODIMP
    1925          21 : HttpBaseChannel::GetResponseHeader(const nsACString &header, nsACString &value)
    1926             : {
    1927          21 :   value.Truncate();
    1928             : 
    1929          21 :   if (!mResponseHead)
    1930           0 :     return NS_ERROR_NOT_AVAILABLE;
    1931             : 
    1932          21 :   nsHttpAtom atom = nsHttp::ResolveAtom(header);
    1933          21 :   if (!atom)
    1934           0 :     return NS_ERROR_NOT_AVAILABLE;
    1935             : 
    1936          21 :   return mResponseHead->GetHeader(atom, value);
    1937             : }
    1938             : 
    1939             : NS_IMETHODIMP
    1940           0 : HttpBaseChannel::SetResponseHeader(const nsACString& header,
    1941             :                                    const nsACString& value,
    1942             :                                    bool merge)
    1943             : {
    1944           0 :   LOG(("HttpBaseChannel::SetResponseHeader [this=%p header=\"%s\" value=\"%s\" merge=%u]\n",
    1945             :       this, PromiseFlatCString(header).get(), PromiseFlatCString(value).get(), merge));
    1946             : 
    1947           0 :   if (!mResponseHead)
    1948           0 :     return NS_ERROR_NOT_AVAILABLE;
    1949             : 
    1950           0 :   nsHttpAtom atom = nsHttp::ResolveAtom(header);
    1951           0 :   if (!atom)
    1952           0 :     return NS_ERROR_NOT_AVAILABLE;
    1953             : 
    1954             :   // these response headers must not be changed
    1955           0 :   if (atom == nsHttp::Content_Type ||
    1956           0 :       atom == nsHttp::Content_Length ||
    1957           0 :       atom == nsHttp::Content_Encoding ||
    1958           0 :       atom == nsHttp::Trailer ||
    1959           0 :       atom == nsHttp::Transfer_Encoding)
    1960           0 :     return NS_ERROR_ILLEGAL_VALUE;
    1961             : 
    1962           0 :   mResponseHeadersModified = true;
    1963             : 
    1964           0 :   return mResponseHead->SetHeader(header, value, merge);
    1965             : }
    1966             : 
    1967             : NS_IMETHODIMP
    1968           0 : HttpBaseChannel::VisitResponseHeaders(nsIHttpHeaderVisitor *visitor)
    1969             : {
    1970           0 :   if (!mResponseHead) {
    1971           0 :     return NS_ERROR_NOT_AVAILABLE;
    1972             :   }
    1973           0 :   return mResponseHead->VisitHeaders(visitor,
    1974           0 :     nsHttpHeaderArray::eFilterResponse);
    1975             : }
    1976             : 
    1977             : NS_IMETHODIMP
    1978           0 : HttpBaseChannel::GetOriginalResponseHeader(const nsACString& aHeader,
    1979             :                                            nsIHttpHeaderVisitor *aVisitor)
    1980             : {
    1981           0 :   if (!mResponseHead) {
    1982           0 :     return NS_ERROR_NOT_AVAILABLE;
    1983             :   }
    1984             : 
    1985           0 :   nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
    1986           0 :   if (!atom) {
    1987           0 :     return NS_ERROR_NOT_AVAILABLE;
    1988             :   }
    1989             : 
    1990           0 :   return mResponseHead->GetOriginalHeader(atom, aVisitor);
    1991             : }
    1992             : 
    1993             : NS_IMETHODIMP
    1994           0 : HttpBaseChannel::VisitOriginalResponseHeaders(nsIHttpHeaderVisitor *aVisitor)
    1995             : {
    1996           0 :   if (!mResponseHead) {
    1997           0 :     return NS_ERROR_NOT_AVAILABLE;
    1998             :   }
    1999             : 
    2000           0 :   return mResponseHead->VisitHeaders(aVisitor,
    2001           0 :       nsHttpHeaderArray::eFilterResponseOriginal);
    2002             : }
    2003             : 
    2004             : NS_IMETHODIMP
    2005           0 : HttpBaseChannel::GetAllowPipelining(bool *value)
    2006             : {
    2007           0 :   NS_ENSURE_ARG_POINTER(value);
    2008           0 :   *value = false;
    2009           0 :   return NS_OK;
    2010             : }
    2011             : 
    2012             : NS_IMETHODIMP
    2013           0 : HttpBaseChannel::SetAllowPipelining(bool value)
    2014             : {
    2015           0 :   ENSURE_CALLED_BEFORE_CONNECT();
    2016             :   // nop
    2017           0 :   return NS_OK;
    2018             : }
    2019             : 
    2020             : NS_IMETHODIMP
    2021           0 : HttpBaseChannel::GetAllowSTS(bool *value)
    2022             : {
    2023           0 :   NS_ENSURE_ARG_POINTER(value);
    2024           0 :   *value = mAllowSTS;
    2025           0 :   return NS_OK;
    2026             : }
    2027             : 
    2028             : NS_IMETHODIMP
    2029           3 : HttpBaseChannel::SetAllowSTS(bool value)
    2030             : {
    2031           3 :   ENSURE_CALLED_BEFORE_CONNECT();
    2032             : 
    2033           3 :   mAllowSTS = value;
    2034           3 :   return NS_OK;
    2035             : }
    2036             : 
    2037             : NS_IMETHODIMP
    2038           0 : HttpBaseChannel::GetRedirectionLimit(uint32_t *value)
    2039             : {
    2040           0 :   NS_ENSURE_ARG_POINTER(value);
    2041           0 :   *value = mRedirectionLimit;
    2042           0 :   return NS_OK;
    2043             : }
    2044             : 
    2045             : NS_IMETHODIMP
    2046           3 : HttpBaseChannel::SetRedirectionLimit(uint32_t value)
    2047             : {
    2048           3 :   ENSURE_CALLED_BEFORE_CONNECT();
    2049             : 
    2050           3 :   mRedirectionLimit = std::min<uint32_t>(value, 0xff);
    2051           3 :   return NS_OK;
    2052             : }
    2053             : 
    2054             : nsresult
    2055           0 : HttpBaseChannel::OverrideSecurityInfo(nsISupports* aSecurityInfo)
    2056             : {
    2057           0 :   MOZ_ASSERT(!mSecurityInfo,
    2058             :              "This can only be called when we don't have a security info object already");
    2059           0 :   MOZ_RELEASE_ASSERT(aSecurityInfo,
    2060             :                      "This can only be called with a valid security info object");
    2061           0 :   MOZ_ASSERT(!BypassServiceWorker(),
    2062             :              "This can only be called on channels that are not bypassing interception");
    2063           0 :   MOZ_ASSERT(mResponseCouldBeSynthesized,
    2064             :              "This can only be called on channels that can be intercepted");
    2065           0 :   if (mSecurityInfo) {
    2066           0 :     LOG(("HttpBaseChannel::OverrideSecurityInfo mSecurityInfo is null! "
    2067             :          "[this=%p]\n", this));
    2068           0 :     return NS_ERROR_UNEXPECTED;
    2069             :   }
    2070           0 :   if (!mResponseCouldBeSynthesized) {
    2071           0 :     LOG(("HttpBaseChannel::OverrideSecurityInfo channel cannot be intercepted! "
    2072             :          "[this=%p]\n", this));
    2073           0 :     return NS_ERROR_UNEXPECTED;
    2074             :   }
    2075             : 
    2076           0 :   mSecurityInfo = aSecurityInfo;
    2077           0 :   return NS_OK;
    2078             : }
    2079             : 
    2080             : NS_IMETHODIMP
    2081           3 : HttpBaseChannel::IsNoStoreResponse(bool *value)
    2082             : {
    2083           3 :   if (!mResponseHead)
    2084           0 :     return NS_ERROR_NOT_AVAILABLE;
    2085           3 :   *value = mResponseHead->NoStore();
    2086           3 :   return NS_OK;
    2087             : }
    2088             : 
    2089             : NS_IMETHODIMP
    2090           1 : HttpBaseChannel::IsNoCacheResponse(bool *value)
    2091             : {
    2092           1 :   if (!mResponseHead)
    2093           0 :     return NS_ERROR_NOT_AVAILABLE;
    2094           1 :   *value = mResponseHead->NoCache();
    2095           1 :   if (!*value)
    2096           1 :     *value = mResponseHead->ExpiresInPast();
    2097           1 :   return NS_OK;
    2098             : }
    2099             : 
    2100             : NS_IMETHODIMP
    2101           0 : HttpBaseChannel::IsPrivateResponse(bool *value)
    2102             : {
    2103           0 :   if (!mResponseHead)
    2104           0 :     return NS_ERROR_NOT_AVAILABLE;
    2105           0 :   *value = mResponseHead->Private();
    2106           0 :   return NS_OK;
    2107             : }
    2108             : 
    2109             : NS_IMETHODIMP
    2110          14 : HttpBaseChannel::GetResponseStatus(uint32_t *aValue)
    2111             : {
    2112          14 :   if (!mResponseHead)
    2113           3 :     return NS_ERROR_NOT_AVAILABLE;
    2114          11 :   *aValue = mResponseHead->Status();
    2115          11 :   return NS_OK;
    2116             : }
    2117             : 
    2118             : NS_IMETHODIMP
    2119           0 : HttpBaseChannel::GetResponseStatusText(nsACString& aValue)
    2120             : {
    2121           0 :   if (!mResponseHead)
    2122           0 :     return NS_ERROR_NOT_AVAILABLE;
    2123           0 :   mResponseHead->StatusText(aValue);
    2124           0 :   return NS_OK;
    2125             : }
    2126             : 
    2127             : NS_IMETHODIMP
    2128           6 : HttpBaseChannel::GetRequestSucceeded(bool *aValue)
    2129             : {
    2130           6 :   if (!mResponseHead)
    2131           0 :     return NS_ERROR_NOT_AVAILABLE;
    2132           6 :   uint32_t status = mResponseHead->Status();
    2133           6 :   *aValue = (status / 100 == 2);
    2134           6 :   return NS_OK;
    2135             : }
    2136             : 
    2137             : NS_IMETHODIMP
    2138           0 : HttpBaseChannel::RedirectTo(nsIURI *targetURI)
    2139             : {
    2140           0 :   NS_ENSURE_ARG(targetURI);
    2141             : 
    2142           0 :   nsAutoCString spec;
    2143           0 :   targetURI->GetAsciiSpec(spec);
    2144           0 :   LOG(("HttpBaseChannel::RedirectTo [this=%p, uri=%s]", this, spec.get()));
    2145             : 
    2146             :   // We cannot redirect after OnStartRequest of the listener
    2147             :   // has been called, since to redirect we have to switch channels
    2148             :   // and the dance with OnStartRequest et al has to start over.
    2149             :   // This would break the nsIStreamListener contract.
    2150           0 :   NS_ENSURE_FALSE(mOnStartRequestCalled, NS_ERROR_NOT_AVAILABLE);
    2151             : 
    2152           0 :   mAPIRedirectToURI = targetURI;
    2153           0 :   return NS_OK;
    2154             : }
    2155             : 
    2156             : NS_IMETHODIMP
    2157           0 : HttpBaseChannel::GetRequestContextID(uint64_t *aRCID)
    2158             : {
    2159           0 :   NS_ENSURE_ARG_POINTER(aRCID);
    2160           0 :   *aRCID = mRequestContextID;
    2161           0 :   return NS_OK;
    2162             : }
    2163             : 
    2164             : NS_IMETHODIMP
    2165           3 : HttpBaseChannel::SetRequestContextID(uint64_t aRCID)
    2166             : {
    2167           3 :   mRequestContextID = aRCID;
    2168           3 :   return NS_OK;
    2169             : }
    2170             : 
    2171             : NS_IMETHODIMP
    2172           0 : HttpBaseChannel::GetIsMainDocumentChannel(bool* aValue)
    2173             : {
    2174           0 :   NS_ENSURE_ARG_POINTER(aValue);
    2175           0 :   *aValue = mForceMainDocumentChannel || (mLoadFlags & LOAD_DOCUMENT_URI);
    2176           0 :   return NS_OK;
    2177             : }
    2178             : 
    2179             : NS_IMETHODIMP
    2180           0 : HttpBaseChannel::SetIsMainDocumentChannel(bool aValue)
    2181             : {
    2182           0 :   mForceMainDocumentChannel = aValue;
    2183           0 :   return NS_OK;
    2184             : }
    2185             : 
    2186             : NS_IMETHODIMP
    2187           3 : HttpBaseChannel::GetProtocolVersion(nsACString& aProtocolVersion)
    2188             : {
    2189             :   nsresult rv;
    2190           6 :   nsCOMPtr<nsISSLSocketControl> ssl = do_QueryInterface(mSecurityInfo, &rv);
    2191           6 :   nsAutoCString protocol;
    2192           6 :   if (NS_SUCCEEDED(rv) && ssl &&
    2193           3 :       NS_SUCCEEDED(ssl->GetNegotiatedNPN(protocol)) &&
    2194           0 :       !protocol.IsEmpty()) {
    2195             :     // The negotiated protocol was not empty so we can use it.
    2196           0 :     aProtocolVersion = protocol;
    2197           0 :     return NS_OK;
    2198             :   }
    2199             : 
    2200           3 :   if (mResponseHead) {
    2201           3 :     uint32_t version = mResponseHead->Version();
    2202           3 :     aProtocolVersion.Assign(nsHttp::GetProtocolVersion(version));
    2203           3 :     return NS_OK;
    2204             :   }
    2205             : 
    2206           0 :   return NS_ERROR_NOT_AVAILABLE;
    2207             : }
    2208             : 
    2209             : 
    2210             : //-----------------------------------------------------------------------------
    2211             : // HttpBaseChannel::nsIHttpChannelInternal
    2212             : //-----------------------------------------------------------------------------
    2213             : 
    2214             : NS_IMETHODIMP
    2215           0 : HttpBaseChannel::SetTopWindowURIIfUnknown(nsIURI *aTopWindowURI)
    2216             : {
    2217           0 :   if (!aTopWindowURI) {
    2218           0 :     return NS_ERROR_INVALID_ARG;
    2219             :   }
    2220             : 
    2221           0 :   if (mTopWindowURI) {
    2222           0 :     LOG(("HttpChannelBase::SetTopWindowURIIfUnknown [this=%p] "
    2223             :          "mTopWindowURI is already set.\n", this));
    2224           0 :     return NS_ERROR_FAILURE;
    2225             :   }
    2226             : 
    2227           0 :   nsCOMPtr<nsIURI> topWindowURI;
    2228           0 :   Unused << GetTopWindowURI(getter_AddRefs(topWindowURI));
    2229             : 
    2230             :   // Don't modify |mTopWindowURI| if we can get one from GetTopWindowURI().
    2231           0 :   if (topWindowURI) {
    2232           0 :     LOG(("HttpChannelBase::SetTopWindowURIIfUnknown [this=%p] "
    2233             :          "Return an error since we got a top window uri.\n", this));
    2234           0 :     return NS_ERROR_FAILURE;
    2235             :   }
    2236             : 
    2237           0 :   mTopWindowURI = aTopWindowURI;
    2238           0 :   return NS_OK;
    2239             : }
    2240             : 
    2241             : NS_IMETHODIMP
    2242           7 : HttpBaseChannel::GetTopWindowURI(nsIURI **aTopWindowURI)
    2243             : {
    2244           7 :   nsresult rv = NS_OK;
    2245          14 :   nsCOMPtr<mozIThirdPartyUtil> util;
    2246             :   // Only compute the top window URI once. In e10s, this must be computed in the
    2247             :   // child. The parent gets the top window URI through HttpChannelOpenArgs.
    2248           7 :   if (!mTopWindowURI) {
    2249           5 :     util = do_GetService(THIRDPARTYUTIL_CONTRACTID);
    2250           5 :     if (!util) {
    2251           0 :       return NS_ERROR_NOT_AVAILABLE;
    2252             :     }
    2253          10 :     nsCOMPtr<mozIDOMWindowProxy> win;
    2254           5 :     rv = util->GetTopWindowForChannel(this, getter_AddRefs(win));
    2255           5 :     if (NS_SUCCEEDED(rv)) {
    2256           4 :       rv = util->GetURIFromWindow(win, getter_AddRefs(mTopWindowURI));
    2257             : #if DEBUG
    2258           4 :       if (mTopWindowURI) {
    2259           4 :         nsCString spec;
    2260           2 :         if (NS_SUCCEEDED(mTopWindowURI->GetSpec(spec))) {
    2261           2 :           LOG(("HttpChannelBase::Setting topwindow URI spec %s [this=%p]\n",
    2262             :                spec.get(), this));
    2263             :         }
    2264             :       }
    2265             : #endif
    2266             :     }
    2267             :   }
    2268           7 :   NS_IF_ADDREF(*aTopWindowURI = mTopWindowURI);
    2269           7 :   return rv;
    2270             : }
    2271             : 
    2272             : NS_IMETHODIMP
    2273           0 : HttpBaseChannel::GetDocumentURI(nsIURI **aDocumentURI)
    2274             : {
    2275           0 :   NS_ENSURE_ARG_POINTER(aDocumentURI);
    2276           0 :   *aDocumentURI = mDocumentURI;
    2277           0 :   NS_IF_ADDREF(*aDocumentURI);
    2278           0 :   return NS_OK;
    2279             : }
    2280             : 
    2281             : NS_IMETHODIMP
    2282           3 : HttpBaseChannel::SetDocumentURI(nsIURI *aDocumentURI)
    2283             : {
    2284           3 :   ENSURE_CALLED_BEFORE_CONNECT();
    2285             : 
    2286           3 :   mDocumentURI = aDocumentURI;
    2287           3 :   return NS_OK;
    2288             : }
    2289             : 
    2290             : NS_IMETHODIMP
    2291           0 : HttpBaseChannel::GetRequestVersion(uint32_t *major, uint32_t *minor)
    2292             : {
    2293           0 :   nsHttpVersion version = mRequestHead.Version();
    2294             : 
    2295           0 :   if (major) { *major = version / 10; }
    2296           0 :   if (minor) { *minor = version % 10; }
    2297             : 
    2298           0 :   return NS_OK;
    2299             : }
    2300             : 
    2301             : NS_IMETHODIMP
    2302           0 : HttpBaseChannel::GetResponseVersion(uint32_t *major, uint32_t *minor)
    2303             : {
    2304           0 :   if (!mResponseHead)
    2305             :   {
    2306           0 :     *major = *minor = 0; // we should at least be kind about it
    2307           0 :     return NS_ERROR_NOT_AVAILABLE;
    2308             :   }
    2309             : 
    2310           0 :   nsHttpVersion version = mResponseHead->Version();
    2311             : 
    2312           0 :   if (major) { *major = version / 10; }
    2313           0 :   if (minor) { *minor = version % 10; }
    2314             : 
    2315           0 :   return NS_OK;
    2316             : }
    2317             : 
    2318             : void
    2319           0 : HttpBaseChannel::NotifySetCookie(char const *aCookie)
    2320             : {
    2321           0 :   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
    2322           0 :   if (obs) {
    2323           0 :     nsAutoString cookie;
    2324           0 :     CopyASCIItoUTF16(aCookie, cookie);
    2325           0 :     obs->NotifyObservers(static_cast<nsIChannel*>(this),
    2326             :                          "http-on-response-set-cookie",
    2327           0 :                          cookie.get());
    2328             :   }
    2329           0 : }
    2330             : 
    2331             : NS_IMETHODIMP
    2332           0 : HttpBaseChannel::SetCookie(const char *aCookieHeader)
    2333             : {
    2334           0 :   if (mLoadFlags & LOAD_ANONYMOUS)
    2335           0 :     return NS_OK;
    2336             : 
    2337             :   // empty header isn't an error
    2338           0 :   if (!(aCookieHeader && *aCookieHeader))
    2339           0 :     return NS_OK;
    2340             : 
    2341           0 :   nsICookieService *cs = gHttpHandler->GetCookieService();
    2342           0 :   NS_ENSURE_TRUE(cs, NS_ERROR_FAILURE);
    2343             : 
    2344           0 :   nsAutoCString date;
    2345             :   // empty date is not an error
    2346           0 :   Unused << mResponseHead->GetHeader(nsHttp::Date, date);
    2347           0 :   nsresult rv = cs->SetCookieStringFromHttp(mURI, nullptr, nullptr,
    2348           0 :                                             aCookieHeader, date.get(), this);
    2349           0 :   if (NS_SUCCEEDED(rv)) {
    2350           0 :     NotifySetCookie(aCookieHeader);
    2351             :   }
    2352           0 :   return rv;
    2353             : }
    2354             : 
    2355             : NS_IMETHODIMP
    2356           9 : HttpBaseChannel::GetThirdPartyFlags(uint32_t  *aFlags)
    2357             : {
    2358           9 :   *aFlags = mThirdPartyFlags;
    2359           9 :   return NS_OK;
    2360             : }
    2361             : 
    2362             : NS_IMETHODIMP
    2363           3 : HttpBaseChannel::SetThirdPartyFlags(uint32_t aFlags)
    2364             : {
    2365           3 :   ENSURE_CALLED_BEFORE_ASYNC_OPEN();
    2366             : 
    2367           3 :   mThirdPartyFlags = aFlags;
    2368           3 :   return NS_OK;
    2369             : }
    2370             : 
    2371             : NS_IMETHODIMP
    2372           0 : HttpBaseChannel::GetForceAllowThirdPartyCookie(bool *aForce)
    2373             : {
    2374           0 :   *aForce = !!(mThirdPartyFlags & nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
    2375           0 :   return NS_OK;
    2376             : }
    2377             : 
    2378             : NS_IMETHODIMP
    2379           0 : HttpBaseChannel::SetForceAllowThirdPartyCookie(bool aForce)
    2380             : {
    2381           0 :   ENSURE_CALLED_BEFORE_ASYNC_OPEN();
    2382             : 
    2383           0 :   if (aForce)
    2384           0 :     mThirdPartyFlags |= nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW;
    2385             :   else
    2386           0 :     mThirdPartyFlags &= ~nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW;
    2387             : 
    2388           0 :   return NS_OK;
    2389             : }
    2390             : 
    2391             : NS_IMETHODIMP
    2392           0 : HttpBaseChannel::GetCanceled(bool *aCanceled)
    2393             : {
    2394           0 :   *aCanceled = mCanceled;
    2395           0 :   return NS_OK;
    2396             : }
    2397             : 
    2398             : NS_IMETHODIMP
    2399           0 : HttpBaseChannel::GetChannelIsForDownload(bool *aChannelIsForDownload)
    2400             : {
    2401           0 :   *aChannelIsForDownload = mChannelIsForDownload;
    2402           0 :   return NS_OK;
    2403             : }
    2404             : 
    2405             : NS_IMETHODIMP
    2406           0 : HttpBaseChannel::SetChannelIsForDownload(bool aChannelIsForDownload)
    2407             : {
    2408           0 :   mChannelIsForDownload = aChannelIsForDownload;
    2409           0 :   return NS_OK;
    2410             : }
    2411             : 
    2412             : NS_IMETHODIMP
    2413           0 : HttpBaseChannel::SetCacheKeysRedirectChain(nsTArray<nsCString> *cacheKeys)
    2414             : {
    2415           0 :   mRedirectedCachekeys = cacheKeys;
    2416           0 :   return NS_OK;
    2417             : }
    2418             : 
    2419             : NS_IMETHODIMP
    2420           0 : HttpBaseChannel::GetLocalAddress(nsACString& addr)
    2421             : {
    2422           0 :   if (mSelfAddr.raw.family == PR_AF_UNSPEC)
    2423           0 :     return NS_ERROR_NOT_AVAILABLE;
    2424             : 
    2425           0 :   addr.SetCapacity(kIPv6CStrBufSize);
    2426           0 :   NetAddrToString(&mSelfAddr, addr.BeginWriting(), kIPv6CStrBufSize);
    2427           0 :   addr.SetLength(strlen(addr.BeginReading()));
    2428             : 
    2429           0 :   return NS_OK;
    2430             : }
    2431             : 
    2432             : NS_IMETHODIMP
    2433           1 : HttpBaseChannel::TakeAllSecurityMessages(
    2434             :     nsCOMArray<nsISecurityConsoleMessage> &aMessages)
    2435             : {
    2436           1 :   MOZ_ASSERT(NS_IsMainThread());
    2437             : 
    2438           1 :   aMessages.Clear();
    2439           1 :   for (auto pair : mSecurityConsoleMessages) {
    2440             :     nsresult rv;
    2441             :     nsCOMPtr<nsISecurityConsoleMessage> message =
    2442           0 :       do_CreateInstance(NS_SECURITY_CONSOLE_MESSAGE_CONTRACTID, &rv);
    2443           0 :     NS_ENSURE_SUCCESS(rv, rv);
    2444             : 
    2445           0 :     message->SetTag(pair.first());
    2446           0 :     message->SetCategory(pair.second());
    2447           0 :     aMessages.AppendElement(message);
    2448             :   }
    2449             : 
    2450           1 :   MOZ_ASSERT(mSecurityConsoleMessages.Length() == aMessages.Length());
    2451           1 :   mSecurityConsoleMessages.Clear();
    2452             : 
    2453           1 :   return NS_OK;
    2454             : }
    2455             : 
    2456             : /* Please use this method with care. This can cause the message
    2457             :  * queue to grow large and cause the channel to take up a lot
    2458             :  * of memory. Use only static string messages and do not add
    2459             :  * server side data to the queue, as that can be large.
    2460             :  * Add only a limited number of messages to the queue to keep
    2461             :  * the channel size down and do so only in rare erroneous situations.
    2462             :  * More information can be found here:
    2463             :  * https://bugzilla.mozilla.org/show_bug.cgi?id=846918
    2464             :  */
    2465             : nsresult
    2466           0 : HttpBaseChannel::AddSecurityMessage(const nsAString &aMessageTag,
    2467             :     const nsAString &aMessageCategory)
    2468             : {
    2469           0 :   MOZ_ASSERT(NS_IsMainThread());
    2470             : 
    2471             :   nsresult rv;
    2472             : 
    2473             :   // nsSecurityConsoleMessage is not thread-safe refcounted.
    2474             :   // Delay the object construction until requested.
    2475             :   // See TakeAllSecurityMessages()
    2476           0 :   Pair<nsString, nsString> pair(aMessageTag, aMessageCategory);
    2477           0 :   mSecurityConsoleMessages.AppendElement(Move(pair));
    2478             : 
    2479           0 :   nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
    2480           0 :   if (!console) {
    2481           0 :     return NS_ERROR_FAILURE;
    2482             :   }
    2483             : 
    2484           0 :   nsCOMPtr<nsILoadInfo> loadInfo;
    2485           0 :   GetLoadInfo(getter_AddRefs(loadInfo));
    2486           0 :   if (!loadInfo) {
    2487           0 :     return NS_ERROR_FAILURE;
    2488             :   }
    2489             : 
    2490           0 :   auto innerWindowID = loadInfo->GetInnerWindowID();
    2491             : 
    2492           0 :   nsXPIDLString errorText;
    2493           0 :   rv = nsContentUtils::GetLocalizedString(
    2494             :           nsContentUtils::eSECURITY_PROPERTIES,
    2495           0 :           NS_ConvertUTF16toUTF8(aMessageTag).get(),
    2496           0 :           errorText);
    2497           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2498             : 
    2499           0 :   nsAutoCString spec;
    2500           0 :   if (mURI) {
    2501           0 :     spec = mURI->GetSpecOrDefault();
    2502             :   }
    2503             : 
    2504           0 :   nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
    2505           0 :   error->InitWithWindowID(errorText, NS_ConvertUTF8toUTF16(spec),
    2506           0 :                           EmptyString(), 0, 0, nsIScriptError::warningFlag,
    2507           0 :                           NS_ConvertUTF16toUTF8(aMessageCategory),
    2508           0 :                           innerWindowID);
    2509           0 :   console->LogMessage(error);
    2510             : 
    2511           0 :   return NS_OK;
    2512             : }
    2513             : 
    2514             : NS_IMETHODIMP
    2515           0 : HttpBaseChannel::GetLocalPort(int32_t* port)
    2516             : {
    2517           0 :   NS_ENSURE_ARG_POINTER(port);
    2518             : 
    2519           0 :   if (mSelfAddr.raw.family == PR_AF_INET) {
    2520           0 :     *port = (int32_t)ntohs(mSelfAddr.inet.port);
    2521             :   }
    2522           0 :   else if (mSelfAddr.raw.family == PR_AF_INET6) {
    2523           0 :     *port = (int32_t)ntohs(mSelfAddr.inet6.port);
    2524             :   }
    2525             :   else
    2526           0 :     return NS_ERROR_NOT_AVAILABLE;
    2527             : 
    2528           0 :   return NS_OK;
    2529             : }
    2530             : 
    2531             : NS_IMETHODIMP
    2532           0 : HttpBaseChannel::GetRemoteAddress(nsACString& addr)
    2533             : {
    2534           0 :   if (mPeerAddr.raw.family == PR_AF_UNSPEC)
    2535           0 :     return NS_ERROR_NOT_AVAILABLE;
    2536             : 
    2537           0 :   addr.SetCapacity(kIPv6CStrBufSize);
    2538           0 :   NetAddrToString(&mPeerAddr, addr.BeginWriting(), kIPv6CStrBufSize);
    2539           0 :   addr.SetLength(strlen(addr.BeginReading()));
    2540             : 
    2541           0 :   return NS_OK;
    2542             : }
    2543             : 
    2544             : NS_IMETHODIMP
    2545           0 : HttpBaseChannel::GetRemotePort(int32_t* port)
    2546             : {
    2547           0 :   NS_ENSURE_ARG_POINTER(port);
    2548             : 
    2549           0 :   if (mPeerAddr.raw.family == PR_AF_INET) {
    2550           0 :     *port = (int32_t)ntohs(mPeerAddr.inet.port);
    2551             :   }
    2552           0 :   else if (mPeerAddr.raw.family == PR_AF_INET6) {
    2553           0 :     *port = (int32_t)ntohs(mPeerAddr.inet6.port);
    2554             :   }
    2555             :   else
    2556           0 :     return NS_ERROR_NOT_AVAILABLE;
    2557             : 
    2558           0 :   return NS_OK;
    2559             : }
    2560             : 
    2561             : NS_IMETHODIMP
    2562           0 : HttpBaseChannel::HTTPUpgrade(const nsACString &aProtocolName,
    2563             :                              nsIHttpUpgradeListener *aListener)
    2564             : {
    2565           0 :     NS_ENSURE_ARG(!aProtocolName.IsEmpty());
    2566           0 :     NS_ENSURE_ARG_POINTER(aListener);
    2567             : 
    2568           0 :     mUpgradeProtocol = aProtocolName;
    2569           0 :     mUpgradeProtocolCallback = aListener;
    2570           0 :     return NS_OK;
    2571             : }
    2572             : 
    2573             : NS_IMETHODIMP
    2574           0 : HttpBaseChannel::GetAllowSpdy(bool *aAllowSpdy)
    2575             : {
    2576           0 :   NS_ENSURE_ARG_POINTER(aAllowSpdy);
    2577             : 
    2578           0 :   *aAllowSpdy = mAllowSpdy;
    2579           0 :   return NS_OK;
    2580             : }
    2581             : 
    2582             : NS_IMETHODIMP
    2583           3 : HttpBaseChannel::SetAllowSpdy(bool aAllowSpdy)
    2584             : {
    2585           3 :   mAllowSpdy = aAllowSpdy;
    2586           3 :   return NS_OK;
    2587             : }
    2588             : 
    2589             : NS_IMETHODIMP
    2590           0 : HttpBaseChannel::GetAllowAltSvc(bool *aAllowAltSvc)
    2591             : {
    2592           0 :   NS_ENSURE_ARG_POINTER(aAllowAltSvc);
    2593             : 
    2594           0 :   *aAllowAltSvc = mAllowAltSvc;
    2595           0 :   return NS_OK;
    2596             : }
    2597             : 
    2598             : NS_IMETHODIMP
    2599           3 : HttpBaseChannel::SetAllowAltSvc(bool aAllowAltSvc)
    2600             : {
    2601           3 :   mAllowAltSvc = aAllowAltSvc;
    2602           3 :   return NS_OK;
    2603             : }
    2604             : 
    2605             : NS_IMETHODIMP
    2606           0 : HttpBaseChannel::GetBeConservative(bool *aBeConservative)
    2607             : {
    2608           0 :   NS_ENSURE_ARG_POINTER(aBeConservative);
    2609             : 
    2610           0 :   *aBeConservative = mBeConservative;
    2611           0 :   return NS_OK;
    2612             : }
    2613             : 
    2614             : NS_IMETHODIMP
    2615           3 : HttpBaseChannel::SetBeConservative(bool aBeConservative)
    2616             : {
    2617           3 :   mBeConservative = aBeConservative;
    2618           3 :   return NS_OK;
    2619             : }
    2620             : 
    2621             : NS_IMETHODIMP
    2622           0 : HttpBaseChannel::GetApiRedirectToURI(nsIURI ** aResult)
    2623             : {
    2624           0 :   NS_ENSURE_ARG_POINTER(aResult);
    2625           0 :   NS_IF_ADDREF(*aResult = mAPIRedirectToURI);
    2626           0 :   return NS_OK;
    2627             : }
    2628             : 
    2629             : NS_IMETHODIMP
    2630           3 : HttpBaseChannel::GetResponseTimeoutEnabled(bool *aEnable)
    2631             : {
    2632           3 :   if (NS_WARN_IF(!aEnable)) {
    2633           0 :     return NS_ERROR_NULL_POINTER;
    2634             :   }
    2635           3 :   *aEnable = mResponseTimeoutEnabled;
    2636           3 :   return NS_OK;
    2637             : }
    2638             : 
    2639             : NS_IMETHODIMP
    2640           0 : HttpBaseChannel::SetResponseTimeoutEnabled(bool aEnable)
    2641             : {
    2642           0 :   mResponseTimeoutEnabled = aEnable;
    2643           0 :   return NS_OK;
    2644             : }
    2645             : 
    2646             : NS_IMETHODIMP
    2647           3 : HttpBaseChannel::GetInitialRwin(uint32_t *aRwin)
    2648             : {
    2649           3 :   if (NS_WARN_IF(!aRwin)) {
    2650           0 :     return NS_ERROR_NULL_POINTER;
    2651             :   }
    2652           3 :   *aRwin = mInitialRwin;
    2653           3 :   return NS_OK;
    2654             : }
    2655             : 
    2656             : NS_IMETHODIMP
    2657           3 : HttpBaseChannel::SetInitialRwin(uint32_t aRwin)
    2658             : {
    2659           3 :   ENSURE_CALLED_BEFORE_CONNECT();
    2660           3 :   mInitialRwin = aRwin;
    2661           3 :   return NS_OK;
    2662             : }
    2663             : 
    2664             : NS_IMETHODIMP
    2665           0 : HttpBaseChannel::ForcePending(bool aForcePending)
    2666             : {
    2667           0 :   mForcePending = aForcePending;
    2668           0 :   return NS_OK;
    2669             : }
    2670             : 
    2671             : NS_IMETHODIMP
    2672           0 : HttpBaseChannel::GetLastModifiedTime(PRTime* lastModifiedTime)
    2673             : {
    2674           0 :   if (!mResponseHead)
    2675           0 :     return NS_ERROR_NOT_AVAILABLE;
    2676             :   uint32_t lastMod;
    2677           0 :   nsresult rv = mResponseHead->GetLastModifiedValue(&lastMod);
    2678           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2679           0 :   *lastModifiedTime = lastMod;
    2680           0 :   return NS_OK;
    2681             : }
    2682             : 
    2683             : NS_IMETHODIMP
    2684           0 : HttpBaseChannel::GetCorsIncludeCredentials(bool* aInclude)
    2685             : {
    2686           0 :   *aInclude = mCorsIncludeCredentials;
    2687           0 :   return NS_OK;
    2688             : }
    2689             : 
    2690             : NS_IMETHODIMP
    2691           0 : HttpBaseChannel::SetCorsIncludeCredentials(bool aInclude)
    2692             : {
    2693           0 :   mCorsIncludeCredentials = aInclude;
    2694           0 :   return NS_OK;
    2695             : }
    2696             : 
    2697             : NS_IMETHODIMP
    2698           0 : HttpBaseChannel::GetCorsMode(uint32_t* aMode)
    2699             : {
    2700           0 :   *aMode = mCorsMode;
    2701           0 :   return NS_OK;
    2702             : }
    2703             : 
    2704             : NS_IMETHODIMP
    2705           0 : HttpBaseChannel::SetCorsMode(uint32_t aMode)
    2706             : {
    2707           0 :   mCorsMode = aMode;
    2708           0 :   return NS_OK;
    2709             : }
    2710             : 
    2711             : NS_IMETHODIMP
    2712           0 : HttpBaseChannel::GetRedirectMode(uint32_t* aMode)
    2713             : {
    2714           0 :   *aMode = mRedirectMode;
    2715           0 :   return NS_OK;
    2716             : }
    2717             : 
    2718             : NS_IMETHODIMP
    2719           1 : HttpBaseChannel::SetRedirectMode(uint32_t aMode)
    2720             : {
    2721           1 :   mRedirectMode = aMode;
    2722           1 :   return NS_OK;
    2723             : }
    2724             : 
    2725             : NS_IMETHODIMP
    2726           0 : HttpBaseChannel::GetFetchCacheMode(uint32_t* aFetchCacheMode)
    2727             : {
    2728           0 :   NS_ENSURE_ARG_POINTER(aFetchCacheMode);
    2729             : 
    2730             :   // If the fetch cache mode is overriden, then use it directly.
    2731           0 :   if (mFetchCacheMode != nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT) {
    2732           0 :     *aFetchCacheMode = mFetchCacheMode;
    2733           0 :     return NS_OK;
    2734             :   }
    2735             : 
    2736             :   // Otherwise try to guess an appropriate cache mode from the load flags.
    2737           0 :   if (mLoadFlags & (INHIBIT_CACHING | LOAD_BYPASS_CACHE)) {
    2738           0 :     *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_STORE;
    2739           0 :   } else if (mLoadFlags & LOAD_BYPASS_CACHE) {
    2740           0 :     *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_RELOAD;
    2741           0 :   } else if (mLoadFlags & VALIDATE_ALWAYS) {
    2742           0 :     *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE;
    2743           0 :   } else if (mLoadFlags & (LOAD_FROM_CACHE | nsICachingChannel::LOAD_ONLY_FROM_CACHE)) {
    2744           0 :     *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED;
    2745           0 :   } else if (mLoadFlags & LOAD_FROM_CACHE) {
    2746           0 :     *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_FORCE_CACHE;
    2747             :   } else {
    2748           0 :     *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT;
    2749             :   }
    2750             : 
    2751           0 :   return NS_OK;
    2752             : }
    2753             : 
    2754             : NS_IMETHODIMP
    2755           0 : HttpBaseChannel::SetFetchCacheMode(uint32_t aFetchCacheMode)
    2756             : {
    2757           0 :   ENSURE_CALLED_BEFORE_CONNECT();
    2758           0 :   MOZ_ASSERT(mFetchCacheMode == nsIHttpChannelInternal::FETCH_CACHE_MODE_DEFAULT,
    2759             :              "SetFetchCacheMode() should only be called once per channel");
    2760             : 
    2761           0 :   mFetchCacheMode = aFetchCacheMode;
    2762             : 
    2763             :   // Now, set the load flags that implement each cache mode.
    2764           0 :   switch (mFetchCacheMode) {
    2765             :   case nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_STORE:
    2766             :     // no-store means don't consult the cache on the way to the network, and
    2767             :     // don't store the response in the cache even if it's cacheable.
    2768           0 :     mLoadFlags |= INHIBIT_CACHING | LOAD_BYPASS_CACHE;
    2769           0 :     break;
    2770             :   case nsIHttpChannelInternal::FETCH_CACHE_MODE_RELOAD:
    2771             :     // reload means don't consult the cache on the way to the network, but
    2772             :     // do store the response in the cache if possible.
    2773           0 :     mLoadFlags |= LOAD_BYPASS_CACHE;
    2774           0 :     break;
    2775             :   case nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE:
    2776             :     // no-cache means always validate what's in the cache.
    2777           0 :     mLoadFlags |= VALIDATE_ALWAYS;
    2778           0 :     break;
    2779             :   case nsIHttpChannelInternal::FETCH_CACHE_MODE_FORCE_CACHE:
    2780             :     // force-cache means don't validate unless if the response would vary.
    2781           0 :     mLoadFlags |= LOAD_FROM_CACHE;
    2782           0 :     break;
    2783             :   case nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED:
    2784             :     // only-if-cached means only from cache, no network, no validation, generate
    2785             :     // a network error if the document was't in the cache.
    2786             :     // The privacy implications of these flags (making it fast/easy to check if
    2787             :     // the user has things in their cache without any network traffic side
    2788             :     // effects) are addressed in the Request constructor which enforces/requires
    2789             :     // same-origin request mode.
    2790           0 :     mLoadFlags |= LOAD_FROM_CACHE | nsICachingChannel::LOAD_ONLY_FROM_CACHE;
    2791           0 :     break;
    2792             :   }
    2793             : 
    2794           0 :   return NS_OK;
    2795             : }
    2796             : 
    2797             : NS_IMETHODIMP
    2798           2 : HttpBaseChannel::SetIntegrityMetadata(const nsAString& aIntegrityMetadata)
    2799             : {
    2800           2 :   mIntegrityMetadata = aIntegrityMetadata;
    2801           2 :   return NS_OK;
    2802             : }
    2803             : 
    2804             : NS_IMETHODIMP
    2805           0 : HttpBaseChannel::GetIntegrityMetadata(nsAString& aIntegrityMetadata)
    2806             : {
    2807           0 :   aIntegrityMetadata = mIntegrityMetadata;
    2808           0 :   return NS_OK;
    2809             : }
    2810             : 
    2811             : //-----------------------------------------------------------------------------
    2812             : // HttpBaseChannel::nsISupportsPriority
    2813             : //-----------------------------------------------------------------------------
    2814             : 
    2815             : NS_IMETHODIMP
    2816           0 : HttpBaseChannel::GetPriority(int32_t *value)
    2817             : {
    2818           0 :   *value = mPriority;
    2819           0 :   return NS_OK;
    2820             : }
    2821             : 
    2822             : NS_IMETHODIMP
    2823           2 : HttpBaseChannel::AdjustPriority(int32_t delta)
    2824             : {
    2825           2 :   return SetPriority(mPriority + delta);
    2826             : }
    2827             : 
    2828             : //-----------------------------------------------------------------------------
    2829             : // HttpBaseChannel::nsIResumableChannel
    2830             : //-----------------------------------------------------------------------------
    2831             : 
    2832             : NS_IMETHODIMP
    2833           0 : HttpBaseChannel::GetEntityID(nsACString& aEntityID)
    2834             : {
    2835             :   // Don't return an entity ID for Non-GET requests which require
    2836             :   // additional data
    2837           0 :   if (!mRequestHead.IsGet()) {
    2838           0 :     return NS_ERROR_NOT_RESUMABLE;
    2839             :   }
    2840             : 
    2841           0 :   uint64_t size = UINT64_MAX;
    2842           0 :   nsAutoCString etag, lastmod;
    2843           0 :   if (mResponseHead) {
    2844             :     // Don't return an entity if the server sent the following header:
    2845             :     // Accept-Ranges: none
    2846             :     // Not sending the Accept-Ranges header means we can still try
    2847             :     // sending range requests.
    2848           0 :     nsAutoCString acceptRanges;
    2849           0 :     Unused << mResponseHead->GetHeader(nsHttp::Accept_Ranges, acceptRanges);
    2850           0 :     if (!acceptRanges.IsEmpty() &&
    2851           0 :         !nsHttp::FindToken(acceptRanges.get(), "bytes", HTTP_HEADER_VALUE_SEPS)) {
    2852           0 :       return NS_ERROR_NOT_RESUMABLE;
    2853             :     }
    2854             : 
    2855           0 :     size = mResponseHead->TotalEntitySize();
    2856           0 :     Unused << mResponseHead->GetHeader(nsHttp::Last_Modified, lastmod);
    2857           0 :     Unused << mResponseHead->GetHeader(nsHttp::ETag, etag);
    2858             :   }
    2859           0 :   nsCString entityID;
    2860           0 :   NS_EscapeURL(etag.BeginReading(), etag.Length(), esc_AlwaysCopy |
    2861           0 :                esc_FileBaseName | esc_Forced, entityID);
    2862           0 :   entityID.Append('/');
    2863           0 :   entityID.AppendInt(int64_t(size));
    2864           0 :   entityID.Append('/');
    2865           0 :   entityID.Append(lastmod);
    2866             :   // NOTE: Appending lastmod as the last part avoids having to escape it
    2867             : 
    2868           0 :   aEntityID = entityID;
    2869             : 
    2870           0 :   return NS_OK;
    2871             : }
    2872             : 
    2873             : //-----------------------------------------------------------------------------
    2874             : // HttpBaseChannel::nsIConsoleReportCollector
    2875             : //-----------------------------------------------------------------------------
    2876             : 
    2877             : void
    2878           0 : HttpBaseChannel::AddConsoleReport(uint32_t aErrorFlags,
    2879             :                                   const nsACString& aCategory,
    2880             :                                   nsContentUtils::PropertiesFile aPropertiesFile,
    2881             :                                   const nsACString& aSourceFileURI,
    2882             :                                   uint32_t aLineNumber, uint32_t aColumnNumber,
    2883             :                                   const nsACString& aMessageName,
    2884             :                                   const nsTArray<nsString>& aStringParams)
    2885             : {
    2886           0 :   mReportCollector->AddConsoleReport(aErrorFlags, aCategory, aPropertiesFile,
    2887             :                                      aSourceFileURI, aLineNumber,
    2888             :                                      aColumnNumber, aMessageName,
    2889           0 :                                      aStringParams);
    2890           0 : }
    2891             : 
    2892             : void
    2893           0 : HttpBaseChannel::FlushReportsToConsole(uint64_t aInnerWindowID,
    2894             :                                        ReportAction aAction)
    2895             : {
    2896           0 :   mReportCollector->FlushReportsToConsole(aInnerWindowID, aAction);
    2897           0 : }
    2898             : 
    2899             : void
    2900           0 : HttpBaseChannel::FlushConsoleReports(nsIDocument* aDocument,
    2901             :                                      ReportAction aAction)
    2902             : {
    2903           0 :   mReportCollector->FlushConsoleReports(aDocument, aAction);
    2904           0 : }
    2905             : 
    2906             : void
    2907           1 : HttpBaseChannel::FlushConsoleReports(nsILoadGroup* aLoadGroup,
    2908             :                                      ReportAction aAction)
    2909             : {
    2910           1 :   mReportCollector->FlushConsoleReports(aLoadGroup, aAction);
    2911           1 : }
    2912             : 
    2913             : void
    2914           0 : HttpBaseChannel::FlushConsoleReports(nsIConsoleReportCollector* aCollector)
    2915             : {
    2916           0 :   mReportCollector->FlushConsoleReports(aCollector);
    2917           0 : }
    2918             : 
    2919             : void
    2920           0 : HttpBaseChannel::ClearConsoleReports()
    2921             : {
    2922           0 :   mReportCollector->ClearConsoleReports();
    2923           0 : }
    2924             : 
    2925             : nsIPrincipal *
    2926           0 : HttpBaseChannel::GetURIPrincipal()
    2927             : {
    2928           0 :   if (mPrincipal) {
    2929           0 :       return mPrincipal;
    2930             :   }
    2931             : 
    2932             :   nsIScriptSecurityManager *securityManager =
    2933           0 :       nsContentUtils::GetSecurityManager();
    2934             : 
    2935           0 :   if (!securityManager) {
    2936           0 :       LOG(("HttpBaseChannel::GetURIPrincipal: No security manager [this=%p]",
    2937             :            this));
    2938           0 :       return nullptr;
    2939             :   }
    2940             : 
    2941           0 :   securityManager->GetChannelURIPrincipal(this, getter_AddRefs(mPrincipal));
    2942           0 :   if (!mPrincipal) {
    2943           0 :       LOG(("HttpBaseChannel::GetURIPrincipal: No channel principal [this=%p]",
    2944             :            this));
    2945           0 :       return nullptr;
    2946             :   }
    2947             : 
    2948           0 :   return mPrincipal;
    2949             : }
    2950             : 
    2951             : bool
    2952           0 : HttpBaseChannel::IsNavigation()
    2953             : {
    2954           0 :   return mForceMainDocumentChannel;
    2955             : }
    2956             : 
    2957             : bool
    2958           7 : HttpBaseChannel::BypassServiceWorker() const
    2959             : {
    2960           7 :   return mLoadFlags & LOAD_BYPASS_SERVICE_WORKER;
    2961             : }
    2962             : 
    2963             : bool
    2964           9 : HttpBaseChannel::ShouldIntercept(nsIURI* aURI)
    2965             : {
    2966          18 :   nsCOMPtr<nsINetworkInterceptController> controller;
    2967           9 :   GetCallback(controller);
    2968           9 :   bool shouldIntercept = false;
    2969             : 
    2970             :   // We should never intercept internal redirects.  The ServiceWorker code
    2971             :   // can trigger interntal redirects as the result of a FetchEvent.  If
    2972             :   // we re-intercept then an infinite loop can occur.
    2973             :   //
    2974             :   // Its also important that we do not set the LOAD_BYPASS_SERVICE_WORKER
    2975             :   // flag because an internal redirect occurs.  Its possible that another
    2976             :   // interception should occur after the internal redirect.  For example,
    2977             :   // if the ServiceWorker chooses not to call respondWith() the channel
    2978             :   // will be reset with an internal redirect.  If the request is a navigation
    2979             :   // and the network then triggers a redirect its possible the new URL
    2980             :   // should be intercepted again.
    2981             :   //
    2982             :   // Note, HSTS upgrade redirects are often treated the same as internal
    2983             :   // redirects.  In this case, however, we intentionally allow interception
    2984             :   // of HSTS upgrade redirects.  This matches the expected spec behavior and
    2985             :   // does not run the risk of infinite loops as described above.
    2986           9 :   bool internalRedirect = mLastRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL;
    2987             : 
    2988           9 :   if (controller && mLoadInfo && !BypassServiceWorker() && !internalRedirect) {
    2989           8 :     nsresult rv = controller->ShouldPrepareForIntercept(aURI ? aURI : mURI.get(),
    2990           4 :                                                         nsContentUtils::IsNonSubresourceRequest(this),
    2991           8 :                                                         &shouldIntercept);
    2992           4 :     if (NS_FAILED(rv)) {
    2993           0 :       return false;
    2994             :     }
    2995             :   }
    2996           9 :   return shouldIntercept;
    2997             : }
    2998             : 
    2999             : #ifdef DEBUG
    3000           9 : void HttpBaseChannel::AssertPrivateBrowsingId()
    3001             : {
    3002          15 :   nsCOMPtr<nsILoadContext> loadContext;
    3003           9 :   NS_QueryNotificationCallbacks(this, loadContext);
    3004             :   // For addons it's possible that mLoadInfo is null.
    3005           9 :   if (!mLoadInfo) {
    3006           0 :     return;
    3007             :   }
    3008             : 
    3009           9 :   if (!loadContext) {
    3010           2 :     return;
    3011             :   }
    3012             : 
    3013             :   // We skip testing of favicon loading here since it could be triggered by XUL image
    3014             :   // which uses SystemPrincipal. The SystemPrincpal doesn't have mPrivateBrowsingId.
    3015           8 :   if (nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal()) &&
    3016           1 :       mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
    3017           1 :     return;
    3018             :   }
    3019             : 
    3020          12 :   OriginAttributes docShellAttrs;
    3021           6 :   loadContext->GetOriginAttributes(docShellAttrs);
    3022           6 :   MOZ_ASSERT(mLoadInfo->GetOriginAttributes().mPrivateBrowsingId == docShellAttrs.mPrivateBrowsingId,
    3023             :              "PrivateBrowsingId values are not the same between LoadInfo and LoadContext.");
    3024             : }
    3025             : #endif
    3026             : 
    3027             : already_AddRefed<nsILoadInfo>
    3028           0 : HttpBaseChannel::CloneLoadInfoForRedirect(nsIURI * newURI, uint32_t redirectFlags)
    3029             : {
    3030             :   // make a copy of the loadinfo, append to the redirectchain
    3031             :   // this will be set on the newly created channel for the redirect target.
    3032           0 :   if (!mLoadInfo) {
    3033           0 :     return nullptr;
    3034             :   }
    3035             : 
    3036             :   nsCOMPtr<nsILoadInfo> newLoadInfo =
    3037           0 :     static_cast<mozilla::LoadInfo*>(mLoadInfo.get())->Clone();
    3038             : 
    3039           0 :   nsContentPolicyType contentPolicyType = mLoadInfo->GetExternalContentPolicyType();
    3040           0 :   if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
    3041             :       contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
    3042           0 :     nsCOMPtr<nsIPrincipal> nullPrincipalToInherit = NullPrincipal::Create();
    3043           0 :     newLoadInfo->SetPrincipalToInherit(nullPrincipalToInherit);
    3044             :   }
    3045             : 
    3046             :   // re-compute the origin attributes of the loadInfo if it's top-level load.
    3047             :   bool isTopLevelDoc =
    3048           0 :     newLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT;
    3049             : 
    3050           0 :   if (isTopLevelDoc) {
    3051           0 :     nsCOMPtr<nsILoadContext> loadContext;
    3052           0 :     NS_QueryNotificationCallbacks(this, loadContext);
    3053           0 :     OriginAttributes docShellAttrs;
    3054           0 :     if (loadContext) {
    3055           0 :       loadContext->GetOriginAttributes(docShellAttrs);
    3056             :     }
    3057             : 
    3058           0 :     OriginAttributes attrs = newLoadInfo->GetOriginAttributes();
    3059             : 
    3060           0 :     MOZ_ASSERT(docShellAttrs.mUserContextId == attrs.mUserContextId,
    3061             :                 "docshell and necko should have the same userContextId attribute.");
    3062           0 :     MOZ_ASSERT(docShellAttrs.mInIsolatedMozBrowser == attrs.mInIsolatedMozBrowser,
    3063             :                 "docshell and necko should have the same inIsolatedMozBrowser attribute.");
    3064           0 :     MOZ_ASSERT(docShellAttrs.mPrivateBrowsingId == attrs.mPrivateBrowsingId,
    3065             :                 "docshell and necko should have the same privateBrowsingId attribute.");
    3066             : 
    3067           0 :     attrs = docShellAttrs;
    3068           0 :     attrs.SetFirstPartyDomain(true, newURI);
    3069           0 :     newLoadInfo->SetOriginAttributes(attrs);
    3070             :   }
    3071             : 
    3072             :   // Leave empty, we want a 'clean ground' when creating the new channel.
    3073             :   // This will be ensured to be either set by the protocol handler or set
    3074             :   // to the redirect target URI properly after the channel creation.
    3075           0 :   newLoadInfo->SetResultPrincipalURI(nullptr);
    3076             : 
    3077             :   bool isInternalRedirect =
    3078           0 :     (redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
    3079           0 :                       nsIChannelEventSink::REDIRECT_STS_UPGRADE));
    3080             : 
    3081           0 :   nsCString remoteAddress;
    3082           0 :   Unused << GetRemoteAddress(remoteAddress);
    3083             :   nsCOMPtr<nsIRedirectHistoryEntry> entry =
    3084           0 :     new nsRedirectHistoryEntry(GetURIPrincipal(), mReferrer, remoteAddress);
    3085             : 
    3086           0 :   newLoadInfo->AppendRedirectHistoryEntry(entry, isInternalRedirect);
    3087             : 
    3088           0 :   return newLoadInfo.forget();
    3089             : }
    3090             : 
    3091             : //-----------------------------------------------------------------------------
    3092             : // nsHttpChannel::nsITraceableChannel
    3093             : //-----------------------------------------------------------------------------
    3094             : 
    3095             : NS_IMETHODIMP
    3096           0 : HttpBaseChannel::SetNewListener(nsIStreamListener *aListener, nsIStreamListener **_retval)
    3097             : {
    3098           0 :   LOG(("HttpBaseChannel::SetNewListener [this=%p, mListener=%p, newListener=%p]",
    3099             :        this, mListener.get(), aListener));
    3100             : 
    3101           0 :   if (!mTracingEnabled)
    3102           0 :     return NS_ERROR_FAILURE;
    3103             : 
    3104           0 :   NS_ENSURE_STATE(mListener);
    3105           0 :   NS_ENSURE_ARG_POINTER(aListener);
    3106             : 
    3107           0 :   nsCOMPtr<nsIStreamListener> wrapper = new nsStreamListenerWrapper(mListener);
    3108             : 
    3109           0 :   wrapper.forget(_retval);
    3110           0 :   mListener = aListener;
    3111           0 :   return NS_OK;
    3112             : }
    3113             : 
    3114             : //-----------------------------------------------------------------------------
    3115             : // HttpBaseChannel helpers
    3116             : //-----------------------------------------------------------------------------
    3117             : 
    3118             : void
    3119           9 : HttpBaseChannel::ReleaseListeners()
    3120             : {
    3121           9 :   MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
    3122             : 
    3123           9 :   mListener = nullptr;
    3124           9 :   mListenerContext = nullptr;
    3125           9 :   mCallbacks = nullptr;
    3126           9 :   mProgressSink = nullptr;
    3127           9 :   mCompressListener = nullptr;
    3128           9 : }
    3129             : 
    3130             : void
    3131           0 : HttpBaseChannel::DoNotifyListener()
    3132             : {
    3133           0 :   LOG(("HttpBaseChannel::DoNotifyListener this=%p", this));
    3134             : 
    3135           0 :   if (mListener) {
    3136           0 :     MOZ_ASSERT(!mOnStartRequestCalled,
    3137             :                "We should not call OnStartRequest twice");
    3138             : 
    3139           0 :     nsCOMPtr<nsIStreamListener> listener = mListener;
    3140           0 :     listener->OnStartRequest(this, mListenerContext);
    3141             : 
    3142           0 :     mOnStartRequestCalled = true;
    3143             :   }
    3144             : 
    3145             :   // Make sure mIsPending is set to false. At this moment we are done from
    3146             :   // the point of view of our consumer and we have to report our self
    3147             :   // as not-pending.
    3148           0 :   mIsPending = false;
    3149             : 
    3150           0 :   if (mListener) {
    3151           0 :     MOZ_ASSERT(!mOnStopRequestCalled,
    3152             :                "We should not call OnStopRequest twice");
    3153             : 
    3154           0 :     nsCOMPtr<nsIStreamListener> listener = mListener;
    3155           0 :     listener->OnStopRequest(this, mListenerContext, mStatus);
    3156             : 
    3157           0 :     mOnStopRequestCalled = true;
    3158             :   }
    3159             : 
    3160             :   // We have to make sure to drop the references to listeners and callbacks
    3161             :   // no longer  needed
    3162           0 :   ReleaseListeners();
    3163             : 
    3164           0 :   DoNotifyListenerCleanup();
    3165             : 
    3166             :   // If this is a navigation, then we must let the docshell flush the reports
    3167             :   // to the console later.  The LoadDocument() is pointing at the detached
    3168             :   // document that started the navigation.  We want to show the reports on the
    3169             :   // new document.  Otherwise the console is wiped and the user never sees
    3170             :   // the information.
    3171           0 :   if (!IsNavigation()) {
    3172           0 :     if (mLoadGroup) {
    3173           0 :       FlushConsoleReports(mLoadGroup);
    3174           0 :     } else if (mLoadInfo) {
    3175           0 :       nsCOMPtr<nsIDOMDocument> dommyDoc;
    3176           0 :       mLoadInfo->GetLoadingDocument(getter_AddRefs(dommyDoc));
    3177           0 :       nsCOMPtr<nsIDocument> doc = do_QueryInterface(dommyDoc);
    3178           0 :       FlushConsoleReports(doc);
    3179             :     }
    3180             :   }
    3181           0 : }
    3182             : 
    3183             : void
    3184           9 : HttpBaseChannel::AddCookiesToRequest()
    3185             : {
    3186           9 :   if (mLoadFlags & LOAD_ANONYMOUS) {
    3187           0 :     return;
    3188             :   }
    3189             : 
    3190             :   bool useCookieService =
    3191           9 :     (XRE_IsParentProcess());
    3192          18 :   nsXPIDLCString cookie;
    3193           9 :   if (useCookieService) {
    3194           6 :     nsICookieService *cs = gHttpHandler->GetCookieService();
    3195           6 :     if (cs) {
    3196           6 :       cs->GetCookieStringFromHttp(mURI,
    3197             :                                   nullptr,
    3198          12 :                                   this, getter_Copies(cookie));
    3199             :     }
    3200             : 
    3201           6 :     if (cookie.IsEmpty()) {
    3202           6 :       cookie = mUserSetCookieHeader;
    3203             :     }
    3204           0 :     else if (!mUserSetCookieHeader.IsEmpty()) {
    3205           0 :       cookie.AppendLiteral("; ");
    3206           0 :       cookie.Append(mUserSetCookieHeader);
    3207             :     }
    3208             :   }
    3209             :   else {
    3210           3 :     cookie = mUserSetCookieHeader;
    3211             :   }
    3212             : 
    3213             :   // If we are in the child process, we want the parent seeing any
    3214             :   // cookie headers that might have been set by SetRequestHeader()
    3215           9 :   SetRequestHeader(nsDependentCString(nsHttp::Cookie), cookie, false);
    3216             : }
    3217             : 
    3218             : bool
    3219           0 : HttpBaseChannel::ShouldRewriteRedirectToGET(uint32_t httpStatus,
    3220             :                                             nsHttpRequestHead::ParsedMethodType method)
    3221             : {
    3222             :   // for 301 and 302, only rewrite POST
    3223           0 :   if (httpStatus == 301 || httpStatus == 302)
    3224           0 :     return method == nsHttpRequestHead::kMethod_Post;
    3225             : 
    3226             :   // rewrite for 303 unless it was HEAD
    3227           0 :   if (httpStatus == 303)
    3228           0 :     return method != nsHttpRequestHead::kMethod_Head;
    3229             : 
    3230             :   // otherwise, such as for 307, do not rewrite
    3231           0 :   return false;
    3232             : }
    3233             : 
    3234             : nsresult
    3235           0 : HttpBaseChannel::SetupReplacementChannel(nsIURI       *newURI,
    3236             :                                          nsIChannel   *newChannel,
    3237             :                                          bool          preserveMethod,
    3238             :                                          uint32_t      redirectFlags)
    3239             : {
    3240             :   nsresult rv;
    3241             : 
    3242           0 :   LOG(("HttpBaseChannel::SetupReplacementChannel "
    3243             :      "[this=%p newChannel=%p preserveMethod=%d]",
    3244             :      this, newChannel, preserveMethod));
    3245             : 
    3246             :   // Ensure the channel's loadInfo's result principal URI so that it's
    3247             :   // either non-null or updated to the redirect target URI.
    3248             :   // We must do this because in case the loadInfo's result principal URI
    3249             :   // is null, it would be taken from OriginalURI of the channel.  But we
    3250             :   // overwrite it with the whole redirect chain first URI before opening
    3251             :   // the target channel, hence the information would be lost.
    3252             :   // If the protocol handler that created the channel wants to use
    3253             :   // the originalURI of the channel as the principal URI, this fulfills
    3254             :   // that request - newURI is the original URI of the channel.
    3255           0 :   nsCOMPtr<nsILoadInfo> newLoadInfo = newChannel->GetLoadInfo();
    3256           0 :   if (newLoadInfo) {
    3257           0 :     nsCOMPtr<nsIURI> resultPrincipalURI;
    3258           0 :     rv = newLoadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
    3259           0 :     NS_ENSURE_SUCCESS(rv, rv);
    3260             : 
    3261           0 :     if (!resultPrincipalURI) {
    3262           0 :       rv = newLoadInfo->SetResultPrincipalURI(newURI);
    3263           0 :       NS_ENSURE_SUCCESS(rv, rv);
    3264             :     }
    3265             :   }
    3266             : 
    3267           0 :   uint32_t newLoadFlags = mLoadFlags | LOAD_REPLACE;
    3268             :   // if the original channel was using SSL and this channel is not using
    3269             :   // SSL, then no need to inhibit persistent caching.  however, if the
    3270             :   // original channel was not using SSL and has INHIBIT_PERSISTENT_CACHING
    3271             :   // set, then allow the flag to apply to the redirected channel as well.
    3272             :   // since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
    3273             :   // we only need to check if the original channel was using SSL.
    3274           0 :   bool usingSSL = false;
    3275           0 :   rv = mURI->SchemeIs("https", &usingSSL);
    3276           0 :   if (NS_SUCCEEDED(rv) && usingSSL)
    3277           0 :     newLoadFlags &= ~INHIBIT_PERSISTENT_CACHING;
    3278             : 
    3279             :   // Do not pass along LOAD_CHECK_OFFLINE_CACHE
    3280           0 :   newLoadFlags &= ~nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE;
    3281             : 
    3282           0 :   newChannel->SetLoadGroup(mLoadGroup);
    3283           0 :   newChannel->SetNotificationCallbacks(mCallbacks);
    3284           0 :   newChannel->SetLoadFlags(newLoadFlags);
    3285             : 
    3286           0 :   nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(newChannel));
    3287           0 :   if (cos) {
    3288           0 :     cos->SetClassFlags(mClassOfService);
    3289             :   }
    3290             : 
    3291             :   // Try to preserve the privacy bit if it has been overridden
    3292           0 :   if (mPrivateBrowsingOverriden) {
    3293             :     nsCOMPtr<nsIPrivateBrowsingChannel> newPBChannel =
    3294           0 :       do_QueryInterface(newChannel);
    3295           0 :     if (newPBChannel) {
    3296           0 :       newPBChannel->SetPrivate(mPrivateBrowsing);
    3297             :     }
    3298             :   }
    3299             : 
    3300           0 :   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
    3301           0 :   if (!httpChannel)
    3302           0 :     return NS_OK; // no other options to set
    3303             : 
    3304             :   // Preserve the CORS preflight information.
    3305           0 :   nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(newChannel);
    3306           0 :   if (httpInternal) {
    3307           0 :     httpInternal->SetLastRedirectFlags(redirectFlags);
    3308             : 
    3309           0 :     if (mRequireCORSPreflight) {
    3310           0 :       httpInternal->SetCorsPreflightParameters(mUnsafeHeaders);
    3311             :     }
    3312             :   }
    3313             : 
    3314           0 :   if (preserveMethod) {
    3315             :     nsCOMPtr<nsIUploadChannel> uploadChannel =
    3316           0 :       do_QueryInterface(httpChannel);
    3317             :     nsCOMPtr<nsIUploadChannel2> uploadChannel2 =
    3318           0 :       do_QueryInterface(httpChannel);
    3319           0 :     if (mUploadStream && (uploadChannel2 || uploadChannel)) {
    3320             :       // rewind upload stream
    3321           0 :       nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
    3322           0 :       if (seekable)
    3323           0 :         seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
    3324             : 
    3325             :       // replicate original call to SetUploadStream...
    3326           0 :       if (uploadChannel2) {
    3327           0 :         nsAutoCString ctype;
    3328             :         // If header is not present mRequestHead.HasHeaderValue will truncated
    3329             :         // it.  But we want to end up with a void string, not an empty string,
    3330             :         // because ExplicitSetUploadStream treats the former as "no header" and
    3331             :         // the latter as "header with empty string value".
    3332           0 :         nsresult ctypeOK = mRequestHead.GetHeader(nsHttp::Content_Type, ctype);
    3333           0 :         if (NS_FAILED(ctypeOK)) {
    3334           0 :           ctype.SetIsVoid(true);
    3335             :         }
    3336           0 :         nsAutoCString clen;
    3337           0 :         Unused << mRequestHead.GetHeader(nsHttp::Content_Length, clen);
    3338           0 :         nsAutoCString method;
    3339           0 :         mRequestHead.Method(method);
    3340           0 :         int64_t len = clen.IsEmpty() ? -1 : nsCRT::atoll(clen.get());
    3341           0 :         uploadChannel2->ExplicitSetUploadStream(
    3342             :                                   mUploadStream, ctype, len,
    3343             :                                   method,
    3344           0 :                                   mUploadStreamHasHeaders);
    3345             :       } else {
    3346           0 :         if (mUploadStreamHasHeaders) {
    3347           0 :           uploadChannel->SetUploadStream(mUploadStream, EmptyCString(),
    3348           0 :                            -1);
    3349             :         } else {
    3350           0 :           nsAutoCString ctype;
    3351           0 :           if (NS_FAILED(mRequestHead.GetHeader(nsHttp::Content_Type, ctype))) {
    3352           0 :             ctype =  NS_LITERAL_CSTRING("application/octet-stream");
    3353             :           }
    3354           0 :           nsAutoCString clen;
    3355           0 :           if (NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::Content_Length, clen))
    3356           0 :               &&
    3357           0 :               !clen.IsEmpty()) {
    3358           0 :             uploadChannel->SetUploadStream(mUploadStream,
    3359             :                                            ctype,
    3360           0 :                                            nsCRT::atoll(clen.get()));
    3361             :           }
    3362             :         }
    3363             :       }
    3364             :     }
    3365             :     // since preserveMethod is true, we need to ensure that the appropriate
    3366             :     // request method gets set on the channel, regardless of whether or not
    3367             :     // we set the upload stream above. This means SetRequestMethod() will
    3368             :     // be called twice if ExplicitSetUploadStream() gets called above.
    3369             : 
    3370           0 :     nsAutoCString method;
    3371           0 :     mRequestHead.Method(method);
    3372           0 :     rv = httpChannel->SetRequestMethod(method);
    3373           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3374             :   }
    3375             :   // convey the referrer if one was used for this channel to the next one
    3376           0 :   if (mReferrer) {
    3377           0 :     rv = httpChannel->SetReferrerWithPolicy(mReferrer, mReferrerPolicy);
    3378           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3379             :   }
    3380             :   // convey the mAllowSTS flags
    3381           0 :   rv = httpChannel->SetAllowSTS(mAllowSTS);
    3382           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    3383             :   // convey the new redirection limit
    3384             :   // make sure we don't underflow
    3385           0 :   uint32_t redirectionLimit = mRedirectionLimit
    3386           0 :     ? mRedirectionLimit - 1
    3387           0 :     : 0;
    3388           0 :   rv = httpChannel->SetRedirectionLimit(redirectionLimit);
    3389           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    3390             : 
    3391             :   // convey the Accept header value
    3392             :   {
    3393           0 :     nsAutoCString oldAcceptValue;
    3394           0 :     nsresult hasHeader = mRequestHead.GetHeader(nsHttp::Accept, oldAcceptValue);
    3395           0 :     if (NS_SUCCEEDED(hasHeader)) {
    3396           0 :       rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
    3397             :                                          oldAcceptValue,
    3398           0 :                                          false);
    3399           0 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
    3400             :     }
    3401             :   }
    3402             : 
    3403             :   // share the request context - see bug 1236650
    3404           0 :   rv = httpChannel->SetRequestContextID(mRequestContextID);
    3405           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    3406             : 
    3407             :   // When on the parent process, the channel can't attempt to get it itself.
    3408             :   // When on the child process, it would be waste to query it again.
    3409           0 :   rv = httpChannel->SetTopLevelOuterContentWindowId(mTopLevelOuterContentWindowId);
    3410           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    3411             : 
    3412             :   // Preserve the loading order
    3413           0 :   nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(newChannel);
    3414           0 :   if (p) {
    3415           0 :     p->SetPriority(mPriority);
    3416             :   }
    3417             : 
    3418           0 :   if (httpInternal) {
    3419             :     // Convey third party cookie, conservative, and spdy flags.
    3420           0 :     rv = httpInternal->SetThirdPartyFlags(mThirdPartyFlags);
    3421           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3422           0 :     rv = httpInternal->SetAllowSpdy(mAllowSpdy);
    3423           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3424           0 :     rv = httpInternal->SetAllowAltSvc(mAllowAltSvc);
    3425           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3426           0 :     rv = httpInternal->SetBeConservative(mBeConservative);
    3427           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3428             : 
    3429           0 :     RefPtr<nsHttpChannel> realChannel;
    3430           0 :     CallQueryInterface(newChannel, realChannel.StartAssignment());
    3431           0 :     if (realChannel) {
    3432           0 :       rv = realChannel->SetTopWindowURI(mTopWindowURI);
    3433           0 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
    3434             :     }
    3435             : 
    3436             :     // update the DocumentURI indicator since we are being redirected.
    3437             :     // if this was a top-level document channel, then the new channel
    3438             :     // should have its mDocumentURI point to newURI; otherwise, we
    3439             :     // just need to pass along our mDocumentURI to the new channel.
    3440           0 :     if (newURI && (mURI == mDocumentURI))
    3441           0 :       rv = httpInternal->SetDocumentURI(newURI);
    3442             :     else
    3443           0 :       rv = httpInternal->SetDocumentURI(mDocumentURI);
    3444           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3445             : 
    3446             :     // if there is a chain of keys for redirect-responses we transfer it to
    3447             :     // the new channel (see bug #561276)
    3448           0 :     if (mRedirectedCachekeys) {
    3449           0 :         LOG(("HttpBaseChannel::SetupReplacementChannel "
    3450             :              "[this=%p] transferring chain of redirect cache-keys", this));
    3451           0 :         rv = httpInternal->SetCacheKeysRedirectChain(mRedirectedCachekeys.forget());
    3452           0 :         MOZ_ASSERT(NS_SUCCEEDED(rv));
    3453             :     }
    3454             : 
    3455             :     // Preserve CORS mode flag.
    3456           0 :     rv = httpInternal->SetCorsMode(mCorsMode);
    3457           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3458             : 
    3459             :     // Preserve Redirect mode flag.
    3460           0 :     rv = httpInternal->SetRedirectMode(mRedirectMode);
    3461           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3462             : 
    3463             :     // Preserve Cache mode flag.
    3464           0 :     rv = httpInternal->SetFetchCacheMode(mFetchCacheMode);
    3465           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3466             : 
    3467             :     // Preserve Integrity metadata.
    3468           0 :     rv = httpInternal->SetIntegrityMetadata(mIntegrityMetadata);
    3469           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3470             :   }
    3471             : 
    3472             :   // transfer application cache information
    3473             :   nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
    3474           0 :     do_QueryInterface(newChannel);
    3475           0 :   if (appCacheChannel) {
    3476           0 :     appCacheChannel->SetApplicationCache(mApplicationCache);
    3477           0 :     appCacheChannel->SetInheritApplicationCache(mInheritApplicationCache);
    3478             :     // We purposely avoid transfering mChooseApplicationCache.
    3479             :   }
    3480             : 
    3481             :   // transfer any properties
    3482           0 :   nsCOMPtr<nsIWritablePropertyBag> bag(do_QueryInterface(newChannel));
    3483           0 :   if (bag) {
    3484           0 :     for (auto iter = mPropertyHash.Iter(); !iter.Done(); iter.Next()) {
    3485           0 :       bag->SetProperty(iter.Key(), iter.UserData());
    3486             :     }
    3487             :   }
    3488             : 
    3489             :   // Transfer the timing data (if we are dealing with an nsITimedChannel).
    3490           0 :   nsCOMPtr<nsITimedChannel> newTimedChannel(do_QueryInterface(newChannel));
    3491             :   nsCOMPtr<nsITimedChannel> oldTimedChannel(
    3492           0 :       do_QueryInterface(static_cast<nsIHttpChannel*>(this)));
    3493           0 :   if (oldTimedChannel && newTimedChannel) {
    3494           0 :     newTimedChannel->SetTimingEnabled(mTimingEnabled);
    3495           0 :     newTimedChannel->SetRedirectCount(mRedirectCount + 1);
    3496             : 
    3497             :     // If the RedirectStart is null, we will use the AsyncOpen value of the
    3498             :     // previous channel (this is the first redirect in the redirects chain).
    3499           0 :     if (mRedirectStartTimeStamp.IsNull()) {
    3500           0 :       TimeStamp asyncOpen;
    3501           0 :       oldTimedChannel->GetAsyncOpen(&asyncOpen);
    3502           0 :       newTimedChannel->SetRedirectStart(asyncOpen);
    3503             :     }
    3504             :     else {
    3505           0 :       newTimedChannel->SetRedirectStart(mRedirectStartTimeStamp);
    3506             :     }
    3507             : 
    3508             :     // The RedirectEnd timestamp is equal to the previous channel response end.
    3509           0 :     TimeStamp prevResponseEnd;
    3510           0 :     oldTimedChannel->GetResponseEnd(&prevResponseEnd);
    3511           0 :     newTimedChannel->SetRedirectEnd(prevResponseEnd);
    3512             : 
    3513           0 :     nsAutoString initiatorType;
    3514           0 :     oldTimedChannel->GetInitiatorType(initiatorType);
    3515           0 :     newTimedChannel->SetInitiatorType(initiatorType);
    3516             : 
    3517             :     // Check whether or not this was a cross-domain redirect.
    3518           0 :     newTimedChannel->SetAllRedirectsSameOrigin(
    3519           0 :         mAllRedirectsSameOrigin && SameOriginWithOriginalUri(newURI));
    3520             : 
    3521             :     // Execute the timing allow check to determine whether
    3522             :     // to report the redirect timing info
    3523           0 :     nsCOMPtr<nsILoadInfo> loadInfo;
    3524           0 :     GetLoadInfo(getter_AddRefs(loadInfo));
    3525             :     // TYPE_DOCUMENT loads don't have a loadingPrincipal, so we can't set
    3526             :     // AllRedirectsPassTimingAllowCheck on them.
    3527           0 :     if (loadInfo && loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) {
    3528           0 :       nsCOMPtr<nsIPrincipal> principal = loadInfo->LoadingPrincipal();
    3529           0 :       newTimedChannel->SetAllRedirectsPassTimingAllowCheck(
    3530           0 :         mAllRedirectsPassTimingAllowCheck &&
    3531           0 :         oldTimedChannel->TimingAllowCheck(principal));
    3532             :     }
    3533             :   }
    3534             : 
    3535             :   // Pass the preferred alt-data type on to the new channel.
    3536           0 :   nsCOMPtr<nsICacheInfoChannel> cacheInfoChan(do_QueryInterface(newChannel));
    3537           0 :   if (cacheInfoChan) {
    3538           0 :     cacheInfoChan->PreferAlternativeDataType(mPreferredCachedAltDataType);
    3539             :   }
    3540             : 
    3541           0 :   if (redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
    3542             :                        nsIChannelEventSink::REDIRECT_STS_UPGRADE)) {
    3543             :     // Copy non-origin related headers to the new channel.
    3544             :     nsCOMPtr<nsIHttpHeaderVisitor> visitor =
    3545           0 :       new AddHeadersToChannelVisitor(httpChannel);
    3546           0 :     rv = mRequestHead.VisitHeaders(visitor);
    3547           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
    3548             :   }
    3549             : 
    3550             :   // This channel has been redirected. Don't report timing info.
    3551           0 :   mTimingEnabled = false;
    3552           0 :   return NS_OK;
    3553             : }
    3554             : 
    3555             : // Redirect Tracking
    3556             : bool
    3557           0 : HttpBaseChannel::SameOriginWithOriginalUri(nsIURI *aURI)
    3558             : {
    3559           0 :   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
    3560           0 :   nsresult rv = ssm->CheckSameOriginURI(aURI, mOriginalURI, false);
    3561           0 :   return (NS_SUCCEEDED(rv));
    3562             : }
    3563             : 
    3564             : 
    3565             : //-----------------------------------------------------------------------------
    3566             : // HttpBaseChannel::nsIClassifiedChannel
    3567             : 
    3568             : NS_IMETHODIMP
    3569           0 : HttpBaseChannel::GetMatchedList(nsACString& aList)
    3570             : {
    3571           0 :   aList = mMatchedList;
    3572           0 :   return NS_OK;
    3573             : }
    3574             : 
    3575             : NS_IMETHODIMP
    3576           0 : HttpBaseChannel::GetMatchedProvider(nsACString& aProvider)
    3577             : {
    3578           0 :   aProvider = mMatchedProvider;
    3579           0 :   return NS_OK;
    3580             : }
    3581             : 
    3582             : NS_IMETHODIMP
    3583           0 : HttpBaseChannel::GetMatchedPrefix(nsACString& aPrefix)
    3584             : {
    3585           0 :   aPrefix = mMatchedPrefix;
    3586           0 :   return NS_OK;
    3587             : }
    3588             : 
    3589             : NS_IMETHODIMP
    3590           0 : HttpBaseChannel::SetMatchedInfo(const nsACString& aList,
    3591             :                                 const nsACString& aProvider,
    3592             :                                 const nsACString& aPrefix) {
    3593           0 :   NS_ENSURE_ARG(!aList.IsEmpty());
    3594             : 
    3595           0 :   mMatchedList = aList;
    3596           0 :   mMatchedProvider = aProvider;
    3597           0 :   mMatchedPrefix = aPrefix;
    3598           0 :   return NS_OK;
    3599             : }
    3600             : 
    3601             : //-----------------------------------------------------------------------------
    3602             : // HttpBaseChannel::nsITimedChannel
    3603             : //-----------------------------------------------------------------------------
    3604             : 
    3605             : NS_IMETHODIMP
    3606          10 : HttpBaseChannel::SetTimingEnabled(bool enabled) {
    3607          10 :   mTimingEnabled = enabled;
    3608          10 :   return NS_OK;
    3609             : }
    3610             : 
    3611             : NS_IMETHODIMP
    3612           5 : HttpBaseChannel::GetTimingEnabled(bool* _retval) {
    3613           5 :   *_retval = mTimingEnabled;
    3614           5 :   return NS_OK;
    3615             : }
    3616             : 
    3617             : NS_IMETHODIMP
    3618           2 : HttpBaseChannel::GetChannelCreation(TimeStamp* _retval) {
    3619           2 :   *_retval = mChannelCreationTimestamp;
    3620           2 :   return NS_OK;
    3621             : }
    3622             : 
    3623             : NS_IMETHODIMP
    3624          12 : HttpBaseChannel::GetAsyncOpen(TimeStamp* _retval) {
    3625          12 :   *_retval = mAsyncOpenTime;
    3626          12 :   return NS_OK;
    3627             : }
    3628             : 
    3629             : /**
    3630             :  * @return the number of redirects. There is no check for cross-domain
    3631             :  * redirects. This check must be done by the consumers.
    3632             :  */
    3633             : NS_IMETHODIMP
    3634           5 : HttpBaseChannel::GetRedirectCount(uint16_t *aRedirectCount)
    3635             : {
    3636           5 :   *aRedirectCount = mRedirectCount;
    3637           5 :   return NS_OK;
    3638             : }
    3639             : 
    3640             : NS_IMETHODIMP
    3641           0 : HttpBaseChannel::SetRedirectCount(uint16_t aRedirectCount)
    3642             : {
    3643           0 :   mRedirectCount = aRedirectCount;
    3644           0 :   return NS_OK;
    3645             : }
    3646             : 
    3647             : NS_IMETHODIMP
    3648           5 : HttpBaseChannel::GetRedirectStart(TimeStamp* _retval)
    3649             : {
    3650           5 :   *_retval = mRedirectStartTimeStamp;
    3651           5 :   return NS_OK;
    3652             : }
    3653             : 
    3654             : NS_IMETHODIMP
    3655           0 : HttpBaseChannel::SetRedirectStart(TimeStamp aRedirectStart)
    3656             : {
    3657           0 :   mRedirectStartTimeStamp = aRedirectStart;
    3658           0 :   return NS_OK;
    3659             : }
    3660             : 
    3661             : NS_IMETHODIMP
    3662           5 : HttpBaseChannel::GetRedirectEnd(TimeStamp* _retval)
    3663             : {
    3664           5 :   *_retval = mRedirectEndTimeStamp;
    3665           5 :   return NS_OK;
    3666             : }
    3667             : 
    3668             : NS_IMETHODIMP
    3669           0 : HttpBaseChannel::SetRedirectEnd(TimeStamp aRedirectEnd)
    3670             : {
    3671           0 :   mRedirectEndTimeStamp = aRedirectEnd;
    3672           0 :   return NS_OK;
    3673             : }
    3674             : 
    3675             : NS_IMETHODIMP
    3676           2 : HttpBaseChannel::GetAllRedirectsSameOrigin(bool *aAllRedirectsSameOrigin)
    3677             : {
    3678           2 :   *aAllRedirectsSameOrigin = mAllRedirectsSameOrigin;
    3679           2 :   return NS_OK;
    3680             : }
    3681             : 
    3682             : NS_IMETHODIMP
    3683           0 : HttpBaseChannel::SetAllRedirectsSameOrigin(bool aAllRedirectsSameOrigin)
    3684             : {
    3685           0 :   mAllRedirectsSameOrigin = aAllRedirectsSameOrigin;
    3686           0 :   return NS_OK;
    3687             : }
    3688             : 
    3689             : NS_IMETHODIMP
    3690           2 : HttpBaseChannel::GetAllRedirectsPassTimingAllowCheck(bool *aPassesCheck)
    3691             : {
    3692           2 :   *aPassesCheck = mAllRedirectsPassTimingAllowCheck;
    3693           2 :   return NS_OK;
    3694             : }
    3695             : 
    3696             : NS_IMETHODIMP
    3697           0 : HttpBaseChannel::SetAllRedirectsPassTimingAllowCheck(bool aPassesCheck)
    3698             : {
    3699           0 :   mAllRedirectsPassTimingAllowCheck = aPassesCheck;
    3700           0 :   return NS_OK;
    3701             : }
    3702             : 
    3703             : // http://www.w3.org/TR/resource-timing/#timing-allow-check
    3704             : NS_IMETHODIMP
    3705           2 : HttpBaseChannel::TimingAllowCheck(nsIPrincipal *aOrigin, bool *_retval)
    3706             : {
    3707           2 :   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
    3708           4 :   nsCOMPtr<nsIPrincipal> resourcePrincipal;
    3709           2 :   nsresult rv = ssm->GetChannelURIPrincipal(this, getter_AddRefs(resourcePrincipal));
    3710           2 :   if (NS_FAILED(rv) || !resourcePrincipal || !aOrigin) {
    3711           0 :     *_retval = false;
    3712           0 :     return NS_OK;
    3713             :   }
    3714             : 
    3715           2 :   bool sameOrigin = false;
    3716           2 :   rv = resourcePrincipal->Equals(aOrigin, &sameOrigin);
    3717           2 :   if (NS_SUCCEEDED(rv) && sameOrigin) {
    3718           2 :     *_retval = true;
    3719           2 :     return NS_OK;
    3720             :   }
    3721             : 
    3722           0 :   nsAutoCString headerValue;
    3723           0 :   rv = GetResponseHeader(NS_LITERAL_CSTRING("Timing-Allow-Origin"), headerValue);
    3724           0 :   if (NS_FAILED(rv)) {
    3725           0 :     *_retval = false;
    3726           0 :     return NS_OK;
    3727             :   }
    3728             : 
    3729           0 :   if (headerValue == "*") {
    3730           0 :     *_retval = true;
    3731           0 :     return NS_OK;
    3732             :   }
    3733             : 
    3734           0 :   nsAutoCString origin;
    3735           0 :   nsContentUtils::GetASCIIOrigin(aOrigin, origin);
    3736             : 
    3737           0 :   if (headerValue == origin) {
    3738           0 :     *_retval = true;
    3739           0 :     return NS_OK;
    3740             :   }
    3741             : 
    3742           0 :   *_retval = false;
    3743           0 :   return NS_OK;
    3744             : }
    3745             : 
    3746             : NS_IMETHODIMP
    3747           0 : HttpBaseChannel::GetLaunchServiceWorkerStart(TimeStamp* _retval) {
    3748           0 :   MOZ_ASSERT(_retval);
    3749           0 :   *_retval = mLaunchServiceWorkerStart;
    3750           0 :   return NS_OK;
    3751             : }
    3752             : 
    3753             : NS_IMETHODIMP
    3754           3 : HttpBaseChannel::SetLaunchServiceWorkerStart(TimeStamp aTimeStamp) {
    3755           3 :   mLaunchServiceWorkerStart = aTimeStamp;
    3756           3 :   return NS_OK;
    3757             : }
    3758             : 
    3759             : NS_IMETHODIMP
    3760           0 : HttpBaseChannel::GetLaunchServiceWorkerEnd(TimeStamp* _retval) {
    3761           0 :   MOZ_ASSERT(_retval);
    3762           0 :   *_retval = mLaunchServiceWorkerEnd;
    3763           0 :   return NS_OK;
    3764             : }
    3765             : 
    3766             : NS_IMETHODIMP
    3767           3 : HttpBaseChannel::SetLaunchServiceWorkerEnd(TimeStamp aTimeStamp) {
    3768           3 :   mLaunchServiceWorkerEnd = aTimeStamp;
    3769           3 :   return NS_OK;
    3770             : }
    3771             : 
    3772             : NS_IMETHODIMP
    3773           0 : HttpBaseChannel::GetDispatchFetchEventStart(TimeStamp* _retval) {
    3774           0 :   MOZ_ASSERT(_retval);
    3775           0 :   *_retval = mDispatchFetchEventStart;
    3776           0 :   return NS_OK;
    3777             : }
    3778             : 
    3779             : NS_IMETHODIMP
    3780           3 : HttpBaseChannel::SetDispatchFetchEventStart(TimeStamp aTimeStamp) {
    3781           3 :   mDispatchFetchEventStart = aTimeStamp;
    3782           3 :   return NS_OK;
    3783             : }
    3784             : 
    3785             : NS_IMETHODIMP
    3786           0 : HttpBaseChannel::GetDispatchFetchEventEnd(TimeStamp* _retval) {
    3787           0 :   MOZ_ASSERT(_retval);
    3788           0 :   *_retval = mDispatchFetchEventEnd;
    3789           0 :   return NS_OK;
    3790             : }
    3791             : 
    3792             : NS_IMETHODIMP
    3793           3 : HttpBaseChannel::SetDispatchFetchEventEnd(TimeStamp aTimeStamp) {
    3794           3 :   mDispatchFetchEventEnd = aTimeStamp;
    3795           3 :   return NS_OK;
    3796             : }
    3797             : 
    3798             : NS_IMETHODIMP
    3799           0 : HttpBaseChannel::GetHandleFetchEventStart(TimeStamp* _retval) {
    3800           0 :   MOZ_ASSERT(_retval);
    3801           0 :   *_retval = mHandleFetchEventStart;
    3802           0 :   return NS_OK;
    3803             : }
    3804             : 
    3805             : NS_IMETHODIMP
    3806           3 : HttpBaseChannel::SetHandleFetchEventStart(TimeStamp aTimeStamp) {
    3807           3 :   mHandleFetchEventStart = aTimeStamp;
    3808           3 :   return NS_OK;
    3809             : }
    3810             : 
    3811             : NS_IMETHODIMP
    3812           0 : HttpBaseChannel::GetHandleFetchEventEnd(TimeStamp* _retval) {
    3813           0 :   MOZ_ASSERT(_retval);
    3814           0 :   *_retval = mHandleFetchEventEnd;
    3815           0 :   return NS_OK;
    3816             : }
    3817             : 
    3818             : NS_IMETHODIMP
    3819           3 : HttpBaseChannel::SetHandleFetchEventEnd(TimeStamp aTimeStamp) {
    3820           3 :   mHandleFetchEventEnd = aTimeStamp;
    3821           3 :   return NS_OK;
    3822             : }
    3823             : 
    3824             : NS_IMETHODIMP
    3825           6 : HttpBaseChannel::GetDomainLookupStart(TimeStamp* _retval) {
    3826           6 :   *_retval = mTransactionTimings.domainLookupStart;
    3827           6 :   return NS_OK;
    3828             : }
    3829             : 
    3830             : NS_IMETHODIMP
    3831           6 : HttpBaseChannel::GetDomainLookupEnd(TimeStamp* _retval) {
    3832           6 :   *_retval = mTransactionTimings.domainLookupEnd;
    3833           6 :   return NS_OK;
    3834             : }
    3835             : 
    3836             : NS_IMETHODIMP
    3837           6 : HttpBaseChannel::GetConnectStart(TimeStamp* _retval) {
    3838           6 :   *_retval = mTransactionTimings.connectStart;
    3839           6 :   return NS_OK;
    3840             : }
    3841             : 
    3842             : NS_IMETHODIMP
    3843           6 : HttpBaseChannel::GetConnectEnd(TimeStamp* _retval) {
    3844           6 :   *_retval = mTransactionTimings.connectEnd;
    3845           6 :   return NS_OK;
    3846             : }
    3847             : 
    3848             : NS_IMETHODIMP
    3849           6 : HttpBaseChannel::GetRequestStart(TimeStamp* _retval) {
    3850           6 :   *_retval = mTransactionTimings.requestStart;
    3851           6 :   return NS_OK;
    3852             : }
    3853             : 
    3854             : NS_IMETHODIMP
    3855           9 : HttpBaseChannel::GetResponseStart(TimeStamp* _retval) {
    3856           9 :   *_retval = mTransactionTimings.responseStart;
    3857           9 :   return NS_OK;
    3858             : }
    3859             : 
    3860             : NS_IMETHODIMP
    3861           6 : HttpBaseChannel::GetResponseEnd(TimeStamp* _retval) {
    3862           6 :   *_retval = mTransactionTimings.responseEnd;
    3863           6 :   return NS_OK;
    3864             : }
    3865             : 
    3866             : NS_IMETHODIMP
    3867          12 : HttpBaseChannel::GetCacheReadStart(TimeStamp* _retval) {
    3868          12 :   *_retval = mCacheReadStart;
    3869          12 :   return NS_OK;
    3870             : }
    3871             : 
    3872             : NS_IMETHODIMP
    3873           9 : HttpBaseChannel::GetCacheReadEnd(TimeStamp* _retval) {
    3874           9 :   *_retval = mCacheReadEnd;
    3875           9 :   return NS_OK;
    3876             : }
    3877             : 
    3878             : NS_IMETHODIMP
    3879           3 : HttpBaseChannel::GetInitiatorType(nsAString & aInitiatorType)
    3880             : {
    3881           3 :   aInitiatorType = mInitiatorType;
    3882           3 :   return NS_OK;
    3883             : }
    3884             : 
    3885             : NS_IMETHODIMP
    3886           4 : HttpBaseChannel::SetInitiatorType(const nsAString & aInitiatorType)
    3887             : {
    3888           4 :   mInitiatorType = aInitiatorType;
    3889           4 :   return NS_OK;
    3890             : }
    3891             : 
    3892             : #define IMPL_TIMING_ATTR(name)                                 \
    3893             : NS_IMETHODIMP                                                  \
    3894             : HttpBaseChannel::Get##name##Time(PRTime* _retval) {            \
    3895             :     TimeStamp stamp;                                           \
    3896             :     Get##name(&stamp);                                         \
    3897             :     if (stamp.IsNull()) {                                      \
    3898             :         *_retval = 0;                                          \
    3899             :         return NS_OK;                                          \
    3900             :     }                                                          \
    3901             :     *_retval = mChannelCreationTime +                          \
    3902             :         (PRTime) ((stamp - mChannelCreationTimestamp).ToSeconds() * 1e6); \
    3903             :     return NS_OK;                                              \
    3904             : }
    3905             : 
    3906           0 : IMPL_TIMING_ATTR(ChannelCreation)
    3907           0 : IMPL_TIMING_ATTR(AsyncOpen)
    3908           0 : IMPL_TIMING_ATTR(LaunchServiceWorkerStart)
    3909           0 : IMPL_TIMING_ATTR(LaunchServiceWorkerEnd)
    3910           0 : IMPL_TIMING_ATTR(DispatchFetchEventStart)
    3911           0 : IMPL_TIMING_ATTR(DispatchFetchEventEnd)
    3912           0 : IMPL_TIMING_ATTR(HandleFetchEventStart)
    3913           0 : IMPL_TIMING_ATTR(HandleFetchEventEnd)
    3914           0 : IMPL_TIMING_ATTR(DomainLookupStart)
    3915           0 : IMPL_TIMING_ATTR(DomainLookupEnd)
    3916           0 : IMPL_TIMING_ATTR(ConnectStart)
    3917           0 : IMPL_TIMING_ATTR(ConnectEnd)
    3918           0 : IMPL_TIMING_ATTR(RequestStart)
    3919           0 : IMPL_TIMING_ATTR(ResponseStart)
    3920           0 : IMPL_TIMING_ATTR(ResponseEnd)
    3921           0 : IMPL_TIMING_ATTR(CacheReadStart)
    3922           0 : IMPL_TIMING_ATTR(CacheReadEnd)
    3923           0 : IMPL_TIMING_ATTR(RedirectStart)
    3924           0 : IMPL_TIMING_ATTR(RedirectEnd)
    3925             : 
    3926             : #undef IMPL_TIMING_ATTR
    3927             : 
    3928             : mozilla::dom::Performance*
    3929           9 : HttpBaseChannel::GetPerformance()
    3930             : {
    3931             :   // If performance timing is disabled, there is no need for the Performance
    3932             :   // object anymore.
    3933           9 :   if (!mTimingEnabled) {
    3934           2 :     return nullptr;
    3935             :   }
    3936             : 
    3937             :   // There is no point in continuing, since the performance object in the parent
    3938             :   // isn't the same as the one in the child which will be reporting resource performance.
    3939           7 :   if (XRE_IsE10sParentProcess()) {
    3940           4 :     return nullptr;
    3941             :   }
    3942             : 
    3943           3 :   if (!mLoadInfo) {
    3944           0 :     return nullptr;
    3945             :   }
    3946             : 
    3947             :   // We don't need to report the resource timing entry for a TYPE_DOCUMENT load.
    3948           3 :   if (mLoadInfo->GetExternalContentPolicyType() == nsIContentPolicyBase::TYPE_DOCUMENT) {
    3949           1 :     return nullptr;
    3950             :   }
    3951             : 
    3952           4 :   nsCOMPtr<nsIDOMDocument> domDocument;
    3953           2 :   mLoadInfo->GetLoadingDocument(getter_AddRefs(domDocument));
    3954           2 :   if (!domDocument) {
    3955           0 :     return nullptr;
    3956             :   }
    3957             : 
    3958           4 :   nsCOMPtr<nsIDocument> loadingDocument = do_QueryInterface(domDocument);
    3959           2 :   if (!loadingDocument) {
    3960           0 :     return nullptr;
    3961             :   }
    3962             : 
    3963           4 :   nsCOMPtr<nsPIDOMWindowInner> innerWindow = loadingDocument->GetInnerWindow();
    3964           2 :   if (!innerWindow) {
    3965           0 :     return nullptr;
    3966             :   }
    3967             : 
    3968           2 :   mozilla::dom::Performance* docPerformance = innerWindow->GetPerformance();
    3969           2 :   if (!docPerformance) {
    3970           0 :     return nullptr;
    3971             :   }
    3972             : 
    3973           2 :   return docPerformance;
    3974             : }
    3975             : 
    3976             : nsIURI*
    3977           3 : HttpBaseChannel::GetReferringPage()
    3978             : {
    3979           6 :   nsCOMPtr<nsPIDOMWindowInner> pDomWindow = GetInnerDOMWindow();
    3980           3 :   if (!pDomWindow) {
    3981           3 :     return nullptr;
    3982             :   }
    3983           0 :   return pDomWindow->GetDocumentURI();
    3984             : }
    3985             : 
    3986             : nsPIDOMWindowInner*
    3987           3 : HttpBaseChannel::GetInnerDOMWindow()
    3988             : {
    3989           6 :     nsCOMPtr<nsILoadContext> loadContext;
    3990           3 :     NS_QueryNotificationCallbacks(this, loadContext);
    3991           3 :     if (!loadContext) {
    3992           2 :         return nullptr;
    3993             :     }
    3994           2 :     nsCOMPtr<mozIDOMWindowProxy> domWindow;
    3995           1 :     loadContext->GetAssociatedWindow(getter_AddRefs(domWindow));
    3996           1 :     if (!domWindow) {
    3997           1 :         return nullptr;
    3998             :     }
    3999           0 :     auto* pDomWindow = nsPIDOMWindowOuter::From(domWindow);
    4000           0 :     if (!pDomWindow) {
    4001           0 :         return nullptr;
    4002             :     }
    4003           0 :     nsCOMPtr<nsPIDOMWindowInner> innerWindow = pDomWindow->GetCurrentInnerWindow();
    4004           0 :     if (!innerWindow) {
    4005           0 :       return nullptr;
    4006             :     }
    4007             : 
    4008           0 :     return innerWindow;
    4009             : }
    4010             : 
    4011             : //-----------------------------------------------------------------------------
    4012             : // HttpBaseChannel::nsIThrottledInputChannel
    4013             : //-----------------------------------------------------------------------------
    4014             : 
    4015             : NS_IMETHODIMP
    4016           0 : HttpBaseChannel::SetThrottleQueue(nsIInputChannelThrottleQueue* aQueue)
    4017             : {
    4018           0 :   if (!XRE_IsParentProcess()) {
    4019           0 :     return NS_ERROR_FAILURE;
    4020             :   }
    4021             : 
    4022           0 :   mThrottleQueue = aQueue;
    4023           0 :   return NS_OK;
    4024             : }
    4025             : 
    4026             : NS_IMETHODIMP
    4027           3 : HttpBaseChannel::GetThrottleQueue(nsIInputChannelThrottleQueue** aQueue)
    4028             : {
    4029           3 :   *aQueue = mThrottleQueue;
    4030           3 :   return NS_OK;
    4031             : }
    4032             : 
    4033             : //------------------------------------------------------------------------------
    4034             : 
    4035             : bool
    4036           6 : HttpBaseChannel::EnsureRequestContextID()
    4037             : {
    4038           6 :     if (mRequestContextID) {
    4039             :         // Already have a request context ID, no need to do the rest of this work
    4040           1 :         return true;
    4041             :     }
    4042             : 
    4043             :     // Find the loadgroup at the end of the chain in order
    4044             :     // to make sure all channels derived from the load group
    4045             :     // use the same connection scope.
    4046          10 :     nsCOMPtr<nsILoadGroupChild> childLoadGroup = do_QueryInterface(mLoadGroup);
    4047           5 :     if (!childLoadGroup) {
    4048           2 :         return false;
    4049             :     }
    4050             : 
    4051           6 :     nsCOMPtr<nsILoadGroup> rootLoadGroup;
    4052           3 :     childLoadGroup->GetRootLoadGroup(getter_AddRefs(rootLoadGroup));
    4053           3 :     if (!rootLoadGroup) {
    4054           0 :         return false;
    4055             :     }
    4056             : 
    4057             :     // Set the load group connection scope on the transaction
    4058           3 :     rootLoadGroup->GetRequestContextID(&mRequestContextID);
    4059           3 :     return true;
    4060             : }
    4061             : 
    4062             : void
    4063           3 : HttpBaseChannel::EnsureTopLevelOuterContentWindowId()
    4064             : {
    4065           3 :   if (mTopLevelOuterContentWindowId) {
    4066           4 :     return;
    4067             :   }
    4068             : 
    4069           2 :   nsCOMPtr<nsILoadContext> loadContext;
    4070           2 :   GetCallback(loadContext);
    4071           2 :   if (!loadContext) {
    4072           2 :     return;
    4073             :   }
    4074             : 
    4075           0 :   nsCOMPtr<mozIDOMWindowProxy> topWindow;
    4076           0 :   loadContext->GetTopWindow(getter_AddRefs(topWindow));
    4077           0 :   if (!topWindow) {
    4078           0 :     return;
    4079             :   }
    4080             : 
    4081           0 :   mTopLevelOuterContentWindowId =
    4082           0 :     nsPIDOMWindowOuter::From(topWindow)->WindowID();
    4083             : }
    4084             : 
    4085             : void
    4086           0 : HttpBaseChannel::SetCorsPreflightParameters(const nsTArray<nsCString>& aUnsafeHeaders)
    4087             : {
    4088           0 :   MOZ_RELEASE_ASSERT(!mRequestObserversCalled);
    4089             : 
    4090           0 :   mRequireCORSPreflight = true;
    4091           0 :   mUnsafeHeaders = aUnsafeHeaders;
    4092           0 : }
    4093             : 
    4094             : NS_IMETHODIMP
    4095           0 : HttpBaseChannel::GetBlockAuthPrompt(bool* aValue)
    4096             : {
    4097           0 :   if (!aValue) {
    4098           0 :     return NS_ERROR_FAILURE;
    4099             :   }
    4100             : 
    4101           0 :   *aValue = mBlockAuthPrompt;
    4102           0 :   return NS_OK;
    4103             : }
    4104             : 
    4105             : NS_IMETHODIMP
    4106           3 : HttpBaseChannel::SetBlockAuthPrompt(bool aValue)
    4107             : {
    4108           3 :   ENSURE_CALLED_BEFORE_CONNECT();
    4109             : 
    4110           3 :   mBlockAuthPrompt = aValue;
    4111           3 :   return NS_OK;
    4112             : }
    4113             : 
    4114             : NS_IMETHODIMP
    4115           0 : HttpBaseChannel::GetConnectionInfoHashKey(nsACString& aConnectionInfoHashKey)
    4116             : {
    4117           0 :   if (!mConnectionInfo) {
    4118           0 :     return NS_ERROR_FAILURE;
    4119             :   }
    4120           0 :   aConnectionInfoHashKey.Assign(mConnectionInfo->HashKey());
    4121           0 :   return NS_OK;
    4122             : }
    4123             : 
    4124             : NS_IMETHODIMP
    4125           0 : HttpBaseChannel::GetLastRedirectFlags(uint32_t *aValue)
    4126             : {
    4127           0 :   NS_ENSURE_ARG(aValue);
    4128           0 :   *aValue = mLastRedirectFlags;
    4129           0 :   return NS_OK;
    4130             : }
    4131             : 
    4132             : NS_IMETHODIMP
    4133           0 : HttpBaseChannel::SetLastRedirectFlags(uint32_t aValue)
    4134             : {
    4135           0 :   mLastRedirectFlags = aValue;
    4136           0 :   return NS_OK;
    4137             : }
    4138             : 
    4139             : } // namespace net
    4140           9 : } // namespace mozilla

Generated by: LCOV version 1.13