/*
 * 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 "WebRequest.h"

#include "JNIUtility.h"
#include "MainThread.h"
#include "UrlInterceptResponse.h"
#include "WebCoreFrameBridge.h"
#include "WebCoreJni.h"
#include "WebRequestContext.h"
#include "WebResourceRequest.h"
#include "WebUrlLoaderClient.h"
#include "jni.h"

#include <cutils/log.h>
#include <openssl/x509.h>
#include <string>
#include <androidfw/AssetManager.h>

extern android::AssetManager* globalAssetManager();

// TODO:
// - Finish the file upload. Testcase is mobile buzz
// - Add network throttle needed by Android plugins

// TODO: Turn off asserts crashing before release
// http://b/issue?id=2951985
#undef ASSERT
#define ASSERT(assertion, ...) do \
    if (!(assertion)) { \
        android_printLog(ANDROID_LOG_ERROR, __FILE__, __VA_ARGS__); \
    } \
while (0)

namespace android {

namespace {
const int kInitialReadBufSize = 32768;
const char* kXRequestedWithHeader = "X-Requested-With";

struct RequestPackageName {
    std::string value;
    RequestPackageName();
};

RequestPackageName::RequestPackageName() {
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    jclass bridgeClass = env->FindClass("android/webkit/JniUtil");
    jmethodID method = env->GetStaticMethodID(bridgeClass, "getPackageName", "()Ljava/lang/String;");
    value = jstringToStdString(env, static_cast<jstring>(env->CallStaticObjectMethod(bridgeClass, method)));
    env->DeleteLocalRef(bridgeClass);
}

base::LazyInstance<RequestPackageName> s_packageName(base::LINKER_INITIALIZED);

}

WebRequest::WebRequest(WebUrlLoaderClient* loader, const WebResourceRequest& webResourceRequest)
    : m_urlLoader(loader)
    , m_url(webResourceRequest.url())
    , m_userAgent(webResourceRequest.userAgent())
    , m_referer(webResourceRequest.referrer())
    , m_loadState(Created)
    , m_authRequestCount(0)
    , m_cacheMode(0)
    , m_runnableFactory(this)
    , m_wantToPause(false)
    , m_isPaused(false)
    , m_isSync(false)
{
    GURL gurl(m_url);

    m_request = new net::URLRequest(gurl, this);

    m_request->SetExtraRequestHeaders(webResourceRequest.requestHeaders());
    m_request->SetExtraRequestHeaderByName(kXRequestedWithHeader, s_packageName.Get().value, false);
    m_request->set_referrer(webResourceRequest.referrer());
    m_request->set_method(webResourceRequest.method());
    m_request->set_load_flags(webResourceRequest.loadFlags());
}

// This is a special URL for Android. Query the Java InputStream
// for data and send to WebCore
WebRequest::WebRequest(WebUrlLoaderClient* loader, const WebResourceRequest& webResourceRequest, UrlInterceptResponse* intercept)
    : m_urlLoader(loader)
    , m_interceptResponse(intercept)
    , m_url(webResourceRequest.url())
    , m_userAgent(webResourceRequest.userAgent())
    , m_referer(webResourceRequest.referrer())
    , m_loadState(Created)
    , m_authRequestCount(0)
    , m_cacheMode(0)
    , m_runnableFactory(this)
    , m_wantToPause(false)
    , m_isPaused(false)
    , m_isSync(false)
{
}

WebRequest::~WebRequest()
{
    ASSERT(m_loadState == Finished, "dtor called on a WebRequest in a different state than finished (%d)", m_loadState);

    m_loadState = Deleted;
}

const std::string& WebRequest::getUrl() const
{
    return m_url;
}

const std::string& WebRequest::getUserAgent() const
{
    return m_userAgent;
}

const std::string& WebRequest::getReferer() const
{
    return m_referer;
}

#ifdef LOG_REQUESTS
namespace {
int remaining = 0;
}
#endif

void WebRequest::finish(bool success)
{
    m_runnableFactory.RevokeAll();
    ASSERT(m_loadState < Finished, "(%p) called finish on an already finished WebRequest (%d) (%s)", this, m_loadState, m_url.c_str());
    if (m_loadState >= Finished)
        return;
#ifdef LOG_REQUESTS
    time_t finish;
    time(&finish);
    finish = finish - m_startTime;
    struct tm * timeinfo;
    char buffer[80];
    timeinfo = localtime(&finish);
    strftime(buffer, 80, "Time: %M:%S",timeinfo);
    android_printLog(ANDROID_LOG_DEBUG, "KM", "(%p) finish (%d) (%s) (%d) (%s)", this, --remaining, buffer, success, m_url.c_str());
#endif

    // Make sure WebUrlLoaderClient doesn't delete us in the middle of this method.
    scoped_refptr<WebRequest> guard(this);

    m_loadState = Finished;
    if (success) {
        m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
                m_urlLoader.get(), &WebUrlLoaderClient::didFinishLoading));
    } else {
        if (m_interceptResponse == NULL) {
            OwnPtr<WebResponse> webResponse(new WebResponse(m_request.get()));
            m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
                    m_urlLoader.get(), &WebUrlLoaderClient::didFail, webResponse.release()));
        } else {
            OwnPtr<WebResponse> webResponse(new WebResponse(m_url, m_interceptResponse->mimeType(), 0,
                    m_interceptResponse->encoding(), m_interceptResponse->status()));
            m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
                    m_urlLoader.get(), &WebUrlLoaderClient::didFail, webResponse.release()));
        }
    }
    m_networkBuffer = 0;
    m_request = 0;
    m_urlLoader = 0;
}

void WebRequest::appendFileToUpload(const std::string& filename)
{
    // AppendFileToUpload is only valid before calling start
    ASSERT(m_loadState == Created, "appendFileToUpload called on a WebRequest not in CREATED state: (%s)", m_url.c_str());
    FilePath filePath(filename);
    m_request->AppendFileToUpload(filePath);
}

void WebRequest::appendBytesToUpload(WTF::Vector<char>* data)
{
    // AppendBytesToUpload is only valid before calling start
    ASSERT(m_loadState == Created, "appendBytesToUpload called on a WebRequest not in CREATED state: (%s)", m_url.c_str());
    m_request->AppendBytesToUpload(data->data(), data->size());
    delete data;
}

void WebRequest::setRequestContext(WebRequestContext* context)
{
    m_cacheMode = context->getCacheMode();
    if (m_request)
        m_request->set_context(context);
}

void WebRequest::updateLoadFlags(int& loadFlags)
{
    if (m_cacheMode == 1) { // LOAD_CACHE_ELSE_NETWORK
        loadFlags |= net::LOAD_PREFERRING_CACHE;
        loadFlags &= ~net::LOAD_VALIDATE_CACHE;
    }
    if (m_cacheMode == 2) // LOAD_NO_CACHE
        loadFlags |= net::LOAD_BYPASS_CACHE;
    if (m_cacheMode == 3) // LOAD_CACHE_ONLY
        loadFlags |= net::LOAD_ONLY_FROM_CACHE;

    if (m_isSync)
        loadFlags |= net::LOAD_IGNORE_LIMITS;
}

void WebRequest::start()
{
    ASSERT(m_loadState == Created, "Start called on a WebRequest not in CREATED state: (%s)", m_url.c_str());
#ifdef LOG_REQUESTS
    android_printLog(ANDROID_LOG_DEBUG, "KM", "(%p) start (%d) (%s)", this, ++remaining, m_url.c_str());
    time(&m_startTime);
#endif

    m_loadState = Started;

    if (m_interceptResponse != NULL)
        return handleInterceptedURL();

    // Handle data urls before we send it off to the http stack
    if (m_request->url().SchemeIs("data"))
        return handleDataURL(m_request->url());

    if (m_request->url().SchemeIs("browser"))
        return handleBrowserURL(m_request->url());

    // Update load flags with settings from WebSettings
    int loadFlags = m_request->load_flags();
    updateLoadFlags(loadFlags);
    m_request->set_load_flags(loadFlags);

    m_request->Start();
}

void WebRequest::cancel()
{
    ASSERT(m_loadState >= Started, "Cancel called on a not started WebRequest: (%s)", m_url.c_str());
    ASSERT(m_loadState != Cancelled, "Cancel called on an already cancelled WebRequest: (%s)", m_url.c_str());

    // There is a possible race condition between the IO thread finishing the request and
    // the WebCore thread cancelling it. If the request has already finished, do
    // nothing to avoid sending duplicate finish messages to WebCore.
    if (m_loadState > Cancelled) {
        return;
    }
    ASSERT(m_request, "Request set to 0 before it is finished");

    m_loadState = Cancelled;

    m_request->Cancel();
    finish(true);
}

void WebRequest::pauseLoad(bool pause)
{
    ASSERT(m_loadState >= GotData, "PauseLoad in state other than RESPONSE and GOTDATA");
    if (pause) {
        if (!m_isPaused)
            m_wantToPause = true;
    } else {
        m_wantToPause = false;
        if (m_isPaused) {
            m_isPaused = false;
            MessageLoop::current()->PostTask(FROM_HERE, m_runnableFactory.NewRunnableMethod(&WebRequest::startReading));
        }
    }
}

void WebRequest::handleInterceptedURL()
{
    m_loadState = Response;

    const std::string& mime = m_interceptResponse->mimeType();
    // Get the MIME type from the URL. "text/html" is a last resort, hopefully overridden.
    std::string mimeType("text/html");
    if (mime == "") {
        // Get the MIME type from the file extension, if any.
        FilePath path(m_url);
        net::GetMimeTypeFromFile(path, &mimeType);
    } else {
        // Set from the intercept response.
        mimeType = mime;
    }


    OwnPtr<WebResponse> webResponse(new WebResponse(m_url, mimeType, 0, m_interceptResponse->encoding(), m_interceptResponse->status()));
    m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
            m_urlLoader.get(), &WebUrlLoaderClient::didReceiveResponse, webResponse.release()));

    do {
        // data is deleted in WebUrlLoaderClient::didReceiveAndroidFileData
        // data is sent to the webcore thread
        OwnPtr<std::vector<char> > data(new std::vector<char>);
        data->reserve(kInitialReadBufSize);

        // Read returns false on error and size of 0 on eof.
        if (!m_interceptResponse->readStream(data.get()) || data->size() == 0)
            break;

        m_loadState = GotData;
        m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
                m_urlLoader.get(), &WebUrlLoaderClient::didReceiveAndroidFileData, data.release()));
    } while (true);

    finish(m_interceptResponse->status() == 200);
}

void WebRequest::handleDataURL(GURL url)
{
    OwnPtr<std::string> data(new std::string);
    std::string mimeType;
    std::string charset;

    if (net::DataURL::Parse(url, &mimeType, &charset, data.get())) {
        // PopulateURLResponse from chrome implementation
        // weburlloader_impl.cc
        m_loadState = Response;
        OwnPtr<WebResponse> webResponse(new WebResponse(url.spec(), mimeType, data->size(), charset, 200));
        m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
                m_urlLoader.get(), &WebUrlLoaderClient::didReceiveResponse, webResponse.release()));

        if (!data->empty()) {
            m_loadState = GotData;
            m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
                    m_urlLoader.get(), &WebUrlLoaderClient::didReceiveDataUrl, data.release()));
        }
    } else {
        // handle the failed case
    }

    finish(true);
}

void WebRequest::handleBrowserURL(GURL url)
{
    std::string data("data:text/html;charset=utf-8,");
    if (url.spec() == "browser:incognito") {
        AssetManager* assetManager = globalAssetManager();
        Asset* asset = assetManager->open("webkit/incognito_mode_start_page.html", Asset::ACCESS_BUFFER);
        if (asset) {
            data.append((const char*)asset->getBuffer(false), asset->getLength());
            delete asset;
        }
    }
    GURL dataURL(data.c_str());
    handleDataURL(dataURL);
}

// Called upon a server-initiated redirect.  The delegate may call the
// request's Cancel method to prevent the redirect from being followed.
// Since there may be multiple chained redirects, there may also be more
// than one redirect call.
//
// When this function is called, the request will still contain the
// original URL, the destination of the redirect is provided in 'new_url'.
// If the delegate does not cancel the request and |*defer_redirect| is
// false, then the redirect will be followed, and the request's URL will be
// changed to the new URL.  Otherwise if the delegate does not cancel the
// request and |*defer_redirect| is true, then the redirect will be
// followed once FollowDeferredRedirect is called on the URLRequest.
//
// The caller must set |*defer_redirect| to false, so that delegates do not
// need to set it if they are happy with the default behavior of not
// deferring redirect.
void WebRequest::OnReceivedRedirect(net::URLRequest* newRequest, const GURL& newUrl, bool* deferRedirect)
{
    ASSERT(m_loadState < Response, "Redirect after receiving response");
    ASSERT(newRequest && newRequest->status().is_success(), "Invalid redirect");

    OwnPtr<WebResponse> webResponse(new WebResponse(newRequest));
    webResponse->setUrl(newUrl.spec());
    m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
            m_urlLoader.get(), &WebUrlLoaderClient::willSendRequest, webResponse.release()));

    // Defer the redirect until followDeferredRedirect() is called.
    *deferRedirect = true;
}

// Called when we receive an authentication failure.  The delegate should
// call request->SetAuth() with the user's credentials once it obtains them,
// or request->CancelAuth() to cancel the login and display the error page.
// When it does so, the request will be reissued, restarting the sequence
// of On* callbacks.
void WebRequest::OnAuthRequired(net::URLRequest* request, net::AuthChallengeInfo* authInfo)
{
    ASSERT(m_loadState == Started, "OnAuthRequired called on a WebRequest not in STARTED state (state=%d)", m_loadState);

    scoped_refptr<net::AuthChallengeInfo> authInfoPtr(authInfo);
    bool firstTime = (m_authRequestCount == 0);
    ++m_authRequestCount;

    bool suppressDialog = (request->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN);

    m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
            m_urlLoader.get(), &WebUrlLoaderClient::authRequired, authInfoPtr, firstTime, suppressDialog));
}

// Called when we received an SSL certificate error. The delegate will provide
// the user the options to proceed, cancel, or view certificates.
void WebRequest::OnSSLCertificateError(net::URLRequest* request, int cert_error, net::X509Certificate* cert)
{
    scoped_refptr<net::X509Certificate> scoped_cert = cert;
    m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
            m_urlLoader.get(), &WebUrlLoaderClient::reportSslCertError, cert_error, scoped_cert));
}

void WebRequest::OnCertificateRequested(net::URLRequest* request, net::SSLCertRequestInfo* cert_request_info)
{
    scoped_refptr<net::SSLCertRequestInfo> scoped_cert_request_info = cert_request_info;
    m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
            m_urlLoader.get(), &WebUrlLoaderClient::requestClientCert, scoped_cert_request_info));
}


// After calling Start(), the delegate will receive an OnResponseStarted
// callback when the request has completed.  If an error occurred, the
// request->status() will be set.  On success, all redirects have been
// followed and the final response is beginning to arrive.  At this point,
// meta data about the response is available, including for example HTTP
// response headers if this is a request for a HTTP resource.
void WebRequest::OnResponseStarted(net::URLRequest* request)
{
    ASSERT(m_loadState == Started, "Got response after receiving response");

    m_loadState = Response;
    if (request && request->status().is_success()) {
        OwnPtr<WebResponse> webResponse(new WebResponse(request));
        m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
                m_urlLoader.get(), &WebUrlLoaderClient::didReceiveResponse, webResponse.release()));

        // Start reading the response
        startReading();
    } else {
        finish(false);
    }
}

void WebRequest::setAuth(const string16& username, const string16& password)
{
    ASSERT(m_loadState == Started, "setAuth called on a WebRequest not in STARTED state (state=%d)", m_loadState);

    m_request->SetAuth(username, password);
}

void WebRequest::cancelAuth()
{
    ASSERT(m_loadState == Started, "cancelAuth called on a WebRequest not in STARTED state (state=%d)", m_loadState);

    m_request->CancelAuth();
}

void WebRequest::followDeferredRedirect()
{
    ASSERT(m_loadState < Response, "Redirect after receiving response");

    m_request->FollowDeferredRedirect();
}

void WebRequest::proceedSslCertError()
{
    m_request->ContinueDespiteLastError();
}

void WebRequest::cancelSslCertError(int cert_error)
{
    m_request->SimulateError(cert_error);
}

void WebRequest::sslClientCert(EVP_PKEY* pkey, scoped_refptr<net::X509Certificate> chain)
{
    base::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> privateKey(pkey);
    if (privateKey.get() == NULL || chain.get() == NULL) {
        m_request->ContinueWithCertificate(NULL);
        return;
    }
    GURL gurl(m_url);
    net::OpenSSLPrivateKeyStore::GetInstance()->StorePrivateKey(gurl, privateKey.release());
    m_request->ContinueWithCertificate(chain.release());
}

void WebRequest::startReading()
{
    ASSERT(m_networkBuffer == 0, "startReading called with a nonzero buffer");
    ASSERT(m_isPaused == 0, "startReading called in paused state");
    ASSERT(m_loadState == Response || m_loadState == GotData, "StartReading in state other than RESPONSE and GOTDATA");
    if (m_loadState > GotData) // We have been cancelled between reads
        return;

    if (m_wantToPause) {
        m_isPaused = true;
        return;
    }

    int bytesRead = 0;

    if (!read(&bytesRead)) {
        if (m_request && m_request->status().is_io_pending())
            return; // Wait for OnReadCompleted()
        return finish(false);
    }

    // bytesRead == 0 indicates finished
    if (!bytesRead)
        return finish(true);

    m_loadState = GotData;
    // Read ok, forward buffer to webcore
    m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(m_urlLoader.get(), &WebUrlLoaderClient::didReceiveData, m_networkBuffer, bytesRead));
    m_networkBuffer = 0;
    MessageLoop::current()->PostTask(FROM_HERE, m_runnableFactory.NewRunnableMethod(&WebRequest::startReading));
}

bool WebRequest::read(int* bytesRead)
{
    ASSERT(m_loadState == Response || m_loadState == GotData, "read in state other than RESPONSE and GOTDATA");
    ASSERT(m_networkBuffer == 0, "Read called with a nonzero buffer");

    // TODO: when asserts work, check that the buffer is 0 here
    m_networkBuffer = new net::IOBuffer(kInitialReadBufSize);
    return m_request->Read(m_networkBuffer, kInitialReadBufSize, bytesRead);
}

// This is called when there is data available

// Called when the a Read of the response body is completed after an
// IO_PENDING status from a Read() call.
// The data read is filled into the buffer which the caller passed
// to Read() previously.
//
// If an error occurred, request->status() will contain the error,
// and bytes read will be -1.
void WebRequest::OnReadCompleted(net::URLRequest* request, int bytesRead)
{
    ASSERT(m_loadState == Response || m_loadState == GotData, "OnReadCompleted in state other than RESPONSE and GOTDATA");

    if (request->status().is_success()) {
        m_loadState = GotData;
        m_urlLoader->maybeCallOnMainThread(NewRunnableMethod(
                m_urlLoader.get(), &WebUrlLoaderClient::didReceiveData, m_networkBuffer, bytesRead));
        m_networkBuffer = 0;

        // Get the rest of the data
        startReading();
    } else {
        finish(false);
    }
}

} // namespace android
