Shrink various loading-related enums to shrink CachedResource
[WebKit-https.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 #include <wtf/WallTime.h>
37
38 namespace WebCore {
39
40 class ResourceResponse;
41
42 bool isScriptAllowedByNosniff(const ResourceResponse&);
43
44 // Do not use this class directly, use the class ResponseResponse instead
45 class ResourceResponseBase {
46     WTF_MAKE_FAST_ALLOCATED;
47 public:
48     enum class Type : uint8_t { Basic, Cors, Default, Error, Opaque, Opaqueredirect };
49     enum class Tainting : uint8_t { Basic, Cors, Opaque, Opaqueredirect };
50
51     static bool isRedirectionStatusCode(int code) { return code == 301 || code == 302 || code == 303 || code == 307 || code == 308; }
52
53     struct CrossThreadData {
54         CrossThreadData(const CrossThreadData&) = delete;
55         CrossThreadData& operator=(const CrossThreadData&) = delete;
56         CrossThreadData() = default;
57         CrossThreadData(CrossThreadData&&) = default;
58
59         URL url;
60         String mimeType;
61         long long expectedContentLength;
62         String textEncodingName;
63         int httpStatusCode;
64         String httpStatusText;
65         String httpVersion;
66         HTTPHeaderMap httpHeaderFields;
67         NetworkLoadMetrics networkLoadMetrics;
68         Type type;
69         Tainting tainting;
70         bool isRedirected;
71     };
72
73     CrossThreadData crossThreadData() const;
74     static ResourceResponse fromCrossThreadData(CrossThreadData&&);
75
76     bool isNull() const { return m_isNull; }
77     WEBCORE_EXPORT bool isHTTP() const;
78     WEBCORE_EXPORT bool isSuccessful() const;
79
80     WEBCORE_EXPORT const URL& url() const;
81     WEBCORE_EXPORT void setURL(const URL&);
82
83     WEBCORE_EXPORT const String& mimeType() const;
84     WEBCORE_EXPORT void setMimeType(const String& mimeType);
85
86     WEBCORE_EXPORT long long expectedContentLength() const;
87     WEBCORE_EXPORT void setExpectedContentLength(long long expectedContentLength);
88
89     WEBCORE_EXPORT const String& textEncodingName() const;
90     WEBCORE_EXPORT void setTextEncodingName(const String& name);
91
92     WEBCORE_EXPORT int httpStatusCode() const;
93     WEBCORE_EXPORT void setHTTPStatusCode(int);
94     bool isRedirection() const { return isRedirectionStatusCode(m_httpStatusCode); }
95
96     WEBCORE_EXPORT const String& httpStatusText() const;
97     WEBCORE_EXPORT void setHTTPStatusText(const String&);
98
99     WEBCORE_EXPORT const String& httpVersion() const;
100     WEBCORE_EXPORT void setHTTPVersion(const String&);
101     WEBCORE_EXPORT bool isHTTP09() const;
102
103     WEBCORE_EXPORT const HTTPHeaderMap& httpHeaderFields() const;
104     void setHTTPHeaderFields(HTTPHeaderMap&&);
105
106     enum class SanitizationType { Redirection, RemoveCookies, CrossOriginSafe };
107     WEBCORE_EXPORT void sanitizeHTTPHeaderFields(SanitizationType);
108
109     String httpHeaderField(const String& name) const;
110     WEBCORE_EXPORT String httpHeaderField(HTTPHeaderName) const;
111     WEBCORE_EXPORT void setHTTPHeaderField(const String& name, const String& value);
112     WEBCORE_EXPORT void setHTTPHeaderField(HTTPHeaderName, const String& value);
113
114     WEBCORE_EXPORT void addHTTPHeaderField(HTTPHeaderName, const String& value);
115     WEBCORE_EXPORT void addHTTPHeaderField(const String& name, const String& value);
116
117     // Instead of passing a string literal to any of these functions, just use a HTTPHeaderName instead.
118     template<size_t length> String httpHeaderField(const char (&)[length]) const = delete;
119     template<size_t length> void setHTTPHeaderField(const char (&)[length], const String&) = delete;
120     template<size_t length> void addHTTPHeaderField(const char (&)[length], const String&) = delete;
121
122     bool isMultipart() const { return mimeType() == "multipart/x-mixed-replace"; }
123
124     WEBCORE_EXPORT bool isAttachment() const;
125     WEBCORE_EXPORT bool isAttachmentWithFilename() const;
126     WEBCORE_EXPORT String suggestedFilename() const;
127     WEBCORE_EXPORT static String sanitizeSuggestedFilename(const String&);
128
129     WEBCORE_EXPORT void includeCertificateInfo() const;
130     const std::optional<CertificateInfo>& certificateInfo() const { return m_certificateInfo; };
131     
132     // These functions return parsed values of the corresponding response headers.
133     WEBCORE_EXPORT bool cacheControlContainsNoCache() const;
134     WEBCORE_EXPORT bool cacheControlContainsNoStore() const;
135     WEBCORE_EXPORT bool cacheControlContainsMustRevalidate() const;
136     WEBCORE_EXPORT bool cacheControlContainsImmutable() const;
137     WEBCORE_EXPORT bool hasCacheValidatorFields() const;
138     WEBCORE_EXPORT std::optional<Seconds> cacheControlMaxAge() const;
139     WEBCORE_EXPORT std::optional<WallTime> date() const;
140     WEBCORE_EXPORT std::optional<Seconds> age() const;
141     WEBCORE_EXPORT std::optional<WallTime> expires() const;
142     WEBCORE_EXPORT std::optional<WallTime> lastModified() const;
143     ParsedContentRange& contentRange() const;
144
145     enum class Source : uint8_t { Unknown, Network, DiskCache, DiskCacheAfterValidation, MemoryCache, MemoryCacheAfterValidation, ServiceWorker, ApplicationCache };
146     WEBCORE_EXPORT Source source() const;
147     void setSource(Source source)
148     {
149         ASSERT(source != Source::Unknown);
150         m_source = source;
151     }
152
153     const std::optional<SHA1::Digest>& cacheBodyKey() const { return m_cacheBodyKey; }
154     void setCacheBodyKey(const SHA1::Digest& key) { m_cacheBodyKey = key; }
155
156     // FIXME: This should be eliminated from ResourceResponse.
157     // Network loading metrics should be delivered via didFinishLoad
158     // and should not be part of the ResourceResponse.
159     NetworkLoadMetrics& deprecatedNetworkLoadMetrics() const { return m_networkLoadMetrics; }
160
161     // The ResourceResponse subclass may "shadow" this method to provide platform-specific memory usage information
162     unsigned memoryUsage() const
163     {
164         // average size, mostly due to URL and Header Map strings
165         return 1280;
166     }
167
168     WEBCORE_EXPORT void setType(Type);
169     Type type() const { return m_type; }
170
171     void setRedirected(bool isRedirected) { m_isRedirected = isRedirected; }
172     bool isRedirected() const { return m_isRedirected; }
173
174     void setTainting(Tainting tainting) { m_tainting = tainting; }
175     Tainting tainting() const { return m_tainting; }
176
177     static ResourceResponse filter(const ResourceResponse&);
178
179     static bool compare(const ResourceResponse&, const ResourceResponse&);
180
181     template<class Encoder> void encode(Encoder&) const;
182     template<class Decoder> static bool decode(Decoder&, ResourceResponseBase&);
183
184 protected:
185     enum InitLevel {
186         Uninitialized,
187         CommonFieldsOnly,
188         AllFields
189     };
190
191     WEBCORE_EXPORT ResourceResponseBase();
192     WEBCORE_EXPORT ResourceResponseBase(const URL&, const String& mimeType, long long expectedLength, const String& textEncodingName);
193
194     WEBCORE_EXPORT void lazyInit(InitLevel) const;
195
196     // The ResourceResponse subclass should shadow these functions to lazily initialize platform specific fields
197     void platformLazyInit(InitLevel) { }
198     CertificateInfo platformCertificateInfo() const { return CertificateInfo(); };
199     String platformSuggestedFileName() const { return String(); }
200
201     static bool platformCompare(const ResourceResponse&, const ResourceResponse&) { return true; }
202
203 private:
204     void parseCacheControlDirectives() const;
205     void updateHeaderParsedState(HTTPHeaderName);
206     void sanitizeHTTPHeaderFieldsAccordingToTainting();
207
208 protected:
209     URL m_url;
210     AtomicString m_mimeType;
211     long long m_expectedContentLength { 0 };
212     AtomicString m_textEncodingName;
213     AtomicString m_httpStatusText;
214     AtomicString m_httpVersion;
215     HTTPHeaderMap m_httpHeaderFields;
216     mutable NetworkLoadMetrics m_networkLoadMetrics;
217
218     mutable std::optional<CertificateInfo> m_certificateInfo;
219
220 private:
221     mutable std::optional<Seconds> m_age;
222     mutable std::optional<WallTime> m_date;
223     mutable std::optional<WallTime> m_expires;
224     mutable std::optional<WallTime> m_lastModified;
225     mutable ParsedContentRange m_contentRange;
226     mutable CacheControlDirectives m_cacheControlDirectives;
227     std::optional<SHA1::Digest> m_cacheBodyKey;
228
229     Source m_source { Source::Unknown };
230     Type m_type { Type::Default };
231     Tainting m_tainting { Tainting::Basic };
232
233 protected:
234     int m_httpStatusCode { 0 };
235     bool m_isNull { true };
236
237 private:
238     mutable bool m_haveParsedCacheControlHeader { false };
239     mutable bool m_haveParsedAgeHeader { false };
240     mutable bool m_haveParsedDateHeader { false };
241     mutable bool m_haveParsedExpiresHeader { false };
242     mutable bool m_haveParsedLastModifiedHeader { false };
243     mutable bool m_haveParsedContentRangeHeader { false };
244     bool m_isRedirected { false };
245 };
246
247 inline bool operator==(const ResourceResponse& a, const ResourceResponse& b) { return ResourceResponseBase::compare(a, b); }
248 inline bool operator!=(const ResourceResponse& a, const ResourceResponse& b) { return !(a == b); }
249
250 template<class Encoder>
251 void ResourceResponseBase::encode(Encoder& encoder) const
252 {
253     encoder << m_isNull;
254     if (m_isNull)
255         return;
256     lazyInit(AllFields);
257
258     encoder << m_url;
259     encoder << m_mimeType;
260     encoder << static_cast<int64_t>(m_expectedContentLength);
261     encoder << m_textEncodingName;
262     encoder << m_httpStatusText;
263     encoder << m_httpVersion;
264     encoder << m_httpHeaderFields;
265
266     // We don't want to put the networkLoadMetrics info
267     // into the disk cache, because we will never use the old info.
268     if (Encoder::isIPCEncoder)
269         encoder << m_networkLoadMetrics;
270
271     encoder << m_httpStatusCode;
272     encoder << m_certificateInfo;
273     encoder.encodeEnum(m_source);
274     encoder << m_cacheBodyKey;
275     encoder.encodeEnum(m_type);
276     encoder.encodeEnum(m_tainting);
277     encoder << m_isRedirected;
278 }
279
280 template<class Decoder>
281 bool ResourceResponseBase::decode(Decoder& decoder, ResourceResponseBase& response)
282 {
283     ASSERT(response.m_isNull);
284     bool responseIsNull;
285     if (!decoder.decode(responseIsNull))
286         return false;
287     if (responseIsNull)
288         return true;
289
290     if (!decoder.decode(response.m_url))
291         return false;
292     if (!decoder.decode(response.m_mimeType))
293         return false;
294     int64_t expectedContentLength;
295     if (!decoder.decode(expectedContentLength))
296         return false;
297     response.m_expectedContentLength = expectedContentLength;
298     if (!decoder.decode(response.m_textEncodingName))
299         return false;
300     if (!decoder.decode(response.m_httpStatusText))
301         return false;
302     if (!decoder.decode(response.m_httpVersion))
303         return false;
304     if (!decoder.decode(response.m_httpHeaderFields))
305         return false;
306     // The networkLoadMetrics info is only send over IPC and not stored in disk cache.
307     if (Decoder::isIPCDecoder && !decoder.decode(response.m_networkLoadMetrics))
308         return false;
309     if (!decoder.decode(response.m_httpStatusCode))
310         return false;
311     if (!decoder.decode(response.m_certificateInfo))
312         return false;
313     if (!decoder.decodeEnum(response.m_source))
314         return false;
315     if (!decoder.decode(response.m_cacheBodyKey))
316         return false;
317     if (!decoder.decodeEnum(response.m_type))
318         return false;
319     if (!decoder.decodeEnum(response.m_tainting))
320         return false;
321     if (!decoder.decode(response.m_isRedirected))
322         return false;
323     response.m_isNull = false;
324
325     return true;
326 }
327
328 } // namespace WebCore