ResourceResponseBase.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  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. #include "config.h"
  27. #include "ResourceResponseBase.h"
  28. #include "CacheValidation.h"
  29. #include "HTTPHeaderNames.h"
  30. #include "HTTPParsers.h"
  31. #include "MIMETypeRegistry.h"
  32. #include "ParsedContentRange.h"
  33. #include "ResourceResponse.h"
  34. #include <wtf/MathExtras.h>
  35. #include <wtf/StdLibExtras.h>
  36. #include <wtf/text/StringView.h>
  37. namespace WebCore {
  38. bool isScriptAllowedByNosniff(const ResourceResponse& response)
  39. {
  40. if (parseContentTypeOptionsHeader(response.httpHeaderField(HTTPHeaderName::XContentTypeOptions)) != ContentTypeOptionsDisposition::Nosniff)
  41. return true;
  42. String mimeType = extractMIMETypeFromMediaType(response.httpHeaderField(HTTPHeaderName::ContentType));
  43. return MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType);
  44. }
  45. ResourceResponseBase::ResourceResponseBase()
  46. : m_haveParsedCacheControlHeader(false)
  47. , m_haveParsedAgeHeader(false)
  48. , m_haveParsedDateHeader(false)
  49. , m_haveParsedExpiresHeader(false)
  50. , m_haveParsedLastModifiedHeader(false)
  51. , m_haveParsedContentRangeHeader(false)
  52. , m_isRedirected(false)
  53. , m_isRangeRequested(false)
  54. , m_isNull(true)
  55. , m_usedLegacyTLS(UsedLegacyTLS::No)
  56. , m_tainting(Tainting::Basic)
  57. , m_source(Source::Unknown)
  58. , m_type(Type::Default)
  59. {
  60. }
  61. ResourceResponseBase::ResourceResponseBase(const URL& url, const String& mimeType, long long expectedLength, const String& textEncodingName)
  62. : m_url(url)
  63. , m_mimeType(mimeType)
  64. , m_expectedContentLength(expectedLength)
  65. , m_textEncodingName(textEncodingName)
  66. , m_certificateInfo(CertificateInfo()) // Empty but valid for synthetic responses.
  67. , m_haveParsedCacheControlHeader(false)
  68. , m_haveParsedAgeHeader(false)
  69. , m_haveParsedDateHeader(false)
  70. , m_haveParsedExpiresHeader(false)
  71. , m_haveParsedLastModifiedHeader(false)
  72. , m_haveParsedContentRangeHeader(false)
  73. , m_isRedirected(false)
  74. , m_isRangeRequested(false)
  75. , m_isNull(false)
  76. , m_usedLegacyTLS(UsedLegacyTLS::No)
  77. , m_tainting(Tainting::Basic)
  78. , m_source(Source::Unknown)
  79. , m_type(Type::Default)
  80. {
  81. }
  82. ResourceResponseBase::CrossThreadData ResourceResponseBase::crossThreadData() const
  83. {
  84. CrossThreadData data;
  85. data.url = url().isolatedCopy();
  86. data.mimeType = mimeType().isolatedCopy();
  87. data.expectedContentLength = expectedContentLength();
  88. data.textEncodingName = textEncodingName().isolatedCopy();
  89. data.httpStatusCode = httpStatusCode();
  90. data.httpStatusText = httpStatusText().isolatedCopy();
  91. data.httpVersion = httpVersion().isolatedCopy();
  92. data.httpHeaderFields = httpHeaderFields().isolatedCopy();
  93. if (m_networkLoadMetrics)
  94. data.networkLoadMetrics = m_networkLoadMetrics->isolatedCopy();
  95. data.type = m_type;
  96. data.tainting = m_tainting;
  97. data.isRedirected = m_isRedirected;
  98. data.isRangeRequested = m_isRangeRequested;
  99. return data;
  100. }
  101. ResourceResponse ResourceResponseBase::fromCrossThreadData(CrossThreadData&& data)
  102. {
  103. ResourceResponse response;
  104. response.setURL(data.url);
  105. response.setMimeType(data.mimeType);
  106. response.setExpectedContentLength(data.expectedContentLength);
  107. response.setTextEncodingName(data.textEncodingName);
  108. response.setHTTPStatusCode(data.httpStatusCode);
  109. response.setHTTPStatusText(data.httpStatusText);
  110. response.setHTTPVersion(data.httpVersion);
  111. response.m_httpHeaderFields = WTFMove(data.httpHeaderFields);
  112. if (data.networkLoadMetrics)
  113. response.m_networkLoadMetrics = Box<NetworkLoadMetrics>::create(WTFMove(data.networkLoadMetrics.value()));
  114. else
  115. response.m_networkLoadMetrics = nullptr;
  116. response.m_type = data.type;
  117. response.m_tainting = data.tainting;
  118. response.m_isRedirected = data.isRedirected;
  119. response.m_isRangeRequested = data.isRangeRequested;
  120. return response;
  121. }
  122. ResourceResponse ResourceResponseBase::syntheticRedirectResponse(const URL& fromURL, const URL& toURL)
  123. {
  124. ResourceResponse redirectResponse;
  125. redirectResponse.setURL(fromURL);
  126. redirectResponse.setHTTPStatusCode(302);
  127. redirectResponse.setHTTPVersion("HTTP/1.1"_s);
  128. redirectResponse.setHTTPHeaderField(HTTPHeaderName::Location, toURL.string());
  129. redirectResponse.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-store"_s);
  130. return redirectResponse;
  131. }
  132. ResourceResponse ResourceResponseBase::filter(const ResourceResponse& response, PerformExposeAllHeadersCheck performCheck)
  133. {
  134. if (response.tainting() == Tainting::Opaque) {
  135. ResourceResponse opaqueResponse;
  136. opaqueResponse.setTainting(Tainting::Opaque);
  137. opaqueResponse.setType(Type::Opaque);
  138. return opaqueResponse;
  139. }
  140. if (response.tainting() == Tainting::Opaqueredirect) {
  141. ResourceResponse opaqueResponse;
  142. opaqueResponse.setTainting(Tainting::Opaqueredirect);
  143. opaqueResponse.setType(Type::Opaqueredirect);
  144. opaqueResponse.setURL(response.url());
  145. return opaqueResponse;
  146. }
  147. ResourceResponse filteredResponse = response;
  148. // Let's initialize filteredResponse to remove some header fields.
  149. filteredResponse.lazyInit(AllFields);
  150. filteredResponse.m_httpHeaderFields.remove(HTTPHeaderName::SetCookie);
  151. filteredResponse.m_httpHeaderFields.remove(HTTPHeaderName::SetCookie2);
  152. if (response.tainting() == Tainting::Basic) {
  153. filteredResponse.setType(Type::Basic);
  154. return filteredResponse;
  155. }
  156. ASSERT(response.tainting() == Tainting::Cors);
  157. filteredResponse.setType(Type::Cors);
  158. auto accessControlExposeHeaderSet = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(response.httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders)).valueOr(HashSet<String, ASCIICaseInsensitiveHash> { });
  159. if (performCheck == PerformExposeAllHeadersCheck::Yes && accessControlExposeHeaderSet.contains("*"))
  160. return filteredResponse;
  161. filteredResponse.m_httpHeaderFields.uncommonHeaders().removeAllMatching([&](auto& entry) {
  162. return !isCrossOriginSafeHeader(entry.key, accessControlExposeHeaderSet);
  163. });
  164. filteredResponse.m_httpHeaderFields.commonHeaders().removeAllMatching([&](auto& entry) {
  165. return !isCrossOriginSafeHeader(entry.key, accessControlExposeHeaderSet);
  166. });
  167. return filteredResponse;
  168. }
  169. bool ResourceResponseBase::isInHTTPFamily() const
  170. {
  171. lazyInit(CommonFieldsOnly);
  172. return m_url.protocolIsInHTTPFamily();
  173. }
  174. const URL& ResourceResponseBase::url() const
  175. {
  176. lazyInit(CommonFieldsOnly);
  177. return m_url;
  178. }
  179. void ResourceResponseBase::setURL(const URL& url)
  180. {
  181. lazyInit(CommonFieldsOnly);
  182. m_isNull = false;
  183. m_url = url;
  184. // FIXME: Should invalidate or update platform response if present.
  185. }
  186. const String& ResourceResponseBase::mimeType() const
  187. {
  188. lazyInit(CommonFieldsOnly);
  189. return m_mimeType;
  190. }
  191. void ResourceResponseBase::setMimeType(const String& mimeType)
  192. {
  193. lazyInit(CommonFieldsOnly);
  194. m_isNull = false;
  195. // FIXME: MIME type is determined by HTTP Content-Type header. We should update the header, so that it doesn't disagree with m_mimeType.
  196. m_mimeType = mimeType;
  197. // FIXME: Should invalidate or update platform response if present.
  198. }
  199. long long ResourceResponseBase::expectedContentLength() const
  200. {
  201. lazyInit(CommonFieldsOnly);
  202. return m_expectedContentLength;
  203. }
  204. void ResourceResponseBase::setExpectedContentLength(long long expectedContentLength)
  205. {
  206. lazyInit(CommonFieldsOnly);
  207. m_isNull = false;
  208. // FIXME: Content length is determined by HTTP Content-Length header. We should update the header, so that it doesn't disagree with m_expectedContentLength.
  209. m_expectedContentLength = expectedContentLength;
  210. // FIXME: Should invalidate or update platform response if present.
  211. }
  212. const String& ResourceResponseBase::textEncodingName() const
  213. {
  214. lazyInit(CommonFieldsOnly);
  215. return m_textEncodingName;
  216. }
  217. void ResourceResponseBase::setTextEncodingName(const String& encodingName)
  218. {
  219. lazyInit(CommonFieldsOnly);
  220. m_isNull = false;
  221. // FIXME: Text encoding is determined by HTTP Content-Type header. We should update the header, so that it doesn't disagree with m_textEncodingName.
  222. m_textEncodingName = encodingName;
  223. // FIXME: Should invalidate or update platform response if present.
  224. }
  225. void ResourceResponseBase::setType(Type type)
  226. {
  227. m_isNull = false;
  228. m_type = type;
  229. }
  230. void ResourceResponseBase::includeCertificateInfo() const
  231. {
  232. if (m_certificateInfo)
  233. return;
  234. m_certificateInfo = static_cast<const ResourceResponse*>(this)->platformCertificateInfo();
  235. }
  236. String ResourceResponseBase::suggestedFilename() const
  237. {
  238. return static_cast<const ResourceResponse*>(this)->platformSuggestedFilename();
  239. }
  240. String ResourceResponseBase::sanitizeSuggestedFilename(const String& suggestedFilename)
  241. {
  242. if (suggestedFilename.isEmpty())
  243. return suggestedFilename;
  244. ResourceResponse response(URL({ }, "http://example.com/"), String(), -1, String());
  245. response.setHTTPStatusCode(200);
  246. String escapedSuggestedFilename = String(suggestedFilename).replace('\\', "\\\\").replace('"', "\\\"");
  247. String value = makeString("attachment; filename=\"", escapedSuggestedFilename, '"');
  248. response.setHTTPHeaderField(HTTPHeaderName::ContentDisposition, value);
  249. return response.suggestedFilename();
  250. }
  251. bool ResourceResponseBase::isSuccessful() const
  252. {
  253. int code = httpStatusCode();
  254. return code >= 200 && code < 300;
  255. }
  256. int ResourceResponseBase::httpStatusCode() const
  257. {
  258. lazyInit(CommonFieldsOnly);
  259. return m_httpStatusCode;
  260. }
  261. void ResourceResponseBase::setHTTPStatusCode(int statusCode)
  262. {
  263. lazyInit(CommonFieldsOnly);
  264. m_httpStatusCode = statusCode;
  265. m_isNull = false;
  266. // FIXME: Should invalidate or update platform response if present.
  267. }
  268. bool ResourceResponseBase::isRedirection() const
  269. {
  270. return isRedirectionStatusCode(m_httpStatusCode);
  271. }
  272. const String& ResourceResponseBase::httpStatusText() const
  273. {
  274. lazyInit(AllFields);
  275. return m_httpStatusText;
  276. }
  277. void ResourceResponseBase::setHTTPStatusText(const String& statusText)
  278. {
  279. lazyInit(AllFields);
  280. m_httpStatusText = statusText;
  281. // FIXME: Should invalidate or update platform response if present.
  282. }
  283. const String& ResourceResponseBase::httpVersion() const
  284. {
  285. lazyInit(AllFields);
  286. return m_httpVersion;
  287. }
  288. void ResourceResponseBase::setHTTPVersion(const String& versionText)
  289. {
  290. lazyInit(AllFields);
  291. m_httpVersion = versionText;
  292. // FIXME: Should invalidate or update platform response if present.
  293. }
  294. static bool isSafeRedirectionResponseHeader(HTTPHeaderName name)
  295. {
  296. // WebCore needs to keep location and cache related headers as it does caching.
  297. // We also keep CORS/ReferrerPolicy headers until CORS checks/Referrer computation are done in NetworkProcess.
  298. return name == HTTPHeaderName::Location
  299. || name == HTTPHeaderName::ReferrerPolicy
  300. || name == HTTPHeaderName::CacheControl
  301. || name == HTTPHeaderName::Date
  302. || name == HTTPHeaderName::Expires
  303. || name == HTTPHeaderName::ETag
  304. || name == HTTPHeaderName::LastModified
  305. || name == HTTPHeaderName::Age
  306. || name == HTTPHeaderName::Pragma
  307. || name == HTTPHeaderName::ReferrerPolicy
  308. || name == HTTPHeaderName::Refresh
  309. || name == HTTPHeaderName::Vary
  310. || name == HTTPHeaderName::AccessControlAllowCredentials
  311. || name == HTTPHeaderName::AccessControlAllowHeaders
  312. || name == HTTPHeaderName::AccessControlAllowMethods
  313. || name == HTTPHeaderName::AccessControlAllowOrigin
  314. || name == HTTPHeaderName::AccessControlExposeHeaders
  315. || name == HTTPHeaderName::AccessControlMaxAge
  316. || name == HTTPHeaderName::CrossOriginResourcePolicy
  317. || name == HTTPHeaderName::TimingAllowOrigin;
  318. }
  319. static bool isSafeCrossOriginResponseHeader(HTTPHeaderName name)
  320. {
  321. // All known response headers used in WebProcesses.
  322. return name == HTTPHeaderName::AcceptRanges
  323. || name == HTTPHeaderName::AccessControlAllowCredentials
  324. || name == HTTPHeaderName::AccessControlAllowHeaders
  325. || name == HTTPHeaderName::AccessControlAllowMethods
  326. || name == HTTPHeaderName::AccessControlAllowOrigin
  327. || name == HTTPHeaderName::AccessControlExposeHeaders
  328. || name == HTTPHeaderName::AccessControlMaxAge
  329. || name == HTTPHeaderName::AccessControlRequestHeaders
  330. || name == HTTPHeaderName::AccessControlRequestMethod
  331. || name == HTTPHeaderName::Age
  332. || name == HTTPHeaderName::CacheControl
  333. || name == HTTPHeaderName::ContentDisposition
  334. || name == HTTPHeaderName::ContentEncoding
  335. || name == HTTPHeaderName::ContentLanguage
  336. || name == HTTPHeaderName::ContentLength
  337. || name == HTTPHeaderName::ContentRange
  338. || name == HTTPHeaderName::ContentSecurityPolicy
  339. || name == HTTPHeaderName::ContentSecurityPolicyReportOnly
  340. || name == HTTPHeaderName::ContentType
  341. || name == HTTPHeaderName::CrossOriginResourcePolicy
  342. || name == HTTPHeaderName::Date
  343. || name == HTTPHeaderName::ETag
  344. || name == HTTPHeaderName::Expires
  345. || name == HTTPHeaderName::IcyMetaInt
  346. || name == HTTPHeaderName::IcyMetadata
  347. || name == HTTPHeaderName::LastEventID
  348. || name == HTTPHeaderName::LastModified
  349. || name == HTTPHeaderName::Link
  350. || name == HTTPHeaderName::Location
  351. || name == HTTPHeaderName::Pragma
  352. || name == HTTPHeaderName::Range
  353. || name == HTTPHeaderName::ReferrerPolicy
  354. || name == HTTPHeaderName::Refresh
  355. || name == HTTPHeaderName::ServerTiming
  356. || name == HTTPHeaderName::SourceMap
  357. || name == HTTPHeaderName::XSourceMap
  358. || name == HTTPHeaderName::TimingAllowOrigin
  359. || name == HTTPHeaderName::Trailer
  360. || name == HTTPHeaderName::Vary
  361. || name == HTTPHeaderName::XContentTypeOptions
  362. || name == HTTPHeaderName::XDNSPrefetchControl
  363. || name == HTTPHeaderName::XFrameOptions
  364. || name == HTTPHeaderName::XXSSProtection;
  365. }
  366. void ResourceResponseBase::sanitizeHTTPHeaderFieldsAccordingToTainting()
  367. {
  368. if(m_tainting == ResourceResponse::Tainting::Basic) {
  369. return;
  370. }
  371. else if(m_tainting == ResourceResponse::Tainting::Cors) {
  372. auto corsSafeHeaderSet = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders)).valueOr(HashSet<String, ASCIICaseInsensitiveHash> { });
  373. if (corsSafeHeaderSet.contains("*"))
  374. return;
  375. HTTPHeaderMap filteredHeaders;
  376. for (auto& header : m_httpHeaderFields.commonHeaders()) {
  377. if (isSafeCrossOriginResponseHeader(header.key))
  378. filteredHeaders.add(header.key, WTFMove(header.value));
  379. }
  380. for (auto& headerName : corsSafeHeaderSet) {
  381. if (!filteredHeaders.contains(headerName)) {
  382. auto value = m_httpHeaderFields.get(headerName);
  383. if (!value.isNull())
  384. filteredHeaders.add(headerName, value);
  385. }
  386. }
  387. m_httpHeaderFields = WTFMove(filteredHeaders);
  388. return;
  389. } else if((ResourceResponse::Tainting::Opaque ==m_tainting) ||
  390. (ResourceResponse::Tainting::Opaqueredirect == m_tainting)) {
  391. HTTPHeaderMap filteredHeaders;
  392. for (auto& header : m_httpHeaderFields.commonHeaders()) {
  393. if (isSafeCrossOriginResponseHeader(header.key))
  394. filteredHeaders.add(header.key, WTFMove(header.value));
  395. }
  396. m_httpHeaderFields = WTFMove(filteredHeaders);
  397. return;
  398. } else {
  399. return;
  400. }
  401. #if 0
  402. switch (m_tainting) {
  403. case ResourceResponse::Tainting::Basic:
  404. return;
  405. case ResourceResponse::Tainting::Cors: {
  406. auto corsSafeHeaderSet = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders)).valueOr(HashSet<String, ASCIICaseInsensitiveHash> { });
  407. if (corsSafeHeaderSet.contains("*"))
  408. return;
  409. HTTPHeaderMap filteredHeaders;
  410. for (auto& header : m_httpHeaderFields.commonHeaders()) {
  411. if (isSafeCrossOriginResponseHeader(header.key))
  412. filteredHeaders.add(header.key, WTFMove(header.value));
  413. }
  414. for (auto& headerName : corsSafeHeaderSet) {
  415. if (!filteredHeaders.contains(headerName)) {
  416. auto value = m_httpHeaderFields.get(headerName);
  417. if (!value.isNull())
  418. filteredHeaders.add(headerName, value);
  419. }
  420. }
  421. m_httpHeaderFields = WTFMove(filteredHeaders);
  422. return;
  423. }
  424. case ResourceResponse::Tainting::Opaque:
  425. case ResourceResponse::Tainting::Opaqueredirect: {
  426. HTTPHeaderMap filteredHeaders;
  427. for (auto& header : m_httpHeaderFields.commonHeaders()) {
  428. if (isSafeCrossOriginResponseHeader(header.key))
  429. filteredHeaders.add(header.key, WTFMove(header.value));
  430. }
  431. m_httpHeaderFields = WTFMove(filteredHeaders);
  432. return;
  433. }
  434. }
  435. #endif
  436. }
  437. void ResourceResponseBase::sanitizeHTTPHeaderFields(SanitizationType type)
  438. {
  439. lazyInit(AllFields);
  440. m_httpHeaderFields.remove(HTTPHeaderName::SetCookie);
  441. m_httpHeaderFields.remove(HTTPHeaderName::SetCookie2);
  442. switch (type) {
  443. case SanitizationType::RemoveCookies:
  444. return;
  445. case SanitizationType::Redirection: {
  446. auto commonHeaders = WTFMove(m_httpHeaderFields.commonHeaders());
  447. for (auto& header : commonHeaders) {
  448. if (isSafeRedirectionResponseHeader(header.key))
  449. m_httpHeaderFields.add(header.key, WTFMove(header.value));
  450. }
  451. m_httpHeaderFields.uncommonHeaders().clear();
  452. return;
  453. }
  454. case SanitizationType::CrossOriginSafe:
  455. sanitizeHTTPHeaderFieldsAccordingToTainting();
  456. }
  457. }
  458. bool ResourceResponseBase::isHTTP09() const
  459. {
  460. lazyInit(AllFields);
  461. return m_httpVersion.startsWith("HTTP/0.9");
  462. }
  463. String ResourceResponseBase::httpHeaderField(const String& name) const
  464. {
  465. lazyInit(CommonFieldsOnly);
  466. // If we already have the header, just return it instead of consuming memory by grabing all headers.
  467. String value = m_httpHeaderFields.get(name);
  468. if (!value.isEmpty())
  469. return value;
  470. lazyInit(AllFields);
  471. return m_httpHeaderFields.get(name);
  472. }
  473. String ResourceResponseBase::httpHeaderField(HTTPHeaderName name) const
  474. {
  475. lazyInit(CommonFieldsOnly);
  476. // If we already have the header, just return it instead of consuming memory by grabing all headers.
  477. String value = m_httpHeaderFields.get(name);
  478. if (!value.isEmpty())
  479. return value;
  480. lazyInit(AllFields);
  481. return m_httpHeaderFields.get(name);
  482. }
  483. void ResourceResponseBase::updateHeaderParsedState(HTTPHeaderName name)
  484. {
  485. switch (name) {
  486. case HTTPHeaderName::Age:
  487. m_haveParsedAgeHeader = false;
  488. break;
  489. case HTTPHeaderName::CacheControl:
  490. case HTTPHeaderName::Pragma:
  491. m_haveParsedCacheControlHeader = false;
  492. break;
  493. case HTTPHeaderName::Date:
  494. m_haveParsedDateHeader = false;
  495. break;
  496. case HTTPHeaderName::Expires:
  497. m_haveParsedExpiresHeader = false;
  498. break;
  499. case HTTPHeaderName::LastModified:
  500. m_haveParsedLastModifiedHeader = false;
  501. break;
  502. case HTTPHeaderName::ContentRange:
  503. m_haveParsedContentRangeHeader = false;
  504. break;
  505. default:
  506. break;
  507. }
  508. }
  509. void ResourceResponseBase::setHTTPHeaderField(const String& name, const String& value)
  510. {
  511. lazyInit(AllFields);
  512. HTTPHeaderName headerName;
  513. if (findHTTPHeaderName(name, headerName))
  514. updateHeaderParsedState(headerName);
  515. m_httpHeaderFields.set(name, value);
  516. // FIXME: Should invalidate or update platform response if present.
  517. }
  518. void ResourceResponseBase::setHTTPHeaderFields(HTTPHeaderMap&& headerFields)
  519. {
  520. lazyInit(AllFields);
  521. m_httpHeaderFields = WTFMove(headerFields);
  522. }
  523. void ResourceResponseBase::setHTTPHeaderField(HTTPHeaderName name, const String& value)
  524. {
  525. lazyInit(AllFields);
  526. updateHeaderParsedState(name);
  527. m_httpHeaderFields.set(name, value);
  528. // FIXME: Should invalidate or update platform response if present.
  529. }
  530. void ResourceResponseBase::addHTTPHeaderField(HTTPHeaderName name, const String& value)
  531. {
  532. lazyInit(AllFields);
  533. updateHeaderParsedState(name);
  534. m_httpHeaderFields.add(name, value);
  535. }
  536. void ResourceResponseBase::addHTTPHeaderField(const String& name, const String& value)
  537. {
  538. HTTPHeaderName headerName;
  539. if (findHTTPHeaderName(name, headerName))
  540. addHTTPHeaderField(headerName, value);
  541. else {
  542. lazyInit(AllFields);
  543. m_httpHeaderFields.add(name, value);
  544. }
  545. }
  546. const HTTPHeaderMap& ResourceResponseBase::httpHeaderFields() const
  547. {
  548. lazyInit(AllFields);
  549. return m_httpHeaderFields;
  550. }
  551. void ResourceResponseBase::parseCacheControlDirectives() const
  552. {
  553. ASSERT(!m_haveParsedCacheControlHeader);
  554. lazyInit(CommonFieldsOnly);
  555. m_cacheControlDirectives = WebCore::parseCacheControlDirectives(m_httpHeaderFields);
  556. m_haveParsedCacheControlHeader = true;
  557. }
  558. bool ResourceResponseBase::cacheControlContainsNoCache() const
  559. {
  560. if (!m_haveParsedCacheControlHeader)
  561. parseCacheControlDirectives();
  562. return m_cacheControlDirectives.noCache;
  563. }
  564. bool ResourceResponseBase::cacheControlContainsNoStore() const
  565. {
  566. if (!m_haveParsedCacheControlHeader)
  567. parseCacheControlDirectives();
  568. return m_cacheControlDirectives.noStore;
  569. }
  570. bool ResourceResponseBase::cacheControlContainsMustRevalidate() const
  571. {
  572. if (!m_haveParsedCacheControlHeader)
  573. parseCacheControlDirectives();
  574. return m_cacheControlDirectives.mustRevalidate;
  575. }
  576. bool ResourceResponseBase::cacheControlContainsImmutable() const
  577. {
  578. if (!m_haveParsedCacheControlHeader)
  579. parseCacheControlDirectives();
  580. return m_cacheControlDirectives.immutable;
  581. }
  582. bool ResourceResponseBase::hasCacheValidatorFields() const
  583. {
  584. lazyInit(CommonFieldsOnly);
  585. return !m_httpHeaderFields.get(HTTPHeaderName::LastModified).isEmpty() || !m_httpHeaderFields.get(HTTPHeaderName::ETag).isEmpty();
  586. }
  587. Optional<Seconds> ResourceResponseBase::cacheControlMaxAge() const
  588. {
  589. if (!m_haveParsedCacheControlHeader)
  590. parseCacheControlDirectives();
  591. return m_cacheControlDirectives.maxAge;
  592. }
  593. Optional<Seconds> ResourceResponseBase::cacheControlStaleWhileRevalidate() const
  594. {
  595. if (!m_haveParsedCacheControlHeader)
  596. parseCacheControlDirectives();
  597. return m_cacheControlDirectives.staleWhileRevalidate;
  598. }
  599. static Optional<WallTime> parseDateValueInHeader(const HTTPHeaderMap& headers, HTTPHeaderName headerName)
  600. {
  601. String headerValue = headers.get(headerName);
  602. if (headerValue.isEmpty())
  603. return WTF::nullopt;
  604. // This handles all date formats required by RFC2616:
  605. // Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
  606. // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
  607. // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
  608. return parseHTTPDate(headerValue);
  609. }
  610. Optional<WallTime> ResourceResponseBase::date() const
  611. {
  612. lazyInit(CommonFieldsOnly);
  613. if (!m_haveParsedDateHeader) {
  614. m_date = parseDateValueInHeader(m_httpHeaderFields, HTTPHeaderName::Date);
  615. m_haveParsedDateHeader = true;
  616. }
  617. return m_date;
  618. }
  619. Optional<Seconds> ResourceResponseBase::age() const
  620. {
  621. lazyInit(CommonFieldsOnly);
  622. if (!m_haveParsedAgeHeader) {
  623. String headerValue = m_httpHeaderFields.get(HTTPHeaderName::Age);
  624. bool ok;
  625. double ageDouble = headerValue.toDouble(&ok);
  626. if (ok)
  627. m_age = Seconds { ageDouble };
  628. m_haveParsedAgeHeader = true;
  629. }
  630. return m_age;
  631. }
  632. Optional<WallTime> ResourceResponseBase::expires() const
  633. {
  634. lazyInit(CommonFieldsOnly);
  635. if (!m_haveParsedExpiresHeader) {
  636. m_expires = parseDateValueInHeader(m_httpHeaderFields, HTTPHeaderName::Expires);
  637. m_haveParsedExpiresHeader = true;
  638. }
  639. return m_expires;
  640. }
  641. Optional<WallTime> ResourceResponseBase::lastModified() const
  642. {
  643. lazyInit(CommonFieldsOnly);
  644. if (!m_haveParsedLastModifiedHeader) {
  645. m_lastModified = parseDateValueInHeader(m_httpHeaderFields, HTTPHeaderName::LastModified);
  646. #if PLATFORM(COCOA)
  647. // CFNetwork converts malformed dates into Epoch so we need to treat Epoch as
  648. // an invalid value (rdar://problem/22352838).
  649. const WallTime epoch = WallTime::fromRawSeconds(0);
  650. if (m_lastModified && m_lastModified.value() == epoch)
  651. m_lastModified = WTF::nullopt;
  652. #endif
  653. m_haveParsedLastModifiedHeader = true;
  654. }
  655. return m_lastModified;
  656. }
  657. static ParsedContentRange parseContentRangeInHeader(const HTTPHeaderMap& headers)
  658. {
  659. String contentRangeValue = headers.get(HTTPHeaderName::ContentRange);
  660. if (contentRangeValue.isEmpty())
  661. return ParsedContentRange();
  662. return ParsedContentRange(contentRangeValue);
  663. }
  664. const ParsedContentRange& ResourceResponseBase::contentRange() const
  665. {
  666. lazyInit(CommonFieldsOnly);
  667. if (!m_haveParsedContentRangeHeader) {
  668. m_contentRange = parseContentRangeInHeader(m_httpHeaderFields);
  669. m_haveParsedContentRangeHeader = true;
  670. }
  671. return m_contentRange;
  672. }
  673. bool ResourceResponseBase::isAttachment() const
  674. {
  675. lazyInit(AllFields);
  676. auto value = m_httpHeaderFields.get(HTTPHeaderName::ContentDisposition);
  677. return equalLettersIgnoringASCIICase(value.left(value.find(';')).stripWhiteSpace(), "attachment");
  678. }
  679. bool ResourceResponseBase::isAttachmentWithFilename() const
  680. {
  681. lazyInit(AllFields);
  682. String contentDisposition = m_httpHeaderFields.get(HTTPHeaderName::ContentDisposition);
  683. if (contentDisposition.isNull())
  684. return false;
  685. if (!equalLettersIgnoringASCIICase(contentDisposition.left(contentDisposition.find(';')).stripWhiteSpace(), "attachment"))
  686. return false;
  687. String filename = filenameFromHTTPContentDisposition(contentDisposition);
  688. return !filename.isNull();
  689. }
  690. ResourceResponseBase::Source ResourceResponseBase::source() const
  691. {
  692. lazyInit(AllFields);
  693. return m_source;
  694. }
  695. void ResourceResponseBase::lazyInit(InitLevel initLevel) const
  696. {
  697. const_cast<ResourceResponse*>(static_cast<const ResourceResponse*>(this))->platformLazyInit(initLevel);
  698. }
  699. bool ResourceResponseBase::compare(const ResourceResponse& a, const ResourceResponse& b)
  700. {
  701. if (a.isNull() != b.isNull())
  702. return false;
  703. if (a.url() != b.url())
  704. return false;
  705. if (a.mimeType() != b.mimeType())
  706. return false;
  707. if (a.expectedContentLength() != b.expectedContentLength())
  708. return false;
  709. if (a.textEncodingName() != b.textEncodingName())
  710. return false;
  711. if (a.suggestedFilename() != b.suggestedFilename())
  712. return false;
  713. if (a.httpStatusCode() != b.httpStatusCode())
  714. return false;
  715. if (a.httpStatusText() != b.httpStatusText())
  716. return false;
  717. if (a.httpHeaderFields() != b.httpHeaderFields())
  718. return false;
  719. if (a.m_networkLoadMetrics.get() != b.m_networkLoadMetrics.get()) {
  720. if (!a.m_networkLoadMetrics) {
  721. if (NetworkLoadMetrics() != *b.m_networkLoadMetrics.get())
  722. return false;
  723. } else if (!b.m_networkLoadMetrics) {
  724. if (NetworkLoadMetrics() != *a.m_networkLoadMetrics.get())
  725. return false;
  726. } else if (*a.m_networkLoadMetrics.get() != *b.m_networkLoadMetrics.get())
  727. return false;
  728. }
  729. return ResourceResponse::platformCompare(a, b);
  730. }
  731. bool ResourceResponseBase::containsInvalidHTTPHeaders() const
  732. {
  733. for (auto& header : httpHeaderFields()) {
  734. if (!isValidHTTPHeaderValue(stripLeadingAndTrailingHTTPSpaces(header.value)))
  735. return true;
  736. }
  737. return false;
  738. }
  739. }