12a82a4d359535ffd6876506e3298fd3855ea280
[WebKit.git] / Source / WebCore / platform / network / ResourceResponseBase.h
1 /*
2  * Copyright (C) 2006, 2008, 2016 Apple Inc. All rights reserved.
3  * Copyright (C) 2009 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #pragma once
28
29 #include "CacheValidation.h"
30 #include "CertificateInfo.h"
31 #include "HTTPHeaderMap.h"
32 #include "NetworkLoadMetrics.h"
33 #include "ParsedContentRange.h"
34 #include "URL.h"
35 #include <wtf/SHA1.h>
36
37 namespace WebCore {
38
39 class ResourceResponse;
40
41 bool isScriptAllowedByNosniff(const ResourceResponse&);
42
43 // Do not use this class directly, use the class ResponseResponse instead
44 class ResourceResponseBase {
45     WTF_MAKE_FAST_ALLOCATED;
46 public:
47     enum class Type { Basic, Cors, Default, Error, Opaque, Opaqueredirect };
48     enum class Tainting { Basic, Cors, Opaque, Opaqueredirect };
49
50     static bool isRedirectionStatusCode(int code) { return code == 301 || code == 302 || code == 303 || code == 307 || code == 308; }
51
52     struct CrossThreadData {
53         CrossThreadData(const CrossThreadData&) = delete;
54         CrossThreadData& operator=(const CrossThreadData&) = delete;
55         CrossThreadData() = default;
56         CrossThreadData(CrossThreadData&&) = default;
57
58         URL url;
59         String mimeType;
60         long long expectedContentLength;
61         String textEncodingName;
62         int httpStatusCode;
63         String httpStatusText;
64         String httpVersion;
65         HTTPHeaderMap httpHeaderFields;
66         NetworkLoadMetrics networkLoadMetrics;
67         Type type;
68         Tainting tainting;
69         bool isRedirected;
70     };
71
72     CrossThreadData crossThreadData() const;
73     static ResourceResponse fromCrossThreadData(CrossThreadData&&);
74
75     bool isNull() const { return m_isNull; }
76     WEBCORE_EXPORT bool isHTTP() const;
77     bool isSuccessful() const;
78
79     WEBCORE_EXPORT const URL& url() const;
80     WEBCORE_EXPORT void setURL(const URL&);
81
82     WEBCORE_EXPORT const String& mimeType() const;
83     WEBCORE_EXPORT void setMimeType(const String& mimeType);
84
85     WEBCORE_EXPORT long long expectedContentLength() const;
86     WEBCORE_EXPORT void setExpectedContentLength(long long expectedContentLength);
87
88     WEBCORE_EXPORT const String& textEncodingName() const;
89     WEBCORE_EXPORT void setTextEncodingName(const String& name);
90
91     WEBCORE_EXPORT int httpStatusCode() const;
92     WEBCORE_EXPORT void setHTTPStatusCode(int);
93     bool isRedirection() const { return isRedirectionStatusCode(m_httpStatusCode); }
94
95     WEBCORE_EXPORT const String& httpStatusText() const;
96     WEBCORE_EXPORT void setHTTPStatusText(const String&);
97
98     WEBCORE_EXPORT const String& httpVersion() const;
99     WEBCORE_EXPORT void setHTTPVersion(const String&);
100     WEBCORE_EXPORT bool isHTTP09() const;
101
102     WEBCORE_EXPORT const HTTPHeaderMap& httpHeaderFields() const;
103
104     String httpHeaderField(const String& name) const;
105     WEBCORE_EXPORT String httpHeaderField(HTTPHeaderName) const;
106     WEBCORE_EXPORT void setHTTPHeaderField(const String& name, const String& value);
107     WEBCORE_EXPORT void setHTTPHeaderField(HTTPHeaderName, const String& value);
108
109     void addHTTPHeaderField(HTTPHeaderName, const String& value);
110     void addHTTPHeaderField(const String& name, const String& value);
111
112     // Instead of passing a string literal to any of these functions, just use a HTTPHeaderName instead.
113     template<size_t length> String httpHeaderField(const char (&)[length]) const = delete;
114     template<size_t length> void setHTTPHeaderField(const char (&)[length], const String&) = delete;
115     template<size_t length> void addHTTPHeaderField(const char (&)[length], const String&) = delete;
116
117     bool isMultipart() const { return mimeType() == "multipart/x-mixed-replace"; }
118
119     WEBCORE_EXPORT bool isAttachment() const;
120     WEBCORE_EXPORT bool isAttachmentWithFilename() const;
121     WEBCORE_EXPORT String suggestedFilename() const;
122     WEBCORE_EXPORT static String sanitizeSuggestedFilename(const String&);
123
124     WEBCORE_EXPORT void includeCertificateInfo() const;
125     const std::optional<CertificateInfo>& certificateInfo() const { return m_certificateInfo; };
126     
127     // These functions return parsed values of the corresponding response headers.
128     WEBCORE_EXPORT bool cacheControlContainsNoCache() const;
129     WEBCORE_EXPORT bool cacheControlContainsNoStore() const;
130     WEBCORE_EXPORT bool cacheControlContainsMustRevalidate() const;
131     WEBCORE_EXPORT bool cacheControlContainsImmutable() const;
132     WEBCORE_EXPORT bool hasCacheValidatorFields() const;
133     WEBCORE_EXPORT std::optional<std::chrono::microseconds> cacheControlMaxAge() const;
134     WEBCORE_EXPORT std::optional<std::chrono::system_clock::time_point> date() const;
135     WEBCORE_EXPORT std::optional<std::chrono::microseconds> age() const;
136     WEBCORE_EXPORT std::optional<std::chrono::system_clock::time_point> expires() const;
137     WEBCORE_EXPORT std::optional<std::chrono::system_clock::time_point> lastModified() const;
138     ParsedContentRange& contentRange() const;
139
140     enum class Source { Unknown, Network, DiskCache, DiskCacheAfterValidation, MemoryCache, MemoryCacheAfterValidation, ServiceWorker };
141     WEBCORE_EXPORT Source source() const;
142     void setSource(Source source) { m_source = source; }
143
144     const std::optional<SHA1::Digest>& cacheBodyKey() const { return m_cacheBodyKey; }
145     void setCacheBodyKey(const SHA1::Digest& key) { m_cacheBodyKey = key; }
146
147     // FIXME: This should be eliminated from ResourceResponse.
148     // Network loading metrics should be delivered via didFinishLoad
149     // and should not be part of the ResourceResponse.
150     NetworkLoadMetrics& deprecatedNetworkLoadMetrics() const { return m_networkLoadMetrics; }
151
152     // The ResourceResponse subclass may "shadow" this method to provide platform-specific memory usage information
153     unsigned memoryUsage() const
154     {
155         // average size, mostly due to URL and Header Map strings
156         return 1280;
157     }
158
159     WEBCORE_EXPORT void setType(Type);
160     Type type() const { return m_type; }
161
162     void setRedirected(bool isRedirected) { m_isRedirected = isRedirected; }
163     bool isRedirected() const { return m_isRedirected; }
164
165     void setTainting(Tainting tainting) { m_tainting = tainting; }
166     Tainting tainting() const { return m_tainting; }
167
168     static ResourceResponse filter(const ResourceResponse&);
169
170     static bool compare(const ResourceResponse&, const ResourceResponse&);
171
172     template<class Encoder> void encode(Encoder&) const;
173     template<class Decoder> static bool decode(Decoder&, ResourceResponseBase&);
174
175 protected:
176     enum InitLevel {
177         Uninitialized,
178         CommonFieldsOnly,
179         AllFields
180     };
181
182     WEBCORE_EXPORT ResourceResponseBase();
183     WEBCORE_EXPORT ResourceResponseBase(const URL&, const String& mimeType, long long expectedLength, const String& textEncodingName);
184
185     WEBCORE_EXPORT void lazyInit(InitLevel) const;
186
187     // The ResourceResponse subclass should shadow these functions to lazily initialize platform specific fields
188     void platformLazyInit(InitLevel) { }
189     CertificateInfo platformCertificateInfo() const { return CertificateInfo(); };
190     String platformSuggestedFileName() const { return String(); }
191
192     static bool platformCompare(const ResourceResponse&, const ResourceResponse&) { return true; }
193
194 private:
195     void parseCacheControlDirectives() const;
196     void updateHeaderParsedState(HTTPHeaderName);
197
198 protected:
199     bool m_isNull;
200     URL m_url;
201     AtomicString m_mimeType;
202     long long m_expectedContentLength;
203     AtomicString m_textEncodingName;
204     AtomicString m_httpStatusText;
205     AtomicString m_httpVersion;
206     HTTPHeaderMap m_httpHeaderFields;
207     mutable NetworkLoadMetrics m_networkLoadMetrics;
208
209     mutable std::optional<CertificateInfo> m_certificateInfo;
210
211     int m_httpStatusCode;
212
213 private:
214     mutable std::optional<std::chrono::microseconds> m_age;
215     mutable std::optional<std::chrono::system_clock::time_point> m_date;
216     mutable std::optional<std::chrono::system_clock::time_point> m_expires;
217     mutable std::optional<std::chrono::system_clock::time_point> m_lastModified;
218     mutable ParsedContentRange m_contentRange;
219     mutable CacheControlDirectives m_cacheControlDirectives;
220
221     mutable bool m_haveParsedCacheControlHeader { false };
222     mutable bool m_haveParsedAgeHeader { false };
223     mutable bool m_haveParsedDateHeader { false };
224     mutable bool m_haveParsedExpiresHeader { false };
225     mutable bool m_haveParsedLastModifiedHeader { false };
226     mutable bool m_haveParsedContentRangeHeader { false };
227
228     Source m_source { Source::Unknown };
229
230     std::optional<SHA1::Digest> m_cacheBodyKey;
231
232     Type m_type { Type::Default };
233     bool m_isRedirected { false };
234     Tainting m_tainting { Tainting::Basic };
235 };
236
237 inline bool operator==(const ResourceResponse& a, const ResourceResponse& b) { return ResourceResponseBase::compare(a, b); }
238 inline bool operator!=(const ResourceResponse& a, const ResourceResponse& b) { return !(a == b); }
239
240 template<class Encoder>
241 void ResourceResponseBase::encode(Encoder& encoder) const
242 {
243     encoder << m_isNull;
244     if (m_isNull)
245         return;
246     lazyInit(AllFields);
247
248     encoder << m_url;
249     encoder << m_mimeType;
250     encoder << static_cast<int64_t>(m_expectedContentLength);
251     encoder << m_textEncodingName;
252     encoder << m_httpStatusText;
253     encoder << m_httpVersion;
254     encoder << m_httpHeaderFields;
255
256     // We don't want to put the networkLoadMetrics info
257     // into the disk cache, because we will never use the old info.
258     if (Encoder::isIPCEncoder)
259         encoder << m_networkLoadMetrics;
260
261     encoder << m_httpStatusCode;
262     encoder << m_certificateInfo;
263     encoder.encodeEnum(m_source);
264     encoder << m_cacheBodyKey;
265     encoder.encodeEnum(m_type);
266     encoder.encodeEnum(m_tainting);
267     encoder << m_isRedirected;
268 }
269
270 template<class Decoder>
271 bool ResourceResponseBase::decode(Decoder& decoder, ResourceResponseBase& response)
272 {
273     ASSERT(response.m_isNull);
274     bool responseIsNull;
275     if (!decoder.decode(responseIsNull))
276         return false;
277     if (responseIsNull)
278         return true;
279
280     if (!decoder.decode(response.m_url))
281         return false;
282     if (!decoder.decode(response.m_mimeType))
283         return false;
284     int64_t expectedContentLength;
285     if (!decoder.decode(expectedContentLength))
286         return false;
287     response.m_expectedContentLength = expectedContentLength;
288     if (!decoder.decode(response.m_textEncodingName))
289         return false;
290     if (!decoder.decode(response.m_httpStatusText))
291         return false;
292     if (!decoder.decode(response.m_httpVersion))
293         return false;
294     if (!decoder.decode(response.m_httpHeaderFields))
295         return false;
296     // The networkLoadMetrics info is only send over IPC and not stored in disk cache.
297     if (Decoder::isIPCDecoder && !decoder.decode(response.m_networkLoadMetrics))
298         return false;
299     if (!decoder.decode(response.m_httpStatusCode))
300         return false;
301     if (!decoder.decode(response.m_certificateInfo))
302         return false;
303     if (!decoder.decodeEnum(response.m_source))
304         return false;
305     if (!decoder.decode(response.m_cacheBodyKey))
306         return false;
307     if (!decoder.decodeEnum(response.m_type))
308         return false;
309     if (!decoder.decodeEnum(response.m_tainting))
310         return false;
311     if (!decoder.decode(response.m_isRedirected))
312         return false;
313     response.m_isNull = false;
314
315     return true;
316 }
317
318 } // namespace WebCore