/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "custom_url_loader_factory.h"

#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/net_errors.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"

#include "api/qwebengineurlscheme.h"
#include "net/url_request_custom_job_proxy.h"
#include "profile_adapter.h"
#include "type_conversion.h"

#include <QtCore/qbytearray.h>
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qmimedatabase.h>
#include <QtCore/qmimedata.h>
#include <QtCore/qurl.h>

namespace QtWebEngineCore {

namespace {

class CustomURLLoader : public network::mojom::URLLoader
                      , private URLRequestCustomJobProxy::Client
{
public:
    static void CreateAndStart(const network::ResourceRequest &request,
                               network::mojom::URLLoaderRequest loader,
                               network::mojom::URLLoaderClientPtrInfo client_info,
                               QPointer<ProfileAdapter> profileAdapter)
    {
        // CustomURLLoader will handle its own life-cycle, and delete when
        // the client lets go.
        auto *customUrlLoader = new CustomURLLoader(request, std::move(loader), std::move(client_info), profileAdapter);
        customUrlLoader->Start();
    }

    // network::mojom::URLLoader:
    void FollowRedirect(const std::vector<std::string> &removed_headers,
                        const net::HttpRequestHeaders &modified_headers,
                        const base::Optional<GURL> &new_url) override
    {
        // We can be asked for follow our own redirect
        scoped_refptr<URLRequestCustomJobProxy> proxy = new URLRequestCustomJobProxy(this, m_proxy->m_scheme, m_proxy->m_profileAdapter);
        m_proxy->m_client = nullptr;
//        m_taskRunner->PostTask(FROM_HERE, base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy));
        base::PostTask(FROM_HERE, { content::BrowserThread::UI },
                       base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy));
        m_proxy = std::move(proxy);
        if (new_url)
            m_request.url = *new_url;
        else
            m_request.url = m_redirect;
        m_redirect = GURL();
        for (const std::string &header: removed_headers)
            m_request.headers.RemoveHeader(header);
        m_request.headers.MergeFrom(modified_headers);
        Start();
    }
    void SetPriority(net::RequestPriority priority, int32_t intra_priority_value) override { }
    void PauseReadingBodyFromNet() override { }
    void ResumeReadingBodyFromNet() override { }

private:
    CustomURLLoader(const network::ResourceRequest &request,
                    network::mojom::URLLoaderRequest loader,
                    network::mojom::URLLoaderClientPtrInfo client_info,
                    QPointer<ProfileAdapter> profileAdapter)
        // ### We can opt to run the url-loader on the UI thread instead
        : m_taskRunner(base::CreateSingleThreadTaskRunner({ content::BrowserThread::IO }))
        , m_proxy(new URLRequestCustomJobProxy(this, request.url.scheme(), profileAdapter))
        , m_binding(this, std::move(loader))
        , m_client(std::move(client_info))
        , m_request(request)
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        m_binding.set_connection_error_handler(
                base::BindOnce(&CustomURLLoader::OnConnectionError, m_weakPtrFactory.GetWeakPtr()));
        m_firstBytePosition = 0;
        m_device = nullptr;
        m_error = 0;
        QWebEngineUrlScheme scheme = QWebEngineUrlScheme::schemeByName(QByteArray::fromStdString(request.url.scheme()));
        m_corsEnabled = scheme.flags().testFlag(QWebEngineUrlScheme::CorsEnabled);
    }

    ~CustomURLLoader() override = default;

    void Start()
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        m_head.request_start = base::TimeTicks::Now();

        if (!m_pipe.consumer_handle.is_valid())
            return CompleteWithFailure(net::ERR_FAILED);

        std::map<std::string, std::string> headers;
        net::HttpRequestHeaders::Iterator it(m_request.headers);
        while (it.GetNext())
            headers.emplace(it.name(), it.value());
        if (!m_request.referrer.is_empty())
            headers.emplace("Referer", m_request.referrer.spec());

        std::string rangeHeader;
        if (ParseRange(m_request.headers))
            m_firstBytePosition = m_byteRange.first_byte_position();

//        m_taskRunner->PostTask(FROM_HERE,
        base::PostTask(FROM_HERE, { content::BrowserThread::UI },
                       base::BindOnce(&URLRequestCustomJobProxy::initialize, m_proxy,
                                      m_request.url, m_request.method, m_request.request_initiator, std::move(headers)));
    }

    void CompleteWithFailure(net::Error net_error)
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        m_client->OnComplete(network::URLLoaderCompletionStatus(net_error));
        ClearProxyAndClient(false);
    }

    void OnConnectionError()
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        m_binding.Close();
        if (m_client.is_bound())
            ClearProxyAndClient(false);
        else
            delete this;
    }

    void OnTransferComplete(MojoResult result)
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        if (result == MOJO_RESULT_OK) {
            network::URLLoaderCompletionStatus status(net::OK);
            status.encoded_data_length = m_totalBytesRead + m_head.headers->raw_headers().length();
            status.encoded_body_length = m_totalBytesRead;
            status.decoded_body_length = m_totalBytesRead;
            m_client->OnComplete(status);
        } else {
            m_client->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED));
        }
        ClearProxyAndClient(false /* result == MOJO_RESULT_OK */);
    }

    void ClearProxyAndClient(bool wait_for_loader_error = false)
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        m_proxy->m_client = nullptr;
        m_client.reset();
        if (m_device && m_device->isOpen())
            m_device->close();
        m_device = nullptr;
//        m_taskRunner->PostTask(FROM_HERE, base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy));
        base::PostTask(FROM_HERE, { content::BrowserThread::UI },
                       base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy));
        if (!wait_for_loader_error || !m_binding.is_bound())
            delete this;
    }

    // URLRequestCustomJobProxy::Client:
    void notifyExpectedContentSize(qint64 size) override
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        m_totalSize = size;
        if (m_byteRange.IsValid()) {
            if (!m_byteRange.ComputeBounds(size)) {
                CompleteWithFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
            } else {
                m_maxBytesToRead = m_byteRange.last_byte_position() - m_byteRange.first_byte_position() + 1;
                m_head.content_length = m_maxBytesToRead;
            }
        } else {
            m_head.content_length = size;
        }
    }
    void notifyHeadersComplete() override
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        DCHECK(!m_error);
        m_head.response_start = base::TimeTicks::Now();

        std::string headers;
        if (!m_redirect.is_empty()) {
            headers += "HTTP/1.1 303 See Other\n";
            headers += base::StringPrintf("Location: %s\n", m_redirect.spec().c_str());
        } else {
            if (m_byteRange.IsValid() && m_totalSize > 0) {
                headers += "HTTP/1.1 206 Partial Content\n";
                headers += net::HttpResponseHeaders::kContentRange;
                headers += base::StringPrintf(": bytes %lld-%lld/%lld",
                                              qlonglong{m_byteRange.first_byte_position()},
                                              qlonglong{m_byteRange.last_byte_position()},
                                              qlonglong{m_totalSize});
                headers += "\n";
            } else {
                headers += "HTTP/1.1 200 OK\n";
            }
            if (m_mimeType.size() > 0) {
                headers += net::HttpRequestHeaders::kContentType;
                headers += base::StringPrintf(": %s", m_mimeType.c_str());
                if (m_charset.size() > 0)
                    headers += base::StringPrintf("; charset=%s", m_charset.c_str());
                headers += "\n";
            }
        }
        if (m_corsEnabled) {
            std::string origin;
            if (m_request.headers.GetHeader("Origin", &origin)) {
                headers += base::StringPrintf("Access-Control-Allow-Origin: %s\n", origin.c_str());
                headers += "Access-Control-Allow-Credentials: true\n";
            }
        }
        m_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers));
        m_head.encoded_data_length = m_head.headers->raw_headers().length();

        if (!m_redirect.is_empty()) {
            m_head.content_length = m_head.encoded_body_length = -1;
            net::URLRequest::FirstPartyURLPolicy first_party_url_policy =
                    m_request.update_first_party_url_on_redirect ? net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT
                                                                 : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL;
            net::RedirectInfo redirectInfo = net::RedirectInfo::ComputeRedirectInfo(
                        m_request.method, m_request.url,
                        m_request.site_for_cookies,
                        first_party_url_policy, m_request.referrer_policy,
                        m_request.referrer.spec(), net::HTTP_SEE_OTHER,
                        m_redirect, base::nullopt, false /*insecure_scheme_was_upgraded*/);
            m_client->OnReceiveRedirect(redirectInfo, m_head);
            // ### should m_request be updated with RedirectInfo? (see FollowRedirect)
            return;
        }
        DCHECK(m_device);
        m_head.mime_type = m_mimeType;
        m_head.charset = m_charset;
        m_client->OnReceiveResponse(m_head);
        m_client->OnStartLoadingResponseBody(std::move(m_pipe.consumer_handle));

        if (readAvailableData()) // May delete this
            return;

        m_watcher = std::make_unique<mojo::SimpleWatcher>(
                FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC, m_taskRunner);
        m_watcher->Watch(m_pipe.producer_handle.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
                         MOJO_WATCH_CONDITION_SATISFIED,
                         base::BindRepeating(&CustomURLLoader::notifyReadyWrite,
                                             m_weakPtrFactory.GetWeakPtr()));
    }
    void notifyCanceled() override
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        OnTransferComplete(MOJO_RESULT_CANCELLED);
    }
    void notifyAborted() override
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        notifyStartFailure(net::ERR_ABORTED);
    }
    void notifyStartFailure(int error) override
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        m_head.response_start = base::TimeTicks::Now();
        std::string headers;
        switch (error) {
        case net::ERR_INVALID_URL:
            headers = "HTTP/1.1 400 Bad Request\n";
            break;
        case net::ERR_FILE_NOT_FOUND:
            headers = "HTTP/1.1 404 Not Found\n";
            break;
        case net::ERR_ABORTED:
            headers = "HTTP/1.1 503 Request Aborted\n";
            break;
        case net::ERR_ACCESS_DENIED:
            headers = "HTTP/1.1 403 Forbidden\n";
            break;
        case net::ERR_FAILED:
            headers = "HTTP/1.1 400 Request Failed\n";
            break;
        default:
            headers = "HTTP/1.1 500 Internal Error\n";
            break;
        }
        m_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers));
        m_head.encoded_data_length = m_head.headers->raw_headers().length();
        m_head.content_length = m_head.encoded_body_length = -1;
        m_client->OnReceiveResponse(m_head);
        CompleteWithFailure(net::Error(error));
    }
    void notifyReadyRead() override
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        readAvailableData();
    }
    void notifyReadyWrite(MojoResult result, const mojo::HandleSignalsState &state)
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        if (result != MOJO_RESULT_OK) {
            CompleteWithFailure(net::ERR_FAILED);
            return;
        }
        readAvailableData();
    }
    bool readAvailableData()
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        for (;;) {
            if (m_error || !m_device)
                break;

            void *buffer = nullptr;
            uint32_t bufferSize = 0;
            MojoResult beginResult = m_pipe.producer_handle->BeginWriteData(
                    &buffer, &bufferSize, MOJO_BEGIN_WRITE_DATA_FLAG_NONE);
            if (beginResult == MOJO_RESULT_SHOULD_WAIT)
                return false; // Wait for pipe watcher
            if (beginResult != MOJO_RESULT_OK)
                break;
            if (m_maxBytesToRead > 0 && m_maxBytesToRead <= int64_t{std::numeric_limits<uint32_t>::max()})
                bufferSize = std::min(bufferSize, uint32_t(m_maxBytesToRead));

            int readResult = m_device->read(static_cast<char *>(buffer), bufferSize);
            uint32_t bytesRead = std::max(readResult, 0);
            m_pipe.producer_handle->EndWriteData(bytesRead);
            m_totalBytesRead += bytesRead;
            m_client->OnTransferSizeUpdated(m_totalBytesRead);

            if (m_device->atEnd() || (m_maxBytesToRead > 0 && m_totalBytesRead >= m_maxBytesToRead)) {
                OnTransferComplete(MOJO_RESULT_OK);
                return true; // Done with reading
            }

            if (readResult == 0)
                return false; // Wait for readyRead
            if (readResult < 0)
                break;
        }

        CompleteWithFailure(m_error ? net::Error(m_error) : net::ERR_FAILED);
        return true; // Done with reading
    }
    bool ParseRange(const net::HttpRequestHeaders &headers)
    {
        std::string range_header;
        if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
            std::vector<net::HttpByteRange> ranges;
            if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
                // Chromium doesn't support multirange requests.
                if (ranges.size() == 1) {
                    m_byteRange = ranges[0];
                    return true;
                }
            }
        }
        return false;
    }
    base::TaskRunner *taskRunner() override
    {
        DCHECK(m_taskRunner->RunsTasksInCurrentSequence());
        return m_taskRunner.get();
    }

    scoped_refptr<base::SequencedTaskRunner> m_taskRunner;
    scoped_refptr<URLRequestCustomJobProxy> m_proxy;

    mojo::Binding<network::mojom::URLLoader> m_binding;
    network::mojom::URLLoaderClientPtr m_client;
    mojo::DataPipe m_pipe;
    std::unique_ptr<mojo::SimpleWatcher> m_watcher;

    net::HttpByteRange m_byteRange;
    int64_t m_totalSize = 0;
    int64_t m_maxBytesToRead = -1;
    network::ResourceRequest m_request;
    network::ResourceResponseHead m_head;
    qint64 m_totalBytesRead = 0;
    bool m_corsEnabled;

    base::WeakPtrFactory<CustomURLLoader> m_weakPtrFactory{this};

    DISALLOW_COPY_AND_ASSIGN(CustomURLLoader);
};

class CustomURLLoaderFactory : public network::mojom::URLLoaderFactory {
public:
    CustomURLLoaderFactory(ProfileAdapter *profileAdapter)
        : m_taskRunner(base::CreateSequencedTaskRunner({ content::BrowserThread::IO }))
        , m_profileAdapter(profileAdapter)
    {
    }
    ~CustomURLLoaderFactory() override = default;

    // network::mojom::URLLoaderFactory:
    void CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> loader,
                              int32_t routing_id,
                              int32_t request_id,
                              uint32_t options,
                              const network::ResourceRequest &request,
                              mojo::PendingRemote<network::mojom::URLLoaderClient> client,
                              const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override
    {
        DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
        Q_UNUSED(routing_id);
        Q_UNUSED(request_id);
        Q_UNUSED(options);
        Q_UNUSED(traffic_annotation);

        m_taskRunner->PostTask(FROM_HERE,
                               base::BindOnce(&CustomURLLoader::CreateAndStart, request,
                                              std::move(loader), std::move(client),
                                              m_profileAdapter));

    }

    void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) override
    {
        m_receivers.Add(this, std::move(receiver));
    }

    const scoped_refptr<base::SequencedTaskRunner> m_taskRunner;
    mojo::ReceiverSet<network::mojom::URLLoaderFactory> m_receivers;
    QPointer<ProfileAdapter> m_profileAdapter;
    DISALLOW_COPY_AND_ASSIGN(CustomURLLoaderFactory);
};

} // namespace

std::unique_ptr<network::mojom::URLLoaderFactory> CreateCustomURLLoaderFactory(ProfileAdapter *profileAdapter)
{
    return std::make_unique<CustomURLLoaderFactory>(profileAdapter);
}

} // namespace QtWebEngineCore

