/*
 * Copyright (C) 2015 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 "DataURLDecoder.h"

#include "DecodeEscapeSequences.h"
#include "HTTPParsers.h"
#include "ParsedContentType.h"
#include "SharedBuffer.h"
#include "TextEncoding.h"
#include <wtf/MainThread.h>
#include <wtf/Optional.h>
#include <wtf/RunLoop.h>
#include <wtf/URL.h>
#include <wtf/WorkQueue.h>
#include <wtf/text/Base64.h>

namespace WebCore {
namespace DataURLDecoder {

static WorkQueue& decodeQueue()
{
    static auto& queue = WorkQueue::create("org.webkit.DataURLDecoder", WorkQueue::Type::Serial, WorkQueue::QOS::UserInitiated).leakRef();
    return queue;
}

static Result parseMediaType(const String& mediaType)
{
    if (Optional<ParsedContentType> parsedContentType = ParsedContentType::create(mediaType))
        return { parsedContentType->mimeType(), parsedContentType->charset(), parsedContentType->serialize(), nullptr };
    return { "text/plain"_s, "US-ASCII"_s, "text/plain;charset=US-ASCII"_s, nullptr };
}

struct DecodeTask {
    WTF_MAKE_FAST_ALLOCATED;
public:
    DecodeTask(const String& urlString, const ScheduleContext& scheduleContext, DecodeCompletionHandler&& completionHandler)
        : urlString(urlString.isolatedCopy())
        , scheduleContext(scheduleContext)
        , completionHandler(WTFMove(completionHandler))
    {
    }

    bool process()
    {
        if (urlString.find(',') == notFound)
            return false;
        const char dataString[] = "data:";
        const char base64String[] = ";base64";

        ASSERT(urlString.startsWith(dataString));

        size_t headerEnd = urlString.find(',', strlen(dataString));
        size_t encodedDataStart = headerEnd == notFound ? headerEnd : headerEnd + 1;

        encodedData = StringView(urlString).substring(encodedDataStart);
        auto header = StringView(urlString).substring(strlen(dataString), headerEnd - strlen(dataString));
        isBase64 = header.endsWithIgnoringASCIICase(StringView(base64String));
        auto mediaType = (isBase64 ? header.substring(0, header.length() - strlen(base64String)) : header).toString();
        mediaType = mediaType.stripWhiteSpace();
        if (mediaType.startsWith(';'))
            mediaType.insert("text/plain", 0);
        result = parseMediaType(mediaType);

        return true;
    }

    const String urlString;
    StringView encodedData;
    bool isBase64 { false };
    const ScheduleContext scheduleContext;
    const DecodeCompletionHandler completionHandler;

    Result result;
};

#if HAVE(RUNLOOP_TIMER)

class DecodingResultDispatcher : public ThreadSafeRefCounted<DecodingResultDispatcher> {
public:
    static void dispatch(std::unique_ptr<DecodeTask> decodeTask)
    {
        Ref<DecodingResultDispatcher> dispatcher = adoptRef(*new DecodingResultDispatcher(WTFMove(decodeTask)));
        dispatcher->startTimer();
    }

private:
    DecodingResultDispatcher(std::unique_ptr<DecodeTask> decodeTask)
        : m_timer(*this, &DecodingResultDispatcher::timerFired)
        , m_decodeTask(WTFMove(decodeTask))
    {
    }

    void startTimer()
    {
        // Keep alive until the timer has fired.
        ref();

        auto scheduledPairs = m_decodeTask->scheduleContext.scheduledPairs;
        m_timer.startOneShot(0_s);
        m_timer.schedule(scheduledPairs);
    }

    void timerFired()
    {
        if (m_decodeTask->result.data)
            m_decodeTask->completionHandler(WTFMove(m_decodeTask->result));
        else
            m_decodeTask->completionHandler({ });

        // Ensure DecodeTask gets deleted in the main thread.
        m_decodeTask = nullptr;

        deref();
    }

    RunLoopTimer<DecodingResultDispatcher> m_timer;
    std::unique_ptr<DecodeTask> m_decodeTask;
};

#endif // HAVE(RUNLOOP_TIMER)

static std::unique_ptr<DecodeTask> createDecodeTask(const URL& url, const ScheduleContext& scheduleContext, DecodeCompletionHandler&& completionHandler)
{
    return makeUnique<DecodeTask>(
        url.string(),
        scheduleContext,
        WTFMove(completionHandler)
    );
}

static void decodeBase64(DecodeTask& task)
{
    Vector<char> buffer;
    // First try base64url.
    if (!base64URLDecode(task.encodedData.toStringWithoutCopying(), buffer)) {
        // Didn't work, try unescaping and decoding as base64.
        auto unescapedString = decodeURLEscapeSequences(task.encodedData.toStringWithoutCopying());
        if (!base64Decode(unescapedString, buffer, Base64IgnoreSpacesAndNewLines))
            return;
    }
    buffer.shrinkToFit();
    task.result.data = SharedBuffer::create(WTFMove(buffer));
}

static void decodeEscaped(DecodeTask& task)
{
    TextEncoding encodingFromCharset(task.result.charset);
    auto& encoding = encodingFromCharset.isValid() ? encodingFromCharset : UTF8Encoding();
    auto buffer = decodeURLEscapeSequencesAsData(task.encodedData, encoding);

    buffer.shrinkToFit();
    task.result.data = SharedBuffer::create(WTFMove(buffer));
}

void decode(const URL& url, const ScheduleContext& scheduleContext, DecodeCompletionHandler&& completionHandler)
{
    ASSERT(url.protocolIsData());

    decodeQueue().dispatch([decodeTask = createDecodeTask(url, scheduleContext, WTFMove(completionHandler))]() mutable {
        if (decodeTask->process()) {
            if (decodeTask->isBase64)
                decodeBase64(*decodeTask);
            else
                decodeEscaped(*decodeTask);
        }

#if HAVE(RUNLOOP_TIMER)
        DecodingResultDispatcher::dispatch(WTFMove(decodeTask));
#else
        callOnMainThread([decodeTask = WTFMove(decodeTask)] {
            if (!decodeTask->result.data) {
                decodeTask->completionHandler({ });
                return;
            }
            decodeTask->completionHandler(WTFMove(decodeTask->result));
        });
#endif
    });
}

}
}
