| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. | |
| 3 * Copyright (C) 2009, 2012 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/ResourceRequest.h" | |
| 28 | |
| 29 #include "platform/HTTPNames.h" | |
| 30 #include "platform/RuntimeEnabledFeatures.h" | |
| 31 #include "platform/network/NetworkUtils.h" | |
| 32 #include "platform/weborigin/SecurityOrigin.h" | |
| 33 #include "public/platform/WebAddressSpace.h" | |
| 34 #include "public/platform/WebCachePolicy.h" | |
| 35 #include "public/platform/WebURLRequest.h" | |
| 36 #include "wtf/PtrUtil.h" | |
| 37 #include <memory> | |
| 38 | |
| 39 namespace blink { | |
| 40 | |
| 41 double ResourceRequest::s_defaultTimeoutInterval = INT_MAX; | |
| 42 | |
| 43 ResourceRequest::ResourceRequest() : ResourceRequest(KURL()) {} | |
| 44 | |
| 45 ResourceRequest::ResourceRequest(const String& urlString) | |
| 46 : ResourceRequest(KURL(ParsedURLString, urlString)) {} | |
| 47 | |
| 48 ResourceRequest::ResourceRequest(const KURL& url) | |
| 49 : m_url(url), | |
| 50 m_cachePolicy(WebCachePolicy::UseProtocolCachePolicy), | |
| 51 m_timeoutInterval(s_defaultTimeoutInterval), | |
| 52 m_requestorOrigin(SecurityOrigin::createUnique()), | |
| 53 m_httpMethod(HTTPNames::GET), | |
| 54 m_allowStoredCredentials(true), | |
| 55 m_reportUploadProgress(false), | |
| 56 m_reportRawHeaders(false), | |
| 57 m_hasUserGesture(false), | |
| 58 m_downloadToFile(false), | |
| 59 m_useStreamOnResponse(false), | |
| 60 m_shouldResetAppCache(false), | |
| 61 m_serviceWorkerMode(WebURLRequest::ServiceWorkerMode::All), | |
| 62 m_priority(ResourceLoadPriorityLowest), | |
| 63 m_intraPriorityValue(0), | |
| 64 m_requestorID(0), | |
| 65 m_requestorProcessID(0), | |
| 66 m_appCacheHostID(0), | |
| 67 m_requestContext(WebURLRequest::RequestContextUnspecified), | |
| 68 m_frameType(WebURLRequest::FrameTypeNone), | |
| 69 m_fetchRequestMode(WebURLRequest::FetchRequestModeNoCORS), | |
| 70 m_fetchCredentialsMode(WebURLRequest::FetchCredentialsModeInclude), | |
| 71 m_fetchRedirectMode(WebURLRequest::FetchRedirectModeFollow), | |
| 72 m_previewsState(WebURLRequest::PreviewsUnspecified), | |
| 73 m_referrerPolicy(ReferrerPolicyDefault), | |
| 74 m_didSetHTTPReferrer(false), | |
| 75 m_checkForBrowserSideNavigation(true), | |
| 76 m_uiStartTime(0), | |
| 77 m_isExternalRequest(false), | |
| 78 m_isSameDocumentNavigation(false), | |
| 79 m_inputPerfMetricReportPolicy( | |
| 80 InputToLoadPerfMetricReportPolicy::NoReport), | |
| 81 m_redirectStatus(RedirectStatus::NoRedirect) {} | |
| 82 | |
| 83 ResourceRequest::ResourceRequest(CrossThreadResourceRequestData* data) | |
| 84 : ResourceRequest(data->m_url) { | |
| 85 setCachePolicy(data->m_cachePolicy); | |
| 86 setTimeoutInterval(data->m_timeoutInterval); | |
| 87 setFirstPartyForCookies(data->m_firstPartyForCookies); | |
| 88 setRequestorOrigin(data->m_requestorOrigin); | |
| 89 setHTTPMethod(AtomicString(data->m_httpMethod)); | |
| 90 setPriority(data->m_priority, data->m_intraPriorityValue); | |
| 91 | |
| 92 m_httpHeaderFields.adopt(std::move(data->m_httpHeaders)); | |
| 93 | |
| 94 setHTTPBody(data->m_httpBody); | |
| 95 setAttachedCredential(data->m_attachedCredential); | |
| 96 setAllowStoredCredentials(data->m_allowStoredCredentials); | |
| 97 setReportUploadProgress(data->m_reportUploadProgress); | |
| 98 setHasUserGesture(data->m_hasUserGesture); | |
| 99 setDownloadToFile(data->m_downloadToFile); | |
| 100 setUseStreamOnResponse(data->m_useStreamOnResponse); | |
| 101 setServiceWorkerMode(data->m_serviceWorkerMode); | |
| 102 setShouldResetAppCache(data->m_shouldResetAppCache); | |
| 103 setRequestorID(data->m_requestorID); | |
| 104 setRequestorProcessID(data->m_requestorProcessID); | |
| 105 setAppCacheHostID(data->m_appCacheHostID); | |
| 106 setRequestContext(data->m_requestContext); | |
| 107 setFrameType(data->m_frameType); | |
| 108 setFetchRequestMode(data->m_fetchRequestMode); | |
| 109 setFetchCredentialsMode(data->m_fetchCredentialsMode); | |
| 110 setFetchRedirectMode(data->m_fetchRedirectMode); | |
| 111 setPreviewsState(data->m_previewsState); | |
| 112 m_referrerPolicy = data->m_referrerPolicy; | |
| 113 m_didSetHTTPReferrer = data->m_didSetHTTPReferrer; | |
| 114 m_checkForBrowserSideNavigation = data->m_checkForBrowserSideNavigation; | |
| 115 m_uiStartTime = data->m_uiStartTime; | |
| 116 m_isExternalRequest = data->m_isExternalRequest; | |
| 117 m_inputPerfMetricReportPolicy = data->m_inputPerfMetricReportPolicy; | |
| 118 m_redirectStatus = data->m_redirectStatus; | |
| 119 } | |
| 120 | |
| 121 ResourceRequest::ResourceRequest(const ResourceRequest&) = default; | |
| 122 | |
| 123 ResourceRequest& ResourceRequest::operator=(const ResourceRequest&) = default; | |
| 124 | |
| 125 std::unique_ptr<CrossThreadResourceRequestData> ResourceRequest::copyData() | |
| 126 const { | |
| 127 std::unique_ptr<CrossThreadResourceRequestData> data = | |
| 128 WTF::makeUnique<CrossThreadResourceRequestData>(); | |
| 129 data->m_url = url().copy(); | |
| 130 data->m_cachePolicy = getCachePolicy(); | |
| 131 data->m_timeoutInterval = timeoutInterval(); | |
| 132 data->m_firstPartyForCookies = firstPartyForCookies().copy(); | |
| 133 data->m_requestorOrigin = | |
| 134 requestorOrigin() ? requestorOrigin()->isolatedCopy() : nullptr; | |
| 135 data->m_httpMethod = httpMethod().getString().isolatedCopy(); | |
| 136 data->m_httpHeaders = httpHeaderFields().copyData(); | |
| 137 data->m_priority = priority(); | |
| 138 data->m_intraPriorityValue = m_intraPriorityValue; | |
| 139 | |
| 140 if (m_httpBody) | |
| 141 data->m_httpBody = m_httpBody->deepCopy(); | |
| 142 if (m_attachedCredential) | |
| 143 data->m_attachedCredential = m_attachedCredential->deepCopy(); | |
| 144 data->m_allowStoredCredentials = m_allowStoredCredentials; | |
| 145 data->m_reportUploadProgress = m_reportUploadProgress; | |
| 146 data->m_hasUserGesture = m_hasUserGesture; | |
| 147 data->m_downloadToFile = m_downloadToFile; | |
| 148 data->m_useStreamOnResponse = m_useStreamOnResponse; | |
| 149 data->m_serviceWorkerMode = m_serviceWorkerMode; | |
| 150 data->m_shouldResetAppCache = m_shouldResetAppCache; | |
| 151 data->m_requestorID = m_requestorID; | |
| 152 data->m_requestorProcessID = m_requestorProcessID; | |
| 153 data->m_appCacheHostID = m_appCacheHostID; | |
| 154 data->m_requestContext = m_requestContext; | |
| 155 data->m_frameType = m_frameType; | |
| 156 data->m_fetchRequestMode = m_fetchRequestMode; | |
| 157 data->m_fetchCredentialsMode = m_fetchCredentialsMode; | |
| 158 data->m_fetchRedirectMode = m_fetchRedirectMode; | |
| 159 data->m_previewsState = m_previewsState; | |
| 160 data->m_referrerPolicy = m_referrerPolicy; | |
| 161 data->m_didSetHTTPReferrer = m_didSetHTTPReferrer; | |
| 162 data->m_checkForBrowserSideNavigation = m_checkForBrowserSideNavigation; | |
| 163 data->m_uiStartTime = m_uiStartTime; | |
| 164 data->m_isExternalRequest = m_isExternalRequest; | |
| 165 data->m_inputPerfMetricReportPolicy = m_inputPerfMetricReportPolicy; | |
| 166 data->m_redirectStatus = m_redirectStatus; | |
| 167 return data; | |
| 168 } | |
| 169 | |
| 170 bool ResourceRequest::isEmpty() const { | |
| 171 return m_url.isEmpty(); | |
| 172 } | |
| 173 | |
| 174 bool ResourceRequest::isNull() const { | |
| 175 return m_url.isNull(); | |
| 176 } | |
| 177 | |
| 178 const KURL& ResourceRequest::url() const { | |
| 179 return m_url; | |
| 180 } | |
| 181 | |
| 182 void ResourceRequest::setURL(const KURL& url) { | |
| 183 m_url = url; | |
| 184 } | |
| 185 | |
| 186 void ResourceRequest::removeUserAndPassFromURL() { | |
| 187 if (m_url.user().isEmpty() && m_url.pass().isEmpty()) | |
| 188 return; | |
| 189 | |
| 190 m_url.setUser(String()); | |
| 191 m_url.setPass(String()); | |
| 192 } | |
| 193 | |
| 194 WebCachePolicy ResourceRequest::getCachePolicy() const { | |
| 195 return m_cachePolicy; | |
| 196 } | |
| 197 | |
| 198 void ResourceRequest::setCachePolicy(WebCachePolicy cachePolicy) { | |
| 199 m_cachePolicy = cachePolicy; | |
| 200 } | |
| 201 | |
| 202 double ResourceRequest::timeoutInterval() const { | |
| 203 return m_timeoutInterval; | |
| 204 } | |
| 205 | |
| 206 void ResourceRequest::setTimeoutInterval(double timoutIntervalSeconds) { | |
| 207 m_timeoutInterval = timoutIntervalSeconds; | |
| 208 } | |
| 209 | |
| 210 const KURL& ResourceRequest::firstPartyForCookies() const { | |
| 211 return m_firstPartyForCookies; | |
| 212 } | |
| 213 | |
| 214 void ResourceRequest::setFirstPartyForCookies( | |
| 215 const KURL& firstPartyForCookies) { | |
| 216 m_firstPartyForCookies = firstPartyForCookies; | |
| 217 } | |
| 218 | |
| 219 PassRefPtr<SecurityOrigin> ResourceRequest::requestorOrigin() const { | |
| 220 return m_requestorOrigin; | |
| 221 } | |
| 222 | |
| 223 void ResourceRequest::setRequestorOrigin( | |
| 224 PassRefPtr<SecurityOrigin> requestorOrigin) { | |
| 225 m_requestorOrigin = requestorOrigin; | |
| 226 } | |
| 227 | |
| 228 const AtomicString& ResourceRequest::httpMethod() const { | |
| 229 return m_httpMethod; | |
| 230 } | |
| 231 | |
| 232 void ResourceRequest::setHTTPMethod(const AtomicString& httpMethod) { | |
| 233 m_httpMethod = httpMethod; | |
| 234 } | |
| 235 | |
| 236 const HTTPHeaderMap& ResourceRequest::httpHeaderFields() const { | |
| 237 return m_httpHeaderFields; | |
| 238 } | |
| 239 | |
| 240 const AtomicString& ResourceRequest::httpHeaderField( | |
| 241 const AtomicString& name) const { | |
| 242 return m_httpHeaderFields.get(name); | |
| 243 } | |
| 244 | |
| 245 void ResourceRequest::setHTTPHeaderField(const AtomicString& name, | |
| 246 const AtomicString& value) { | |
| 247 m_httpHeaderFields.set(name, value); | |
| 248 } | |
| 249 | |
| 250 void ResourceRequest::setHTTPReferrer(const Referrer& referrer) { | |
| 251 if (referrer.referrer.isEmpty()) | |
| 252 m_httpHeaderFields.remove(HTTPNames::Referer); | |
| 253 else | |
| 254 setHTTPHeaderField(HTTPNames::Referer, referrer.referrer); | |
| 255 m_referrerPolicy = referrer.referrerPolicy; | |
| 256 m_didSetHTTPReferrer = true; | |
| 257 } | |
| 258 | |
| 259 void ResourceRequest::clearHTTPReferrer() { | |
| 260 m_httpHeaderFields.remove(HTTPNames::Referer); | |
| 261 m_referrerPolicy = ReferrerPolicyDefault; | |
| 262 m_didSetHTTPReferrer = false; | |
| 263 } | |
| 264 | |
| 265 void ResourceRequest::setHTTPOrigin(const SecurityOrigin* origin) { | |
| 266 setHTTPHeaderField(HTTPNames::Origin, origin->toAtomicString()); | |
| 267 if (origin->hasSuborigin()) { | |
| 268 setHTTPHeaderField(HTTPNames::Suborigin, | |
| 269 AtomicString(origin->suborigin()->name())); | |
| 270 } | |
| 271 } | |
| 272 | |
| 273 void ResourceRequest::clearHTTPOrigin() { | |
| 274 m_httpHeaderFields.remove(HTTPNames::Origin); | |
| 275 m_httpHeaderFields.remove(HTTPNames::Suborigin); | |
| 276 } | |
| 277 | |
| 278 void ResourceRequest::addHTTPOriginIfNeeded(const SecurityOrigin* origin) { | |
| 279 if (needsHTTPOrigin()) | |
| 280 setHTTPOrigin(origin); | |
| 281 } | |
| 282 | |
| 283 void ResourceRequest::addHTTPOriginIfNeeded(const String& originString) { | |
| 284 if (needsHTTPOrigin()) | |
| 285 setHTTPOrigin(SecurityOrigin::createFromString(originString).get()); | |
| 286 } | |
| 287 | |
| 288 void ResourceRequest::clearHTTPUserAgent() { | |
| 289 m_httpHeaderFields.remove(HTTPNames::User_Agent); | |
| 290 } | |
| 291 | |
| 292 EncodedFormData* ResourceRequest::httpBody() const { | |
| 293 return m_httpBody.get(); | |
| 294 } | |
| 295 | |
| 296 void ResourceRequest::setHTTPBody(PassRefPtr<EncodedFormData> httpBody) { | |
| 297 m_httpBody = httpBody; | |
| 298 } | |
| 299 | |
| 300 EncodedFormData* ResourceRequest::attachedCredential() const { | |
| 301 return m_attachedCredential.get(); | |
| 302 } | |
| 303 | |
| 304 void ResourceRequest::setAttachedCredential( | |
| 305 PassRefPtr<EncodedFormData> attachedCredential) { | |
| 306 m_attachedCredential = attachedCredential; | |
| 307 } | |
| 308 | |
| 309 bool ResourceRequest::allowStoredCredentials() const { | |
| 310 return m_allowStoredCredentials; | |
| 311 } | |
| 312 | |
| 313 void ResourceRequest::setAllowStoredCredentials(bool allowCredentials) { | |
| 314 m_allowStoredCredentials = allowCredentials; | |
| 315 } | |
| 316 | |
| 317 ResourceLoadPriority ResourceRequest::priority() const { | |
| 318 return m_priority; | |
| 319 } | |
| 320 | |
| 321 void ResourceRequest::setPriority(ResourceLoadPriority priority, | |
| 322 int intraPriorityValue) { | |
| 323 m_priority = priority; | |
| 324 m_intraPriorityValue = intraPriorityValue; | |
| 325 } | |
| 326 | |
| 327 void ResourceRequest::addHTTPHeaderField(const AtomicString& name, | |
| 328 const AtomicString& value) { | |
| 329 HTTPHeaderMap::AddResult result = m_httpHeaderFields.add(name, value); | |
| 330 if (!result.isNewEntry) | |
| 331 result.storedValue->value = result.storedValue->value + ',' + value; | |
| 332 } | |
| 333 | |
| 334 void ResourceRequest::addHTTPHeaderFields(const HTTPHeaderMap& headerFields) { | |
| 335 HTTPHeaderMap::const_iterator end = headerFields.end(); | |
| 336 for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it) | |
| 337 addHTTPHeaderField(it->key, it->value); | |
| 338 } | |
| 339 | |
| 340 void ResourceRequest::clearHTTPHeaderField(const AtomicString& name) { | |
| 341 m_httpHeaderFields.remove(name); | |
| 342 } | |
| 343 | |
| 344 void ResourceRequest::setExternalRequestStateFromRequestorAddressSpace( | |
| 345 WebAddressSpace requestorSpace) { | |
| 346 static_assert(WebAddressSpaceLocal < WebAddressSpacePrivate, | |
| 347 "Local is inside Private"); | |
| 348 static_assert(WebAddressSpaceLocal < WebAddressSpacePublic, | |
| 349 "Local is inside Public"); | |
| 350 static_assert(WebAddressSpacePrivate < WebAddressSpacePublic, | |
| 351 "Private is inside Public"); | |
| 352 | |
| 353 // TODO(mkwst): This only checks explicit IP addresses. We'll have to move all | |
| 354 // this up to //net and //content in order to have any real impact on gateway | |
| 355 // attacks. That turns out to be a TON of work. https://crbug.com/378566 | |
| 356 if (!RuntimeEnabledFeatures::corsRFC1918Enabled()) { | |
| 357 m_isExternalRequest = false; | |
| 358 return; | |
| 359 } | |
| 360 | |
| 361 WebAddressSpace targetSpace = WebAddressSpacePublic; | |
| 362 if (NetworkUtils::isReservedIPAddress(m_url.host())) | |
| 363 targetSpace = WebAddressSpacePrivate; | |
| 364 if (SecurityOrigin::create(m_url)->isLocalhost()) | |
| 365 targetSpace = WebAddressSpaceLocal; | |
| 366 | |
| 367 m_isExternalRequest = requestorSpace > targetSpace; | |
| 368 } | |
| 369 | |
| 370 void ResourceRequest::setNavigationStartTime(double navigationStart) { | |
| 371 m_navigationStart = navigationStart; | |
| 372 } | |
| 373 | |
| 374 bool ResourceRequest::isConditional() const { | |
| 375 return (m_httpHeaderFields.contains(HTTPNames::If_Match) || | |
| 376 m_httpHeaderFields.contains(HTTPNames::If_Modified_Since) || | |
| 377 m_httpHeaderFields.contains(HTTPNames::If_None_Match) || | |
| 378 m_httpHeaderFields.contains(HTTPNames::If_Range) || | |
| 379 m_httpHeaderFields.contains(HTTPNames::If_Unmodified_Since)); | |
| 380 } | |
| 381 | |
| 382 void ResourceRequest::setHasUserGesture(bool hasUserGesture) { | |
| 383 m_hasUserGesture |= hasUserGesture; | |
| 384 } | |
| 385 | |
| 386 const CacheControlHeader& ResourceRequest::cacheControlHeader() const { | |
| 387 if (!m_cacheControlHeaderCache.parsed) | |
| 388 m_cacheControlHeaderCache = parseCacheControlDirectives( | |
| 389 m_httpHeaderFields.get(HTTPNames::Cache_Control), | |
| 390 m_httpHeaderFields.get(HTTPNames::Pragma)); | |
| 391 return m_cacheControlHeaderCache; | |
| 392 } | |
| 393 | |
| 394 bool ResourceRequest::cacheControlContainsNoCache() const { | |
| 395 return cacheControlHeader().containsNoCache; | |
| 396 } | |
| 397 | |
| 398 bool ResourceRequest::cacheControlContainsNoStore() const { | |
| 399 return cacheControlHeader().containsNoStore; | |
| 400 } | |
| 401 | |
| 402 bool ResourceRequest::hasCacheValidatorFields() const { | |
| 403 return !m_httpHeaderFields.get(HTTPNames::Last_Modified).isEmpty() || | |
| 404 !m_httpHeaderFields.get(HTTPNames::ETag).isEmpty(); | |
| 405 } | |
| 406 | |
| 407 bool ResourceRequest::needsHTTPOrigin() const { | |
| 408 if (!httpOrigin().isEmpty()) | |
| 409 return false; // Request already has an Origin header. | |
| 410 | |
| 411 // Don't send an Origin header for GET or HEAD to avoid privacy issues. | |
| 412 // For example, if an intranet page has a hyperlink to an external web | |
| 413 // site, we don't want to include the Origin of the request because it | |
| 414 // will leak the internal host name. Similar privacy concerns have lead | |
| 415 // to the widespread suppression of the Referer header at the network | |
| 416 // layer. | |
| 417 if (httpMethod() == HTTPNames::GET || httpMethod() == HTTPNames::HEAD) | |
| 418 return false; | |
| 419 | |
| 420 // For non-GET and non-HEAD methods, always send an Origin header so the | |
| 421 // server knows we support this feature. | |
| 422 return true; | |
| 423 } | |
| 424 | |
| 425 } // namespace blink | |
| OLD | NEW |