/* * Copyright 2010, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "WebResponse.h" #include "MIMETypeRegistry.h" #include "PlatformString.h" #include "ResourceResponse.h" #include "ResourceError.h" #include using namespace std; namespace android { WebResponse::WebResponse(net::URLRequest* request) : m_httpStatusCode(0) { // The misleadingly-named os_error() is actually a net::Error enum constant. m_error = net::Error(request->status().os_error()); m_url = request->url().spec(); m_host = request->url().HostNoBrackets(); request->GetMimeType(&m_mime); request->GetCharset(&m_encoding); m_expectedSize = request->GetExpectedContentSize(); m_sslInfo = request->ssl_info(); net::HttpResponseHeaders* responseHeaders = request->response_headers(); if (!responseHeaders) return; m_httpStatusCode = responseHeaders->response_code(); m_httpStatusText = responseHeaders->GetStatusText(); string value; string name; void* iter = 0; while (responseHeaders->EnumerateHeaderLines(&iter, &name, &value)) m_headerFields[name] = value; } WebResponse::WebResponse(const string &url, const string &mimeType, long long expectedSize, const string &encoding, int httpStatusCode) : m_error(net::OK) , m_encoding(encoding) , m_httpStatusCode(httpStatusCode) , m_expectedSize(expectedSize) , m_mime(mimeType) , m_url(url) { } WebCore::ResourceResponse WebResponse::createResourceResponse() { WebCore::ResourceResponse resourceResponse(createKurl(), getMimeType().c_str(), m_expectedSize, m_encoding.c_str(), ""); resourceResponse.setHTTPStatusCode(m_httpStatusCode); resourceResponse.setHTTPStatusText(m_httpStatusText.c_str()); map::const_iterator it; for (it = m_headerFields.begin(); it != m_headerFields.end(); ++it) resourceResponse.setHTTPHeaderField(it->first.c_str(), it->second.c_str()); return resourceResponse; } WebCore::ResourceError WebResponse::createResourceError() { WebCore::ResourceError error(m_host.c_str(), ToWebViewClientError(m_error), m_url.c_str(), WTF::String()); return error; } WebCore::KURL WebResponse::createKurl() { WebCore::KURL kurl(WebCore::ParsedURLString, m_url.c_str()); return kurl; } const string& WebResponse::getUrl() const { return m_url; } void WebResponse::setUrl(const string& url) { m_url = url; } // Calls WebCore APIs so should only be called from the WebCore thread. // TODO: can we return a WTF::String directly? Need to check all callsites. const string& WebResponse::getMimeType() { if (!m_url.length()) return m_mime; if (!m_mime.length() || !m_mime.compare("text/plain") || !m_mime.compare("application/octet-stream")) m_mime = resolveMimeType(m_url, m_mime); return m_mime; } const string WebResponse::resolveMimeType(const string& url, const string& old_mime) { // Use "text/html" as a default (matching the behaviour of the Apache // HTTP stack -- see guessMimeType() in LoadListener.java). string mimeType = old_mime.length() ? old_mime : "text/html"; // Try to guess a better MIME type from the URL. We call // getMIMETypeForExtension rather than getMIMETypeForPath because the // latter defaults to "application/octet-stream" on failure. WebCore::KURL kurl(WebCore::ParsedURLString, url.c_str()); WTF::String path = kurl.path(); size_t extensionPos = path.reverseFind('.'); if (extensionPos != WTF::notFound) { // We found a file extension. path.remove(0, extensionPos + 1); // TODO: Should use content-disposition instead of url if it is there WTF::String mime = WebCore::MIMETypeRegistry::getMIMETypeForExtension(path); if (!mime.isEmpty()) { // Great, we found a MIME type. mimeType = std::string(mime.utf8().data(), mime.length()); } } return mimeType; } bool WebResponse::getHeader(const string& header, string* result) const { map::const_iterator iter = m_headerFields.find(header); if (iter == m_headerFields.end()) return false; if (result) *result = iter->second; return true; } long long WebResponse::getExpectedSize() const { return m_expectedSize; } } // namespace android