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