LCOV - code coverage report
Current view: top level - netwerk/base - nsBaseChannel.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 260 446 58.3 %
Date: 2017-07-14 16:53:18 Functions: 51 67 76.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set sw=2 sts=2 ts=8 et tw=80 : */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsBaseChannel.h"
       8             : #include "nsContentUtils.h"
       9             : #include "nsURLHelper.h"
      10             : #include "nsNetCID.h"
      11             : #include "nsMimeTypes.h"
      12             : #include "nsIContentSniffer.h"
      13             : #include "nsIScriptSecurityManager.h"
      14             : #include "nsMimeTypes.h"
      15             : #include "nsIHttpEventSink.h"
      16             : #include "nsIHttpChannel.h"
      17             : #include "nsIChannelEventSink.h"
      18             : #include "nsIStreamConverterService.h"
      19             : #include "nsChannelClassifier.h"
      20             : #include "nsAsyncRedirectVerifyHelper.h"
      21             : #include "nsProxyRelease.h"
      22             : #include "nsXULAppAPI.h"
      23             : #include "nsContentSecurityManager.h"
      24             : #include "LoadInfo.h"
      25             : #include "nsServiceManagerUtils.h"
      26             : #include "nsRedirectHistoryEntry.h"
      27             : 
      28             : // This class is used to suspend a request across a function scope.
      29             : class ScopedRequestSuspender {
      30             : public:
      31         256 :   explicit ScopedRequestSuspender(nsIRequest *request)
      32         256 :     : mRequest(request) {
      33         256 :     if (mRequest && NS_FAILED(mRequest->Suspend())) {
      34           0 :       NS_WARNING("Couldn't suspend pump");
      35           0 :       mRequest = nullptr;
      36             :     }
      37         256 :   }
      38         512 :   ~ScopedRequestSuspender() {
      39         256 :     if (mRequest)
      40         256 :       mRequest->Resume();
      41         256 :   }
      42             : private:
      43             :   nsIRequest *mRequest;
      44             : };
      45             : 
      46             : // Used to suspend data events from mRequest within a function scope.  This is
      47             : // usually needed when a function makes callbacks that could process events.
      48             : #define SUSPEND_PUMP_FOR_SCOPE() \
      49             :   ScopedRequestSuspender pump_suspender__(mRequest)
      50             : 
      51             : //-----------------------------------------------------------------------------
      52             : // nsBaseChannel
      53             : 
      54        1183 : nsBaseChannel::nsBaseChannel()
      55             :   : NeckoTargetHolder(nullptr)
      56             :   , mPumpingData(false)
      57             :   , mLoadFlags(LOAD_NORMAL)
      58             :   , mQueriedProgressSink(true)
      59             :   , mSynthProgressEvents(false)
      60             :   , mAllowThreadRetargeting(true)
      61             :   , mWaitingOnAsyncRedirect(false)
      62             :   , mOpenRedirectChannel(false)
      63             :   , mStatus(NS_OK)
      64             :   , mContentDispositionHint(UINT32_MAX)
      65             :   , mContentLength(-1)
      66        1183 :   , mWasOpened(false)
      67             : {
      68        1183 :   mContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
      69        1183 : }
      70             : 
      71        2298 : nsBaseChannel::~nsBaseChannel()
      72             : {
      73             :   NS_ReleaseOnMainThread(
      74        1149 :     "nsBaseChannel::mLoadInfo", mLoadInfo.forget());
      75        1149 : }
      76             : 
      77             : nsresult
      78           0 : nsBaseChannel::Redirect(nsIChannel *newChannel, uint32_t redirectFlags,
      79             :                         bool openNewChannel)
      80             : {
      81           0 :   SUSPEND_PUMP_FOR_SCOPE();
      82             : 
      83             :   // Transfer properties
      84             : 
      85           0 :   newChannel->SetLoadGroup(mLoadGroup);
      86           0 :   newChannel->SetNotificationCallbacks(mCallbacks);
      87           0 :   newChannel->SetLoadFlags(mLoadFlags | LOAD_REPLACE);
      88             : 
      89             :   // make a copy of the loadinfo, append to the redirectchain
      90             :   // and set it on the new channel
      91           0 :   if (mLoadInfo) {
      92           0 :     nsSecurityFlags secFlags = mLoadInfo->GetSecurityFlags() &
      93           0 :                                ~nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
      94             :     nsCOMPtr<nsILoadInfo> newLoadInfo =
      95           0 :       static_cast<mozilla::LoadInfo*>(mLoadInfo.get())->CloneWithNewSecFlags(secFlags);
      96             : 
      97           0 :     nsCOMPtr<nsIPrincipal> uriPrincipal;
      98           0 :     nsIScriptSecurityManager *sm = nsContentUtils::GetSecurityManager();
      99           0 :     sm->GetChannelURIPrincipal(this, getter_AddRefs(uriPrincipal));
     100             :     bool isInternalRedirect =
     101           0 :       (redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
     102           0 :                         nsIChannelEventSink::REDIRECT_STS_UPGRADE));
     103             : 
     104             :     // nsBaseChannel hst no thing to do with HttpBaseChannel, we would not care
     105             :     // about referrer and remote address in this case
     106             :     nsCOMPtr<nsIRedirectHistoryEntry> entry =
     107           0 :       new nsRedirectHistoryEntry(uriPrincipal, nullptr, EmptyCString());
     108             : 
     109           0 :     newLoadInfo->AppendRedirectHistoryEntry(entry, isInternalRedirect);
     110           0 :     newChannel->SetLoadInfo(newLoadInfo);
     111             :   }
     112             :   else {
     113             :     // the newChannel was created with a dummy loadInfo, we should clear
     114             :     // it in case the original channel does not have a loadInfo
     115           0 :     newChannel->SetLoadInfo(nullptr);
     116             :   }
     117             : 
     118             :   // Preserve the privacy bit if it has been overridden
     119           0 :   if (mPrivateBrowsingOverriden) {
     120             :     nsCOMPtr<nsIPrivateBrowsingChannel> newPBChannel =
     121           0 :       do_QueryInterface(newChannel);
     122           0 :     if (newPBChannel) {
     123           0 :       newPBChannel->SetPrivate(mPrivateBrowsing);
     124             :     }
     125             :   }
     126             : 
     127           0 :   nsCOMPtr<nsIWritablePropertyBag> bag = ::do_QueryInterface(newChannel);
     128           0 :   if (bag) {
     129           0 :     for (auto iter = mPropertyHash.Iter(); !iter.Done(); iter.Next()) {
     130           0 :       bag->SetProperty(iter.Key(), iter.UserData());
     131             :     }
     132             :   }
     133             : 
     134             :   // Notify consumer, giving chance to cancel redirect.  For backwards compat,
     135             :   // we support nsIHttpEventSink if we are an HTTP channel and if this is not
     136             :   // an internal redirect.
     137             : 
     138             :   RefPtr<nsAsyncRedirectVerifyHelper> redirectCallbackHelper =
     139           0 :       new nsAsyncRedirectVerifyHelper();
     140             : 
     141           0 :   bool checkRedirectSynchronously = !openNewChannel;
     142           0 :   nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
     143             : 
     144           0 :   mRedirectChannel = newChannel;
     145           0 :   mRedirectFlags = redirectFlags;
     146           0 :   mOpenRedirectChannel = openNewChannel;
     147           0 :   nsresult rv = redirectCallbackHelper->Init(this, newChannel, redirectFlags,
     148           0 :                                              target, checkRedirectSynchronously);
     149           0 :   if (NS_FAILED(rv))
     150           0 :     return rv;
     151             : 
     152           0 :   if (checkRedirectSynchronously && NS_FAILED(mStatus))
     153           0 :     return mStatus;
     154             : 
     155           0 :   return NS_OK;
     156             : }
     157             : 
     158             : nsresult
     159           0 : nsBaseChannel::ContinueRedirect()
     160             : {
     161             :   // Backwards compat for non-internal redirects from a HTTP channel.
     162             :   // XXX Is our http channel implementation going to derive from nsBaseChannel?
     163             :   //     If not, this code can be removed.
     164           0 :   if (!(mRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
     165           0 :     nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface();
     166           0 :     if (httpChannel) {
     167           0 :       nsCOMPtr<nsIHttpEventSink> httpEventSink;
     168           0 :       GetCallback(httpEventSink);
     169           0 :       if (httpEventSink) {
     170           0 :         nsresult rv = httpEventSink->OnRedirect(httpChannel, mRedirectChannel);
     171           0 :         if (NS_FAILED(rv)) {
     172           0 :           return rv;
     173             :         }
     174             :       }
     175             :     }
     176             :   }
     177             : 
     178             :   // Make sure to do this _after_ making all the OnChannelRedirect calls
     179           0 :   mRedirectChannel->SetOriginalURI(OriginalURI());
     180             : 
     181             :   // If we fail to open the new channel, then we want to leave this channel
     182             :   // unaffected, so we defer tearing down our channel until we have succeeded
     183             :   // with the redirect.
     184             : 
     185           0 :   if (mOpenRedirectChannel) {
     186           0 :     nsresult rv = NS_OK;
     187           0 :     if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
     188           0 :       MOZ_ASSERT(!mListenerContext, "mListenerContext should be null!");
     189           0 :       rv = mRedirectChannel->AsyncOpen2(mListener);
     190             :     }
     191             :     else {
     192           0 :       rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
     193             :     }
     194           0 :     NS_ENSURE_SUCCESS(rv, rv);
     195             :   }
     196             : 
     197           0 :   mRedirectChannel = nullptr;
     198             : 
     199             :   // close down this channel
     200           0 :   Cancel(NS_BINDING_REDIRECTED);
     201           0 :   ChannelDone();
     202             : 
     203           0 :   return NS_OK;
     204             : }
     205             : 
     206             : bool
     207         172 : nsBaseChannel::HasContentTypeHint() const
     208             : {
     209         172 :   NS_ASSERTION(!Pending(), "HasContentTypeHint called too late");
     210         172 :   return !mContentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE);
     211             : }
     212             : 
     213             : nsresult
     214           0 : nsBaseChannel::PushStreamConverter(const char *fromType,
     215             :                                    const char *toType,
     216             :                                    bool invalidatesContentLength,
     217             :                                    nsIStreamListener **result)
     218             : {
     219           0 :   NS_ASSERTION(mListener, "no listener");
     220             : 
     221             :   nsresult rv;
     222             :   nsCOMPtr<nsIStreamConverterService> scs =
     223           0 :       do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
     224           0 :   if (NS_FAILED(rv))
     225           0 :     return rv;
     226             : 
     227           0 :   nsCOMPtr<nsIStreamListener> converter;
     228           0 :   rv = scs->AsyncConvertData(fromType, toType, mListener, mListenerContext,
     229           0 :                              getter_AddRefs(converter));
     230           0 :   if (NS_SUCCEEDED(rv)) {
     231           0 :     mListener = converter;
     232           0 :     if (invalidatesContentLength)
     233           0 :       mContentLength = -1;
     234           0 :     if (result) {
     235           0 :       *result = nullptr;
     236           0 :       converter.swap(*result);
     237             :     }
     238             :   }
     239           0 :   return rv;
     240             : }
     241             : 
     242             : nsresult
     243          66 : nsBaseChannel::BeginPumpingData()
     244             : {
     245             :   nsresult rv;
     246             : 
     247          66 :   rv = BeginAsyncRead(this, getter_AddRefs(mRequest));
     248          66 :   if (NS_SUCCEEDED(rv)) {
     249           0 :     mPumpingData = true;
     250           0 :     return NS_OK;
     251             :   }
     252          66 :   if (rv != NS_ERROR_NOT_IMPLEMENTED) {
     253           0 :     return rv;
     254             :   }
     255             : 
     256         132 :   nsCOMPtr<nsIInputStream> stream;
     257         132 :   nsCOMPtr<nsIChannel> channel;
     258         132 :   rv = OpenContentStream(true, getter_AddRefs(stream),
     259         198 :                          getter_AddRefs(channel));
     260          66 :   if (NS_FAILED(rv))
     261           0 :     return rv;
     262             : 
     263          66 :   NS_ASSERTION(!stream || !channel, "Got both a channel and a stream?");
     264             : 
     265          66 :   if (channel) {
     266           0 :       nsCOMPtr<nsIRunnable> runnable = new RedirectRunnable(this, channel);
     267           0 :       rv = Dispatch(runnable.forget());
     268           0 :       if (NS_SUCCEEDED(rv))
     269           0 :           mWaitingOnAsyncRedirect = true;
     270           0 :       return rv;
     271             :   }
     272             : 
     273             :   // By assigning mPump, we flag this channel as pending (see Pending).  It's
     274             :   // important that the pending flag is set when we call into the stream (the
     275             :   // call to AsyncRead results in the stream's AsyncWait method being called)
     276             :   // and especially when we call into the loadgroup.  Our caller takes care to
     277             :   // release mPump if we return an error.
     278             : 
     279         132 :   nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
     280         132 :   rv = nsInputStreamPump::Create(getter_AddRefs(mPump), stream, -1, -1, 0, 0,
     281          66 :                                  true, target);
     282          66 :   if (NS_SUCCEEDED(rv)) {
     283          66 :     mPumpingData = true;
     284          66 :     mRequest = mPump;
     285          66 :     rv = mPump->AsyncRead(this, nullptr);
     286             :   }
     287             : 
     288          66 :   return rv;
     289             : }
     290             : 
     291             : void
     292           0 : nsBaseChannel::HandleAsyncRedirect(nsIChannel* newChannel)
     293             : {
     294           0 :   NS_ASSERTION(!mPumpingData, "Shouldn't have gotten here");
     295             : 
     296           0 :   nsresult rv = mStatus;
     297           0 :   if (NS_SUCCEEDED(mStatus)) {
     298             :     rv = Redirect(newChannel,
     299             :                   nsIChannelEventSink::REDIRECT_TEMPORARY,
     300           0 :                   true);
     301           0 :     if (NS_SUCCEEDED(rv)) {
     302             :       // OnRedirectVerifyCallback will be called asynchronously
     303           0 :       return;
     304             :     }
     305             :   }
     306             : 
     307           0 :   ContinueHandleAsyncRedirect(rv);
     308             : }
     309             : 
     310             : void
     311           0 : nsBaseChannel::ContinueHandleAsyncRedirect(nsresult result)
     312             : {
     313           0 :   mWaitingOnAsyncRedirect = false;
     314             : 
     315           0 :   if (NS_FAILED(result))
     316           0 :     Cancel(result);
     317             : 
     318           0 :   if (NS_FAILED(result) && mListener) {
     319             :     // Notify our consumer ourselves
     320           0 :     mListener->OnStartRequest(this, mListenerContext);
     321           0 :     mListener->OnStopRequest(this, mListenerContext, mStatus);
     322           0 :     ChannelDone();
     323             :   }
     324             : 
     325           0 :   if (mLoadGroup)
     326           0 :     mLoadGroup->RemoveRequest(this, nullptr, mStatus);
     327             : 
     328             :   // Drop notification callbacks to prevent cycles.
     329           0 :   mCallbacks = nullptr;
     330           0 :   CallbacksChanged();
     331           0 : }
     332             : 
     333             : void
     334         181 : nsBaseChannel::ClassifyURI()
     335             : {
     336             :   // For channels created in the child process, delegate to the parent to
     337             :   // classify URIs.
     338         181 :   if (!XRE_IsParentProcess()) {
     339          44 :     return;
     340             :   }
     341             : 
     342         137 :   if (mLoadFlags & LOAD_CLASSIFY_URI) {
     343         126 :     RefPtr<nsChannelClassifier> classifier = new nsChannelClassifier(this);
     344          63 :     if (classifier) {
     345          63 :       classifier->Start();
     346             :     } else {
     347           0 :       Cancel(NS_ERROR_OUT_OF_MEMORY);
     348             :     }
     349             :   }
     350             : }
     351             : 
     352             : //-----------------------------------------------------------------------------
     353             : // nsBaseChannel::nsISupports
     354             : 
     355       26753 : NS_IMPL_ISUPPORTS_INHERITED(nsBaseChannel,
     356             :                             nsHashPropertyBag,
     357             :                             nsIRequest,
     358             :                             nsIChannel,
     359             :                             nsIThreadRetargetableRequest,
     360             :                             nsIInterfaceRequestor,
     361             :                             nsITransportEventSink,
     362             :                             nsIRequestObserver,
     363             :                             nsIStreamListener,
     364             :                             nsIThreadRetargetableStreamListener,
     365             :                             nsIAsyncVerifyRedirectCallback,
     366             :                             nsIPrivateBrowsingChannel)
     367             : 
     368             : //-----------------------------------------------------------------------------
     369             : // nsBaseChannel::nsIRequest
     370             : 
     371             : NS_IMETHODIMP
     372         170 : nsBaseChannel::GetName(nsACString &result)
     373             : {
     374         170 :   if (!mURI) {
     375           0 :     result.Truncate();
     376           0 :     return NS_OK;
     377             :   }
     378         170 :   return mURI->GetSpec(result);
     379             : }
     380             : 
     381             : NS_IMETHODIMP
     382           0 : nsBaseChannel::IsPending(bool *result)
     383             : {
     384           0 :   *result = Pending();
     385           0 :   return NS_OK;
     386             : }
     387             : 
     388             : NS_IMETHODIMP
     389          83 : nsBaseChannel::GetStatus(nsresult *status)
     390             : {
     391          83 :   if (mRequest && NS_SUCCEEDED(mStatus)) {
     392          70 :     mRequest->GetStatus(status);
     393             :   } else {
     394          13 :     *status = mStatus;
     395             :   }
     396          83 :   return NS_OK;
     397             : }
     398             : 
     399             : NS_IMETHODIMP
     400           2 : nsBaseChannel::Cancel(nsresult status)
     401             : {
     402             :   // Ignore redundant cancelation
     403           2 :   if (NS_FAILED(mStatus))
     404           0 :     return NS_OK;
     405             : 
     406           2 :   mStatus = status;
     407             : 
     408           2 :   if (mRequest)
     409           2 :     mRequest->Cancel(status);
     410             : 
     411           2 :   return NS_OK;
     412             : }
     413             : 
     414             : NS_IMETHODIMP
     415           0 : nsBaseChannel::Suspend()
     416             : {
     417           0 :   NS_ENSURE_TRUE(mPumpingData, NS_ERROR_NOT_INITIALIZED);
     418           0 :   NS_ENSURE_TRUE(mRequest, NS_ERROR_NOT_IMPLEMENTED);
     419           0 :   return mRequest->Suspend();
     420             : }
     421             : 
     422             : NS_IMETHODIMP
     423           0 : nsBaseChannel::Resume()
     424             : {
     425           0 :   NS_ENSURE_TRUE(mPumpingData, NS_ERROR_NOT_INITIALIZED);
     426           0 :   NS_ENSURE_TRUE(mRequest, NS_ERROR_NOT_IMPLEMENTED);
     427           0 :   return mRequest->Resume();
     428             : }
     429             : 
     430             : NS_IMETHODIMP
     431        2535 : nsBaseChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
     432             : {
     433        2535 :   *aLoadFlags = mLoadFlags;
     434        2535 :   return NS_OK;
     435             : }
     436             : 
     437             : NS_IMETHODIMP
     438          80 : nsBaseChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
     439             : {
     440          80 :   mLoadFlags = aLoadFlags;
     441          80 :   return NS_OK;
     442             : }
     443             : 
     444             : NS_IMETHODIMP
     445         140 : nsBaseChannel::GetLoadGroup(nsILoadGroup **aLoadGroup)
     446             : {
     447         140 :   NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
     448         140 :   return NS_OK;
     449             : }
     450             : 
     451             : NS_IMETHODIMP
     452          68 : nsBaseChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
     453             : {
     454          68 :   if (!CanSetLoadGroup(aLoadGroup)) {
     455           0 :     return NS_ERROR_FAILURE;
     456             :   }
     457             : 
     458          68 :   mLoadGroup = aLoadGroup;
     459          68 :   CallbacksChanged();
     460          68 :   UpdatePrivateBrowsing();
     461          68 :   return NS_OK;
     462             : }
     463             : 
     464             : //-----------------------------------------------------------------------------
     465             : // nsBaseChannel::nsIChannel
     466             : 
     467             : NS_IMETHODIMP
     468         708 : nsBaseChannel::GetOriginalURI(nsIURI **aURI)
     469             : {
     470         708 :   *aURI = OriginalURI();
     471         708 :   NS_ADDREF(*aURI);
     472         708 :   return NS_OK;
     473             : }
     474             : 
     475             : NS_IMETHODIMP
     476        2253 : nsBaseChannel::SetOriginalURI(nsIURI *aURI)
     477             : {
     478        2253 :   NS_ENSURE_ARG_POINTER(aURI);
     479        2253 :   mOriginalURI = aURI;
     480        2253 :   return NS_OK;
     481             : }
     482             : 
     483             : NS_IMETHODIMP
     484        1159 : nsBaseChannel::GetURI(nsIURI **aURI)
     485             : {
     486        1159 :   NS_IF_ADDREF(*aURI = mURI);
     487        1159 :   return NS_OK;
     488             : }
     489             : 
     490             : NS_IMETHODIMP
     491         106 : nsBaseChannel::GetOwner(nsISupports **aOwner)
     492             : {
     493         106 :   NS_IF_ADDREF(*aOwner = mOwner);
     494         106 :   return NS_OK;
     495             : }
     496             : 
     497             : NS_IMETHODIMP
     498          49 : nsBaseChannel::SetOwner(nsISupports *aOwner)
     499             : {
     500          49 :   mOwner = aOwner;
     501          49 :   return NS_OK;
     502             : }
     503             : 
     504             : NS_IMETHODIMP
     505        1183 : nsBaseChannel::SetLoadInfo(nsILoadInfo* aLoadInfo)
     506             : {
     507        1183 :   mLoadInfo = aLoadInfo;
     508             : 
     509             :   // Need to update |mNeckoTarget| when load info has changed.
     510        1183 :   SetupNeckoTarget();
     511        1183 :   return NS_OK;
     512             : }
     513             : 
     514             : NS_IMETHODIMP
     515        3900 : nsBaseChannel::GetLoadInfo(nsILoadInfo** aLoadInfo)
     516             : {
     517        3900 :   NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
     518        3900 :   return NS_OK;
     519             : }
     520             : 
     521             : NS_IMETHODIMP
     522           0 : nsBaseChannel::GetIsDocument(bool *aIsDocument)
     523             : {
     524           0 :   return NS_GetIsDocumentChannel(this, aIsDocument);
     525             : }
     526             : 
     527             : NS_IMETHODIMP
     528         328 : nsBaseChannel::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks)
     529             : {
     530         328 :   NS_IF_ADDREF(*aCallbacks = mCallbacks);
     531         328 :   return NS_OK;
     532             : }
     533             : 
     534             : NS_IMETHODIMP
     535         172 : nsBaseChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
     536             : {
     537         172 :   if (!CanSetCallbacks(aCallbacks)) {
     538           0 :     return NS_ERROR_FAILURE;
     539             :   }
     540             : 
     541         172 :   mCallbacks = aCallbacks;
     542         172 :   CallbacksChanged();
     543         172 :   UpdatePrivateBrowsing();
     544         172 :   return NS_OK;
     545             : }
     546             : 
     547             : NS_IMETHODIMP
     548          58 : nsBaseChannel::GetSecurityInfo(nsISupports **aSecurityInfo)
     549             : {
     550          58 :   NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
     551          58 :   return NS_OK;
     552             : }
     553             : 
     554             : NS_IMETHODIMP
     555         173 : nsBaseChannel::GetContentType(nsACString &aContentType)
     556             : {
     557         173 :   aContentType = mContentType;
     558         173 :   return NS_OK;
     559             : }
     560             : 
     561             : NS_IMETHODIMP
     562         183 : nsBaseChannel::SetContentType(const nsACString &aContentType)
     563             : {
     564             :   // mContentCharset is unchanged if not parsed
     565             :   bool dummy;
     566         183 :   net_ParseContentType(aContentType, mContentType, mContentCharset, &dummy);
     567         183 :   return NS_OK;
     568             : }
     569             : 
     570             : NS_IMETHODIMP
     571         111 : nsBaseChannel::GetContentCharset(nsACString &aContentCharset)
     572             : {
     573         111 :   aContentCharset = mContentCharset;
     574         111 :   return NS_OK;
     575             : }
     576             : 
     577             : NS_IMETHODIMP
     578         180 : nsBaseChannel::SetContentCharset(const nsACString &aContentCharset)
     579             : {
     580         180 :   mContentCharset = aContentCharset;
     581         180 :   return NS_OK;
     582             : }
     583             : 
     584             : NS_IMETHODIMP
     585           3 : nsBaseChannel::GetContentDisposition(uint32_t *aContentDisposition)
     586             : {
     587             :   // preserve old behavior, fail unless explicitly set.
     588           3 :   if (mContentDispositionHint == UINT32_MAX) {
     589           3 :     return NS_ERROR_NOT_AVAILABLE;
     590             :   }
     591             : 
     592           0 :   *aContentDisposition = mContentDispositionHint;
     593           0 :   return NS_OK;
     594             : }
     595             : 
     596             : NS_IMETHODIMP
     597           0 : nsBaseChannel::SetContentDisposition(uint32_t aContentDisposition)
     598             : {
     599           0 :   mContentDispositionHint = aContentDisposition;
     600           0 :   return NS_OK;
     601             : }
     602             : 
     603             : NS_IMETHODIMP
     604           0 : nsBaseChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
     605             : {
     606           0 :   if (!mContentDispositionFilename) {
     607           0 :     return NS_ERROR_NOT_AVAILABLE;
     608             :   }
     609             : 
     610           0 :   aContentDispositionFilename = *mContentDispositionFilename;
     611           0 :   return NS_OK;
     612             : }
     613             : 
     614             : NS_IMETHODIMP
     615           0 : nsBaseChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
     616             : {
     617           0 :   mContentDispositionFilename = new nsString(aContentDispositionFilename);
     618           0 :   return NS_OK;
     619             : }
     620             : 
     621             : NS_IMETHODIMP
     622          41 : nsBaseChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
     623             : {
     624          41 :   return NS_ERROR_NOT_AVAILABLE;
     625             : }
     626             : 
     627             : NS_IMETHODIMP
     628          91 : nsBaseChannel::GetContentLength(int64_t *aContentLength)
     629             : {
     630          91 :   *aContentLength = mContentLength;
     631          91 :   return NS_OK;
     632             : }
     633             : 
     634             : NS_IMETHODIMP
     635           0 : nsBaseChannel::SetContentLength(int64_t aContentLength)
     636             : {
     637           0 :   mContentLength = aContentLength;
     638           0 :   return NS_OK;
     639             : }
     640             : 
     641             : NS_IMETHODIMP
     642         115 : nsBaseChannel::Open(nsIInputStream **result)
     643             : {
     644         115 :   NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_INITIALIZED);
     645         115 :   NS_ENSURE_TRUE(!mPumpingData, NS_ERROR_IN_PROGRESS);
     646         115 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_IN_PROGRESS);
     647             : 
     648         230 :   nsCOMPtr<nsIChannel> chan;
     649         115 :   nsresult rv = OpenContentStream(false, result, getter_AddRefs(chan));
     650         115 :   NS_ASSERTION(!chan || !*result, "Got both a channel and a stream?");
     651         115 :   if (NS_SUCCEEDED(rv) && chan) {
     652           0 :       rv = Redirect(chan, nsIChannelEventSink::REDIRECT_INTERNAL, false);
     653           0 :       if (NS_FAILED(rv))
     654           0 :           return rv;
     655           0 :       rv = chan->Open(result);
     656         115 :   } else if (rv == NS_ERROR_NOT_IMPLEMENTED)
     657           0 :     return NS_ImplementChannelOpen(this, result);
     658             : 
     659         115 :   if (NS_SUCCEEDED(rv)) {
     660         115 :     mWasOpened = true;
     661         115 :     ClassifyURI();
     662             :   }
     663             : 
     664         115 :   return rv;
     665             : }
     666             : 
     667             : NS_IMETHODIMP
     668         115 : nsBaseChannel::Open2(nsIInputStream** aStream)
     669             : {
     670         230 :   nsCOMPtr<nsIStreamListener> listener;
     671         115 :   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
     672         115 :   NS_ENSURE_SUCCESS(rv, rv);
     673         115 :   return Open(aStream);
     674             : }
     675             : 
     676             : NS_IMETHODIMP
     677          66 : nsBaseChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
     678             : {
     679          66 :   MOZ_ASSERT(!mLoadInfo ||
     680             :              mLoadInfo->GetSecurityMode() == 0 ||
     681             :              mLoadInfo->GetInitialSecurityCheckDone() ||
     682             :              (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
     683             :               nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
     684             :              "security flags in loadInfo but asyncOpen2() not called");
     685             : 
     686          66 :   NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_INITIALIZED);
     687          66 :   NS_ENSURE_TRUE(!mPumpingData, NS_ERROR_IN_PROGRESS);
     688          66 :   NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
     689          66 :   NS_ENSURE_ARG(listener);
     690             : 
     691          66 :   SetupNeckoTarget();
     692             : 
     693             :   // Skip checking for chrome:// sub-resources.
     694         132 :   nsAutoCString scheme;
     695          66 :   mURI->GetScheme(scheme);
     696          66 :   if (!scheme.EqualsLiteral("file")) {
     697           3 :     NS_CompareLoadInfoAndLoadContext(this);
     698             :   }
     699             : 
     700             :   // Ensure that this is an allowed port before proceeding.
     701          66 :   nsresult rv = NS_CheckPortSafety(mURI);
     702          66 :   if (NS_FAILED(rv)) {
     703           0 :     mCallbacks = nullptr;
     704           0 :     return rv;
     705             :   }
     706             : 
     707             :   // Store the listener and context early so that OpenContentStream and the
     708             :   // stream's AsyncWait method (called by AsyncRead) can have access to them
     709             :   // via PushStreamConverter and the StreamListener methods.  However, since
     710             :   // this typically introduces a reference cycle between this and the listener,
     711             :   // we need to be sure to break the reference if this method does not succeed.
     712          66 :   mListener = listener;
     713          66 :   mListenerContext = ctxt;
     714             : 
     715             :   // This method assigns mPump as a side-effect.  We need to clear mPump if
     716             :   // this method fails.
     717          66 :   rv = BeginPumpingData();
     718          66 :   if (NS_FAILED(rv)) {
     719           0 :     mPump = nullptr;
     720           0 :     mRequest = nullptr;
     721           0 :     mPumpingData = false;
     722           0 :     ChannelDone();
     723           0 :     mCallbacks = nullptr;
     724           0 :     return rv;
     725             :   }
     726             : 
     727             :   // At this point, we are going to return success no matter what.
     728             : 
     729          66 :   mWasOpened = true;
     730             : 
     731         132 :   SUSPEND_PUMP_FOR_SCOPE();
     732             : 
     733          66 :   if (mLoadGroup)
     734          66 :     mLoadGroup->AddRequest(this, nullptr);
     735             : 
     736          66 :   ClassifyURI();
     737             : 
     738          66 :   return NS_OK;
     739             : }
     740             : 
     741             : NS_IMETHODIMP
     742          66 : nsBaseChannel::AsyncOpen2(nsIStreamListener *aListener)
     743             : {
     744         132 :   nsCOMPtr<nsIStreamListener> listener = aListener;
     745          66 :   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
     746          66 :   if (NS_FAILED(rv)) {
     747           0 :     mCallbacks = nullptr;
     748           0 :     return rv;
     749             :   }
     750          66 :   return AsyncOpen(listener, nullptr);
     751             : }
     752             : 
     753             : //-----------------------------------------------------------------------------
     754             : // nsBaseChannel::nsITransportEventSink
     755             : 
     756             : NS_IMETHODIMP
     757          62 : nsBaseChannel::OnTransportStatus(nsITransport *transport, nsresult status,
     758             :                                  int64_t progress, int64_t progressMax)
     759             : {
     760             :   // In some cases, we may wish to suppress transport-layer status events.
     761             : 
     762          62 :   if (!mPumpingData || NS_FAILED(mStatus)) {
     763           0 :     return NS_OK;
     764             :   }
     765             : 
     766         124 :   SUSPEND_PUMP_FOR_SCOPE();
     767             : 
     768             :   // Lazily fetch mProgressSink
     769          62 :   if (!mProgressSink) {
     770          62 :     if (mQueriedProgressSink) {
     771           0 :       return NS_OK;
     772             :     }
     773          62 :     GetCallback(mProgressSink);
     774          62 :     mQueriedProgressSink = true;
     775          62 :     if (!mProgressSink) {
     776           9 :       return NS_OK;
     777             :     }
     778             :   }
     779             : 
     780          53 :   if (!HasLoadFlag(LOAD_BACKGROUND)) {
     781         106 :     nsAutoString statusArg;
     782          53 :     if (GetStatusArg(status, statusArg)) {
     783           0 :       mProgressSink->OnStatus(this, mListenerContext, status, statusArg.get());
     784             :     }
     785             :   }
     786             : 
     787          53 :   if (progress) {
     788          53 :     mProgressSink->OnProgress(this, mListenerContext, progress, progressMax);
     789             :   }
     790             : 
     791          53 :   return NS_OK;
     792             : }
     793             : 
     794             : //-----------------------------------------------------------------------------
     795             : // nsBaseChannel::nsIInterfaceRequestor
     796             : 
     797             : NS_IMETHODIMP
     798          62 : nsBaseChannel::GetInterface(const nsIID &iid, void **result)
     799             : {
     800          62 :   NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, iid, result);
     801          62 :   return *result ? NS_OK : NS_ERROR_NO_INTERFACE;
     802             : }
     803             : 
     804             : //-----------------------------------------------------------------------------
     805             : // nsBaseChannel::nsIRequestObserver
     806             : 
     807             : static void
     808           2 : CallTypeSniffers(void *aClosure, const uint8_t *aData, uint32_t aCount)
     809             : {
     810           2 :   nsIChannel *chan = static_cast<nsIChannel*>(aClosure);
     811             : 
     812           4 :   nsAutoCString newType;
     813           2 :   NS_SniffContent(NS_CONTENT_SNIFFER_CATEGORY, chan, aData, aCount, newType);
     814           2 :   if (!newType.IsEmpty()) {
     815           0 :     chan->SetContentType(newType);
     816             :   }
     817           2 : }
     818             : 
     819             : static void
     820           0 : CallUnknownTypeSniffer(void *aClosure, const uint8_t *aData, uint32_t aCount)
     821             : {
     822           0 :   nsIChannel *chan = static_cast<nsIChannel*>(aClosure);
     823             : 
     824             :   nsCOMPtr<nsIContentSniffer> sniffer =
     825           0 :     do_CreateInstance(NS_GENERIC_CONTENT_SNIFFER);
     826           0 :   if (!sniffer)
     827           0 :     return;
     828             : 
     829           0 :   nsAutoCString detected;
     830           0 :   nsresult rv = sniffer->GetMIMETypeFromContent(chan, aData, aCount, detected);
     831           0 :   if (NS_SUCCEEDED(rv))
     832           0 :     chan->SetContentType(detected);
     833             : }
     834             : 
     835             : NS_IMETHODIMP
     836          66 : nsBaseChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
     837             : {
     838          66 :   MOZ_ASSERT_IF(mRequest, request == mRequest);
     839             : 
     840          66 :   if (mPump) {
     841             :     // If our content type is unknown, use the content type
     842             :     // sniffer. If the sniffer is not available for some reason, then we just keep
     843             :     // going as-is.
     844         130 :     if (NS_SUCCEEDED(mStatus) &&
     845          64 :         mContentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE)) {
     846           0 :       mPump->PeekStream(CallUnknownTypeSniffer, static_cast<nsIChannel*>(this));
     847             :     }
     848             : 
     849             :     // Now, the general type sniffers. Skip this if we have none.
     850          66 :     if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS)
     851           5 :       mPump->PeekStream(CallTypeSniffers, static_cast<nsIChannel*>(this));
     852             :   }
     853             : 
     854         132 :   SUSPEND_PUMP_FOR_SCOPE();
     855             : 
     856          66 :   if (mListener) // null in case of redirect
     857          66 :       return mListener->OnStartRequest(this, mListenerContext);
     858           0 :   return NS_OK;
     859             : }
     860             : 
     861             : NS_IMETHODIMP
     862          66 : nsBaseChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
     863             :                              nsresult status)
     864             : {
     865             :   // If both mStatus and status are failure codes, we keep mStatus as-is since
     866             :   // that is consistent with our GetStatus and Cancel methods.
     867          66 :   if (NS_SUCCEEDED(mStatus))
     868          64 :     mStatus = status;
     869             : 
     870             :   // Cause Pending to return false.
     871          66 :   mPump = nullptr;
     872          66 :   mRequest = nullptr;
     873          66 :   mPumpingData = false;
     874             : 
     875          66 :   if (mListener) // null in case of redirect
     876          66 :       mListener->OnStopRequest(this, mListenerContext, mStatus);
     877          66 :   ChannelDone();
     878             : 
     879             :   // No need to suspend pump in this scope since we will not be receiving
     880             :   // any more events from it.
     881             : 
     882          66 :   if (mLoadGroup)
     883          66 :     mLoadGroup->RemoveRequest(this, nullptr, mStatus);
     884             : 
     885             :   // Drop notification callbacks to prevent cycles.
     886          66 :   mCallbacks = nullptr;
     887          66 :   CallbacksChanged();
     888             : 
     889          66 :   return NS_OK;
     890             : }
     891             : 
     892             : //-----------------------------------------------------------------------------
     893             : // nsBaseChannel::nsIStreamListener
     894             : 
     895             : NS_IMETHODIMP
     896          62 : nsBaseChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
     897             :                                nsIInputStream *stream, uint64_t offset,
     898             :                                uint32_t count)
     899             : {
     900         124 :   SUSPEND_PUMP_FOR_SCOPE();
     901             : 
     902         124 :   nsresult rv = mListener->OnDataAvailable(this, mListenerContext, stream,
     903         124 :                                            offset, count);
     904          62 :   if (mSynthProgressEvents && NS_SUCCEEDED(rv)) {
     905          62 :     int64_t prog = offset + count;
     906          62 :     if (NS_IsMainThread()) {
     907          60 :       OnTransportStatus(nullptr, NS_NET_STATUS_READING, prog, mContentLength);
     908             :     } else {
     909           6 :       class OnTransportStatusAsyncEvent : public mozilla::Runnable
     910             :       {
     911             :         RefPtr<nsBaseChannel> mChannel;
     912             :         int64_t mProgress;
     913             :         int64_t mContentLength;
     914             :       public:
     915           2 :         OnTransportStatusAsyncEvent(nsBaseChannel* aChannel,
     916             :                                     int64_t aProgress,
     917             :                                     int64_t aContentLength)
     918           2 :           : mozilla::Runnable("OnTransportStatusAsyncEvent")
     919             :           , mChannel(aChannel)
     920             :           , mProgress(aProgress)
     921           2 :           , mContentLength(aContentLength)
     922           2 :         { }
     923             : 
     924           2 :         NS_IMETHOD Run() override
     925             :         {
     926           4 :           return mChannel->OnTransportStatus(nullptr, NS_NET_STATUS_READING,
     927           4 :                                              mProgress, mContentLength);
     928             :         }
     929             :       };
     930             : 
     931             :       nsCOMPtr<nsIRunnable> runnable =
     932           4 :         new OnTransportStatusAsyncEvent(this, prog, mContentLength);
     933           2 :       Dispatch(runnable.forget());
     934             :     }
     935             :   }
     936             : 
     937         124 :   return rv;
     938             : }
     939             : 
     940             : NS_IMETHODIMP
     941           0 : nsBaseChannel::OnRedirectVerifyCallback(nsresult result)
     942             : {
     943           0 :   if (NS_SUCCEEDED(result))
     944           0 :     result = ContinueRedirect();
     945             : 
     946           0 :   if (NS_FAILED(result) && !mWaitingOnAsyncRedirect) {
     947           0 :     if (NS_SUCCEEDED(mStatus))
     948           0 :       mStatus = result;
     949           0 :     return NS_OK;
     950             :   }
     951             : 
     952           0 :   if (mWaitingOnAsyncRedirect)
     953           0 :     ContinueHandleAsyncRedirect(result);
     954             : 
     955           0 :   return NS_OK;
     956             : }
     957             : 
     958             : NS_IMETHODIMP
     959           2 : nsBaseChannel::RetargetDeliveryTo(nsIEventTarget* aEventTarget)
     960             : {
     961           2 :   MOZ_ASSERT(NS_IsMainThread());
     962             : 
     963           2 :   NS_ENSURE_TRUE(mRequest, NS_ERROR_NOT_INITIALIZED);
     964             : 
     965           4 :   nsCOMPtr<nsIThreadRetargetableRequest> req;
     966           2 :   if (mAllowThreadRetargeting) {
     967           2 :     req = do_QueryInterface(mRequest);
     968             :   }
     969             : 
     970           2 :   NS_ENSURE_TRUE(req, NS_ERROR_NOT_IMPLEMENTED);
     971             : 
     972           2 :   return req->RetargetDeliveryTo(aEventTarget);
     973             : }
     974             : 
     975             : NS_IMETHODIMP
     976           2 : nsBaseChannel::CheckListenerChain()
     977             : {
     978           2 :   MOZ_ASSERT(NS_IsMainThread());
     979             : 
     980           2 :   if (!mAllowThreadRetargeting) {
     981           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     982             :   }
     983             : 
     984             :   nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
     985           4 :     do_QueryInterface(mListener);
     986           2 :   if (!listener) {
     987           0 :     return NS_ERROR_NO_INTERFACE;
     988             :   }
     989             : 
     990           2 :   return listener->CheckListenerChain();
     991             : }
     992             : 
     993             : void
     994        1249 : nsBaseChannel::SetupNeckoTarget()
     995             : {
     996             :   mNeckoTarget =
     997        1249 :     nsContentUtils::GetEventTargetByLoadInfo(mLoadInfo, TaskCategory::Other);
     998        1249 : }

Generated by: LCOV version 1.13