netwerk/protocol/http/HttpBaseChannel.h

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set sw=2 ts=8 et tw=80 : */
     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/. */
     8 #ifndef mozilla_net_HttpBaseChannel_h
     9 #define mozilla_net_HttpBaseChannel_h
    11 #include "nsHttp.h"
    12 #include "nsAutoPtr.h"
    13 #include "nsHashPropertyBag.h"
    14 #include "nsProxyInfo.h"
    15 #include "nsHttpRequestHead.h"
    16 #include "nsHttpResponseHead.h"
    17 #include "nsHttpConnectionInfo.h"
    18 #include "nsIEncodedChannel.h"
    19 #include "nsIHttpChannel.h"
    20 #include "nsHttpHandler.h"
    21 #include "nsIHttpChannelInternal.h"
    22 #include "nsIUploadChannel.h"
    23 #include "nsIUploadChannel2.h"
    24 #include "nsIProgressEventSink.h"
    25 #include "nsIURI.h"
    26 #include "nsIEffectiveTLDService.h"
    27 #include "nsIStringEnumerator.h"
    28 #include "nsISupportsPriority.h"
    29 #include "nsIApplicationCache.h"
    30 #include "nsIResumableChannel.h"
    31 #include "nsITraceableChannel.h"
    32 #include "nsILoadContext.h"
    33 #include "mozilla/net/NeckoCommon.h"
    34 #include "nsThreadUtils.h"
    35 #include "PrivateBrowsingChannel.h"
    36 #include "mozilla/net/DNS.h"
    37 #include "nsITimedChannel.h"
    38 #include "nsISecurityConsoleMessage.h"
    40 extern PRLogModuleInfo *gHttpLog;
    42 namespace mozilla {
    43 namespace net {
    45 /*
    46  * This class is a partial implementation of nsIHttpChannel.  It contains code
    47  * shared by nsHttpChannel and HttpChannelChild.
    48  * - Note that this class has nothing to do with nsBaseChannel, which is an
    49  *   earlier effort at a base class for channels that somehow never made it all
    50  *   the way to the HTTP channel.
    51  */
    52 class HttpBaseChannel : public nsHashPropertyBag
    53                       , public nsIEncodedChannel
    54                       , public nsIHttpChannel
    55                       , public nsIHttpChannelInternal
    56                       , public nsIUploadChannel
    57                       , public nsIUploadChannel2
    58                       , public nsISupportsPriority
    59                       , public nsIResumableChannel
    60                       , public nsITraceableChannel
    61                       , public PrivateBrowsingChannel<HttpBaseChannel>
    62                       , public nsITimedChannel
    63 {
    64 public:
    65   NS_DECL_ISUPPORTS_INHERITED
    66   NS_DECL_NSIUPLOADCHANNEL
    67   NS_DECL_NSIUPLOADCHANNEL2
    68   NS_DECL_NSITRACEABLECHANNEL
    69   NS_DECL_NSITIMEDCHANNEL
    71   HttpBaseChannel();
    72   virtual ~HttpBaseChannel();
    74   virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo,
    75                         uint32_t aProxyResolveFlags,
    76                         nsIURI *aProxyURI);
    78   // nsIRequest
    79   NS_IMETHOD GetName(nsACString& aName);
    80   NS_IMETHOD IsPending(bool *aIsPending);
    81   NS_IMETHOD GetStatus(nsresult *aStatus);
    82   NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup);
    83   NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup);
    84   NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags);
    85   NS_IMETHOD SetLoadFlags(nsLoadFlags aLoadFlags);
    87   // nsIChannel
    88   NS_IMETHOD GetOriginalURI(nsIURI **aOriginalURI);
    89   NS_IMETHOD SetOriginalURI(nsIURI *aOriginalURI);
    90   NS_IMETHOD GetURI(nsIURI **aURI);
    91   NS_IMETHOD GetOwner(nsISupports **aOwner);
    92   NS_IMETHOD SetOwner(nsISupports *aOwner);
    93   NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks);
    94   NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks);
    95   NS_IMETHOD GetContentType(nsACString& aContentType);
    96   NS_IMETHOD SetContentType(const nsACString& aContentType);
    97   NS_IMETHOD GetContentCharset(nsACString& aContentCharset);
    98   NS_IMETHOD SetContentCharset(const nsACString& aContentCharset);
    99   NS_IMETHOD GetContentDisposition(uint32_t *aContentDisposition);
   100   NS_IMETHOD SetContentDisposition(uint32_t aContentDisposition);
   101   NS_IMETHOD GetContentDispositionFilename(nsAString& aContentDispositionFilename);
   102   NS_IMETHOD SetContentDispositionFilename(const nsAString& aContentDispositionFilename);
   103   NS_IMETHOD GetContentDispositionHeader(nsACString& aContentDispositionHeader);
   104   NS_IMETHOD GetContentLength(int64_t *aContentLength);
   105   NS_IMETHOD SetContentLength(int64_t aContentLength);
   106   NS_IMETHOD Open(nsIInputStream **aResult);
   108   // nsIEncodedChannel
   109   NS_IMETHOD GetApplyConversion(bool *value);
   110   NS_IMETHOD SetApplyConversion(bool value);
   111   NS_IMETHOD GetContentEncodings(nsIUTF8StringEnumerator** aEncodings);
   113   // HttpBaseChannel::nsIHttpChannel
   114   NS_IMETHOD GetRequestMethod(nsACString& aMethod);
   115   NS_IMETHOD SetRequestMethod(const nsACString& aMethod);
   116   NS_IMETHOD GetReferrer(nsIURI **referrer);
   117   NS_IMETHOD SetReferrer(nsIURI *referrer);
   118   NS_IMETHOD GetProxyURI(nsIURI **proxyURI);
   119   NS_IMETHOD GetRequestHeader(const nsACString& aHeader, nsACString& aValue);
   120   NS_IMETHOD SetRequestHeader(const nsACString& aHeader,
   121                               const nsACString& aValue, bool aMerge);
   122   NS_IMETHOD VisitRequestHeaders(nsIHttpHeaderVisitor *visitor);
   123   NS_IMETHOD GetResponseHeader(const nsACString &header, nsACString &value);
   124   NS_IMETHOD SetResponseHeader(const nsACString& header,
   125                                const nsACString& value, bool merge);
   126   NS_IMETHOD VisitResponseHeaders(nsIHttpHeaderVisitor *visitor);
   127   NS_IMETHOD GetAllowPipelining(bool *value);
   128   NS_IMETHOD SetAllowPipelining(bool value);
   129   NS_IMETHOD GetRedirectionLimit(uint32_t *value);
   130   NS_IMETHOD SetRedirectionLimit(uint32_t value);
   131   NS_IMETHOD IsNoStoreResponse(bool *value);
   132   NS_IMETHOD IsNoCacheResponse(bool *value);
   133   NS_IMETHOD GetResponseStatus(uint32_t *aValue);
   134   NS_IMETHOD GetResponseStatusText(nsACString& aValue);
   135   NS_IMETHOD GetRequestSucceeded(bool *aValue);
   136   NS_IMETHOD RedirectTo(nsIURI *newURI);
   138   // nsIHttpChannelInternal
   139   NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI);
   140   NS_IMETHOD SetDocumentURI(nsIURI *aDocumentURI);
   141   NS_IMETHOD GetRequestVersion(uint32_t *major, uint32_t *minor);
   142   NS_IMETHOD GetResponseVersion(uint32_t *major, uint32_t *minor);
   143   NS_IMETHOD SetCookie(const char *aCookieHeader);
   144   NS_IMETHOD GetForceAllowThirdPartyCookie(bool *aForce);
   145   NS_IMETHOD SetForceAllowThirdPartyCookie(bool aForce);
   146   NS_IMETHOD GetCanceled(bool *aCanceled);
   147   NS_IMETHOD GetChannelIsForDownload(bool *aChannelIsForDownload);
   148   NS_IMETHOD SetChannelIsForDownload(bool aChannelIsForDownload);
   149   NS_IMETHOD SetCacheKeysRedirectChain(nsTArray<nsCString> *cacheKeys);
   150   NS_IMETHOD GetLocalAddress(nsACString& addr);
   151   NS_IMETHOD GetLocalPort(int32_t* port);
   152   NS_IMETHOD GetRemoteAddress(nsACString& addr);
   153   NS_IMETHOD GetRemotePort(int32_t* port);
   154   NS_IMETHOD GetAllowSpdy(bool *aAllowSpdy);
   155   NS_IMETHOD SetAllowSpdy(bool aAllowSpdy);
   156   NS_IMETHOD GetLoadAsBlocking(bool *aLoadAsBlocking);
   157   NS_IMETHOD SetLoadAsBlocking(bool aLoadAsBlocking);
   158   NS_IMETHOD GetLoadUnblocked(bool *aLoadUnblocked);
   159   NS_IMETHOD SetLoadUnblocked(bool aLoadUnblocked);
   160   NS_IMETHOD GetApiRedirectToURI(nsIURI * *aApiRedirectToURI);
   161   NS_IMETHOD AddSecurityMessage(const nsAString &aMessageTag, const nsAString &aMessageCategory);
   162   NS_IMETHOD TakeAllSecurityMessages(nsCOMArray<nsISecurityConsoleMessage> &aMessages);
   163   NS_IMETHOD GetResponseTimeoutEnabled(bool *aEnable);
   164   NS_IMETHOD SetResponseTimeoutEnabled(bool aEnable);
   166   inline void CleanRedirectCacheChainIfNecessary()
   167   {
   168       mRedirectedCachekeys = nullptr;
   169   }
   170   NS_IMETHOD HTTPUpgrade(const nsACString & aProtocolName,
   171                          nsIHttpUpgradeListener *aListener);
   173   // nsISupportsPriority
   174   NS_IMETHOD GetPriority(int32_t *value);
   175   NS_IMETHOD AdjustPriority(int32_t delta);
   177   // nsIResumableChannel
   178   NS_IMETHOD GetEntityID(nsACString& aEntityID);
   180   class nsContentEncodings : public nsIUTF8StringEnumerator
   181     {
   182     public:
   183         NS_DECL_ISUPPORTS
   184         NS_DECL_NSIUTF8STRINGENUMERATOR
   186         nsContentEncodings(nsIHttpChannel* aChannel, const char* aEncodingHeader);
   187         virtual ~nsContentEncodings();
   189     private:
   190         nsresult PrepareForNext(void);
   192         // We do not own the buffer.  The channel owns it.
   193         const char* mEncodingHeader;
   194         const char* mCurStart;  // points to start of current header
   195         const char* mCurEnd;  // points to end of current header
   197         // Hold a ref to our channel so that it can't go away and take the
   198         // header with it.
   199         nsCOMPtr<nsIHttpChannel> mChannel;
   201         bool mReady;
   202     };
   204     nsHttpResponseHead * GetResponseHead() const { return mResponseHead; }
   205     nsHttpRequestHead * GetRequestHead() { return &mRequestHead; }
   207     const NetAddr& GetSelfAddr() { return mSelfAddr; }
   208     const NetAddr& GetPeerAddr() { return mPeerAddr; }
   210 public: /* Necko internal use only... */
   213     // Return whether upon a redirect code of httpStatus for method, the
   214     // request method should be rewritten to GET.
   215     static bool ShouldRewriteRedirectToGET(uint32_t httpStatus,
   216                                            nsHttpRequestHead::ParsedMethodType method);
   218 protected:
   219     nsCOMArray<nsISecurityConsoleMessage> mSecurityConsoleMessages;
   221   // Handle notifying listener, removing from loadgroup if request failed.
   222   void     DoNotifyListener();
   223   virtual void DoNotifyListenerCleanup() = 0;
   225   // drop reference to listener, its callbacks, and the progress sink
   226   void ReleaseListeners();
   228   nsresult ApplyContentConversions();
   230   void AddCookiesToRequest();
   231   virtual nsresult SetupReplacementChannel(nsIURI *,
   232                                            nsIChannel *,
   233                                            bool preserveMethod);
   235   // bundle calling OMR observers and marking flag into one function
   236   inline void CallOnModifyRequestObservers() {
   237     gHttpHandler->OnModifyRequest(this);
   238     mRequestObserversCalled = true;
   239   }
   241   // Helper function to simplify getting notification callbacks.
   242   template <class T>
   243   void GetCallback(nsCOMPtr<T> &aResult)
   244   {
   245     NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
   246                                   NS_GET_TEMPLATE_IID(T),
   247                                   getter_AddRefs(aResult));
   248   }
   250   // Redirect tracking
   251   // Checks whether or not aURI and mOriginalURI share the same domain.
   252   bool SameOriginWithOriginalUri(nsIURI *aURI);
   254   friend class PrivateBrowsingChannel<HttpBaseChannel>;
   256   nsCOMPtr<nsIURI>                  mURI;
   257   nsCOMPtr<nsIURI>                  mOriginalURI;
   258   nsCOMPtr<nsIURI>                  mDocumentURI;
   259   nsCOMPtr<nsIStreamListener>       mListener;
   260   nsCOMPtr<nsISupports>             mListenerContext;
   261   nsCOMPtr<nsILoadGroup>            mLoadGroup;
   262   nsCOMPtr<nsISupports>             mOwner;
   263   nsCOMPtr<nsIInterfaceRequestor>   mCallbacks;
   264   nsCOMPtr<nsIProgressEventSink>    mProgressSink;
   265   nsCOMPtr<nsIURI>                  mReferrer;
   266   nsCOMPtr<nsIApplicationCache>     mApplicationCache;
   268   nsHttpRequestHead                 mRequestHead;
   269   nsCOMPtr<nsIInputStream>          mUploadStream;
   270   nsAutoPtr<nsHttpResponseHead>     mResponseHead;
   271   nsRefPtr<nsHttpConnectionInfo>    mConnectionInfo;
   272   nsCOMPtr<nsIProxyInfo>            mProxyInfo;
   274   nsCString                         mSpec; // ASCII encoded URL spec
   275   nsCString                         mContentTypeHint;
   276   nsCString                         mContentCharsetHint;
   277   nsCString                         mUserSetCookieHeader;
   279   NetAddr                           mSelfAddr;
   280   NetAddr                           mPeerAddr;
   282   // HTTP Upgrade Data
   283   nsCString                        mUpgradeProtocol;
   284   nsCOMPtr<nsIHttpUpgradeListener> mUpgradeProtocolCallback;
   286   // Resumable channel specific data
   287   nsCString                         mEntityID;
   288   uint64_t                          mStartPos;
   290   nsresult                          mStatus;
   291   uint32_t                          mLoadFlags;
   292   uint32_t                          mCaps;
   293   int16_t                           mPriority;
   294   uint8_t                           mRedirectionLimit;
   296   uint32_t                          mApplyConversion            : 1;
   297   uint32_t                          mCanceled                   : 1;
   298   uint32_t                          mIsPending                  : 1;
   299   uint32_t                          mWasOpened                  : 1;
   300   // if 1 all "http-on-{opening|modify|etc}-request" observers have been called
   301   uint32_t                          mRequestObserversCalled     : 1;
   302   uint32_t                          mResponseHeadersModified    : 1;
   303   uint32_t                          mAllowPipelining            : 1;
   304   uint32_t                          mForceAllowThirdPartyCookie : 1;
   305   uint32_t                          mUploadStreamHasHeaders     : 1;
   306   uint32_t                          mInheritApplicationCache    : 1;
   307   uint32_t                          mChooseApplicationCache     : 1;
   308   uint32_t                          mLoadedFromApplicationCache : 1;
   309   uint32_t                          mChannelIsForDownload       : 1;
   310   uint32_t                          mTracingEnabled             : 1;
   311   // True if timing collection is enabled
   312   uint32_t                          mTimingEnabled              : 1;
   313   uint32_t                          mAllowSpdy                  : 1;
   314   uint32_t                          mLoadAsBlocking             : 1;
   315   uint32_t                          mLoadUnblocked              : 1;
   316   uint32_t                          mResponseTimeoutEnabled     : 1;
   317   // A flag that should be false only if a cross-domain redirect occurred
   318   uint32_t                          mAllRedirectsSameOrigin     : 1;
   320   // Current suspension depth for this channel object
   321   uint32_t                          mSuspendCount;
   323   nsCOMPtr<nsIURI>                  mAPIRedirectToURI;
   324   nsAutoPtr<nsTArray<nsCString> >   mRedirectedCachekeys;
   326   uint32_t                          mProxyResolveFlags;
   327   nsCOMPtr<nsIURI>                  mProxyURI;
   329   uint32_t                          mContentDispositionHint;
   330   nsAutoPtr<nsString>               mContentDispositionFilename;
   332   nsRefPtr<nsHttpHandler>           mHttpHandler;  // keep gHttpHandler alive
   334   // Performance tracking
   335   // The initiator type (for this resource) - how was the resource referenced in
   336   // the HTML file.
   337   nsString                          mInitiatorType;
   338   // Number of redirects that has occurred.
   339   int16_t                           mRedirectCount;
   340   // A time value equal to the starting time of the fetch that initiates the
   341   // redirect.
   342   mozilla::TimeStamp                mRedirectStartTimeStamp;
   343   // A time value equal to the time immediately after receiving the last byte of
   344   // the response of the last redirect.
   345   mozilla::TimeStamp                mRedirectEndTimeStamp;
   347   PRTime                            mChannelCreationTime;
   348   TimeStamp                         mChannelCreationTimestamp;
   349   TimeStamp                         mAsyncOpenTime;
   350   TimeStamp                         mCacheReadStart;
   351   TimeStamp                         mCacheReadEnd;
   352   // copied from the transaction before we null out mTransaction
   353   // so that the timing can still be queried from OnStopRequest
   354   TimingStruct                      mTransactionTimings;
   355 };
   357 // Share some code while working around C++'s absurd inability to handle casting
   358 // of member functions between base/derived types.
   359 // - We want to store member function pointer to call at resume time, but one
   360 //   such function--HandleAsyncAbort--we want to share between the
   361 //   nsHttpChannel/HttpChannelChild.  Can't define it in base class, because
   362 //   then we'd have to cast member function ptr between base/derived class
   363 //   types.  Sigh...
   364 template <class T>
   365 class HttpAsyncAborter
   366 {
   367 public:
   368   HttpAsyncAborter(T *derived) : mThis(derived), mCallOnResume(0) {}
   370   // Aborts channel: calls OnStart/Stop with provided status, removes channel
   371   // from loadGroup.
   372   nsresult AsyncAbort(nsresult status);
   374   // Does most the actual work.
   375   void HandleAsyncAbort();
   377   // AsyncCall calls a member function asynchronously (via an event).
   378   // retval isn't refcounted and is set only when event was successfully
   379   // posted, the event is returned for the purpose of cancelling when needed
   380   nsresult AsyncCall(void (T::*funcPtr)(),
   381                      nsRunnableMethod<T> **retval = nullptr);
   382 private:
   383   T *mThis;
   385 protected:
   386   // Function to be called at resume time
   387   void (T::* mCallOnResume)(void);
   388 };
   390 template <class T>
   391 nsresult HttpAsyncAborter<T>::AsyncAbort(nsresult status)
   392 {
   393   PR_LOG(gHttpLog, 4,
   394          ("HttpAsyncAborter::AsyncAbort [this=%p status=%x]\n", mThis, status));
   396   mThis->mStatus = status;
   397   mThis->mIsPending = false;
   399   // if this fails?  Callers ignore our return value anyway....
   400   return AsyncCall(&T::HandleAsyncAbort);
   401 }
   403 // Each subclass needs to define its own version of this (which just calls this
   404 // base version), else we wind up casting base/derived member function ptrs
   405 template <class T>
   406 inline void HttpAsyncAborter<T>::HandleAsyncAbort()
   407 {
   408   NS_PRECONDITION(!mCallOnResume, "How did that happen?");
   410   if (mThis->mSuspendCount) {
   411     PR_LOG(gHttpLog, 4,
   412            ("Waiting until resume to do async notification [this=%p]\n", mThis));
   413     mCallOnResume = &T::HandleAsyncAbort;
   414     return;
   415   }
   417   mThis->DoNotifyListener();
   419   // finally remove ourselves from the load group.
   420   if (mThis->mLoadGroup)
   421     mThis->mLoadGroup->RemoveRequest(mThis, nullptr, mThis->mStatus);
   422 }
   424 template <class T>
   425 nsresult HttpAsyncAborter<T>::AsyncCall(void (T::*funcPtr)(),
   426                                    nsRunnableMethod<T> **retval)
   427 {
   428   nsresult rv;
   430   nsRefPtr<nsRunnableMethod<T> > event = NS_NewRunnableMethod(mThis, funcPtr);
   431   rv = NS_DispatchToCurrentThread(event);
   432   if (NS_SUCCEEDED(rv) && retval) {
   433     *retval = event;
   434   }
   436   return rv;
   437 }
   439 } // namespace net
   440 } // namespace mozilla
   442 #endif // mozilla_net_HttpBaseChannel_h

mercurial