// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "Request.h"

#include "bindings/core/v8/Dictionary.h"
#include "core/dom/ExecutionContext.h"
#include "core/fetch/FetchUtils.h"
#include "core/fetch/ResourceLoaderOptions.h"
#include "core/loader/ThreadableLoader.h"
#include "modules/serviceworkers/FetchManager.h"
#include "modules/serviceworkers/RequestInit.h"
#include "platform/network/HTTPParsers.h"
#include "platform/network/ResourceRequest.h"
#include "platform/weborigin/Referrer.h"
#include "public/platform/WebServiceWorkerRequest.h"
#include "public/platform/WebURLRequest.h"

namespace blink {

Request* Request::createRequestWithRequestData(ExecutionContext* context, FetchRequestData* request, const RequestInit& init, WebURLRequest::FetchRequestMode mode, WebURLRequest::FetchCredentialsMode credentials, ExceptionState& exceptionState)
{
    // "7. Let |mode| be |init|'s mode member if it is present, and
    // |fallbackMode| otherwise."
    // "8. If |mode| is non-null, set |request|'s mode to |mode|."
    if (init.mode == "same-origin") {
        request->setMode(WebURLRequest::FetchRequestModeSameOrigin);
    } else if (init.mode == "no-cors") {
        request->setMode(mode = WebURLRequest::FetchRequestModeNoCORS);
    } else if (init.mode == "cors") {
        request->setMode(WebURLRequest::FetchRequestModeCORS);
    } else {
        // Instead of using null as a special fallback value, we pass the
        // current mode in Request::create(). So we just set here.
        request->setMode(mode);
    }

    // "9. Let |credentials| be |init|'s credentials member if it is present,
    // and |fallbackCredentials| otherwise."
    // "10. If |credentials| is non-null, set |request|'s credentials mode to
    // |credentials|.
    if (init.credentials == "omit") {
        request->setCredentials(WebURLRequest::FetchCredentialsModeOmit);
    } else if (init.credentials == "same-origin") {
        request->setCredentials(WebURLRequest::FetchCredentialsModeSameOrigin);
    } else if (init.credentials == "include") {
        request->setCredentials(WebURLRequest::FetchCredentialsModeInclude);
    } else {
        // Instead of using null as a special fallback value, we pass the
        // current credentials in Request::create(). So we just set here.
        request->setCredentials(credentials);
    }

    // "11. If |init|'s method member is present, let |method| be it and run
    // these substeps:"
    if (!init.method.isEmpty()) {
        // "1. If |method| is not a useful method, throw a TypeError."
        if (!FetchUtils::isUsefulMethod(init.method)) {
            exceptionState.throwTypeError("'" + init.method + "' HTTP method is unsupported.");
            return 0;
        }
        if (!isValidHTTPToken(init.method)) {
            exceptionState.throwTypeError("'" + init.method + "' is not a valid HTTP method.");
            return 0;
        }
        // FIXME: "2. Add case correction as in XMLHttpRequest?"
        // "3. Set |request|'s method to |method|."
        request->setMethod(FetchUtils::normalizeMethod(AtomicString(init.method)));
    }
    // "12. Let |r| be a new Request object associated with |request|, Headers
    // object."
    Request* r = Request::create(context, request);

    // "13. Let |headers| be a copy of |r|'s Headers object."
    // "14. If |init|'s headers member is present, set |headers| to |init|'s
    // headers member."
    // We don't create a copy of r's Headers object when init's headers member
    // is present.
    Headers* headers = 0;
    if (!init.headers && init.headersDictionary.isUndefinedOrNull()) {
        headers = r->headers()->createCopy();
    }
    // "15. Empty |r|'s request's header list."
    r->clearHeaderList();

    // "16. If |r|'s request's mode is no CORS, run these substeps:
    if (r->request()->mode() == WebURLRequest::FetchRequestModeNoCORS) {
        // "1. If |r|'s request's method is not a simple method, throw a
        // TypeError."
        if (!FetchUtils::isSimpleMethod(r->request()->method())) {
            exceptionState.throwTypeError("'" + r->request()->method() + "' is unsupported in no-cors mode.");
            return 0;
        }
        // "Set |r|'s Headers object's guard to |request-no-CORS|.
        r->headers()->setGuard(Headers::RequestNoCORSGuard);
    }

    // "17. Fill |r|'s Headers object with |headers|. Rethrow any exceptions."
    if (init.headers) {
        ASSERT(init.headersDictionary.isUndefinedOrNull());
        r->headers()->fillWith(init.headers.get(), exceptionState);
    } else if (!init.headersDictionary.isUndefinedOrNull()) {
        r->headers()->fillWith(init.headersDictionary, exceptionState);
    } else {
        ASSERT(headers);
        r->headers()->fillWith(headers, exceptionState);
    }
    if (exceptionState.hadException())
        return 0;
    // "18. If |init|'s body member is present, run these substeps:"
    if (init.bodyBlobHandle) {
        // "1. Let |stream| and |Content-Type| be the result of extracting
        // |init|'s body member."
        // "2. Set |r|'s request's body to |stream|."
        // "3.If |Content-Type| is non-null and |r|'s request's header list
        //  contains no header named `Content-Type`, append
        // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any
        // exception."
        r->setBodyBlobHandle(init.bodyBlobHandle);
        if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Content-Type", exceptionState)) {
            r->headers()->append("Content-Type", init.bodyBlobHandle->type(), exceptionState);
        }
        if (exceptionState.hadException())
            return 0;
    }
    // "19. Set |r|'s MIME type to the result of extracting a MIME type from
    // |r|'s request's header list."
    // FIXME: We don't have MIME type in Request object yet.

    // "20. Return |r|."
    return r;
}

Request* Request::create(ExecutionContext* context, const String& input, ExceptionState& exceptionState)
{
    return create(context, input, Dictionary(), exceptionState);
}

Request* Request::create(ExecutionContext* context, const String& input, const Dictionary& init, ExceptionState& exceptionState)
{
    // "2. Let |request| be |input|'s associated request, if |input| is a
    // Request object, and a new request otherwise."
    FetchRequestData* request(FetchRequestData::create(context));
    // "3. Set |request| to a restricted copy of itself."
    request = request->createRestrictedCopy(context, SecurityOrigin::create(context->url()));
    // "6. If |input| is a string, run these substeps:"
    // "1. Let |parsedURL| be the result of parsing |input| with entry settings
    // object's API base URL."
    KURL parsedURL = context->completeURL(input);
    // "2. If |parsedURL| is failure, throw a TypeError."
    if (!parsedURL.isValid()) {
        exceptionState.throwTypeError("Invalid URL");
        return 0;
    }
    // "3. Set |request|'s url to |parsedURL|."
    request->setURL(parsedURL);
    // "4. Set |fallbackMode| to CORS."
    // "5. Set |fallbackCredentials| to omit."
    return createRequestWithRequestData(context, request, RequestInit(context, init, exceptionState), WebURLRequest::FetchRequestModeCORS, WebURLRequest::FetchCredentialsModeOmit, exceptionState);
}

Request* Request::create(ExecutionContext* context, Request* input, ExceptionState& exceptionState)
{
    return create(context, input, Dictionary(), exceptionState);
}

Request* Request::create(ExecutionContext* context, Request* input, const Dictionary& init, ExceptionState& exceptionState)
{
    // "1. If input is a Request object, run these substeps:"
    // "  1. If input's used flag is set, throw a TypeError."
    // "  2. Set input's used flag."
    if (input->bodyUsed()) {
        exceptionState.throwTypeError(
            "Cannot construct a Request with a Request object that has already been used.");
        return 0;
    }
    input->setBodyUsed();
    // "2. Let |request| be |input|'s associated request, if |input| is a
    // Request object, and a new request otherwise."
    // "3. Set |request| to a restricted copy of itself."
    FetchRequestData* request(input->request()->createRestrictedCopy(context, SecurityOrigin::create(context->url())));
    // "4. Let |fallbackMode| be null."
    // "5. Let |fallbackCredentials| be null."
    // Instead of using null as a special fallback value, just pass the current
    // mode and credentials; it has the same effect.
    const WebURLRequest::FetchRequestMode currentMode = request->mode();
    const WebURLRequest::FetchCredentialsMode currentCredentials = request->credentials();
    return createRequestWithRequestData(context, request, RequestInit(context, init, exceptionState), currentMode, currentCredentials, exceptionState);
}

Request* Request::create(ExecutionContext* context, FetchRequestData* request)
{
    Request* r = new Request(context, request);
    r->suspendIfNeeded();
    return r;
}

Request::Request(ExecutionContext* context, FetchRequestData* request)
    : Body(context)
    , m_request(request)
    , m_headers(Headers::create(m_request->headerList()))
{
    m_headers->setGuard(Headers::RequestGuard);
}

Request* Request::create(ExecutionContext* context, const WebServiceWorkerRequest& webRequest)
{
    Request* r = new Request(context, webRequest);
    r->suspendIfNeeded();
    return r;
}

Request* Request::create(const Request& copyFrom)
{
    Request* r = new Request(copyFrom);
    r->suspendIfNeeded();
    return r;
}

Request::Request(ExecutionContext* context, const WebServiceWorkerRequest& webRequest)
    : Body(context)
    , m_request(FetchRequestData::create(webRequest))
    , m_headers(Headers::create(m_request->headerList()))
{
    m_headers->setGuard(Headers::RequestGuard);
}

Request::Request(const Request& copy_from)
    : Body(copy_from)
    , m_request(copy_from.m_request)
    , m_headers(copy_from.m_headers->createCopy())
{
}


String Request::method() const
{
    // "The method attribute's getter must return request's method."
    return m_request->method();
}

String Request::url() const
{
    // The url attribute's getter must return request's url, serialized with the exclude fragment flag set.
    if (!m_request->url().hasFragmentIdentifier())
        return m_request->url();
    KURL url(m_request->url());
    url.removeFragmentIdentifier();
    return url;
}

String Request::referrer() const
{
    // "The referrer attribute's getter must return the empty string if
    // request's referrer is none, and request's referrer, serialized,
    // otherwise."
    return m_request->referrer().referrer().referrer;
}

String Request::mode() const
{
    // "The mode attribute's getter must return the value corresponding to the
    // first matching statement, switching on request's mode:"
    switch (m_request->mode()) {
    case WebURLRequest::FetchRequestModeSameOrigin:
        return "same-origin";
    case WebURLRequest::FetchRequestModeNoCORS:
        return "no-cors";
    case WebURLRequest::FetchRequestModeCORS:
    case WebURLRequest::FetchRequestModeCORSWithForcedPreflight:
        return "cors";
    }
    ASSERT_NOT_REACHED();
    return "";
}

String Request::credentials() const
{
    // "The credentials attribute's getter must return the value corresponding
    // to the first matching statement, switching on request's credentials
    // mode:"
    switch (m_request->credentials()) {
    case WebURLRequest::FetchCredentialsModeOmit:
        return "omit";
    case WebURLRequest::FetchCredentialsModeSameOrigin:
        return "same-origin";
    case WebURLRequest::FetchCredentialsModeInclude:
        return "include";
    }
    ASSERT_NOT_REACHED();
    return "";
}

Request* Request::clone() const
{
    return Request::create(*this);
}

void Request::populateWebServiceWorkerRequest(WebServiceWorkerRequest& webRequest) const
{
    webRequest.setMethod(method());
    webRequest.setURL(m_request->url());

    const FetchHeaderList* headerList = m_headers->headerList();
    for (size_t i = 0, size = headerList->size(); i < size; ++i) {
        const FetchHeaderList::Header& header = headerList->entry(i);
        webRequest.appendHeader(header.first, header.second);
    }

    webRequest.setReferrer(m_request->referrer().referrer().referrer, static_cast<WebReferrerPolicy>(m_request->referrer().referrer().referrerPolicy));
    // FIXME: How can we set isReload properly? What is the correct place to load it in to the Request object? We should investigate the right way
    // to plumb this information in to here.
}

void Request::setBodyBlobHandle(PassRefPtr<BlobDataHandle> blobDataHandle)
{
    m_request->setBlobDataHandle(blobDataHandle);
}

void Request::clearHeaderList()
{
    m_request->headerList()->clearList();
}

PassRefPtr<BlobDataHandle> Request::blobDataHandle()
{
    return m_request->blobDataHandle();
}

void Request::trace(Visitor* visitor)
{
    Body::trace(visitor);
    visitor->trace(m_request);
    visitor->trace(m_headers);
}

} // namespace blink
