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