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