1 /* 2 * Copyright (C) 2003, 2006 Apple Computer, 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 #include "config.h" 27 28 #include "ResourceRequestBase.h" 29 #include "ResourceRequest.h" 30 31 using namespace std; 32 33 namespace WebCore { 34 35 #if !PLATFORM(MAC) || USE(CFNETWORK) 36 double ResourceRequestBase::s_defaultTimeoutInterval = INT_MAX; 37 #else 38 // Will use NSURLRequest default timeout unless set to a non-zero value with setDefaultTimeoutInterval(). 39 double ResourceRequestBase::s_defaultTimeoutInterval = 0; 40 #endif 41 42 inline const ResourceRequest& ResourceRequestBase::asResourceRequest() const 43 { 44 return *static_cast<const ResourceRequest*>(this); 45 } 46 47 PassOwnPtr<ResourceRequest> ResourceRequestBase::adopt(PassOwnPtr<CrossThreadResourceRequestData> data) 48 { 49 OwnPtr<ResourceRequest> request(new ResourceRequest()); 50 request->setURL(data->m_url); 51 request->setCachePolicy(data->m_cachePolicy); 52 request->setTimeoutInterval(data->m_timeoutInterval); 53 request->setFirstPartyForCookies(data->m_firstPartyForCookies); 54 request->setHTTPMethod(data->m_httpMethod); 55 request->setPriority(data->m_priority); 56 request->setTargetType(data->m_targetType); 57 58 request->updateResourceRequest(); 59 request->m_httpHeaderFields.adopt(data->m_httpHeaders.release()); 60 61 size_t encodingCount = data->m_responseContentDispositionEncodingFallbackArray.size(); 62 if (encodingCount > 0) { 63 String encoding1 = data->m_responseContentDispositionEncodingFallbackArray[0]; 64 String encoding2; 65 String encoding3; 66 if (encodingCount > 1) { 67 encoding2 = data->m_responseContentDispositionEncodingFallbackArray[1]; 68 if (encodingCount > 2) 69 encoding3 = data->m_responseContentDispositionEncodingFallbackArray[2]; 70 } 71 ASSERT(encodingCount <= 3); 72 request->setResponseContentDispositionEncodingFallbackArray(encoding1, encoding2, encoding3); 73 } 74 request->setHTTPBody(data->m_httpBody); 75 request->setAllowCookies(data->m_allowCookies); 76 request->doPlatformAdopt(data); 77 return request.release(); 78 } 79 80 PassOwnPtr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const 81 { 82 OwnPtr<CrossThreadResourceRequestData> data(new CrossThreadResourceRequestData()); 83 data->m_url = url().copy(); 84 data->m_cachePolicy = cachePolicy(); 85 data->m_timeoutInterval = timeoutInterval(); 86 data->m_firstPartyForCookies = firstPartyForCookies().copy(); 87 data->m_httpMethod = httpMethod().crossThreadString(); 88 data->m_httpHeaders = httpHeaderFields().copyData(); 89 data->m_priority = priority(); 90 data->m_targetType = m_targetType; 91 92 data->m_responseContentDispositionEncodingFallbackArray.reserveInitialCapacity(m_responseContentDispositionEncodingFallbackArray.size()); 93 size_t encodingArraySize = m_responseContentDispositionEncodingFallbackArray.size(); 94 for (size_t index = 0; index < encodingArraySize; ++index) { 95 data->m_responseContentDispositionEncodingFallbackArray.append(m_responseContentDispositionEncodingFallbackArray[index].crossThreadString()); 96 } 97 if (m_httpBody) 98 data->m_httpBody = m_httpBody->deepCopy(); 99 data->m_allowCookies = m_allowCookies; 100 return asResourceRequest().doPlatformCopyData(data.release()); 101 } 102 103 bool ResourceRequestBase::isEmpty() const 104 { 105 updateResourceRequest(); 106 107 return m_url.isEmpty(); 108 } 109 110 bool ResourceRequestBase::isNull() const 111 { 112 updateResourceRequest(); 113 114 return m_url.isNull(); 115 } 116 117 const KURL& ResourceRequestBase::url() const 118 { 119 updateResourceRequest(); 120 121 return m_url; 122 } 123 124 void ResourceRequestBase::setURL(const KURL& url) 125 { 126 updateResourceRequest(); 127 128 m_url = url; 129 130 m_platformRequestUpdated = false; 131 } 132 133 void ResourceRequestBase::removeCredentials() 134 { 135 updateResourceRequest(); 136 137 m_url.setUser(String()); 138 m_url.setPass(String()); 139 140 m_platformRequestUpdated = false; 141 } 142 143 ResourceRequestCachePolicy ResourceRequestBase::cachePolicy() const 144 { 145 updateResourceRequest(); 146 147 return m_cachePolicy; 148 } 149 150 void ResourceRequestBase::setCachePolicy(ResourceRequestCachePolicy cachePolicy) 151 { 152 updateResourceRequest(); 153 154 m_cachePolicy = cachePolicy; 155 156 if (url().protocolInHTTPFamily()) 157 m_platformRequestUpdated = false; 158 } 159 160 double ResourceRequestBase::timeoutInterval() const 161 { 162 updateResourceRequest(); 163 164 return m_timeoutInterval; 165 } 166 167 void ResourceRequestBase::setTimeoutInterval(double timeoutInterval) 168 { 169 updateResourceRequest(); 170 171 m_timeoutInterval = timeoutInterval; 172 173 if (url().protocolInHTTPFamily()) 174 m_platformRequestUpdated = false; 175 } 176 177 const KURL& ResourceRequestBase::firstPartyForCookies() const 178 { 179 updateResourceRequest(); 180 181 return m_firstPartyForCookies; 182 } 183 184 void ResourceRequestBase::setFirstPartyForCookies(const KURL& firstPartyForCookies) 185 { 186 updateResourceRequest(); 187 188 m_firstPartyForCookies = firstPartyForCookies; 189 190 m_platformRequestUpdated = false; 191 } 192 193 const String& ResourceRequestBase::httpMethod() const 194 { 195 updateResourceRequest(); 196 197 return m_httpMethod; 198 } 199 200 void ResourceRequestBase::setHTTPMethod(const String& httpMethod) 201 { 202 updateResourceRequest(); 203 204 m_httpMethod = httpMethod; 205 206 if (url().protocolInHTTPFamily()) 207 m_platformRequestUpdated = false; 208 } 209 210 const HTTPHeaderMap& ResourceRequestBase::httpHeaderFields() const 211 { 212 updateResourceRequest(); 213 214 return m_httpHeaderFields; 215 } 216 217 String ResourceRequestBase::httpHeaderField(const AtomicString& name) const 218 { 219 updateResourceRequest(); 220 221 return m_httpHeaderFields.get(name); 222 } 223 224 String ResourceRequestBase::httpHeaderField(const char* name) const 225 { 226 updateResourceRequest(); 227 228 return m_httpHeaderFields.get(name); 229 } 230 231 void ResourceRequestBase::setHTTPHeaderField(const AtomicString& name, const String& value) 232 { 233 updateResourceRequest(); 234 235 m_httpHeaderFields.set(name, value); 236 237 if (url().protocolInHTTPFamily()) 238 m_platformRequestUpdated = false; 239 } 240 241 void ResourceRequestBase::setHTTPHeaderField(const char* name, const String& value) 242 { 243 setHTTPHeaderField(AtomicString(name), value); 244 } 245 246 void ResourceRequestBase::clearHTTPAuthorization() 247 { 248 updateResourceRequest(); 249 250 m_httpHeaderFields.remove("Authorization"); 251 252 if (url().protocolInHTTPFamily()) 253 m_platformRequestUpdated = false; 254 } 255 256 void ResourceRequestBase::clearHTTPReferrer() 257 { 258 updateResourceRequest(); 259 260 m_httpHeaderFields.remove("Referer"); 261 262 if (url().protocolInHTTPFamily()) 263 m_platformRequestUpdated = false; 264 } 265 266 void ResourceRequestBase::clearHTTPOrigin() 267 { 268 updateResourceRequest(); 269 270 m_httpHeaderFields.remove("Origin"); 271 272 if (url().protocolInHTTPFamily()) 273 m_platformRequestUpdated = false; 274 } 275 276 void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2, const String& encoding3) 277 { 278 updateResourceRequest(); 279 280 m_responseContentDispositionEncodingFallbackArray.clear(); 281 if (!encoding1.isNull()) 282 m_responseContentDispositionEncodingFallbackArray.append(encoding1); 283 if (!encoding2.isNull()) 284 m_responseContentDispositionEncodingFallbackArray.append(encoding2); 285 if (!encoding3.isNull()) 286 m_responseContentDispositionEncodingFallbackArray.append(encoding3); 287 288 if (url().protocolInHTTPFamily()) 289 m_platformRequestUpdated = false; 290 } 291 292 FormData* ResourceRequestBase::httpBody() const 293 { 294 updateResourceRequest(); 295 296 return m_httpBody.get(); 297 } 298 299 void ResourceRequestBase::setHTTPBody(PassRefPtr<FormData> httpBody) 300 { 301 updateResourceRequest(); 302 303 m_httpBody = httpBody; 304 305 if (url().protocolInHTTPFamily()) 306 m_platformRequestUpdated = false; 307 } 308 309 bool ResourceRequestBase::allowCookies() const 310 { 311 updateResourceRequest(); 312 313 return m_allowCookies; 314 } 315 316 void ResourceRequestBase::setAllowCookies(bool allowCookies) 317 { 318 updateResourceRequest(); 319 320 m_allowCookies = allowCookies; 321 322 if (url().protocolInHTTPFamily()) 323 m_platformRequestUpdated = false; 324 } 325 326 ResourceLoadPriority ResourceRequestBase::priority() const 327 { 328 updateResourceRequest(); 329 330 return m_priority; 331 } 332 333 void ResourceRequestBase::setPriority(ResourceLoadPriority priority) 334 { 335 updateResourceRequest(); 336 337 m_priority = priority; 338 339 if (url().protocolInHTTPFamily()) 340 m_platformRequestUpdated = false; 341 } 342 343 void ResourceRequestBase::addHTTPHeaderField(const AtomicString& name, const String& value) 344 { 345 updateResourceRequest(); 346 pair<HTTPHeaderMap::iterator, bool> result = m_httpHeaderFields.add(name, value); 347 if (!result.second) 348 result.first->second += "," + value; 349 350 if (url().protocolInHTTPFamily()) 351 m_platformRequestUpdated = false; 352 } 353 354 void ResourceRequestBase::addHTTPHeaderFields(const HTTPHeaderMap& headerFields) 355 { 356 HTTPHeaderMap::const_iterator end = headerFields.end(); 357 for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it) 358 addHTTPHeaderField(it->first, it->second); 359 } 360 361 bool equalIgnoringHeaderFields(const ResourceRequestBase& a, const ResourceRequestBase& b) 362 { 363 if (a.url() != b.url()) 364 return false; 365 366 if (a.cachePolicy() != b.cachePolicy()) 367 return false; 368 369 if (a.timeoutInterval() != b.timeoutInterval()) 370 return false; 371 372 if (a.firstPartyForCookies() != b.firstPartyForCookies()) 373 return false; 374 375 if (a.httpMethod() != b.httpMethod()) 376 return false; 377 378 if (a.allowCookies() != b.allowCookies()) 379 return false; 380 381 if (a.priority() != b.priority()) 382 return false; 383 384 FormData* formDataA = a.httpBody(); 385 FormData* formDataB = b.httpBody(); 386 387 if (!formDataA) 388 return !formDataB; 389 if (!formDataB) 390 return !formDataA; 391 392 if (*formDataA != *formDataB) 393 return false; 394 395 return true; 396 } 397 398 bool ResourceRequestBase::compare(const ResourceRequest& a, const ResourceRequest& b) 399 { 400 if (!equalIgnoringHeaderFields(a, b)) 401 return false; 402 403 if (a.httpHeaderFields() != b.httpHeaderFields()) 404 return false; 405 406 return ResourceRequest::platformCompare(a, b); 407 } 408 409 bool ResourceRequestBase::isConditional() const 410 { 411 return (m_httpHeaderFields.contains("If-Match") || 412 m_httpHeaderFields.contains("If-Modified-Since") || 413 m_httpHeaderFields.contains("If-None-Match") || 414 m_httpHeaderFields.contains("If-Range") || 415 m_httpHeaderFields.contains("If-Unmodified-Since")); 416 } 417 418 double ResourceRequestBase::defaultTimeoutInterval() 419 { 420 return s_defaultTimeoutInterval; 421 } 422 423 void ResourceRequestBase::setDefaultTimeoutInterval(double timeoutInterval) 424 { 425 s_defaultTimeoutInterval = timeoutInterval; 426 } 427 428 void ResourceRequestBase::updatePlatformRequest() const 429 { 430 if (m_platformRequestUpdated) 431 return; 432 433 ASSERT(m_resourceRequestUpdated); 434 const_cast<ResourceRequest&>(asResourceRequest()).doUpdatePlatformRequest(); 435 m_platformRequestUpdated = true; 436 } 437 438 void ResourceRequestBase::updateResourceRequest() const 439 { 440 if (m_resourceRequestUpdated) 441 return; 442 443 ASSERT(m_platformRequestUpdated); 444 const_cast<ResourceRequest&>(asResourceRequest()).doUpdateResourceRequest(); 445 m_resourceRequestUpdated = true; 446 } 447 448 #if !PLATFORM(MAC) && !USE(CFNETWORK) && !USE(SOUP) && !PLATFORM(CHROMIUM) && !PLATFORM(ANDROID) && !PLATFORM(QT) 449 unsigned initializeMaximumHTTPConnectionCountPerHost() 450 { 451 // This is used by the loader to control the number of issued parallel load requests. 452 // Four seems to be a common default in HTTP frameworks. 453 return 4; 454 } 455 #endif 456 457 } 458