9e30ef5f68aab96d1bc9391b9a8465e245c9230a
[WebKit-https.git] / Source / WebCore / platform / network / blackberry / ResourceRequestBlackBerry.cpp
1 /*
2  * Copyright (C) 2009, 2010, 2011 Research In Motion Limited. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include "config.h"
20 #include "ResourceRequest.h"
21
22 #include "BlobRegistryImpl.h"
23 #include "CookieManager.h"
24 #include <BlackBerryPlatformClient.h>
25 #include <network/NetworkRequest.h>
26 #include <wtf/HashMap.h>
27 #include <wtf/text/CString.h>
28
29 using BlackBerry::Platform::NetworkRequest;
30
31 namespace WebCore {
32
33 unsigned initializeMaximumHTTPConnectionCountPerHost()
34 {
35     return 6;
36 }
37
38 static inline NetworkRequest::CachePolicy platformCachePolicyForRequest(const ResourceRequest& request)
39 {
40     switch (request.cachePolicy()) {
41     case WebCore::UseProtocolCachePolicy:
42         return NetworkRequest::UseProtocolCachePolicy;
43     case WebCore::ReloadIgnoringCacheData:
44         return NetworkRequest::ReloadIgnoringCacheData;
45     case WebCore::ReturnCacheDataElseLoad:
46         return NetworkRequest::ReturnCacheDataElseLoad;
47     case WebCore::ReturnCacheDataDontLoad:
48         return NetworkRequest::ReturnCacheDataDontLoad;
49     default:
50         return NetworkRequest::UseProtocolCachePolicy;
51     }
52 }
53
54 static inline NetworkRequest::TargetType platformTargetTypeForRequest(const ResourceRequest& request)
55 {
56     if (request.isXMLHTTPRequest())
57         return NetworkRequest::TargetIsXMLHTTPRequest;
58
59     switch (request.targetType()) {
60     case ResourceRequest::TargetIsMainFrame:
61         return NetworkRequest::TargetIsMainFrame;
62     case ResourceRequest::TargetIsSubframe:
63         return NetworkRequest::TargetIsSubframe;
64     case ResourceRequest::TargetIsSubresource:
65         return NetworkRequest::TargetIsSubresource;
66     case ResourceRequest::TargetIsStyleSheet:
67         return NetworkRequest::TargetIsStyleSheet;
68     case ResourceRequest::TargetIsScript:
69         return NetworkRequest::TargetIsScript;
70     case ResourceRequest::TargetIsFontResource:
71         return NetworkRequest::TargetIsFontResource;
72     case ResourceRequest::TargetIsImage:
73         return NetworkRequest::TargetIsImage;
74     case ResourceRequest::TargetIsObject:
75         return NetworkRequest::TargetIsObject;
76     case ResourceRequest::TargetIsMedia:
77         return NetworkRequest::TargetIsMedia;
78     case ResourceRequest::TargetIsWorker:
79         return NetworkRequest::TargetIsWorker;
80     case ResourceRequest::TargetIsSharedWorker:
81         return NetworkRequest::TargetIsSharedWorker;
82
83         // FIXME: this need to be updated to the right value, but
84         // we need to coordinate with AIR api change.
85     case ResourceRequest::TargetIsFavicon:
86         return NetworkRequest::TargetIsImage;
87     case ResourceRequest::TargetIsPrefetch:
88         return NetworkRequest::TargetIsSubresource;
89     case ResourceRequest::TargetIsPrerender:
90         return NetworkRequest::TargetIsSubresource;
91     case ResourceRequest::TargetIsXHR:
92         return NetworkRequest::TargetIsSubresource;
93     case ResourceRequest::TargetIsTextTrack:
94         return NetworkRequest::TargetIsSubresource;
95     case ResourceRequest::TargetIsUnspecified:
96         return NetworkRequest::TargetIsSubresource;
97
98     default:
99         ASSERT_NOT_REACHED();
100         return NetworkRequest::TargetIsUnknown;
101     }
102 }
103
104 typedef HashMap<String, ResourceRequest::TargetType> MimeTypeResourceRequestTypeMap;
105
106 static const MimeTypeResourceRequestTypeMap& mimeTypeRequestTypeMap()
107 {
108     static MimeTypeResourceRequestTypeMap* map = 0;
109     if (!map) {
110         map = new MimeTypeResourceRequestTypeMap;
111
112         if (map) {
113             // The list here should match extensionMap[] in MIMETypeRegistryBlackBerry.cpp
114             map->add(String("text/css"), ResourceRequest::TargetIsStyleSheet);
115             map->add(String("application/x-javascript"), ResourceRequest::TargetIsScript);
116             map->add(String("image/bmp"), ResourceRequest::TargetIsImage);
117             map->add(String("image/gif"), ResourceRequest::TargetIsImage);
118             map->add(String("image/x-icon"), ResourceRequest::TargetIsImage);
119             map->add(String("image/jpeg"), ResourceRequest::TargetIsImage);
120             map->add(String("image/png"), ResourceRequest::TargetIsImage);
121             map->add(String("image/x-portable-bitmap"), ResourceRequest::TargetIsImage);
122             map->add(String("image/x-portable-graymap"), ResourceRequest::TargetIsImage);
123             map->add(String("image/x-portable-pixmap"), ResourceRequest::TargetIsImage);
124             map->add(String("image/svg+xml"), ResourceRequest::TargetIsImage);
125             map->add(String("image/tiff"), ResourceRequest::TargetIsImage);
126             map->add(String("image/x-xbitmap"), ResourceRequest::TargetIsImage);
127             map->add(String("image/x-xpm"), ResourceRequest::TargetIsImage);
128         }
129     }
130
131     return *map;
132 }
133
134 ResourceRequest::TargetType ResourceRequest::targetTypeFromMimeType(const String& mimeType)
135 {
136     const MimeTypeResourceRequestTypeMap& map = mimeTypeRequestTypeMap();
137
138     MimeTypeResourceRequestTypeMap::const_iterator iter = map.find(mimeType);
139     if (iter == map.end())
140         return ResourceRequest::TargetIsUnspecified;
141
142     return iter->second;
143 }
144
145 void ResourceRequest::initializePlatformRequest(NetworkRequest& platformRequest, bool cookiesEnabled, bool isInitial, bool isRedirect) const
146 {
147     // If this is the initial load, skip the request body and headers.
148     if (isInitial)
149         platformRequest.setRequestInitial(timeoutInterval());
150     else {
151         platformRequest.setRequestUrl(url().string().utf8().data(),
152                 httpMethod().latin1().data(),
153                 platformCachePolicyForRequest(*this),
154                 platformTargetTypeForRequest(*this),
155                 timeoutInterval());
156
157         platformRequest.setConditional(isConditional());
158
159         if (httpBody() && !httpBody()->isEmpty()) {
160             const Vector<FormDataElement>& elements = httpBody()->elements();
161             // Use setData for simple forms because it is slightly more efficient.
162             if (elements.size() == 1 && elements[0].m_type == FormDataElement::data)
163                 platformRequest.setData(elements[0].m_data.data(), elements[0].m_data.size());
164             else {
165                 for (unsigned i = 0; i < elements.size(); ++i) {
166                     const FormDataElement& element = elements[i];
167                     if (element.m_type == FormDataElement::data)
168                         platformRequest.addMultipartData(element.m_data.data(), element.m_data.size());
169                     else if (element.m_type == FormDataElement::encodedFile)
170                         platformRequest.addMultipartFilename(element.m_filename.characters(), element.m_filename.length());
171 #if ENABLE(BLOB)
172                     else if (element.m_type == FormDataElement::encodedBlob) {
173                         RefPtr<BlobStorageData> blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(KURL(ParsedURLString, element.m_blobURL));
174                         if (blobData) {
175                             for (size_t j = 0; j < blobData->items().size(); ++j) {
176                                 const BlobDataItem& blobItem = blobData->items()[j];
177                                 if (blobItem.type == BlobDataItem::Data)
178                                     platformRequest.addMultipartData(blobItem.data->data() + static_cast<int>(blobItem.offset), static_cast<int>(blobItem.length));
179                                 else {
180                                     ASSERT(blobItem.type == BlobDataItem::File);
181                                     platformRequest.addMultipartFilename(blobItem.path.characters(), blobItem.path.length(), blobItem.offset, blobItem.length, blobItem.expectedModificationTime);
182                                 }
183                             }
184                         }
185                     }
186 #endif
187                     else
188                         ASSERT_NOT_REACHED(); // unknown type
189                 }
190             }
191         }
192
193         for (HTTPHeaderMap::const_iterator it = httpHeaderFields().begin(); it != httpHeaderFields().end(); ++it) {
194             String key = it->first;
195             String value = it->second;
196             if (!key.isEmpty()) {
197                 // We need to check the encoding and encode the cookie's value using latin1 or utf8 to support unicode characters.
198                 // We wo't use the old cookies of resourceRequest for new location because these cookies may be changed by redirection.
199                 if (!equalIgnoringCase(key, "Cookie"))
200                     platformRequest.addHeader(key.latin1().data(), value.latin1().data());
201                 else if (!isRedirect)
202                     platformRequest.addHeader(key.latin1().data(), value.containsOnlyLatin1() ? value.latin1().data() : value.utf8().data());
203             }
204         }
205        
206         // Redirection's response may add or update cookies, so we get cookies from CookieManager when redirection happens.
207         // If there aren't cookies in the header list, we need trying to add cookies.
208         if (cookiesEnabled && (isRedirect || !httpHeaderFields().contains("Cookie")) && !url().isNull()) {
209             // Prepare a cookie header if there are cookies related to this url.
210             String cookiePairs = cookieManager().getCookie(url(), WithHttpOnlyCookies);
211             if (!cookiePairs.isEmpty())
212                 platformRequest.addHeader("Cookie", cookiePairs.containsOnlyLatin1() ? cookiePairs.latin1().data() : cookiePairs.utf8().data());
213         }
214
215         if (!httpHeaderFields().contains("Accept-Language")) {
216             // Locale has the form "en-US". Construct accept language like "en-US, en;q=0.8".
217             std::string locale = BlackBerry::Platform::Client::get()->getLocale();
218             // POSIX locale has '_' instead of '-'.
219             // Replace to conform to HTTP spec.
220             size_t underscore = locale.find('_');
221             if (underscore != std::string::npos)
222                 locale.replace(underscore, 1, "-");
223             std::string acceptLanguage = locale + ", " + locale.substr(0, 2) + ";q=0.8";
224             platformRequest.addHeader("Accept-Language", acceptLanguage.c_str());
225         }
226     }
227 }
228
229 PassOwnPtr<CrossThreadResourceRequestData> ResourceRequest::doPlatformCopyData(PassOwnPtr<CrossThreadResourceRequestData> data) const
230 {
231     data->m_token = m_token;
232     data->m_anchorText = m_anchorText;
233     data->m_isXMLHTTPRequest = m_isXMLHTTPRequest;
234     data->m_mustHandleInternally = m_mustHandleInternally;
235     data->m_isRequestedByPlugin = m_isRequestedByPlugin;
236     return data;
237 }
238
239 void ResourceRequest::doPlatformAdopt(PassOwnPtr<CrossThreadResourceRequestData> data)
240 {
241     m_token = data->m_token;
242     m_anchorText = data->m_anchorText;
243     m_isXMLHTTPRequest = data->m_isXMLHTTPRequest;
244     m_mustHandleInternally = data->m_mustHandleInternally;
245     m_isRequestedByPlugin = data->m_isRequestedByPlugin;
246     m_forceDownload = data->m_forceDownload;
247 }
248
249 void ResourceRequest::clearHTTPContentLength()
250 {
251     updateResourceRequest();
252
253     m_httpHeaderFields.remove("Content-Length");
254
255     if (url().protocolInHTTPFamily())
256         m_platformRequestUpdated = false;
257 }
258
259 void ResourceRequest::clearHTTPContentType()
260 {
261     updateResourceRequest();
262
263     m_httpHeaderFields.remove("Content-Type");
264
265     if (url().protocolInHTTPFamily())
266         m_platformRequestUpdated = false;
267 }
268
269 } // namespace WebCore