/*
 * Copyright (C) 2009-2019 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.
 */

#import "config.h"
#import "LegacyPreviewLoader.h"

#if USE(QUICK_LOOK)

#import "DocumentLoader.h"
#import "Frame.h"
#import "FrameLoader.h"
#import "FrameLoaderClient.h"
#import "LegacyPreviewLoaderClient.h"
#import "Logging.h"
#import "PreviewConverter.h"
#import "QuickLook.h"
#import "ResourceLoader.h"
#import "Settings.h"
#import <wtf/NeverDestroyed.h>

namespace WebCore {

static RefPtr<LegacyPreviewLoaderClient>& testingClient()
{
    static NeverDestroyed<RefPtr<LegacyPreviewLoaderClient>> testingClient;
    return testingClient.get();
}

static LegacyPreviewLoaderClient& emptyClient()
{
    static NeverDestroyed<LegacyPreviewLoaderClient> emptyClient;
    return emptyClient.get();
}

static Ref<LegacyPreviewLoaderClient> makeClient(const ResourceLoader& loader, const String& previewFileName, const String& previewType)
{
    if (auto client = testingClient())
        return client.releaseNonNull();
    if (auto client = loader.frameLoader()->client().createPreviewLoaderClient(previewFileName, previewType))
        return client.releaseNonNull();
    return emptyClient();
}

bool LegacyPreviewLoader::didReceiveData(const SharedBuffer& buffer)
{
    if (m_finishedLoadingDataIntoConverter)
        return false;

    LOG(Network, "LegacyPreviewLoader appending buffer with size %ld.", buffer.size());
    m_originalData.append(buffer);
    m_converter->updateMainResource();
    m_client->didReceiveData(buffer);
    return true;
}

bool LegacyPreviewLoader::didFinishLoading()
{
    if (m_finishedLoadingDataIntoConverter)
        return false;

    LOG(Network, "LegacyPreviewLoader finished appending data.");
    m_finishedLoadingDataIntoConverter = true;
    m_converter->finishUpdating();
    m_client->didFinishLoading();
    return true;
}

void LegacyPreviewLoader::didFail()
{
    if (m_finishedLoadingDataIntoConverter)
        return;

    LOG(Network, "LegacyPreviewLoader failed.");
    m_finishedLoadingDataIntoConverter = true;
    m_converter->failedUpdating();
    m_client->didFail();
    m_converter = nullptr;
}

void LegacyPreviewLoader::previewConverterDidStartConverting(PreviewConverter& converter)
{
    auto resourceLoader = m_resourceLoader.get();
    if (!resourceLoader)
        return;

    if (resourceLoader->reachedTerminalState())
        return;

    ASSERT(!m_hasProcessedResponse);
    m_originalData.reset();
    resourceLoader->documentLoader()->setPreviewConverter(WTFMove(m_converter));
    auto response { converter.previewResponse() };

    if (m_shouldDecidePolicyBeforeLoading) {
        m_hasProcessedResponse = true;
        resourceLoader->didReceivePreviewResponse(response);
        return;
    }

    resourceLoader->didReceiveResponse(response, [this, weakThis = WeakPtr { static_cast<PreviewConverterClient&>(*this) }, converter = Ref { converter }] {
        if (!weakThis)
            return;

        m_hasProcessedResponse = true;

        auto resourceLoader = m_resourceLoader.get();
        if (!resourceLoader)
            return;

        if (resourceLoader->reachedTerminalState())
            return;

        if (!converter->previewData().isEmpty()) {
            auto bufferSize = converter->previewData().size();
            resourceLoader->didReceiveBuffer(converter->previewData().copy(), bufferSize, DataPayloadBytes);
        }

        if (resourceLoader->reachedTerminalState())
            return;

        if (m_needsToCallDidFinishLoading) {
            m_needsToCallDidFinishLoading = false;
            resourceLoader->didFinishLoading(NetworkLoadMetrics { });
        }
    });
}

void LegacyPreviewLoader::previewConverterDidReceiveData(PreviewConverter&, const FragmentedSharedBuffer& data)
{
    auto resourceLoader = m_resourceLoader.get();
    if (!resourceLoader)
        return;

    if (resourceLoader->reachedTerminalState())
        return;

    if (data.isEmpty())
        return;

    if (!m_hasProcessedResponse)
        return;

    resourceLoader->didReceiveBuffer(data, data.size(), DataPayloadBytes);
}

void LegacyPreviewLoader::previewConverterDidFinishConverting(PreviewConverter&)
{
    auto resourceLoader = m_resourceLoader.get();
    if (!resourceLoader)
        return;

    if (resourceLoader->reachedTerminalState())
        return;

    if (!m_hasProcessedResponse) {
        m_needsToCallDidFinishLoading = true;
        return;
    }

    resourceLoader->didFinishLoading(NetworkLoadMetrics { });
}

void LegacyPreviewLoader::previewConverterDidFailUpdating(PreviewConverter&)
{
    if (auto resourceLoader = m_resourceLoader.get())
        resourceLoader->didFail(resourceLoader->cannotShowURLError());
}

void LegacyPreviewLoader::previewConverterDidFailConverting(PreviewConverter& converter)
{
    auto resourceLoader = m_resourceLoader.get();
    if (!resourceLoader)
        return;

    if (resourceLoader->reachedTerminalState())
        return;

    resourceLoader->didFail(converter.previewError());
}

void LegacyPreviewLoader::providePasswordForPreviewConverter(PreviewConverter& converter, CompletionHandler<void(const String&)>&& completionHandler)
{
    ASSERT_UNUSED(converter, &converter == m_converter);

    auto resourceLoader = m_resourceLoader.get();
    if (!resourceLoader) {
        completionHandler({ });
        return;
    }

    if (resourceLoader->reachedTerminalState()) {
        completionHandler({ });
        return;
    }

    if (!m_client->supportsPasswordEntry()) {
        completionHandler({ });
        return;
    }

    m_client->didRequestPassword(WTFMove(completionHandler));
}

void LegacyPreviewLoader::provideMainResourceForPreviewConverter(PreviewConverter& converter, CompletionHandler<void(Ref<FragmentedSharedBuffer>&&)>&& completionHandler)
{
    ASSERT_UNUSED(converter, &converter == m_converter);
    completionHandler(m_originalData.copy());
}

LegacyPreviewLoader::~LegacyPreviewLoader() = default;

LegacyPreviewLoader::LegacyPreviewLoader(ResourceLoader& loader, const ResourceResponse& response)
    : m_converter { PreviewConverter::create(response, *this) }
    , m_client { makeClient(loader, m_converter->previewFileName(), m_converter->previewUTI()) }
    , m_resourceLoader { loader }
    , m_shouldDecidePolicyBeforeLoading { loader.frame()->settings().shouldDecidePolicyBeforeLoadingQuickLookPreview() }
{
    ASSERT(PreviewConverter::supportsMIMEType(response.mimeType()));
    m_converter->addClient(*this);
    LOG(Network, "LegacyPreviewLoader created with preview file name \"%s\".", m_converter->previewFileName().utf8().data());
}

bool LegacyPreviewLoader::didReceiveResponse(const ResourceResponse&)
{
    return !m_shouldDecidePolicyBeforeLoading;
}

void LegacyPreviewLoader::setClientForTesting(RefPtr<LegacyPreviewLoaderClient>&& client)
{
    testingClient() = WTFMove(client);
}

} // namespace WebCore

#endif // USE(QUICK_LOOK)
