/*
 * Copyright (C) 2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS 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 "WebURLSchemeTaskProxy.h"

#include "URLSchemeTaskParameters.h"
#include "WebCoreArgumentCoders.h"
#include "WebPage.h"
#include "WebPageProxyMessages.h"
#include "WebURLSchemeHandlerProxy.h"
#include <WebCore/NetworkLoadMetrics.h>
#include <WebCore/ResourceError.h>
#include <WebCore/ResourceLoader.h>
#include <wtf/CompletionHandler.h>

namespace WebKit {
using namespace WebCore;

WebURLSchemeTaskProxy::WebURLSchemeTaskProxy(WebURLSchemeHandlerProxy& handler, ResourceLoader& loader)
    : m_urlSchemeHandler(handler)
    , m_coreLoader(&loader)
    , m_request(loader.request())
    , m_identifier(loader.identifier())
{
}

void WebURLSchemeTaskProxy::startLoading()
{
    ASSERT(m_coreLoader);
    m_urlSchemeHandler.page().send(Messages::WebPageProxy::StartURLSchemeTask({m_urlSchemeHandler.identifier(), m_coreLoader->identifier(), m_request}));
}

void WebURLSchemeTaskProxy::stopLoading()
{
    ASSERT(m_coreLoader);
    m_urlSchemeHandler.page().send(Messages::WebPageProxy::StopURLSchemeTask(m_urlSchemeHandler.identifier(), m_coreLoader->identifier()));
    m_coreLoader = nullptr;

    // This line will result in this being deleted.
    m_urlSchemeHandler.taskDidStopLoading(*this);
}
    
void WebURLSchemeTaskProxy::didPerformRedirection(WebCore::ResourceResponse&& redirectResponse, WebCore::ResourceRequest&& request)
{
    if (!hasLoader())
        return;
    
    auto completionHandler = [this, protectedThis = makeRef(*this), originalRequest = request] (ResourceRequest&& request) {
        m_waitingForCompletionHandler = false;
        // We do not inform the UIProcess of WebKit's new request with the given suggested request.
        // We do want to know if WebKit would have generated a request that differs from the suggested request, though.
        if (request.url() != originalRequest.url())
            WTFLogAlways("Redirected scheme task would have been sent to a different URL.");

        processNextPendingTask();
    };
    
    if (m_waitingForCompletionHandler) {
        WTFLogAlways("Received redirect during previous redirect processing, queuing it.");
        queueTask([this, protectedThis = makeRef(*this), redirectResponse = WTFMove(redirectResponse), request = WTFMove(request)]() mutable {
            didPerformRedirection(WTFMove(redirectResponse), WTFMove(request));
        });
        return;
    }
    m_waitingForCompletionHandler = true;

    m_coreLoader->willSendRequest(WTFMove(request), redirectResponse, WTFMove(completionHandler));
}

void WebURLSchemeTaskProxy::didReceiveResponse(const ResourceResponse& response)
{
    if (m_waitingForCompletionHandler) {
        WTFLogAlways("Received response during redirect processing, queuing it.");
        queueTask([this, protectedThis = makeRef(*this), response] {
            didReceiveResponse(response);
        });
        return;
    }
    
    if (!hasLoader())
        return;

    m_waitingForCompletionHandler = true;
    m_coreLoader->didReceiveResponse(response, [this, protectedThis = makeRef(*this)] {
        m_waitingForCompletionHandler = false;
        processNextPendingTask();
    });
}

void WebURLSchemeTaskProxy::didReceiveData(size_t size, const uint8_t* data)
{
    if (!hasLoader())
        return;

    if (m_waitingForCompletionHandler) {
        WTFLogAlways("Received data during response processing, queuing it.");
        Vector<uint8_t> dataVector;
        dataVector.append(data, size);
        queueTask([this, protectedThis = makeRef(*this), dataVector = WTFMove(dataVector)] {
            didReceiveData(dataVector.size(), dataVector.data());
        });
        return;
    }

    m_coreLoader->didReceiveData(reinterpret_cast<const char*>(data), size, 0, DataPayloadType::DataPayloadBytes);
    processNextPendingTask();
}

void WebURLSchemeTaskProxy::didComplete(const ResourceError& error)
{
    if (!hasLoader())
        return;

    if (m_waitingForCompletionHandler) {
        queueTask([this, protectedThis = makeRef(*this), error] {
            didComplete(error);
        });
        return;
    }

    if (error.isNull())
        m_coreLoader->didFinishLoading(NetworkLoadMetrics());
    else
        m_coreLoader->didFail(error);

    m_coreLoader = nullptr;
}

bool WebURLSchemeTaskProxy::hasLoader()
{
    if (m_coreLoader && m_coreLoader->reachedTerminalState())
        m_coreLoader = nullptr;

    return m_coreLoader;
}

void WebURLSchemeTaskProxy::processNextPendingTask()
{
    if (!m_queuedTasks.isEmpty())
        m_queuedTasks.takeFirst()();
}

} // namespace WebKit
