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