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 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 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 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 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 99 WebCore::KURL WebResponse::createKurl() 100 { 101 WebCore::KURL kurl(WebCore::ParsedURLString, m_url.c_str()); 102 return kurl; 103 } 104 105 const string& WebResponse::getUrl() const 106 { 107 return m_url; 108 } 109 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. 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 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 152 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 162 long long WebResponse::getExpectedSize() const 163 { 164 return m_expectedSize; 165 } 166 167 } // namespace android 168