19de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen/* 29de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * Copyright 2010, The Android Open Source Project 39de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * 49de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * Redistribution and use in source and binary forms, with or without 59de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * modification, are permitted provided that the following conditions 69de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * are met: 79de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * * Redistributions of source code must retain the above copyright 89de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * notice, this list of conditions and the following disclaimer. 99de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * * Redistributions in binary form must reproduce the above copyright 109de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * notice, this list of conditions and the following disclaimer in the 119de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * documentation and/or other materials provided with the distribution. 129de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * 139de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 149de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 159de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 169de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 179de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 189de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 199de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 209de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 219de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 229de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 239de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 249de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen */ 259de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 269de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen#include "config.h" 279de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen#include "WebResponse.h" 289de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 29787e29b54f206839549283289018384538f050f0John Reck#include "MIMETypeRegistry.h" 30787e29b54f206839549283289018384538f050f0John Reck#include "PlatformString.h" 319de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen#include "ResourceResponse.h" 3221baf41667f5ac764512f0168a702390daf45bf3Kristian Monsen#include "ResourceError.h" 339de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 34787e29b54f206839549283289018384538f050f0John Reck#include <wtf/text/CString.h> 35787e29b54f206839549283289018384538f050f0John Reck 367d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrickusing namespace std; 377d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick 389de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsennamespace android { 399de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 4041c4de163e4183c0e2a74c5c296de8a734ecc516Kristian MonsenWebResponse::WebResponse(net::URLRequest* request) 419de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen : m_httpStatusCode(0) 429de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen{ 439d2b5a35cbe2528f07d9aa33b2b8cf025f266090Iain Merrick // The misleadingly-named os_error() is actually a net::Error enum constant. 449d2b5a35cbe2528f07d9aa33b2b8cf025f266090Iain Merrick m_error = net::Error(request->status().os_error()); 459d2b5a35cbe2528f07d9aa33b2b8cf025f266090Iain Merrick 469de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen m_url = request->url().spec(); 4721baf41667f5ac764512f0168a702390daf45bf3Kristian Monsen m_host = request->url().HostNoBrackets(); 489de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen request->GetMimeType(&m_mime); 49787e29b54f206839549283289018384538f050f0John Reck 509de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen request->GetCharset(&m_encoding); 517d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick m_expectedSize = request->GetExpectedContentSize(); 529de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 53e777e7663bb6cecc72754dbf56e068f5b6ea30d5Iain Merrick m_sslInfo = request->ssl_info(); 54e777e7663bb6cecc72754dbf56e068f5b6ea30d5Iain Merrick 559de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen net::HttpResponseHeaders* responseHeaders = request->response_headers(); 569de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen if (!responseHeaders) 579de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen return; 589de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 599de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen m_httpStatusCode = responseHeaders->response_code(); 609de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen m_httpStatusText = responseHeaders->GetStatusText(); 619de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 627d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick string value; 637d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick string name; 649de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen void* iter = 0; 659de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen while (responseHeaders->EnumerateHeaderLines(&iter, &name, &value)) 669de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen m_headerFields[name] = value; 679de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen} 689de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 697d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain MerrickWebResponse::WebResponse(const string &url, const string &mimeType, long long expectedSize, const string &encoding, int httpStatusCode) 709d2b5a35cbe2528f07d9aa33b2b8cf025f266090Iain Merrick : m_error(net::OK) 719d2b5a35cbe2528f07d9aa33b2b8cf025f266090Iain Merrick , m_encoding(encoding) 729de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen , m_httpStatusCode(httpStatusCode) 737d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick , m_expectedSize(expectedSize) 749de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen , m_mime(mimeType) 759de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen , m_url(url) 769de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen{ 779de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen} 789de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 799de447de54fcb62a01a3338bb4d2f4d1716f522dKristian MonsenWebCore::ResourceResponse WebResponse::createResourceResponse() 809de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen{ 817911c3f54e13fc70b49ed513e2be226129cd4ea7Ben Murdoch WebCore::ResourceResponse resourceResponse(createKurl(), getMimeType().c_str(), m_expectedSize, m_encoding.c_str(), ""); 829de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen resourceResponse.setHTTPStatusCode(m_httpStatusCode); 839de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen resourceResponse.setHTTPStatusText(m_httpStatusText.c_str()); 849de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 857d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick map<string, string>::const_iterator it; 869de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen for (it = m_headerFields.begin(); it != m_headerFields.end(); ++it) 879de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen resourceResponse.setHTTPHeaderField(it->first.c_str(), it->second.c_str()); 889de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 899de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen return resourceResponse; 909de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen} 919de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 9221baf41667f5ac764512f0168a702390daf45bf3Kristian MonsenWebCore::ResourceError WebResponse::createResourceError() 9321baf41667f5ac764512f0168a702390daf45bf3Kristian Monsen{ 94649040c55ad0f299f58ae83062b40b29f3825fb4Iain Merrick WebCore::ResourceError error(m_host.c_str(), ToWebViewClientError(m_error), m_url.c_str(), WTF::String()); 9521baf41667f5ac764512f0168a702390daf45bf3Kristian Monsen return error; 9621baf41667f5ac764512f0168a702390daf45bf3Kristian Monsen} 9721baf41667f5ac764512f0168a702390daf45bf3Kristian Monsen 9821baf41667f5ac764512f0168a702390daf45bf3Kristian Monsen 997d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain MerrickWebCore::KURL WebResponse::createKurl() 1009de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen{ 1019de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen WebCore::KURL kurl(WebCore::ParsedURLString, m_url.c_str()); 1029de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen return kurl; 1039de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen} 1049de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 1057d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrickconst string& WebResponse::getUrl() const 1067d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick{ 1077d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick return m_url; 1087d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick} 1097d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick 1107d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrickvoid WebResponse::setUrl(const string& url) 1119de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen{ 1129de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen m_url = url; 1139de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen} 1149de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen 1157911c3f54e13fc70b49ed513e2be226129cd4ea7Ben Murdoch// Calls WebCore APIs so should only be called from the WebCore thread. 1167911c3f54e13fc70b49ed513e2be226129cd4ea7Ben Murdoch// TODO: can we return a WTF::String directly? Need to check all callsites. 1177911c3f54e13fc70b49ed513e2be226129cd4ea7Ben Murdochconst string& WebResponse::getMimeType() 1187d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick{ 119319a1ceb63784aba2c0c94808707e1ce9ac90f71Kristian Monsen if (!m_url.length()) 120319a1ceb63784aba2c0c94808707e1ce9ac90f71Kristian Monsen return m_mime; 121319a1ceb63784aba2c0c94808707e1ce9ac90f71Kristian Monsen 122319a1ceb63784aba2c0c94808707e1ce9ac90f71Kristian Monsen if (!m_mime.length() || !m_mime.compare("text/plain") || !m_mime.compare("application/octet-stream")) 12327f2ed8c9c05acf5dbc69547127ad580fb8801fcKristian Monsen m_mime = resolveMimeType(m_url, m_mime); 1247911c3f54e13fc70b49ed513e2be226129cd4ea7Ben Murdoch 1257911c3f54e13fc70b49ed513e2be226129cd4ea7Ben Murdoch return m_mime; 126787e29b54f206839549283289018384538f050f0John Reck} 127787e29b54f206839549283289018384538f050f0John Reck 12827f2ed8c9c05acf5dbc69547127ad580fb8801fcKristian Monsenconst string WebResponse::resolveMimeType(const string& url, const string& old_mime) 129e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch{ 130e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch // Use "text/html" as a default (matching the behaviour of the Apache 131e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch // HTTP stack -- see guessMimeType() in LoadListener.java). 13227f2ed8c9c05acf5dbc69547127ad580fb8801fcKristian Monsen string mimeType = old_mime.length() ? old_mime : "text/html"; 133e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch // Try to guess a better MIME type from the URL. We call 134e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch // getMIMETypeForExtension rather than getMIMETypeForPath because the 135e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch // latter defaults to "application/octet-stream" on failure. 136e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch WebCore::KURL kurl(WebCore::ParsedURLString, url.c_str()); 137e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch WTF::String path = kurl.path(); 138e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch size_t extensionPos = path.reverseFind('.'); 139e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch if (extensionPos != WTF::notFound) { 140e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch // We found a file extension. 141e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch path.remove(0, extensionPos + 1); 142319a1ceb63784aba2c0c94808707e1ce9ac90f71Kristian Monsen // TODO: Should use content-disposition instead of url if it is there 143e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch WTF::String mime = WebCore::MIMETypeRegistry::getMIMETypeForExtension(path); 144e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch if (!mime.isEmpty()) { 145e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch // Great, we found a MIME type. 146e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch mimeType = std::string(mime.utf8().data(), mime.length()); 147e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch } 148e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch } 149e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch return mimeType; 150e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch} 151e95b4a7d9ed67e6d6960e33e794e653aa0bd3887Ben Murdoch 1527d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrickbool WebResponse::getHeader(const string& header, string* result) const 1537d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick{ 1547d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick map<string, string>::const_iterator iter = m_headerFields.find(header); 1557d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick if (iter == m_headerFields.end()) 1567d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick return false; 1577d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick if (result) 1587d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick *result = iter->second; 1597d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick return true; 1607d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick} 1617d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick 1627d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merricklong long WebResponse::getExpectedSize() const 1637d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick{ 1647d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick return m_expectedSize; 1657d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick} 1667d2f6c10941c9083e9ec30fb08444a5755ff8bc9Iain Merrick 1679de447de54fcb62a01a3338bb4d2f4d1716f522dKristian Monsen} // namespace android 168