701b7c1ce0d895ce8bc797efd9abc476d08ab726
[WebKit-https.git] / Source / WebCore / platform / network / ResourceRequestBase.cpp
1 /*
2  * Copyright (C) 2003, 2006 Apple 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 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 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
29 #include "ResourceRequest.h"
30
31 namespace WebCore {
32
33 #if !USE(SOUP) && (!PLATFORM(COCOA) || USE(CFNETWORK))
34 double ResourceRequestBase::s_defaultTimeoutInterval = INT_MAX;
35 #else
36 // Will use NSURLRequest default timeout unless set to a non-zero value with setDefaultTimeoutInterval().
37 // For libsoup the timeout enabled with integer milliseconds. We set 0 as the default value to avoid integer overflow.
38 double ResourceRequestBase::s_defaultTimeoutInterval = 0;
39 #endif
40
41 #if PLATFORM(IOS)
42 bool ResourceRequestBase::s_defaultAllowCookies = true;
43 #endif
44
45 inline const ResourceRequest& ResourceRequestBase::asResourceRequest() const
46 {
47     return *static_cast<const ResourceRequest*>(this);
48 }
49
50 PassOwnPtr<ResourceRequest> ResourceRequestBase::adopt(PassOwnPtr<CrossThreadResourceRequestData> data)
51 {
52     OwnPtr<ResourceRequest> request = adoptPtr(new ResourceRequest());
53     request->setURL(data->m_url);
54     request->setCachePolicy(data->m_cachePolicy);
55     request->setTimeoutInterval(data->m_timeoutInterval);
56     request->setFirstPartyForCookies(data->m_firstPartyForCookies);
57     request->setHTTPMethod(data->m_httpMethod);
58     request->setPriority(data->m_priority);
59
60     request->updateResourceRequest();
61     request->m_httpHeaderFields.adopt(data->m_httpHeaders.release());
62
63     size_t encodingCount = data->m_responseContentDispositionEncodingFallbackArray.size();
64     if (encodingCount > 0) {
65         String encoding1 = data->m_responseContentDispositionEncodingFallbackArray[0];
66         String encoding2;
67         String encoding3;
68         if (encodingCount > 1) {
69             encoding2 = data->m_responseContentDispositionEncodingFallbackArray[1];
70             if (encodingCount > 2)
71                 encoding3 = data->m_responseContentDispositionEncodingFallbackArray[2];
72         }
73         ASSERT(encodingCount <= 3);
74         request->setResponseContentDispositionEncodingFallbackArray(encoding1, encoding2, encoding3);
75     }
76     request->setHTTPBody(data->m_httpBody);
77     request->setAllowCookies(data->m_allowCookies);
78     request->doPlatformAdopt(data);
79     return request.release();
80 }
81
82 PassOwnPtr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const
83 {
84     OwnPtr<CrossThreadResourceRequestData> data = adoptPtr(new CrossThreadResourceRequestData());
85     data->m_url = url().copy();
86     data->m_cachePolicy = cachePolicy();
87     data->m_timeoutInterval = timeoutInterval();
88     data->m_firstPartyForCookies = firstPartyForCookies().copy();
89     data->m_httpMethod = httpMethod().isolatedCopy();
90     data->m_httpHeaders = httpHeaderFields().copyData();
91     data->m_priority = priority();
92
93     data->m_responseContentDispositionEncodingFallbackArray.reserveInitialCapacity(m_responseContentDispositionEncodingFallbackArray.size());
94     size_t encodingArraySize = m_responseContentDispositionEncodingFallbackArray.size();
95     for (size_t index = 0; index < encodingArraySize; ++index) {
96         data->m_responseContentDispositionEncodingFallbackArray.append(m_responseContentDispositionEncodingFallbackArray[index].isolatedCopy());
97     }
98     if (m_httpBody)
99         data->m_httpBody = m_httpBody->deepCopy();
100     data->m_allowCookies = m_allowCookies;
101     return asResourceRequest().doPlatformCopyData(data.release());
102 }
103
104 bool ResourceRequestBase::isEmpty() const
105 {
106     updateResourceRequest(); 
107     
108     return m_url.isEmpty(); 
109 }
110
111 bool ResourceRequestBase::isNull() const
112 {
113     updateResourceRequest(); 
114     
115     return m_url.isNull();
116 }
117
118 const URL& ResourceRequestBase::url() const 
119 {
120     updateResourceRequest(); 
121     
122     return m_url;
123 }
124
125 void ResourceRequestBase::setURL(const URL& url)
126
127     updateResourceRequest(); 
128
129     m_url = url; 
130     
131     m_platformRequestUpdated = false;
132 }
133
134 void ResourceRequestBase::removeCredentials()
135 {
136     updateResourceRequest(); 
137
138     if (m_url.user().isEmpty() && m_url.pass().isEmpty())
139         return;
140
141     m_url.setUser(String());
142     m_url.setPass(String());
143
144     m_platformRequestUpdated = false;
145 }
146
147 ResourceRequestCachePolicy ResourceRequestBase::cachePolicy() const
148 {
149     updateResourceRequest(); 
150     
151     return m_cachePolicy; 
152 }
153
154 void ResourceRequestBase::setCachePolicy(ResourceRequestCachePolicy cachePolicy)
155 {
156     updateResourceRequest(); 
157
158     if (m_cachePolicy == cachePolicy)
159         return;
160     
161     m_cachePolicy = cachePolicy;
162     
163     if (url().protocolIsInHTTPFamily())
164         m_platformRequestUpdated = false;
165 }
166
167 double ResourceRequestBase::timeoutInterval() const
168 {
169     updateResourceRequest(); 
170     
171     return m_timeoutInterval; 
172 }
173
174 void ResourceRequestBase::setTimeoutInterval(double timeoutInterval) 
175 {
176     updateResourceRequest(); 
177     
178     if (m_timeoutInterval == timeoutInterval)
179         return;
180
181     m_timeoutInterval = timeoutInterval;
182     
183     if (url().protocolIsInHTTPFamily())
184         m_platformRequestUpdated = false;
185 }
186
187 const URL& ResourceRequestBase::firstPartyForCookies() const
188 {
189     updateResourceRequest(); 
190     
191     return m_firstPartyForCookies;
192 }
193
194 void ResourceRequestBase::setFirstPartyForCookies(const URL& firstPartyForCookies)
195
196     updateResourceRequest(); 
197
198     if (m_firstPartyForCookies == firstPartyForCookies)
199         return;
200
201     m_firstPartyForCookies = firstPartyForCookies;
202     
203     m_platformRequestUpdated = false;
204 }
205
206 const String& ResourceRequestBase::httpMethod() const
207 {
208     updateResourceRequest(); 
209     
210     return m_httpMethod; 
211 }
212
213 void ResourceRequestBase::setHTTPMethod(const String& httpMethod) 
214 {
215     updateResourceRequest(); 
216
217     if (m_httpMethod == httpMethod)
218         return;
219
220     m_httpMethod = httpMethod;
221     
222     if (url().protocolIsInHTTPFamily())
223         m_platformRequestUpdated = false;
224 }
225
226 const HTTPHeaderMap& ResourceRequestBase::httpHeaderFields() const
227 {
228     updateResourceRequest(); 
229
230     return m_httpHeaderFields; 
231 }
232
233 String ResourceRequestBase::httpHeaderField(const AtomicString& name) const
234 {
235     updateResourceRequest(); 
236     
237     return m_httpHeaderFields.get(name);
238 }
239
240 String ResourceRequestBase::httpHeaderField(const char* name) const
241 {
242     updateResourceRequest(); 
243     
244     return m_httpHeaderFields.get(name);
245 }
246
247 void ResourceRequestBase::setHTTPHeaderField(const AtomicString& name, const String& value)
248 {
249     updateResourceRequest(); 
250     
251     m_httpHeaderFields.set(name, value); 
252     
253     if (url().protocolIsInHTTPFamily())
254         m_platformRequestUpdated = false;
255 }
256
257 void ResourceRequestBase::setHTTPHeaderField(const char* name, const String& value)
258 {
259     setHTTPHeaderField(AtomicString(name), value);
260 }
261
262 void ResourceRequestBase::clearHTTPAuthorization()
263 {
264     updateResourceRequest(); 
265
266     HTTPHeaderMap::iterator iter = m_httpHeaderFields.find("Authorization");
267     if (iter == m_httpHeaderFields.end())
268         return;
269
270     m_httpHeaderFields.remove(iter);
271
272     if (url().protocolIsInHTTPFamily())
273         m_platformRequestUpdated = false;
274 }
275
276 void ResourceRequestBase::clearHTTPContentType()
277 {
278     updateResourceRequest(); 
279
280     m_httpHeaderFields.remove("Content-Type");
281
282     if (url().protocolIsInHTTPFamily())
283         m_platformRequestUpdated = false;
284 }
285
286 void ResourceRequestBase::clearHTTPReferrer()
287 {
288     updateResourceRequest(); 
289
290     m_httpHeaderFields.remove("Referer");
291
292     if (url().protocolIsInHTTPFamily())
293         m_platformRequestUpdated = false;
294 }
295
296 void ResourceRequestBase::clearHTTPOrigin()
297 {
298     updateResourceRequest(); 
299
300     m_httpHeaderFields.remove("Origin");
301
302     if (url().protocolIsInHTTPFamily())
303         m_platformRequestUpdated = false;
304 }
305
306 void ResourceRequestBase::clearHTTPUserAgent()
307 {
308     updateResourceRequest(); 
309
310     m_httpHeaderFields.remove("User-Agent");
311
312     if (url().protocolIsInHTTPFamily())
313         m_platformRequestUpdated = false;
314 }
315
316 void ResourceRequestBase::clearHTTPAccept()
317 {
318     updateResourceRequest(); 
319
320     m_httpHeaderFields.remove("Accept");
321
322     if (url().protocolIsInHTTPFamily())
323         m_platformRequestUpdated = false;
324 }
325
326 void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2, const String& encoding3)
327 {
328     updateResourceRequest(); 
329     
330     m_responseContentDispositionEncodingFallbackArray.clear();
331     m_responseContentDispositionEncodingFallbackArray.reserveInitialCapacity(!encoding1.isNull() + !encoding2.isNull() + !encoding3.isNull());
332     if (!encoding1.isNull())
333         m_responseContentDispositionEncodingFallbackArray.uncheckedAppend(encoding1);
334     if (!encoding2.isNull())
335         m_responseContentDispositionEncodingFallbackArray.uncheckedAppend(encoding2);
336     if (!encoding3.isNull())
337         m_responseContentDispositionEncodingFallbackArray.uncheckedAppend(encoding3);
338     
339     if (url().protocolIsInHTTPFamily())
340         m_platformRequestUpdated = false;
341 }
342
343 FormData* ResourceRequestBase::httpBody() const
344 {
345     updateResourceRequest(UpdateHTTPBody);
346
347     return m_httpBody.get();
348 }
349
350 void ResourceRequestBase::setHTTPBody(PassRefPtr<FormData> httpBody)
351 {
352     updateResourceRequest();
353
354     m_httpBody = httpBody;
355
356     m_resourceRequestBodyUpdated = true;
357
358     if (url().protocolIsInHTTPFamily())
359         m_platformRequestBodyUpdated = false;
360 }
361
362 bool ResourceRequestBase::allowCookies() const
363 {
364     updateResourceRequest(); 
365     
366     return m_allowCookies;
367 }
368
369 void ResourceRequestBase::setAllowCookies(bool allowCookies)
370 {
371     updateResourceRequest(); 
372
373     if (m_allowCookies == allowCookies)
374         return;
375
376     m_allowCookies = allowCookies;
377     
378     if (url().protocolIsInHTTPFamily())
379         m_platformRequestUpdated = false;
380 }
381
382 ResourceLoadPriority ResourceRequestBase::priority() const
383 {
384     updateResourceRequest();
385
386     return m_priority;
387 }
388
389 void ResourceRequestBase::setPriority(ResourceLoadPriority priority)
390 {
391     updateResourceRequest();
392
393     if (m_priority == priority)
394         return;
395
396     m_priority = priority;
397
398     if (url().protocolIsInHTTPFamily())
399         m_platformRequestUpdated = false;
400 }
401
402 void ResourceRequestBase::addHTTPHeaderField(const AtomicString& name, const String& value) 
403 {
404     updateResourceRequest();
405     HTTPHeaderMap::AddResult result = m_httpHeaderFields.add(name, value);
406     if (!result.isNewEntry)
407         result.iterator->value = result.iterator->value + ',' + value;
408
409     if (url().protocolIsInHTTPFamily())
410         m_platformRequestUpdated = false;
411 }
412
413 void ResourceRequestBase::addHTTPHeaderFields(const HTTPHeaderMap& headerFields)
414 {
415     for (const auto& header : headerFields)
416         addHTTPHeaderField(header.key, header.value);
417 }
418
419 bool equalIgnoringHeaderFields(const ResourceRequestBase& a, const ResourceRequestBase& b)
420 {
421     if (a.url() != b.url())
422         return false;
423     
424     if (a.cachePolicy() != b.cachePolicy())
425         return false;
426     
427     if (a.timeoutInterval() != b.timeoutInterval())
428         return false;
429     
430     if (a.firstPartyForCookies() != b.firstPartyForCookies())
431         return false;
432     
433     if (a.httpMethod() != b.httpMethod())
434         return false;
435     
436     if (a.allowCookies() != b.allowCookies())
437         return false;
438     
439     if (a.priority() != b.priority())
440         return false;
441
442     FormData* formDataA = a.httpBody();
443     FormData* formDataB = b.httpBody();
444     
445     if (!formDataA)
446         return !formDataB;
447     if (!formDataB)
448         return !formDataA;
449     
450     if (*formDataA != *formDataB)
451         return false;
452     
453     return true;
454 }
455
456 bool ResourceRequestBase::compare(const ResourceRequest& a, const ResourceRequest& b)
457 {
458     if (!equalIgnoringHeaderFields(a, b))
459         return false;
460     
461     if (a.httpHeaderFields() != b.httpHeaderFields())
462         return false;
463         
464     return ResourceRequest::platformCompare(a, b);
465 }
466
467 bool ResourceRequestBase::isConditional() const
468 {
469     return (m_httpHeaderFields.contains("If-Match") ||
470             m_httpHeaderFields.contains("If-Modified-Since") ||
471             m_httpHeaderFields.contains("If-None-Match") ||
472             m_httpHeaderFields.contains("If-Range") ||
473             m_httpHeaderFields.contains("If-Unmodified-Since"));
474 }
475
476 void ResourceRequestBase::makeUnconditional()
477 {
478     m_httpHeaderFields.remove("If-Match");
479     m_httpHeaderFields.remove("If-Modified-Since");
480     m_httpHeaderFields.remove("If-None-Match");
481     m_httpHeaderFields.remove("If-Range");
482     m_httpHeaderFields.remove("If-Unmodified-Since");
483 }
484
485 double ResourceRequestBase::defaultTimeoutInterval()
486 {
487     return s_defaultTimeoutInterval;
488 }
489
490 void ResourceRequestBase::setDefaultTimeoutInterval(double timeoutInterval)
491 {
492     s_defaultTimeoutInterval = timeoutInterval;
493 }
494
495 void ResourceRequestBase::updatePlatformRequest(HTTPBodyUpdatePolicy bodyPolicy) const
496 {
497     if (!m_platformRequestUpdated) {
498         ASSERT(m_resourceRequestUpdated);
499         const_cast<ResourceRequest&>(asResourceRequest()).doUpdatePlatformRequest();
500         m_platformRequestUpdated = true;
501     }
502
503     if (!m_platformRequestBodyUpdated && bodyPolicy == UpdateHTTPBody) {
504         ASSERT(m_resourceRequestBodyUpdated);
505         const_cast<ResourceRequest&>(asResourceRequest()).doUpdatePlatformHTTPBody();
506         m_platformRequestBodyUpdated = true;
507     }
508 }
509
510 void ResourceRequestBase::updateResourceRequest(HTTPBodyUpdatePolicy bodyPolicy) const
511 {
512     if (!m_resourceRequestUpdated) {
513         ASSERT(m_platformRequestUpdated);
514         const_cast<ResourceRequest&>(asResourceRequest()).doUpdateResourceRequest();
515         m_resourceRequestUpdated = true;
516     }
517
518     if (!m_resourceRequestBodyUpdated && bodyPolicy == UpdateHTTPBody) {
519         ASSERT(m_platformRequestBodyUpdated);
520         const_cast<ResourceRequest&>(asResourceRequest()).doUpdateResourceHTTPBody();
521         m_resourceRequestBodyUpdated = true;
522     }
523 }
524
525 #if !PLATFORM(COCOA) && !USE(CFNETWORK) && !USE(SOUP)
526 unsigned initializeMaximumHTTPConnectionCountPerHost()
527 {
528     // This is used by the loader to control the number of issued parallel load requests. 
529     // Four seems to be a common default in HTTP frameworks.
530     return 4;
531 }
532 #endif
533
534 #if PLATFORM(IOS)
535 void ResourceRequestBase::setDefaultAllowCookies(bool allowCookies)
536 {
537     s_defaultAllowCookies = allowCookies;
538 }
539
540 bool ResourceRequestBase::defaultAllowCookies()
541 {
542     return s_defaultAllowCookies;
543 }
544 #endif
545
546 }