| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2006, 2008 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 COMPUTER, 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 COMPUTER, 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 #include "platform/network/ResourceResponse.h" | |
| 28 | |
| 29 #include "platform/HTTPNames.h" | |
| 30 #include "platform/network/HTTPParsers.h" | |
| 31 #include "wtf/CurrentTime.h" | |
| 32 #include "wtf/PtrUtil.h" | |
| 33 #include "wtf/StdLibExtras.h" | |
| 34 | |
| 35 #include <memory> | |
| 36 | |
| 37 namespace blink { | |
| 38 | |
| 39 namespace { | |
| 40 | |
| 41 template <typename Interface> | |
| 42 Vector<Interface> isolatedCopy(const Vector<Interface>& src) { | |
| 43 Vector<Interface> result; | |
| 44 result.reserveCapacity(src.size()); | |
| 45 for (const auto& timestamp : src) { | |
| 46 result.push_back(timestamp.isolatedCopy()); | |
| 47 } | |
| 48 return result; | |
| 49 } | |
| 50 | |
| 51 static const char cacheControlHeader[] = "cache-control"; | |
| 52 static const char pragmaHeader[] = "pragma"; | |
| 53 | |
| 54 } // namespace | |
| 55 | |
| 56 ResourceResponse::SignedCertificateTimestamp::SignedCertificateTimestamp( | |
| 57 const blink::WebURLResponse::SignedCertificateTimestamp& sct) | |
| 58 : m_status(sct.status), | |
| 59 m_origin(sct.origin), | |
| 60 m_logDescription(sct.logDescription), | |
| 61 m_logId(sct.logId), | |
| 62 m_timestamp(sct.timestamp), | |
| 63 m_hashAlgorithm(sct.hashAlgorithm), | |
| 64 m_signatureAlgorithm(sct.signatureAlgorithm), | |
| 65 m_signatureData(sct.signatureData) {} | |
| 66 | |
| 67 ResourceResponse::SignedCertificateTimestamp | |
| 68 ResourceResponse::SignedCertificateTimestamp::isolatedCopy() const { | |
| 69 return SignedCertificateTimestamp( | |
| 70 m_status.isolatedCopy(), m_origin.isolatedCopy(), | |
| 71 m_logDescription.isolatedCopy(), m_logId.isolatedCopy(), m_timestamp, | |
| 72 m_hashAlgorithm.isolatedCopy(), m_signatureAlgorithm.isolatedCopy(), | |
| 73 m_signatureData.isolatedCopy()); | |
| 74 } | |
| 75 | |
| 76 ResourceResponse::ResourceResponse() | |
| 77 : m_expectedContentLength(0), | |
| 78 m_httpStatusCode(0), | |
| 79 m_wasCached(false), | |
| 80 m_connectionID(0), | |
| 81 m_connectionReused(false), | |
| 82 m_isNull(true), | |
| 83 m_haveParsedAgeHeader(false), | |
| 84 m_haveParsedDateHeader(false), | |
| 85 m_haveParsedExpiresHeader(false), | |
| 86 m_haveParsedLastModifiedHeader(false), | |
| 87 m_age(0.0), | |
| 88 m_date(0.0), | |
| 89 m_expires(0.0), | |
| 90 m_lastModified(0.0), | |
| 91 m_hasMajorCertificateErrors(false), | |
| 92 m_securityStyle(SecurityStyleUnknown), | |
| 93 m_httpVersion(HTTPVersionUnknown), | |
| 94 m_appCacheID(0), | |
| 95 m_wasFetchedViaSPDY(false), | |
| 96 m_wasFetchedViaProxy(false), | |
| 97 m_wasFetchedViaServiceWorker(false), | |
| 98 m_wasFetchedViaForeignFetch(false), | |
| 99 m_wasFallbackRequiredByServiceWorker(false), | |
| 100 m_serviceWorkerResponseType(WebServiceWorkerResponseTypeDefault), | |
| 101 m_didServiceWorkerNavigationPreload(false), | |
| 102 m_responseTime(0), | |
| 103 m_remotePort(0), | |
| 104 m_encodedDataLength(0), | |
| 105 m_encodedBodyLength(0), | |
| 106 m_decodedBodyLength(0) {} | |
| 107 | |
| 108 ResourceResponse::ResourceResponse(const KURL& url, | |
| 109 const AtomicString& mimeType, | |
| 110 long long expectedLength, | |
| 111 const AtomicString& textEncodingName) | |
| 112 : m_url(url), | |
| 113 m_mimeType(mimeType), | |
| 114 m_expectedContentLength(expectedLength), | |
| 115 m_textEncodingName(textEncodingName), | |
| 116 m_httpStatusCode(0), | |
| 117 m_wasCached(false), | |
| 118 m_connectionID(0), | |
| 119 m_connectionReused(false), | |
| 120 m_isNull(false), | |
| 121 m_haveParsedAgeHeader(false), | |
| 122 m_haveParsedDateHeader(false), | |
| 123 m_haveParsedExpiresHeader(false), | |
| 124 m_haveParsedLastModifiedHeader(false), | |
| 125 m_age(0.0), | |
| 126 m_date(0.0), | |
| 127 m_expires(0.0), | |
| 128 m_lastModified(0.0), | |
| 129 m_hasMajorCertificateErrors(false), | |
| 130 m_securityStyle(SecurityStyleUnknown), | |
| 131 m_httpVersion(HTTPVersionUnknown), | |
| 132 m_appCacheID(0), | |
| 133 m_wasFetchedViaSPDY(false), | |
| 134 m_wasFetchedViaProxy(false), | |
| 135 m_wasFetchedViaServiceWorker(false), | |
| 136 m_wasFetchedViaForeignFetch(false), | |
| 137 m_wasFallbackRequiredByServiceWorker(false), | |
| 138 m_serviceWorkerResponseType(WebServiceWorkerResponseTypeDefault), | |
| 139 m_didServiceWorkerNavigationPreload(false), | |
| 140 m_responseTime(0), | |
| 141 m_remotePort(0), | |
| 142 m_encodedDataLength(0), | |
| 143 m_encodedBodyLength(0), | |
| 144 m_decodedBodyLength(0) {} | |
| 145 | |
| 146 ResourceResponse::ResourceResponse(CrossThreadResourceResponseData* data) | |
| 147 : ResourceResponse() { | |
| 148 setURL(data->m_url); | |
| 149 setMimeType(AtomicString(data->m_mimeType)); | |
| 150 setExpectedContentLength(data->m_expectedContentLength); | |
| 151 setTextEncodingName(AtomicString(data->m_textEncodingName)); | |
| 152 | |
| 153 setHTTPStatusCode(data->m_httpStatusCode); | |
| 154 setHTTPStatusText(AtomicString(data->m_httpStatusText)); | |
| 155 | |
| 156 m_httpHeaderFields.adopt(std::move(data->m_httpHeaders)); | |
| 157 setResourceLoadTiming(data->m_resourceLoadTiming.release()); | |
| 158 m_hasMajorCertificateErrors = data->m_hasMajorCertificateErrors; | |
| 159 m_securityStyle = data->m_securityStyle; | |
| 160 m_securityDetails.protocol = data->m_securityDetails.protocol; | |
| 161 m_securityDetails.cipher = data->m_securityDetails.cipher; | |
| 162 m_securityDetails.keyExchange = data->m_securityDetails.keyExchange; | |
| 163 m_securityDetails.keyExchangeGroup = data->m_securityDetails.keyExchangeGroup; | |
| 164 m_securityDetails.mac = data->m_securityDetails.mac; | |
| 165 m_securityDetails.subjectName = data->m_securityDetails.subjectName; | |
| 166 m_securityDetails.sanList = data->m_securityDetails.sanList; | |
| 167 m_securityDetails.issuer = data->m_securityDetails.issuer; | |
| 168 m_securityDetails.validFrom = data->m_securityDetails.validFrom; | |
| 169 m_securityDetails.validTo = data->m_securityDetails.validTo; | |
| 170 for (auto& cert : data->m_certificate) | |
| 171 m_securityDetails.certificate.push_back(AtomicString(cert)); | |
| 172 m_securityDetails.sctList = data->m_securityDetails.sctList; | |
| 173 m_httpVersion = data->m_httpVersion; | |
| 174 m_appCacheID = data->m_appCacheID; | |
| 175 m_appCacheManifestURL = data->m_appCacheManifestURL.copy(); | |
| 176 m_multipartBoundary = data->m_multipartBoundary; | |
| 177 m_wasFetchedViaSPDY = data->m_wasFetchedViaSPDY; | |
| 178 m_wasFetchedViaProxy = data->m_wasFetchedViaProxy; | |
| 179 m_wasFetchedViaServiceWorker = data->m_wasFetchedViaServiceWorker; | |
| 180 m_wasFetchedViaForeignFetch = data->m_wasFetchedViaForeignFetch; | |
| 181 m_wasFallbackRequiredByServiceWorker = | |
| 182 data->m_wasFallbackRequiredByServiceWorker; | |
| 183 m_serviceWorkerResponseType = data->m_serviceWorkerResponseType; | |
| 184 m_urlListViaServiceWorker = data->m_urlListViaServiceWorker; | |
| 185 m_cacheStorageCacheName = data->m_cacheStorageCacheName; | |
| 186 m_didServiceWorkerNavigationPreload = | |
| 187 data->m_didServiceWorkerNavigationPreload; | |
| 188 m_responseTime = data->m_responseTime; | |
| 189 m_remoteIPAddress = AtomicString(data->m_remoteIPAddress); | |
| 190 m_remotePort = data->m_remotePort; | |
| 191 m_encodedDataLength = data->m_encodedDataLength; | |
| 192 m_encodedBodyLength = data->m_encodedBodyLength; | |
| 193 m_decodedBodyLength = data->m_decodedBodyLength; | |
| 194 m_downloadedFilePath = data->m_downloadedFilePath; | |
| 195 m_downloadedFileHandle = data->m_downloadedFileHandle; | |
| 196 | |
| 197 // Bug https://bugs.webkit.org/show_bug.cgi?id=60397 this doesn't support | |
| 198 // whatever values may be present in the opaque m_extraData structure. | |
| 199 } | |
| 200 | |
| 201 ResourceResponse::ResourceResponse(const ResourceResponse&) = default; | |
| 202 ResourceResponse& ResourceResponse::operator=(const ResourceResponse&) = | |
| 203 default; | |
| 204 | |
| 205 std::unique_ptr<CrossThreadResourceResponseData> ResourceResponse::copyData() | |
| 206 const { | |
| 207 std::unique_ptr<CrossThreadResourceResponseData> data = | |
| 208 WTF::wrapUnique(new CrossThreadResourceResponseData); | |
| 209 data->m_url = url().copy(); | |
| 210 data->m_mimeType = mimeType().getString().isolatedCopy(); | |
| 211 data->m_expectedContentLength = expectedContentLength(); | |
| 212 data->m_textEncodingName = textEncodingName().getString().isolatedCopy(); | |
| 213 data->m_httpStatusCode = httpStatusCode(); | |
| 214 data->m_httpStatusText = httpStatusText().getString().isolatedCopy(); | |
| 215 data->m_httpHeaders = httpHeaderFields().copyData(); | |
| 216 if (m_resourceLoadTiming) | |
| 217 data->m_resourceLoadTiming = m_resourceLoadTiming->deepCopy(); | |
| 218 data->m_hasMajorCertificateErrors = m_hasMajorCertificateErrors; | |
| 219 data->m_securityStyle = m_securityStyle; | |
| 220 data->m_securityDetails.protocol = m_securityDetails.protocol.isolatedCopy(); | |
| 221 data->m_securityDetails.cipher = m_securityDetails.cipher.isolatedCopy(); | |
| 222 data->m_securityDetails.keyExchange = | |
| 223 m_securityDetails.keyExchange.isolatedCopy(); | |
| 224 data->m_securityDetails.keyExchangeGroup = | |
| 225 m_securityDetails.keyExchangeGroup.isolatedCopy(); | |
| 226 data->m_securityDetails.mac = m_securityDetails.mac.isolatedCopy(); | |
| 227 data->m_securityDetails.subjectName = | |
| 228 m_securityDetails.subjectName.isolatedCopy(); | |
| 229 data->m_securityDetails.sanList = isolatedCopy(m_securityDetails.sanList); | |
| 230 data->m_securityDetails.issuer = m_securityDetails.issuer.isolatedCopy(); | |
| 231 data->m_securityDetails.validFrom = m_securityDetails.validFrom; | |
| 232 data->m_securityDetails.validTo = m_securityDetails.validTo; | |
| 233 for (auto& cert : m_securityDetails.certificate) | |
| 234 data->m_certificate.push_back(cert.getString().isolatedCopy()); | |
| 235 data->m_securityDetails.sctList = isolatedCopy(m_securityDetails.sctList); | |
| 236 data->m_httpVersion = m_httpVersion; | |
| 237 data->m_appCacheID = m_appCacheID; | |
| 238 data->m_appCacheManifestURL = m_appCacheManifestURL.copy(); | |
| 239 data->m_multipartBoundary = m_multipartBoundary; | |
| 240 data->m_wasFetchedViaSPDY = m_wasFetchedViaSPDY; | |
| 241 data->m_wasFetchedViaProxy = m_wasFetchedViaProxy; | |
| 242 data->m_wasFetchedViaServiceWorker = m_wasFetchedViaServiceWorker; | |
| 243 data->m_wasFetchedViaForeignFetch = m_wasFetchedViaForeignFetch; | |
| 244 data->m_wasFallbackRequiredByServiceWorker = | |
| 245 m_wasFallbackRequiredByServiceWorker; | |
| 246 data->m_serviceWorkerResponseType = m_serviceWorkerResponseType; | |
| 247 data->m_urlListViaServiceWorker.resize(m_urlListViaServiceWorker.size()); | |
| 248 std::transform(m_urlListViaServiceWorker.begin(), | |
| 249 m_urlListViaServiceWorker.end(), | |
| 250 data->m_urlListViaServiceWorker.begin(), | |
| 251 [](const KURL& url) { return url.copy(); }); | |
| 252 data->m_cacheStorageCacheName = cacheStorageCacheName().isolatedCopy(); | |
| 253 data->m_didServiceWorkerNavigationPreload = | |
| 254 m_didServiceWorkerNavigationPreload; | |
| 255 data->m_responseTime = m_responseTime; | |
| 256 data->m_remoteIPAddress = m_remoteIPAddress.getString().isolatedCopy(); | |
| 257 data->m_remotePort = m_remotePort; | |
| 258 data->m_encodedDataLength = m_encodedDataLength; | |
| 259 data->m_encodedBodyLength = m_encodedBodyLength; | |
| 260 data->m_decodedBodyLength = m_decodedBodyLength; | |
| 261 data->m_downloadedFilePath = m_downloadedFilePath.isolatedCopy(); | |
| 262 data->m_downloadedFileHandle = m_downloadedFileHandle; | |
| 263 | |
| 264 // Bug https://bugs.webkit.org/show_bug.cgi?id=60397 this doesn't support | |
| 265 // whatever values may be present in the opaque m_extraData structure. | |
| 266 | |
| 267 return data; | |
| 268 } | |
| 269 | |
| 270 bool ResourceResponse::isHTTP() const { | |
| 271 return m_url.protocolIsInHTTPFamily(); | |
| 272 } | |
| 273 | |
| 274 const KURL& ResourceResponse::url() const { | |
| 275 return m_url; | |
| 276 } | |
| 277 | |
| 278 void ResourceResponse::setURL(const KURL& url) { | |
| 279 m_isNull = false; | |
| 280 | |
| 281 m_url = url; | |
| 282 } | |
| 283 | |
| 284 const AtomicString& ResourceResponse::mimeType() const { | |
| 285 return m_mimeType; | |
| 286 } | |
| 287 | |
| 288 void ResourceResponse::setMimeType(const AtomicString& mimeType) { | |
| 289 m_isNull = false; | |
| 290 | |
| 291 // FIXME: MIME type is determined by HTTP Content-Type header. We should | |
| 292 // update the header, so that it doesn't disagree with m_mimeType. | |
| 293 m_mimeType = mimeType; | |
| 294 } | |
| 295 | |
| 296 long long ResourceResponse::expectedContentLength() const { | |
| 297 return m_expectedContentLength; | |
| 298 } | |
| 299 | |
| 300 void ResourceResponse::setExpectedContentLength( | |
| 301 long long expectedContentLength) { | |
| 302 m_isNull = false; | |
| 303 | |
| 304 // FIXME: Content length is determined by HTTP Content-Length header. We | |
| 305 // should update the header, so that it doesn't disagree with | |
| 306 // m_expectedContentLength. | |
| 307 m_expectedContentLength = expectedContentLength; | |
| 308 } | |
| 309 | |
| 310 const AtomicString& ResourceResponse::textEncodingName() const { | |
| 311 return m_textEncodingName; | |
| 312 } | |
| 313 | |
| 314 void ResourceResponse::setTextEncodingName(const AtomicString& encodingName) { | |
| 315 m_isNull = false; | |
| 316 | |
| 317 // FIXME: Text encoding is determined by HTTP Content-Type header. We should | |
| 318 // update the header, so that it doesn't disagree with m_textEncodingName. | |
| 319 m_textEncodingName = encodingName; | |
| 320 } | |
| 321 | |
| 322 int ResourceResponse::httpStatusCode() const { | |
| 323 return m_httpStatusCode; | |
| 324 } | |
| 325 | |
| 326 void ResourceResponse::setHTTPStatusCode(int statusCode) { | |
| 327 m_httpStatusCode = statusCode; | |
| 328 } | |
| 329 | |
| 330 const AtomicString& ResourceResponse::httpStatusText() const { | |
| 331 return m_httpStatusText; | |
| 332 } | |
| 333 | |
| 334 void ResourceResponse::setHTTPStatusText(const AtomicString& statusText) { | |
| 335 m_httpStatusText = statusText; | |
| 336 } | |
| 337 | |
| 338 const AtomicString& ResourceResponse::httpHeaderField( | |
| 339 const AtomicString& name) const { | |
| 340 return m_httpHeaderFields.get(name); | |
| 341 } | |
| 342 | |
| 343 void ResourceResponse::updateHeaderParsedState(const AtomicString& name) { | |
| 344 static const char ageHeader[] = "age"; | |
| 345 static const char dateHeader[] = "date"; | |
| 346 static const char expiresHeader[] = "expires"; | |
| 347 static const char lastModifiedHeader[] = "last-modified"; | |
| 348 | |
| 349 if (equalIgnoringCase(name, ageHeader)) | |
| 350 m_haveParsedAgeHeader = false; | |
| 351 else if (equalIgnoringCase(name, cacheControlHeader) || | |
| 352 equalIgnoringCase(name, pragmaHeader)) | |
| 353 m_cacheControlHeader = CacheControlHeader(); | |
| 354 else if (equalIgnoringCase(name, dateHeader)) | |
| 355 m_haveParsedDateHeader = false; | |
| 356 else if (equalIgnoringCase(name, expiresHeader)) | |
| 357 m_haveParsedExpiresHeader = false; | |
| 358 else if (equalIgnoringCase(name, lastModifiedHeader)) | |
| 359 m_haveParsedLastModifiedHeader = false; | |
| 360 } | |
| 361 | |
| 362 void ResourceResponse::setSecurityDetails( | |
| 363 const String& protocol, | |
| 364 const String& keyExchange, | |
| 365 const String& keyExchangeGroup, | |
| 366 const String& cipher, | |
| 367 const String& mac, | |
| 368 const String& subjectName, | |
| 369 const Vector<String>& sanList, | |
| 370 const String& issuer, | |
| 371 time_t validFrom, | |
| 372 time_t validTo, | |
| 373 const Vector<AtomicString>& certificate, | |
| 374 const SignedCertificateTimestampList& sctList) { | |
| 375 m_securityDetails.protocol = protocol; | |
| 376 m_securityDetails.keyExchange = keyExchange; | |
| 377 m_securityDetails.keyExchangeGroup = keyExchangeGroup; | |
| 378 m_securityDetails.cipher = cipher; | |
| 379 m_securityDetails.mac = mac; | |
| 380 m_securityDetails.subjectName = subjectName; | |
| 381 m_securityDetails.sanList = sanList; | |
| 382 m_securityDetails.issuer = issuer; | |
| 383 m_securityDetails.validFrom = validFrom; | |
| 384 m_securityDetails.validTo = validTo; | |
| 385 m_securityDetails.certificate = certificate; | |
| 386 m_securityDetails.sctList = sctList; | |
| 387 } | |
| 388 | |
| 389 void ResourceResponse::setHTTPHeaderField(const AtomicString& name, | |
| 390 const AtomicString& value) { | |
| 391 updateHeaderParsedState(name); | |
| 392 | |
| 393 m_httpHeaderFields.set(name, value); | |
| 394 } | |
| 395 | |
| 396 void ResourceResponse::addHTTPHeaderField(const AtomicString& name, | |
| 397 const AtomicString& value) { | |
| 398 updateHeaderParsedState(name); | |
| 399 | |
| 400 HTTPHeaderMap::AddResult result = m_httpHeaderFields.add(name, value); | |
| 401 if (!result.isNewEntry) | |
| 402 result.storedValue->value = result.storedValue->value + ", " + value; | |
| 403 } | |
| 404 | |
| 405 void ResourceResponse::clearHTTPHeaderField(const AtomicString& name) { | |
| 406 m_httpHeaderFields.remove(name); | |
| 407 } | |
| 408 | |
| 409 const HTTPHeaderMap& ResourceResponse::httpHeaderFields() const { | |
| 410 return m_httpHeaderFields; | |
| 411 } | |
| 412 | |
| 413 bool ResourceResponse::cacheControlContainsNoCache() const { | |
| 414 if (!m_cacheControlHeader.parsed) { | |
| 415 m_cacheControlHeader = | |
| 416 parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeader), | |
| 417 m_httpHeaderFields.get(pragmaHeader)); | |
| 418 } | |
| 419 return m_cacheControlHeader.containsNoCache; | |
| 420 } | |
| 421 | |
| 422 bool ResourceResponse::cacheControlContainsNoStore() const { | |
| 423 if (!m_cacheControlHeader.parsed) { | |
| 424 m_cacheControlHeader = | |
| 425 parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeader), | |
| 426 m_httpHeaderFields.get(pragmaHeader)); | |
| 427 } | |
| 428 return m_cacheControlHeader.containsNoStore; | |
| 429 } | |
| 430 | |
| 431 bool ResourceResponse::cacheControlContainsMustRevalidate() const { | |
| 432 if (!m_cacheControlHeader.parsed) { | |
| 433 m_cacheControlHeader = | |
| 434 parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeader), | |
| 435 m_httpHeaderFields.get(pragmaHeader)); | |
| 436 } | |
| 437 return m_cacheControlHeader.containsMustRevalidate; | |
| 438 } | |
| 439 | |
| 440 bool ResourceResponse::hasCacheValidatorFields() const { | |
| 441 static const char lastModifiedHeader[] = "last-modified"; | |
| 442 static const char eTagHeader[] = "etag"; | |
| 443 return !m_httpHeaderFields.get(lastModifiedHeader).isEmpty() || | |
| 444 !m_httpHeaderFields.get(eTagHeader).isEmpty(); | |
| 445 } | |
| 446 | |
| 447 double ResourceResponse::cacheControlMaxAge() const { | |
| 448 if (!m_cacheControlHeader.parsed) { | |
| 449 m_cacheControlHeader = | |
| 450 parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeader), | |
| 451 m_httpHeaderFields.get(pragmaHeader)); | |
| 452 } | |
| 453 return m_cacheControlHeader.maxAge; | |
| 454 } | |
| 455 | |
| 456 double ResourceResponse::cacheControlStaleWhileRevalidate() const { | |
| 457 if (!m_cacheControlHeader.parsed) { | |
| 458 m_cacheControlHeader = | |
| 459 parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeader), | |
| 460 m_httpHeaderFields.get(pragmaHeader)); | |
| 461 } | |
| 462 return m_cacheControlHeader.staleWhileRevalidate; | |
| 463 } | |
| 464 | |
| 465 static double parseDateValueInHeader(const HTTPHeaderMap& headers, | |
| 466 const AtomicString& headerName) { | |
| 467 const AtomicString& headerValue = headers.get(headerName); | |
| 468 if (headerValue.isEmpty()) | |
| 469 return std::numeric_limits<double>::quiet_NaN(); | |
| 470 // This handles all date formats required by RFC2616: | |
| 471 // Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 | |
| 472 // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 | |
| 473 // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format | |
| 474 double dateInMilliseconds = parseDate(headerValue); | |
| 475 if (!std::isfinite(dateInMilliseconds)) | |
| 476 return std::numeric_limits<double>::quiet_NaN(); | |
| 477 return dateInMilliseconds / 1000; | |
| 478 } | |
| 479 | |
| 480 double ResourceResponse::date() const { | |
| 481 if (!m_haveParsedDateHeader) { | |
| 482 static const char headerName[] = "date"; | |
| 483 m_date = parseDateValueInHeader(m_httpHeaderFields, headerName); | |
| 484 m_haveParsedDateHeader = true; | |
| 485 } | |
| 486 return m_date; | |
| 487 } | |
| 488 | |
| 489 double ResourceResponse::age() const { | |
| 490 if (!m_haveParsedAgeHeader) { | |
| 491 static const char headerName[] = "age"; | |
| 492 const AtomicString& headerValue = m_httpHeaderFields.get(headerName); | |
| 493 bool ok; | |
| 494 m_age = headerValue.toDouble(&ok); | |
| 495 if (!ok) | |
| 496 m_age = std::numeric_limits<double>::quiet_NaN(); | |
| 497 m_haveParsedAgeHeader = true; | |
| 498 } | |
| 499 return m_age; | |
| 500 } | |
| 501 | |
| 502 double ResourceResponse::expires() const { | |
| 503 if (!m_haveParsedExpiresHeader) { | |
| 504 static const char headerName[] = "expires"; | |
| 505 m_expires = parseDateValueInHeader(m_httpHeaderFields, headerName); | |
| 506 m_haveParsedExpiresHeader = true; | |
| 507 } | |
| 508 return m_expires; | |
| 509 } | |
| 510 | |
| 511 double ResourceResponse::lastModified() const { | |
| 512 if (!m_haveParsedLastModifiedHeader) { | |
| 513 static const char headerName[] = "last-modified"; | |
| 514 m_lastModified = parseDateValueInHeader(m_httpHeaderFields, headerName); | |
| 515 m_haveParsedLastModifiedHeader = true; | |
| 516 } | |
| 517 return m_lastModified; | |
| 518 } | |
| 519 | |
| 520 bool ResourceResponse::isAttachment() const { | |
| 521 static const char attachmentString[] = "attachment"; | |
| 522 String value = m_httpHeaderFields.get(HTTPNames::Content_Disposition); | |
| 523 size_t loc = value.find(';'); | |
| 524 if (loc != kNotFound) | |
| 525 value = value.left(loc); | |
| 526 value = value.stripWhiteSpace(); | |
| 527 return equalIgnoringCase(value, attachmentString); | |
| 528 } | |
| 529 | |
| 530 AtomicString ResourceResponse::httpContentType() const { | |
| 531 return extractMIMETypeFromMediaType( | |
| 532 httpHeaderField(HTTPNames::Content_Type).lower()); | |
| 533 } | |
| 534 | |
| 535 bool ResourceResponse::wasCached() const { | |
| 536 return m_wasCached; | |
| 537 } | |
| 538 | |
| 539 void ResourceResponse::setWasCached(bool value) { | |
| 540 m_wasCached = value; | |
| 541 } | |
| 542 | |
| 543 bool ResourceResponse::connectionReused() const { | |
| 544 return m_connectionReused; | |
| 545 } | |
| 546 | |
| 547 void ResourceResponse::setConnectionReused(bool connectionReused) { | |
| 548 m_connectionReused = connectionReused; | |
| 549 } | |
| 550 | |
| 551 unsigned ResourceResponse::connectionID() const { | |
| 552 return m_connectionID; | |
| 553 } | |
| 554 | |
| 555 void ResourceResponse::setConnectionID(unsigned connectionID) { | |
| 556 m_connectionID = connectionID; | |
| 557 } | |
| 558 | |
| 559 ResourceLoadTiming* ResourceResponse::resourceLoadTiming() const { | |
| 560 return m_resourceLoadTiming.get(); | |
| 561 } | |
| 562 | |
| 563 void ResourceResponse::setResourceLoadTiming( | |
| 564 PassRefPtr<ResourceLoadTiming> resourceLoadTiming) { | |
| 565 m_resourceLoadTiming = resourceLoadTiming; | |
| 566 } | |
| 567 | |
| 568 PassRefPtr<ResourceLoadInfo> ResourceResponse::resourceLoadInfo() const { | |
| 569 return m_resourceLoadInfo.get(); | |
| 570 } | |
| 571 | |
| 572 void ResourceResponse::setResourceLoadInfo( | |
| 573 PassRefPtr<ResourceLoadInfo> loadInfo) { | |
| 574 m_resourceLoadInfo = loadInfo; | |
| 575 } | |
| 576 | |
| 577 KURL ResourceResponse::originalURLViaServiceWorker() const { | |
| 578 if (m_urlListViaServiceWorker.isEmpty()) | |
| 579 return KURL(); | |
| 580 return m_urlListViaServiceWorker.back(); | |
| 581 } | |
| 582 | |
| 583 void ResourceResponse::setEncodedDataLength(long long value) { | |
| 584 m_encodedDataLength = value; | |
| 585 } | |
| 586 | |
| 587 void ResourceResponse::addToEncodedBodyLength(long long value) { | |
| 588 m_encodedBodyLength += value; | |
| 589 } | |
| 590 | |
| 591 void ResourceResponse::addToDecodedBodyLength(long long value) { | |
| 592 m_decodedBodyLength += value; | |
| 593 } | |
| 594 | |
| 595 void ResourceResponse::setDownloadedFilePath(const String& downloadedFilePath) { | |
| 596 m_downloadedFilePath = downloadedFilePath; | |
| 597 if (m_downloadedFilePath.isEmpty()) { | |
| 598 m_downloadedFileHandle.clear(); | |
| 599 return; | |
| 600 } | |
| 601 // TODO(dmurph): Investigate whether we need the mimeType on this blob. | |
| 602 std::unique_ptr<BlobData> blobData = | |
| 603 BlobData::createForFileWithUnknownSize(m_downloadedFilePath); | |
| 604 blobData->detachFromCurrentThread(); | |
| 605 m_downloadedFileHandle = BlobDataHandle::create(std::move(blobData), -1); | |
| 606 } | |
| 607 | |
| 608 void ResourceResponse::appendRedirectResponse( | |
| 609 const ResourceResponse& response) { | |
| 610 m_redirectResponses.push_back(response); | |
| 611 } | |
| 612 | |
| 613 bool ResourceResponse::compare(const ResourceResponse& a, | |
| 614 const ResourceResponse& b) { | |
| 615 if (a.isNull() != b.isNull()) | |
| 616 return false; | |
| 617 if (a.url() != b.url()) | |
| 618 return false; | |
| 619 if (a.mimeType() != b.mimeType()) | |
| 620 return false; | |
| 621 if (a.expectedContentLength() != b.expectedContentLength()) | |
| 622 return false; | |
| 623 if (a.textEncodingName() != b.textEncodingName()) | |
| 624 return false; | |
| 625 if (a.httpStatusCode() != b.httpStatusCode()) | |
| 626 return false; | |
| 627 if (a.httpStatusText() != b.httpStatusText()) | |
| 628 return false; | |
| 629 if (a.httpHeaderFields() != b.httpHeaderFields()) | |
| 630 return false; | |
| 631 if (a.resourceLoadTiming() && b.resourceLoadTiming() && | |
| 632 *a.resourceLoadTiming() == *b.resourceLoadTiming()) | |
| 633 return true; | |
| 634 if (a.resourceLoadTiming() != b.resourceLoadTiming()) | |
| 635 return false; | |
| 636 if (a.encodedBodyLength() != b.encodedBodyLength()) | |
| 637 return false; | |
| 638 if (a.decodedBodyLength() != b.decodedBodyLength()) | |
| 639 return false; | |
| 640 return true; | |
| 641 } | |
| 642 | |
| 643 } // namespace blink | |
| OLD | NEW |