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 "config.h" 28#include "platform/network/ResourceRequest.h" 29#include "platform/weborigin/SecurityOrigin.h" 30#include "public/platform/WebURLRequest.h" 31 32namespace blink { 33 34double ResourceRequest::s_defaultTimeoutInterval = INT_MAX; 35 36PassOwnPtr<ResourceRequest> ResourceRequest::adopt(PassOwnPtr<CrossThreadResourceRequestData> data) 37{ 38 OwnPtr<ResourceRequest> request = adoptPtr(new ResourceRequest()); 39 request->setURL(data->m_url); 40 request->setCachePolicy(data->m_cachePolicy); 41 request->setTimeoutInterval(data->m_timeoutInterval); 42 request->setFirstPartyForCookies(data->m_firstPartyForCookies); 43 request->setHTTPMethod(AtomicString(data->m_httpMethod)); 44 request->setPriority(data->m_priority, data->m_intraPriorityValue); 45 46 request->m_httpHeaderFields.adopt(data->m_httpHeaders.release()); 47 48 request->setHTTPBody(data->m_httpBody); 49 request->setAllowStoredCredentials(data->m_allowStoredCredentials); 50 request->setReportUploadProgress(data->m_reportUploadProgress); 51 request->setHasUserGesture(data->m_hasUserGesture); 52 request->setDownloadToFile(data->m_downloadToFile); 53 request->setSkipServiceWorker(data->m_skipServiceWorker); 54 request->setRequestorID(data->m_requestorID); 55 request->setRequestorProcessID(data->m_requestorProcessID); 56 request->setAppCacheHostID(data->m_appCacheHostID); 57 request->setRequestContext(data->m_requestContext); 58 request->setFrameType(data->m_frameType); 59 request->m_referrerPolicy = data->m_referrerPolicy; 60 return request.release(); 61} 62 63PassOwnPtr<CrossThreadResourceRequestData> ResourceRequest::copyData() const 64{ 65 OwnPtr<CrossThreadResourceRequestData> data = adoptPtr(new CrossThreadResourceRequestData()); 66 data->m_url = url().copy(); 67 data->m_cachePolicy = cachePolicy(); 68 data->m_timeoutInterval = timeoutInterval(); 69 data->m_firstPartyForCookies = firstPartyForCookies().copy(); 70 data->m_httpMethod = httpMethod().string().isolatedCopy(); 71 data->m_httpHeaders = httpHeaderFields().copyData(); 72 data->m_priority = priority(); 73 data->m_intraPriorityValue = m_intraPriorityValue; 74 75 if (m_httpBody) 76 data->m_httpBody = m_httpBody->deepCopy(); 77 data->m_allowStoredCredentials = m_allowStoredCredentials; 78 data->m_reportUploadProgress = m_reportUploadProgress; 79 data->m_hasUserGesture = m_hasUserGesture; 80 data->m_downloadToFile = m_downloadToFile; 81 data->m_skipServiceWorker = m_skipServiceWorker; 82 data->m_requestorID = m_requestorID; 83 data->m_requestorProcessID = m_requestorProcessID; 84 data->m_appCacheHostID = m_appCacheHostID; 85 data->m_requestContext = m_requestContext; 86 data->m_frameType = m_frameType; 87 data->m_referrerPolicy = m_referrerPolicy; 88 return data.release(); 89} 90 91bool ResourceRequest::isEmpty() const 92{ 93 return m_url.isEmpty(); 94} 95 96bool ResourceRequest::isNull() const 97{ 98 return m_url.isNull(); 99} 100 101const KURL& ResourceRequest::url() const 102{ 103 return m_url; 104} 105 106void ResourceRequest::setURL(const KURL& url) 107{ 108 m_url = url; 109} 110 111void ResourceRequest::removeCredentials() 112{ 113 if (m_url.user().isEmpty() && m_url.pass().isEmpty()) 114 return; 115 116 m_url.setUser(String()); 117 m_url.setPass(String()); 118} 119 120ResourceRequestCachePolicy ResourceRequest::cachePolicy() const 121{ 122 return m_cachePolicy; 123} 124 125void ResourceRequest::setCachePolicy(ResourceRequestCachePolicy cachePolicy) 126{ 127 m_cachePolicy = cachePolicy; 128} 129 130double ResourceRequest::timeoutInterval() const 131{ 132 return m_timeoutInterval; 133} 134 135void ResourceRequest::setTimeoutInterval(double timeoutInterval) 136{ 137 m_timeoutInterval = timeoutInterval; 138} 139 140const KURL& ResourceRequest::firstPartyForCookies() const 141{ 142 return m_firstPartyForCookies; 143} 144 145void ResourceRequest::setFirstPartyForCookies(const KURL& firstPartyForCookies) 146{ 147 m_firstPartyForCookies = firstPartyForCookies; 148} 149 150const AtomicString& ResourceRequest::httpMethod() const 151{ 152 return m_httpMethod; 153} 154 155void ResourceRequest::setHTTPMethod(const AtomicString& httpMethod) 156{ 157 m_httpMethod = httpMethod; 158} 159 160const HTTPHeaderMap& ResourceRequest::httpHeaderFields() const 161{ 162 return m_httpHeaderFields; 163} 164 165const AtomicString& ResourceRequest::httpHeaderField(const AtomicString& name) const 166{ 167 return m_httpHeaderFields.get(name); 168} 169 170const AtomicString& ResourceRequest::httpHeaderField(const char* name) const 171{ 172 return m_httpHeaderFields.get(name); 173} 174 175void ResourceRequest::setHTTPHeaderField(const AtomicString& name, const AtomicString& value) 176{ 177 m_httpHeaderFields.set(name, value); 178} 179 180void ResourceRequest::setHTTPHeaderField(const char* name, const AtomicString& value) 181{ 182 setHTTPHeaderField(AtomicString(name), value); 183} 184 185void ResourceRequest::clearHTTPAuthorization() 186{ 187 m_httpHeaderFields.remove("Authorization"); 188} 189 190void ResourceRequest::clearHTTPReferrer() 191{ 192 m_httpHeaderFields.remove("Referer"); 193 m_referrerPolicy = ReferrerPolicyDefault; 194} 195 196void ResourceRequest::clearHTTPOrigin() 197{ 198 m_httpHeaderFields.remove("Origin"); 199} 200 201void ResourceRequest::addHTTPOriginIfNeeded(const AtomicString& origin) 202{ 203 if (!httpOrigin().isEmpty()) 204 return; // Request already has an Origin header. 205 206 // Don't send an Origin header for GET or HEAD to avoid privacy issues. 207 // For example, if an intranet page has a hyperlink to an external web 208 // site, we don't want to include the Origin of the request because it 209 // will leak the internal host name. Similar privacy concerns have lead 210 // to the widespread suppression of the Referer header at the network 211 // layer. 212 if (httpMethod() == "GET" || httpMethod() == "HEAD") 213 return; 214 215 // For non-GET and non-HEAD methods, always send an Origin header so the 216 // server knows we support this feature. 217 218 if (origin.isEmpty()) { 219 // If we don't know what origin header to attach, we attach the value 220 // for an empty origin. 221 setHTTPOrigin(SecurityOrigin::createUnique()->toAtomicString()); 222 return; 223 } 224 setHTTPOrigin(origin); 225} 226 227void ResourceRequest::clearHTTPUserAgent() 228{ 229 m_httpHeaderFields.remove("User-Agent"); 230} 231 232FormData* ResourceRequest::httpBody() const 233{ 234 return m_httpBody.get(); 235} 236 237void ResourceRequest::setHTTPBody(PassRefPtr<FormData> httpBody) 238{ 239 m_httpBody = httpBody; 240} 241 242bool ResourceRequest::allowStoredCredentials() const 243{ 244 return m_allowStoredCredentials; 245} 246 247void ResourceRequest::setAllowStoredCredentials(bool allowCredentials) 248{ 249 m_allowStoredCredentials = allowCredentials; 250} 251 252ResourceLoadPriority ResourceRequest::priority() const 253{ 254 return m_priority; 255} 256 257void ResourceRequest::setPriority(ResourceLoadPriority priority, int intraPriorityValue) 258{ 259 m_priority = priority; 260 m_intraPriorityValue = intraPriorityValue; 261} 262 263void ResourceRequest::addHTTPHeaderField(const AtomicString& name, const AtomicString& value) 264{ 265 HTTPHeaderMap::AddResult result = m_httpHeaderFields.add(name, value); 266 if (!result.isNewEntry) 267 result.storedValue->value = result.storedValue->value + ',' + value; 268} 269 270void ResourceRequest::addHTTPHeaderFields(const HTTPHeaderMap& headerFields) 271{ 272 HTTPHeaderMap::const_iterator end = headerFields.end(); 273 for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it) 274 addHTTPHeaderField(it->key, it->value); 275} 276 277void ResourceRequest::clearHTTPHeaderField(const AtomicString& name) 278{ 279 m_httpHeaderFields.remove(name); 280} 281 282bool equalIgnoringHeaderFields(const ResourceRequest& a, const ResourceRequest& b) 283{ 284 if (a.url() != b.url()) 285 return false; 286 287 if (a.cachePolicy() != b.cachePolicy()) 288 return false; 289 290 if (a.timeoutInterval() != b.timeoutInterval()) 291 return false; 292 293 if (a.firstPartyForCookies() != b.firstPartyForCookies()) 294 return false; 295 296 if (a.httpMethod() != b.httpMethod()) 297 return false; 298 299 if (a.allowStoredCredentials() != b.allowStoredCredentials()) 300 return false; 301 302 if (a.priority() != b.priority()) 303 return false; 304 305 if (a.referrerPolicy() != b.referrerPolicy()) 306 return false; 307 308 FormData* formDataA = a.httpBody(); 309 FormData* formDataB = b.httpBody(); 310 311 if (!formDataA) 312 return !formDataB; 313 if (!formDataB) 314 return !formDataA; 315 316 if (*formDataA != *formDataB) 317 return false; 318 319 return true; 320} 321 322bool ResourceRequest::compare(const ResourceRequest& a, const ResourceRequest& b) 323{ 324 if (!equalIgnoringHeaderFields(a, b)) 325 return false; 326 327 if (a.httpHeaderFields() != b.httpHeaderFields()) 328 return false; 329 330 return true; 331} 332 333bool ResourceRequest::isConditional() const 334{ 335 return (m_httpHeaderFields.contains("If-Match") 336 || m_httpHeaderFields.contains("If-Modified-Since") 337 || m_httpHeaderFields.contains("If-None-Match") 338 || m_httpHeaderFields.contains("If-Range") 339 || m_httpHeaderFields.contains("If-Unmodified-Since")); 340} 341 342 343static const AtomicString& cacheControlHeaderString() 344{ 345 DEFINE_STATIC_LOCAL(const AtomicString, cacheControlHeader, ("cache-control", AtomicString::ConstructFromLiteral)); 346 return cacheControlHeader; 347} 348 349static const AtomicString& pragmaHeaderString() 350{ 351 DEFINE_STATIC_LOCAL(const AtomicString, pragmaHeader, ("pragma", AtomicString::ConstructFromLiteral)); 352 return pragmaHeader; 353} 354 355const CacheControlHeader& ResourceRequest::cacheControlHeader() const 356{ 357 if (!m_cacheControlHeaderCache.parsed) 358 m_cacheControlHeaderCache = parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeaderString()), m_httpHeaderFields.get(pragmaHeaderString())); 359 return m_cacheControlHeaderCache; 360} 361 362bool ResourceRequest::cacheControlContainsNoCache() const 363{ 364 return cacheControlHeader().containsNoCache; 365} 366 367bool ResourceRequest::cacheControlContainsNoStore() const 368{ 369 return cacheControlHeader().containsNoStore; 370} 371 372bool ResourceRequest::hasCacheValidatorFields() const 373{ 374 DEFINE_STATIC_LOCAL(const AtomicString, lastModifiedHeader, ("last-modified", AtomicString::ConstructFromLiteral)); 375 DEFINE_STATIC_LOCAL(const AtomicString, eTagHeader, ("etag", AtomicString::ConstructFromLiteral)); 376 return !m_httpHeaderFields.get(lastModifiedHeader).isEmpty() || !m_httpHeaderFields.get(eTagHeader).isEmpty(); 377} 378 379double ResourceRequest::defaultTimeoutInterval() 380{ 381 return s_defaultTimeoutInterval; 382} 383 384void ResourceRequest::setDefaultTimeoutInterval(double timeoutInterval) 385{ 386 s_defaultTimeoutInterval = timeoutInterval; 387} 388 389void ResourceRequest::initialize(const KURL& url, ResourceRequestCachePolicy cachePolicy) 390{ 391 m_url = url; 392 m_cachePolicy = cachePolicy; 393 m_timeoutInterval = s_defaultTimeoutInterval; 394 m_httpMethod = "GET"; 395 m_allowStoredCredentials = true; 396 m_reportUploadProgress = false; 397 m_reportRawHeaders = false; 398 m_hasUserGesture = false; 399 m_downloadToFile = false; 400 m_skipServiceWorker = false; 401 m_priority = ResourceLoadPriorityLow; 402 m_intraPriorityValue = 0; 403 m_requestorID = 0; 404 m_requestorProcessID = 0; 405 m_appCacheHostID = 0; 406 m_requestContext = blink::WebURLRequest::RequestContextUnspecified; 407 m_frameType = blink::WebURLRequest::FrameTypeNone; 408 m_referrerPolicy = ReferrerPolicyDefault; 409} 410 411// This is used by the loader to control the number of issued parallel load requests. 412unsigned initializeMaximumHTTPConnectionCountPerHost() 413{ 414 // The chromium network stack already handles limiting the number of 415 // parallel requests per host, so there's no need to do it here. Therefore, 416 // this is set to a high value that should never be hit in practice. 417 return 10000; 418} 419 420} 421