1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 class nsIHttpHeaderVisitor;
15 
16 // This needs to be forward declared here so we can include only this header
17 // without also including PHttpChannelParams.h
18 namespace IPC {
19 template <typename>
20 struct ParamTraits;
21 }  // namespace IPC
22 
23 namespace mozilla {
24 namespace net {
25 
26 //-----------------------------------------------------------------------------
27 // nsHttpResponseHead represents the status line and headers from an HTTP
28 // response.
29 //-----------------------------------------------------------------------------
30 
31 class nsHttpResponseHead {
32  public:
nsHttpResponseHead()33   nsHttpResponseHead()
34       : mVersion(NS_HTTP_VERSION_1_1),
35         mStatus(200),
36         mContentLength(-1),
37         mCacheControlPrivate(false),
38         mCacheControlNoStore(false),
39         mCacheControlNoCache(false),
40         mCacheControlImmutable(false),
41         mPragmaNoCache(false),
42         mRecursiveMutex("nsHttpResponseHead.mRecursiveMutex"),
43         mInVisitHeaders(false) {}
44 
45   nsHttpResponseHead(const nsHttpResponseHead &aOther);
46   nsHttpResponseHead &operator=(const nsHttpResponseHead &aOther);
47 
Enter()48   void Enter() { mRecursiveMutex.Lock(); }
Exit()49   void Exit() { mRecursiveMutex.Unlock(); }
50 
51   nsHttpVersion Version();
52 // X11's Xlib.h #defines 'Status' to 'int' on some systems!
53 #undef Status
54   uint16_t Status();
55   void StatusText(nsACString &aStatusText);
56   int64_t ContentLength();
57   void ContentType(nsACString &aContentType);
58   void ContentCharset(nsACString &aContentCharset);
59   bool Private();
60   bool NoStore();
61   bool NoCache();
62   bool Immutable();
63   /**
64    * Full length of the entity. For byte-range requests, this may be larger
65    * than ContentLength(), which will only represent the requested part of the
66    * entity.
67    */
68   int64_t TotalEntitySize();
69 
70   MOZ_MUST_USE nsresult SetHeader(const nsACString &h, const nsACString &v,
71                                   bool m = false);
72   MOZ_MUST_USE nsresult SetHeader(nsHttpAtom h, const nsACString &v,
73                                   bool m = false);
74   MOZ_MUST_USE nsresult GetHeader(nsHttpAtom h, nsACString &v);
75   void ClearHeader(nsHttpAtom h);
76   void ClearHeaders();
77   bool HasHeaderValue(nsHttpAtom h, const char *v);
78   bool HasHeader(nsHttpAtom h);
79 
80   void SetContentType(const nsACString &s);
81   void SetContentCharset(const nsACString &s);
82   void SetContentLength(int64_t);
83 
84   // write out the response status line and headers as a single text block,
85   // optionally pruning out transient headers (ie. headers that only make
86   // sense the first time the response is handled).
87   // Both functions append to the string supplied string.
88   void Flatten(nsACString &, bool pruneTransients);
89   void FlattenNetworkOriginalHeaders(nsACString &buf);
90 
91   // The next 2 functions parse flattened response head and original net
92   // headers. They are used when we are reading an entry from the cache.
93   //
94   // To keep proper order of the original headers we MUST call
95   // ParseCachedOriginalHeaders FIRST and then ParseCachedHead.
96   //
97   // block must be null terminated.
98   MOZ_MUST_USE nsresult ParseCachedHead(const char *block);
99   MOZ_MUST_USE nsresult ParseCachedOriginalHeaders(char *block);
100 
101   // parse the status line.
102   void ParseStatusLine(const nsACString &line);
103 
104   // parse a header line.
105   MOZ_MUST_USE nsresult ParseHeaderLine(const nsACString &line);
106 
107   // cache validation support methods
108   MOZ_MUST_USE nsresult ComputeFreshnessLifetime(uint32_t *);
109   MOZ_MUST_USE nsresult ComputeCurrentAge(uint32_t now, uint32_t requestTime,
110                                           uint32_t *result);
111   bool MustValidate();
112   bool MustValidateIfExpired();
113 
114   // returns true if the server appears to support byte range requests.
115   bool IsResumable();
116 
117   // returns true if the Expires header has a value in the past relative to the
118   // value of the Date header.
119   bool ExpiresInPast();
120 
121   // update headers...
122   MOZ_MUST_USE nsresult UpdateHeaders(nsHttpResponseHead *headers);
123 
124   // reset the response head to it's initial state
125   void Reset();
126 
127   MOZ_MUST_USE nsresult GetAgeValue(uint32_t *result);
128   MOZ_MUST_USE nsresult GetMaxAgeValue(uint32_t *result);
129   MOZ_MUST_USE nsresult GetDateValue(uint32_t *result);
130   MOZ_MUST_USE nsresult GetExpiresValue(uint32_t *result);
131   MOZ_MUST_USE nsresult GetLastModifiedValue(uint32_t *result);
132 
133   bool operator==(const nsHttpResponseHead &aOther) const;
134 
135   // Using this function it is possible to itereate through all headers
136   // automatically under one lock.
137   MOZ_MUST_USE nsresult VisitHeaders(nsIHttpHeaderVisitor *visitor,
138                                      nsHttpHeaderArray::VisitorFilter filter);
139   MOZ_MUST_USE nsresult GetOriginalHeader(nsHttpAtom aHeader,
140                                           nsIHttpHeaderVisitor *aVisitor);
141 
142   bool HasContentType();
143   bool HasContentCharset();
144 
145  private:
146   MOZ_MUST_USE nsresult SetHeader_locked(nsHttpAtom atom, const nsACString &h,
147                                          const nsACString &v, bool m = false);
148   void AssignDefaultStatusText();
149   void ParseVersion(const char *);
150   void ParseCacheControl(const char *);
151   void ParsePragma(const char *);
152 
153   void ParseStatusLine_locked(const nsACString &line);
154   MOZ_MUST_USE nsresult ParseHeaderLine_locked(const nsACString &line,
155                                                bool originalFromNetHeaders);
156 
157   // these return failure if the header does not exist.
158   MOZ_MUST_USE nsresult ParseDateHeader(nsHttpAtom header,
159                                         uint32_t *result) const;
160 
161   bool ExpiresInPast_locked() const;
162   MOZ_MUST_USE nsresult GetAgeValue_locked(uint32_t *result) const;
163   MOZ_MUST_USE nsresult GetExpiresValue_locked(uint32_t *result) const;
164   MOZ_MUST_USE nsresult GetMaxAgeValue_locked(uint32_t *result) const;
165 
GetDateValue_locked(uint32_t * result)166   MOZ_MUST_USE nsresult GetDateValue_locked(uint32_t *result) const {
167     return ParseDateHeader(nsHttp::Date, result);
168   }
169 
GetLastModifiedValue_locked(uint32_t * result)170   MOZ_MUST_USE nsresult GetLastModifiedValue_locked(uint32_t *result) const {
171     return ParseDateHeader(nsHttp::Last_Modified, result);
172   }
173 
174  private:
175   // All members must be copy-constructable and assignable
176   nsHttpHeaderArray mHeaders;
177   nsHttpVersion mVersion;
178   uint16_t mStatus;
179   nsCString mStatusText;
180   int64_t mContentLength;
181   nsCString mContentType;
182   nsCString mContentCharset;
183   bool mCacheControlPrivate;
184   bool mCacheControlNoStore;
185   bool mCacheControlNoCache;
186   bool mCacheControlImmutable;
187   bool mPragmaNoCache;
188 
189   // We are using RecursiveMutex instead of a Mutex because VisitHeader
190   // function calls nsIHttpHeaderVisitor::VisitHeader while under lock.
191   RecursiveMutex mRecursiveMutex;
192   // During VisitHeader we sould not allow cal to SetHeader.
193   bool mInVisitHeaders;
194 
195   friend struct IPC::ParamTraits<nsHttpResponseHead>;
196 };
197 
198 }  // namespace net
199 }  // namespace mozilla
200 
201 #endif  // nsHttpResponseHead_h__
202