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