WebCore:
[WebKit-https.git] / WebCore / platform / network / ResourceRequestBase.cpp
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->setMainDocumentURL(data->m_mainDocumentURL);
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
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_mainDocumentURL = mainDocumentURL().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
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 ResourceRequestCachePolicy ResourceRequestBase::cachePolicy() const
121 {
122     updateResourceRequest(); 
123     
124     return m_cachePolicy; 
125 }
126
127 void ResourceRequestBase::setCachePolicy(ResourceRequestCachePolicy cachePolicy)
128 {
129     updateResourceRequest(); 
130     
131     m_cachePolicy = cachePolicy;
132     
133     if (url().protocolInHTTPFamily())
134         m_platformRequestUpdated = false;
135 }
136
137 double ResourceRequestBase::timeoutInterval() const
138 {
139     updateResourceRequest(); 
140     
141     return m_timeoutInterval; 
142 }
143
144 void ResourceRequestBase::setTimeoutInterval(double timeoutInterval) 
145 {
146     updateResourceRequest(); 
147     
148     m_timeoutInterval = timeoutInterval; 
149     
150     if (url().protocolInHTTPFamily())
151         m_platformRequestUpdated = false;
152 }
153
154 const KURL& ResourceRequestBase::mainDocumentURL() const
155 {
156     updateResourceRequest(); 
157     
158     return m_mainDocumentURL; 
159 }
160
161 void ResourceRequestBase::setMainDocumentURL(const KURL& mainDocumentURL)
162
163     updateResourceRequest(); 
164     
165     m_mainDocumentURL = mainDocumentURL; 
166     
167     m_platformRequestUpdated = false;
168 }
169
170 const String& ResourceRequestBase::httpMethod() const
171 {
172     updateResourceRequest(); 
173     
174     return m_httpMethod; 
175 }
176
177 void ResourceRequestBase::setHTTPMethod(const String& httpMethod) 
178 {
179     updateResourceRequest(); 
180
181     m_httpMethod = httpMethod;
182     
183     if (url().protocolInHTTPFamily())
184         m_platformRequestUpdated = false;
185 }
186
187 const HTTPHeaderMap& ResourceRequestBase::httpHeaderFields() const
188 {
189     updateResourceRequest(); 
190
191     return m_httpHeaderFields; 
192 }
193
194 String ResourceRequestBase::httpHeaderField(const AtomicString& name) const
195 {
196     updateResourceRequest(); 
197     
198     return m_httpHeaderFields.get(name);
199 }
200
201 void ResourceRequestBase::setHTTPHeaderField(const AtomicString& name, const String& value)
202 {
203     updateResourceRequest(); 
204     
205     m_httpHeaderFields.set(name, value); 
206     
207     if (url().protocolInHTTPFamily())
208         m_platformRequestUpdated = false;
209 }
210
211 void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2, const String& encoding3)
212 {
213     updateResourceRequest(); 
214     
215     m_responseContentDispositionEncodingFallbackArray.clear();
216     if (!encoding1.isNull())
217         m_responseContentDispositionEncodingFallbackArray.append(encoding1);
218     if (!encoding2.isNull())
219         m_responseContentDispositionEncodingFallbackArray.append(encoding2);
220     if (!encoding3.isNull())
221         m_responseContentDispositionEncodingFallbackArray.append(encoding3);
222     
223     if (url().protocolInHTTPFamily())
224         m_platformRequestUpdated = false;
225 }
226
227 FormData* ResourceRequestBase::httpBody() const 
228
229     updateResourceRequest(); 
230     
231     return m_httpBody.get(); 
232 }
233
234 void ResourceRequestBase::setHTTPBody(PassRefPtr<FormData> httpBody)
235 {
236     updateResourceRequest(); 
237     
238     m_httpBody = httpBody; 
239     
240     if (url().protocolInHTTPFamily())
241         m_platformRequestUpdated = false;
242
243
244 bool ResourceRequestBase::allowHTTPCookies() const 
245 {
246     updateResourceRequest(); 
247     
248     return m_allowHTTPCookies; 
249 }
250
251 void ResourceRequestBase::setAllowHTTPCookies(bool allowHTTPCookies)
252 {
253     updateResourceRequest(); 
254     
255     m_allowHTTPCookies = allowHTTPCookies; 
256     
257     if (url().protocolInHTTPFamily())
258         m_platformRequestUpdated = false;
259 }
260
261 void ResourceRequestBase::addHTTPHeaderField(const AtomicString& name, const String& value) 
262 {
263     updateResourceRequest();
264     pair<HTTPHeaderMap::iterator, bool> result = m_httpHeaderFields.add(name, value); 
265     if (!result.second)
266         result.first->second += "," + value;
267 }
268
269 void ResourceRequestBase::addHTTPHeaderFields(const HTTPHeaderMap& headerFields)
270 {
271     HTTPHeaderMap::const_iterator end = headerFields.end();
272     for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it)
273         addHTTPHeaderField(it->first, it->second);
274 }
275
276 bool equalIgnoringHeaderFields(const ResourceRequestBase& a, const ResourceRequestBase& b)
277 {
278     if (a.url() != b.url())
279         return false;
280     
281     if (a.cachePolicy() != b.cachePolicy())
282         return false;
283     
284     if (a.timeoutInterval() != b.timeoutInterval())
285         return false;
286     
287     if (a.mainDocumentURL() != b.mainDocumentURL())
288         return false;
289     
290     if (a.httpMethod() != b.httpMethod())
291         return false;
292     
293     if (a.allowHTTPCookies() != b.allowHTTPCookies())
294         return false;
295     
296     FormData* formDataA = a.httpBody();
297     FormData* formDataB = b.httpBody();
298     
299     if (!formDataA)
300         return !formDataB;
301     if (!formDataB)
302         return !formDataA;
303     
304     if (*formDataA != *formDataB)
305         return false;
306     
307     return true;
308 }
309
310 bool operator==(const ResourceRequestBase& a, const ResourceRequestBase& b)
311 {
312     if (!equalIgnoringHeaderFields(a, b))
313         return false;
314     
315     if (a.httpHeaderFields() != b.httpHeaderFields())
316         return false;
317         
318     return true;
319 }
320
321 bool ResourceRequestBase::isConditional() const
322 {
323     return (m_httpHeaderFields.contains("If-Match") ||
324             m_httpHeaderFields.contains("If-Modified-Since") ||
325             m_httpHeaderFields.contains("If-None-Match") ||
326             m_httpHeaderFields.contains("If-Range") ||
327             m_httpHeaderFields.contains("If-Unmodified-Since"));
328 }
329
330 void ResourceRequestBase::updatePlatformRequest() const
331 {
332     if (m_platformRequestUpdated)
333         return;
334     
335     const_cast<ResourceRequest&>(asResourceRequest()).doUpdatePlatformRequest();
336     m_platformRequestUpdated = true;
337 }
338
339 void ResourceRequestBase::updateResourceRequest() const
340 {
341     if (m_resourceRequestUpdated)
342         return;
343
344     const_cast<ResourceRequest&>(asResourceRequest()).doUpdateResourceRequest();
345     m_resourceRequestUpdated = true;
346 }
347
348 }