tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsHttpResponseHead.h (10448B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef nsHttpResponseHead_h__
      7 #define nsHttpResponseHead_h__
      8 
      9 #include "nsHttpHeaderArray.h"
     10 #include "nsHttp.h"
     11 #include "nsString.h"
     12 #include "mozilla/RecursiveMutex.h"
     13 
     14 #ifdef Status
     15 /* Xlib headers insist on this for some reason... Nuke it because
     16   it'll override our member name */
     17 typedef Status __StatusTmp;
     18 #  undef Status
     19 typedef __StatusTmp Status;
     20 #endif
     21 
     22 class nsIHttpHeaderVisitor;
     23 
     24 // This needs to be forward declared here so we can include only this header
     25 // without also including PHttpChannelParams.h
     26 namespace IPC {
     27 template <typename>
     28 struct ParamTraits;
     29 }  // namespace IPC
     30 
     31 namespace mozilla {
     32 namespace net {
     33 
     34 //-----------------------------------------------------------------------------
     35 // nsHttpResponseHead represents the status line and headers from an HTTP
     36 // response.
     37 //-----------------------------------------------------------------------------
     38 
     39 class nsHttpResponseHead {
     40 public:
     41  nsHttpResponseHead() = default;
     42 
     43  nsHttpResponseHead(const nsHttpResponseHead& aOther);
     44  nsHttpResponseHead(nsHttpResponseHead&& aOther);
     45  nsHttpResponseHead& operator=(const nsHttpResponseHead& aOther);
     46 
     47  void Enter() const MOZ_CAPABILITY_ACQUIRE(mRecursiveMutex) {
     48    mRecursiveMutex.Lock();
     49  }
     50  void Exit() const MOZ_CAPABILITY_RELEASE(mRecursiveMutex) {
     51    mRecursiveMutex.Unlock();
     52  }
     53  void AssertMutexOwned() const { mRecursiveMutex.AssertCurrentThreadIn(); }
     54 
     55  HttpVersion Version() const;
     56  uint16_t Status() const;
     57  void StatusText(nsACString& aStatusText);
     58  int64_t ContentLength();
     59  void ContentType(nsACString& aContentType) const;
     60  void ContentCharset(nsACString& aContentCharset);
     61  bool Public();
     62  bool Private();
     63  bool NoStore();
     64  bool NoCache();
     65  bool Immutable();
     66  /**
     67   * Full length of the entity. For byte-range requests, this may be larger
     68   * than ContentLength(), which will only represent the requested part of the
     69   * entity.
     70   */
     71  int64_t TotalEntitySize();
     72 
     73  [[nodiscard]] nsresult SetHeader(const nsACString& h, const nsACString& v,
     74                                   bool m = false);
     75  [[nodiscard]] nsresult SetHeaderOverride(const nsHttpAtom& h,
     76                                           const nsACString& v);
     77  [[nodiscard]] nsresult SetHeader(const nsHttpAtom& h, const nsACString& v,
     78                                   bool m = false);
     79  [[nodiscard]] nsresult GetHeader(const nsHttpAtom& h, nsACString& v) const;
     80  void ClearHeader(const nsHttpAtom& h);
     81  void ClearHeaders();
     82  bool HasHeaderValue(const nsHttpAtom& h, const char* v);
     83  bool HasHeader(const nsHttpAtom& h) const;
     84 
     85  void SetContentType(const nsACString& s);
     86  void SetContentCharset(const nsACString& s);
     87  void SetContentLength(int64_t);
     88 
     89  // write out the response status line and headers as a single text block,
     90  // optionally pruning out transient headers (ie. headers that only make
     91  // sense the first time the response is handled).
     92  // Both functions append to the string supplied string.
     93  void Flatten(nsACString&, bool pruneTransients);
     94  void FlattenNetworkOriginalHeaders(nsACString& buf);
     95 
     96  // The next 2 functions parse flattened response head and original net
     97  // headers. They are used when we are reading an entry from the cache.
     98  //
     99  // To keep proper order of the original headers we MUST call
    100  // ParseCachedOriginalHeaders FIRST and then ParseCachedHead.
    101  //
    102  // block must be null terminated.
    103  [[nodiscard]] nsresult ParseCachedHead(const char* block);
    104  [[nodiscard]] nsresult ParseCachedOriginalHeaders(char* block);
    105 
    106  // parse the status line.
    107  nsresult ParseStatusLine(const nsACString& line);
    108 
    109  // parse a header line.
    110  [[nodiscard]] nsresult ParseHeaderLine(const nsACString& line);
    111 
    112  // cache validation support methods
    113  [[nodiscard]] nsresult ComputeFreshnessLifetime(uint32_t*);
    114  [[nodiscard]] nsresult ComputeCurrentAge(uint32_t now, uint32_t requestTime,
    115                                           uint32_t* result);
    116  bool MustValidate();
    117  bool MustValidateIfExpired();
    118 
    119  // return true if the response contains a valid Cache-control:
    120  // stale-while-revalidate and |now| is less than or equal |expiration +
    121  // stale-while-revalidate|.  Otherwise false.
    122  bool StaleWhileRevalidate(uint32_t now, uint32_t expiration);
    123 
    124  // returns true if the server appears to support byte range requests.
    125  bool IsResumable();
    126 
    127  // returns true if the Expires header has a value in the past relative to the
    128  // value of the Date header.
    129  bool ExpiresInPast();
    130 
    131  // update headers...
    132  void UpdateHeaders(nsHttpResponseHead* aOther);
    133 
    134  // reset the response head to it's initial state
    135  void Reset();
    136 
    137  [[nodiscard]] nsresult GetLastModifiedValue(uint32_t* result);
    138 
    139  bool operator==(const nsHttpResponseHead& aOther) const;
    140 
    141  // Using this function it is possible to itereate through all headers
    142  // automatically under one lock.
    143  [[nodiscard]] nsresult VisitHeaders(nsIHttpHeaderVisitor* visitor,
    144                                      nsHttpHeaderArray::VisitorFilter filter);
    145  [[nodiscard]] nsresult GetOriginalHeader(const nsHttpAtom& aHeader,
    146                                           nsIHttpHeaderVisitor* aVisitor);
    147 
    148  bool HasContentType() const;
    149  bool HasContentCharset();
    150  bool GetContentTypeOptionsHeader(nsACString& aOutput);
    151 
    152 private:
    153  [[nodiscard]] nsresult SetHeader_locked(const nsHttpAtom& atom,
    154                                          const nsACString& h,
    155                                          const nsACString& v, bool m = false)
    156      MOZ_REQUIRES(mRecursiveMutex);
    157  void AssignDefaultStatusText() MOZ_REQUIRES(mRecursiveMutex);
    158  void ParseVersion(const char*) MOZ_REQUIRES(mRecursiveMutex);
    159  void ParseCacheControl(const char*) MOZ_REQUIRES(mRecursiveMutex);
    160  void ParsePragma(const char*) MOZ_REQUIRES(mRecursiveMutex);
    161  // Parses a content-length header-value as described in
    162  // https://fetch.spec.whatwg.org/#content-length-header
    163  nsresult ParseResponseContentLength(const nsACString& aHeaderStr)
    164      MOZ_REQUIRES(mRecursiveMutex);
    165 
    166  nsresult ParseStatusLine_locked(const nsACString& line)
    167      MOZ_REQUIRES(mRecursiveMutex);
    168  [[nodiscard]] nsresult ParseHeaderLine_locked(const nsACString& line,
    169                                                bool originalFromNetHeaders)
    170      MOZ_REQUIRES(mRecursiveMutex);
    171 
    172  // these return failure if the header does not exist.
    173  [[nodiscard]] nsresult ParseDateHeader(const nsHttpAtom& header,
    174                                         uint32_t* result) const
    175      MOZ_REQUIRES(mRecursiveMutex);
    176  [[nodiscard]] nsresult GetAgeValue(uint32_t* result);
    177  [[nodiscard]] nsresult GetMaxAgeValue(uint32_t* result);
    178  [[nodiscard]] nsresult GetStaleWhileRevalidateValue(uint32_t* result);
    179  [[nodiscard]] nsresult GetDateValue(uint32_t* result);
    180  [[nodiscard]] nsresult GetExpiresValue(uint32_t* result);
    181 
    182  bool ExpiresInPast_locked() const MOZ_REQUIRES(mRecursiveMutex);
    183  [[nodiscard]] nsresult GetAgeValue_locked(uint32_t* result) const
    184      MOZ_REQUIRES(mRecursiveMutex);
    185  [[nodiscard]] nsresult GetExpiresValue_locked(uint32_t* result) const
    186      MOZ_REQUIRES(mRecursiveMutex);
    187  [[nodiscard]] nsresult GetMaxAgeValue_locked(uint32_t* result) const
    188      MOZ_REQUIRES(mRecursiveMutex);
    189  [[nodiscard]] nsresult GetStaleWhileRevalidateValue_locked(
    190      uint32_t* result) const MOZ_REQUIRES(mRecursiveMutex);
    191 
    192  [[nodiscard]] nsresult GetDateValue_locked(uint32_t* result) const
    193      MOZ_REQUIRES(mRecursiveMutex) {
    194    return ParseDateHeader(nsHttp::Date, result);
    195  }
    196 
    197  [[nodiscard]] nsresult GetLastModifiedValue_locked(uint32_t* result) const
    198      MOZ_REQUIRES(mRecursiveMutex) {
    199    return ParseDateHeader(nsHttp::Last_Modified, result);
    200  }
    201 
    202  bool NoCache_locked() const MOZ_REQUIRES(mRecursiveMutex) {
    203    MOZ_ASSERT_IF(mCacheControlNoCache, mHasCacheControl);
    204    // Normally we would ignore Pragma: no-cache if Cache-Control is set.
    205    // But since all other browsers treat the existence of Pragma: no-cache
    206    // as a signal to not-cache even when it conflicts with Cache-Control
    207    // it is safer just to do the same. Previous behaviour where Pragma
    208    // was ignored when Cache-Control was present resulted in several
    209    // web-compat issues (Bug 1937766)
    210    // However, the presence of cacheControl immutable indicates that
    211    // pragma: no-cache is incorrectly added to the response.
    212    return (mPragmaNoCache && !mCacheControlImmutable) || mCacheControlNoCache;
    213  }
    214 
    215 private:
    216  // All members must be copy-constructable and assignable
    217  nsHttpHeaderArray mHeaders MOZ_GUARDED_BY(mRecursiveMutex);
    218  HttpVersion mVersion MOZ_GUARDED_BY(mRecursiveMutex){HttpVersion::v1_1};
    219  uint16_t mStatus MOZ_GUARDED_BY(mRecursiveMutex){200};
    220  nsCString mStatusText MOZ_GUARDED_BY(mRecursiveMutex);
    221  int64_t mContentLength MOZ_GUARDED_BY(mRecursiveMutex){-1};
    222  nsCString mContentType MOZ_GUARDED_BY(mRecursiveMutex);
    223  nsCString mContentCharset MOZ_GUARDED_BY(mRecursiveMutex);
    224  bool mHasCacheControl MOZ_GUARDED_BY(mRecursiveMutex){false};
    225  bool mCacheControlPublic MOZ_GUARDED_BY(mRecursiveMutex){false};
    226  bool mCacheControlPrivate MOZ_GUARDED_BY(mRecursiveMutex){false};
    227  bool mCacheControlNoStore MOZ_GUARDED_BY(mRecursiveMutex){false};
    228  bool mCacheControlNoCache MOZ_GUARDED_BY(mRecursiveMutex){false};
    229  bool mCacheControlImmutable MOZ_GUARDED_BY(mRecursiveMutex){false};
    230  bool mCacheControlStaleWhileRevalidateSet MOZ_GUARDED_BY(mRecursiveMutex){
    231      false};
    232  uint32_t mCacheControlStaleWhileRevalidate MOZ_GUARDED_BY(mRecursiveMutex){0};
    233  bool mCacheControlMaxAgeSet MOZ_GUARDED_BY(mRecursiveMutex){false};
    234  uint32_t mCacheControlMaxAge MOZ_GUARDED_BY(mRecursiveMutex){0};
    235  bool mPragmaNoCache MOZ_GUARDED_BY(mRecursiveMutex){false};
    236 
    237  // We are using RecursiveMutex instead of a Mutex because VisitHeader
    238  // function calls nsIHttpHeaderVisitor::VisitHeader while under lock.
    239  mutable RecursiveMutex mRecursiveMutex{"nsHttpResponseHead.mRecursiveMutex"};
    240  // During VisitHeader we sould not allow call to SetHeader.
    241  bool mInVisitHeaders MOZ_GUARDED_BY(mRecursiveMutex){false};
    242 
    243  friend struct IPC::ParamTraits<nsHttpResponseHead>;
    244 };
    245 
    246 }  // namespace net
    247 }  // namespace mozilla
    248 
    249 #endif  // nsHttpResponseHead_h__