1 /*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "WebResponse.h"
28
29 #include "MIMETypeRegistry.h"
30 #include "PlatformString.h"
31 #include "ResourceResponse.h"
32 #include "ResourceError.h"
33
34 #include <wtf/text/CString.h>
35
36 using namespace std;
37
38 namespace android {
39
WebResponse(net::URLRequest * request)40 WebResponse::WebResponse(net::URLRequest* request)
41 : m_httpStatusCode(0)
42 {
43 // The misleadingly-named os_error() is actually a net::Error enum constant.
44 m_error = net::Error(request->status().os_error());
45
46 m_url = request->url().spec();
47 m_host = request->url().HostNoBrackets();
48 request->GetMimeType(&m_mime);
49
50 request->GetCharset(&m_encoding);
51 m_expectedSize = request->GetExpectedContentSize();
52
53 m_sslInfo = request->ssl_info();
54
55 net::HttpResponseHeaders* responseHeaders = request->response_headers();
56 if (!responseHeaders)
57 return;
58
59 m_httpStatusCode = responseHeaders->response_code();
60 m_httpStatusText = responseHeaders->GetStatusText();
61
62 string value;
63 string name;
64 void* iter = 0;
65 while (responseHeaders->EnumerateHeaderLines(&iter, &name, &value))
66 m_headerFields[name] = value;
67 }
68
WebResponse(const string & url,const string & mimeType,long long expectedSize,const string & encoding,int httpStatusCode)69 WebResponse::WebResponse(const string &url, const string &mimeType, long long expectedSize, const string &encoding, int httpStatusCode)
70 : m_error(net::OK)
71 , m_encoding(encoding)
72 , m_httpStatusCode(httpStatusCode)
73 , m_expectedSize(expectedSize)
74 , m_mime(mimeType)
75 , m_url(url)
76 {
77 }
78
createResourceResponse()79 WebCore::ResourceResponse WebResponse::createResourceResponse()
80 {
81 WebCore::ResourceResponse resourceResponse(createKurl(), getMimeType().c_str(), m_expectedSize, m_encoding.c_str(), "");
82 resourceResponse.setHTTPStatusCode(m_httpStatusCode);
83 resourceResponse.setHTTPStatusText(m_httpStatusText.c_str());
84
85 map<string, string>::const_iterator it;
86 for (it = m_headerFields.begin(); it != m_headerFields.end(); ++it)
87 resourceResponse.setHTTPHeaderField(it->first.c_str(), it->second.c_str());
88
89 return resourceResponse;
90 }
91
createResourceError()92 WebCore::ResourceError WebResponse::createResourceError()
93 {
94 WebCore::ResourceError error(m_host.c_str(), ToWebViewClientError(m_error), m_url.c_str(), WTF::String());
95 return error;
96 }
97
98
createKurl()99 WebCore::KURL WebResponse::createKurl()
100 {
101 WebCore::KURL kurl(WebCore::ParsedURLString, m_url.c_str());
102 return kurl;
103 }
104
getUrl() const105 const string& WebResponse::getUrl() const
106 {
107 return m_url;
108 }
109
setUrl(const string & url)110 void WebResponse::setUrl(const string& url)
111 {
112 m_url = url;
113 }
114
115 // Calls WebCore APIs so should only be called from the WebCore thread.
116 // TODO: can we return a WTF::String directly? Need to check all callsites.
getMimeType()117 const string& WebResponse::getMimeType()
118 {
119 if (!m_url.length())
120 return m_mime;
121
122 if (!m_mime.length() || !m_mime.compare("text/plain") || !m_mime.compare("application/octet-stream"))
123 m_mime = resolveMimeType(m_url, m_mime);
124
125 return m_mime;
126 }
127
resolveMimeType(const string & url,const string & old_mime)128 const string WebResponse::resolveMimeType(const string& url, const string& old_mime)
129 {
130 // Use "text/html" as a default (matching the behaviour of the Apache
131 // HTTP stack -- see guessMimeType() in LoadListener.java).
132 string mimeType = old_mime.length() ? old_mime : "text/html";
133 // Try to guess a better MIME type from the URL. We call
134 // getMIMETypeForExtension rather than getMIMETypeForPath because the
135 // latter defaults to "application/octet-stream" on failure.
136 WebCore::KURL kurl(WebCore::ParsedURLString, url.c_str());
137 WTF::String path = kurl.path();
138 size_t extensionPos = path.reverseFind('.');
139 if (extensionPos != WTF::notFound) {
140 // We found a file extension.
141 path.remove(0, extensionPos + 1);
142 // TODO: Should use content-disposition instead of url if it is there
143 WTF::String mime = WebCore::MIMETypeRegistry::getMIMETypeForExtension(path);
144 if (!mime.isEmpty()) {
145 // Great, we found a MIME type.
146 mimeType = std::string(mime.utf8().data(), mime.length());
147 }
148 }
149 return mimeType;
150 }
151
getHeader(const string & header,string * result) const152 bool WebResponse::getHeader(const string& header, string* result) const
153 {
154 map<string, string>::const_iterator iter = m_headerFields.find(header);
155 if (iter == m_headerFields.end())
156 return false;
157 if (result)
158 *result = iter->second;
159 return true;
160 }
161
getExpectedSize() const162 long long WebResponse::getExpectedSize() const
163 {
164 return m_expectedSize;
165 }
166
167 } // namespace android
168