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
asResourceRequest() const34 inline const ResourceRequest& ResourceRequestBase::asResourceRequest() const
35 {
36 return *static_cast<const ResourceRequest*>(this);
37 }
38
adopt(auto_ptr<CrossThreadResourceRequestData> data)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->setAllowHTTPCookies(data->m_allowHTTPCookies);
66 return request;
67 }
68
copyData() const69 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().copy();
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].copy());
83 }
84 if (m_httpBody)
85 data->m_httpBody = m_httpBody->deepCopy();
86 data->m_allowHTTPCookies = m_allowHTTPCookies;
87 return data;
88 }
89
isEmpty() const90 bool ResourceRequestBase::isEmpty() const
91 {
92 updateResourceRequest();
93
94 return m_url.isEmpty();
95 }
96
isNull() const97 bool ResourceRequestBase::isNull() const
98 {
99 updateResourceRequest();
100
101 return m_url.isNull();
102 }
103
url() const104 const KURL& ResourceRequestBase::url() const
105 {
106 updateResourceRequest();
107
108 return m_url;
109 }
110
setURL(const KURL & url)111 void ResourceRequestBase::setURL(const KURL& url)
112 {
113 updateResourceRequest();
114
115 m_url = url;
116
117 m_platformRequestUpdated = false;
118 }
119
removeCredentials()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
cachePolicy() const130 ResourceRequestCachePolicy ResourceRequestBase::cachePolicy() const
131 {
132 updateResourceRequest();
133
134 return m_cachePolicy;
135 }
136
setCachePolicy(ResourceRequestCachePolicy cachePolicy)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
timeoutInterval() const147 double ResourceRequestBase::timeoutInterval() const
148 {
149 updateResourceRequest();
150
151 return m_timeoutInterval;
152 }
153
setTimeoutInterval(double timeoutInterval)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
firstPartyForCookies() const164 const KURL& ResourceRequestBase::firstPartyForCookies() const
165 {
166 updateResourceRequest();
167
168 return m_firstPartyForCookies;
169 }
170
setFirstPartyForCookies(const KURL & firstPartyForCookies)171 void ResourceRequestBase::setFirstPartyForCookies(const KURL& firstPartyForCookies)
172 {
173 updateResourceRequest();
174
175 m_firstPartyForCookies = firstPartyForCookies;
176
177 m_platformRequestUpdated = false;
178 }
179
httpMethod() const180 const String& ResourceRequestBase::httpMethod() const
181 {
182 updateResourceRequest();
183
184 return m_httpMethod;
185 }
186
setHTTPMethod(const String & httpMethod)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
httpHeaderFields() const197 const HTTPHeaderMap& ResourceRequestBase::httpHeaderFields() const
198 {
199 updateResourceRequest();
200
201 return m_httpHeaderFields;
202 }
203
httpHeaderField(const AtomicString & name) const204 String ResourceRequestBase::httpHeaderField(const AtomicString& name) const
205 {
206 updateResourceRequest();
207
208 return m_httpHeaderFields.get(name);
209 }
210
setHTTPHeaderField(const AtomicString & name,const String & value)211 void ResourceRequestBase::setHTTPHeaderField(const AtomicString& name, const String& value)
212 {
213 updateResourceRequest();
214
215 m_httpHeaderFields.set(name, value);
216
217 if (url().protocolInHTTPFamily())
218 m_platformRequestUpdated = false;
219 }
220
setResponseContentDispositionEncodingFallbackArray(const String & encoding1,const String & encoding2,const String & encoding3)221 void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2, const String& encoding3)
222 {
223 updateResourceRequest();
224
225 m_responseContentDispositionEncodingFallbackArray.clear();
226 if (!encoding1.isNull())
227 m_responseContentDispositionEncodingFallbackArray.append(encoding1);
228 if (!encoding2.isNull())
229 m_responseContentDispositionEncodingFallbackArray.append(encoding2);
230 if (!encoding3.isNull())
231 m_responseContentDispositionEncodingFallbackArray.append(encoding3);
232
233 if (url().protocolInHTTPFamily())
234 m_platformRequestUpdated = false;
235 }
236
httpBody() const237 FormData* ResourceRequestBase::httpBody() const
238 {
239 updateResourceRequest();
240
241 return m_httpBody.get();
242 }
243
setHTTPBody(PassRefPtr<FormData> httpBody)244 void ResourceRequestBase::setHTTPBody(PassRefPtr<FormData> httpBody)
245 {
246 updateResourceRequest();
247
248 m_httpBody = httpBody;
249
250 if (url().protocolInHTTPFamily())
251 m_platformRequestUpdated = false;
252 }
253
allowHTTPCookies() const254 bool ResourceRequestBase::allowHTTPCookies() const
255 {
256 updateResourceRequest();
257
258 return m_allowHTTPCookies;
259 }
260
setAllowHTTPCookies(bool allowHTTPCookies)261 void ResourceRequestBase::setAllowHTTPCookies(bool allowHTTPCookies)
262 {
263 updateResourceRequest();
264
265 m_allowHTTPCookies = allowHTTPCookies;
266
267 if (url().protocolInHTTPFamily())
268 m_platformRequestUpdated = false;
269 }
270
addHTTPHeaderField(const AtomicString & name,const String & value)271 void ResourceRequestBase::addHTTPHeaderField(const AtomicString& name, const String& value)
272 {
273 updateResourceRequest();
274 pair<HTTPHeaderMap::iterator, bool> result = m_httpHeaderFields.add(name, value);
275 if (!result.second)
276 result.first->second += "," + value;
277 }
278
addHTTPHeaderFields(const HTTPHeaderMap & headerFields)279 void ResourceRequestBase::addHTTPHeaderFields(const HTTPHeaderMap& headerFields)
280 {
281 HTTPHeaderMap::const_iterator end = headerFields.end();
282 for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it)
283 addHTTPHeaderField(it->first, it->second);
284 }
285
equalIgnoringHeaderFields(const ResourceRequestBase & a,const ResourceRequestBase & b)286 bool equalIgnoringHeaderFields(const ResourceRequestBase& a, const ResourceRequestBase& b)
287 {
288 if (a.url() != b.url())
289 return false;
290
291 if (a.cachePolicy() != b.cachePolicy())
292 return false;
293
294 if (a.timeoutInterval() != b.timeoutInterval())
295 return false;
296
297 if (a.firstPartyForCookies() != b.firstPartyForCookies())
298 return false;
299
300 if (a.httpMethod() != b.httpMethod())
301 return false;
302
303 if (a.allowHTTPCookies() != b.allowHTTPCookies())
304 return false;
305
306 FormData* formDataA = a.httpBody();
307 FormData* formDataB = b.httpBody();
308
309 if (!formDataA)
310 return !formDataB;
311 if (!formDataB)
312 return !formDataA;
313
314 if (*formDataA != *formDataB)
315 return false;
316
317 return true;
318 }
319
operator ==(const ResourceRequestBase & a,const ResourceRequestBase & b)320 bool operator==(const ResourceRequestBase& a, const ResourceRequestBase& b)
321 {
322 if (!equalIgnoringHeaderFields(a, b))
323 return false;
324
325 if (a.httpHeaderFields() != b.httpHeaderFields())
326 return false;
327
328 return true;
329 }
330
isConditional() const331 bool ResourceRequestBase::isConditional() const
332 {
333 return (m_httpHeaderFields.contains("If-Match") ||
334 m_httpHeaderFields.contains("If-Modified-Since") ||
335 m_httpHeaderFields.contains("If-None-Match") ||
336 m_httpHeaderFields.contains("If-Range") ||
337 m_httpHeaderFields.contains("If-Unmodified-Since"));
338 }
339
updatePlatformRequest() const340 void ResourceRequestBase::updatePlatformRequest() const
341 {
342 if (m_platformRequestUpdated)
343 return;
344
345 const_cast<ResourceRequest&>(asResourceRequest()).doUpdatePlatformRequest();
346 m_platformRequestUpdated = true;
347 }
348
updateResourceRequest() const349 void ResourceRequestBase::updateResourceRequest() const
350 {
351 if (m_resourceRequestUpdated)
352 return;
353
354 const_cast<ResourceRequest&>(asResourceRequest()).doUpdateResourceRequest();
355 m_resourceRequestUpdated = true;
356 }
357
358 #if !PLATFORM(MAC) && !USE(CFNETWORK) && !PLATFORM(ANDROID)
initializeMaximumHTTPConnectionCountPerHost()359 unsigned initializeMaximumHTTPConnectionCountPerHost()
360 {
361 // This is used by the loader to control the number of issued parallel load requests.
362 // Four seems to be a common default in HTTP frameworks.
363 return 4;
364 }
365 #endif
366
367 }
368