/*
 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Collabora, Ltd. 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. ``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
 * 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 "PluginStream.h"

#include "PluginDebug.h"
#include "WebResourceLoadScheduler.h"
#include <WebCore/DocumentLoader.h>
#include <WebCore/Frame.h>
#include <WebCore/FrameLoader.h>
#include <WebCore/HTTPHeaderNames.h>
#include <WebCore/SharedBuffer.h>
#include <WebCore/SubresourceLoader.h>
#include <wtf/CompletionHandler.h>
#include <wtf/StringExtras.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/text/WTFString.h>

// We use -2 here because some plugins like to return -1 to indicate error
// and this way we won't clash with them.
static const int WebReasonNone = -2;

using std::max;
using std::min;

namespace WebCore {

typedef HashMap<NPStream*, NPP> StreamMap;
static StreamMap& streams()
{
    static StreamMap staticStreams;
    return staticStreams;
}

PluginStream::PluginStream(PluginStreamClient* client, Frame* frame, const ResourceRequest& resourceRequest, bool sendNotification, void* notifyData, const NPPluginFuncs* pluginFuncs, NPP instance, const PluginQuirkSet& quirks)
    : m_resourceRequest(resourceRequest)
    , m_client(client)
    , m_frame(frame)
    , m_notifyData(notifyData)
    , m_sendNotification(sendNotification)
    , m_streamState(StreamBeforeStarted)
    , m_loadManually(false)
    , m_delayDeliveryTimer(*this, &PluginStream::delayDeliveryTimerFired)
    , m_tempFileHandle(FileSystem::invalidPlatformFileHandle)
    , m_pluginFuncs(pluginFuncs)
    , m_instance(instance)
    , m_quirks(quirks)
{
    ASSERT(m_instance);

    m_stream.url = 0;
    m_stream.ndata = 0;
    m_stream.pdata = 0;
    m_stream.end = 0;
    m_stream.notifyData = 0;
    m_stream.lastmodified = 0;
    m_stream.headers = 0;

    streams().add(&m_stream, m_instance);
}

PluginStream::~PluginStream()
{
    ASSERT(m_streamState != StreamStarted);
    ASSERT(!m_loader);

    fastFree((char*)m_stream.url);

    streams().remove(&m_stream);
}

void PluginStream::start()
{
    ASSERT(!m_loadManually);
    ASSERT(m_frame);
    webResourceLoadScheduler().schedulePluginStreamLoad(*m_frame, *this, ResourceRequest(m_resourceRequest), [this, protectedThis = makeRef(*this)] (RefPtr<WebCore::NetscapePlugInStreamLoader>&& loader) {
        m_loader = WTFMove(loader);
    });
}

void PluginStream::stop()
{
    m_streamState = StreamStopped;

    if (m_loadManually) {
        ASSERT(!m_loader);

        DocumentLoader* documentLoader = m_frame->loader().activeDocumentLoader();
        ASSERT(documentLoader);

        if (documentLoader->isLoadingMainResource())
            documentLoader->cancelMainResourceLoad(m_frame->loader().cancelledError(m_resourceRequest));

        return;
    }

    if (m_loader) {
        m_loader->cancel();
        m_loader = nullptr;
    }

    m_client = 0;
}

static uint32_t lastModifiedDateMS(const ResourceResponse& response)
{
    auto lastModified = response.lastModified();
    if (!lastModified)
        return 0;

    return lastModified.value().secondsSinceEpoch().millisecondsAs<uint32_t>();
}

void PluginStream::startStream()
{
    ASSERT(m_streamState == StreamBeforeStarted);

    const URL& responseURL = m_resourceResponse.url();

    // Some plugins (Flash) expect that javascript URLs are passed back decoded as this is the
    // format used when requesting the URL.
    if (protocolIsJavaScript(responseURL))
        m_stream.url = fastStrDup(decodeURLEscapeSequences(responseURL.string()).utf8().data());
    else
        m_stream.url = fastStrDup(responseURL.string().utf8().data());

    CString mimeTypeStr = m_resourceResponse.mimeType().utf8();

    long long expectedContentLength = m_resourceResponse.expectedContentLength();

    if (m_resourceResponse.isHTTP()) {
        StringBuilder stringBuilder;
        String separator = ": "_s;

        String statusLine = "HTTP " + String::number(m_resourceResponse.httpStatusCode()) + " OK\n";
        stringBuilder.append(statusLine);

        HTTPHeaderMap::const_iterator end = m_resourceResponse.httpHeaderFields().end();
        for (HTTPHeaderMap::const_iterator it = m_resourceResponse.httpHeaderFields().begin(); it != end; ++it) {
            stringBuilder.append(it->key);
            stringBuilder.append(separator);
            stringBuilder.append(it->value);
            stringBuilder.append('\n');
        }

        m_headers = stringBuilder.toString().utf8();

        // If the content is encoded (most likely compressed), then don't send its length to the plugin,
        // which is only interested in the decoded length, not yet known at the moment.
        // <rdar://problem/4470599> tracks a request for -[NSURLResponse expectedContentLength] to incorporate this logic.
        String contentEncoding = m_resourceResponse.httpHeaderField(HTTPHeaderName::ContentEncoding);
        if (!contentEncoding.isNull() && contentEncoding != "identity")
            expectedContentLength = -1;
    }

    m_stream.headers = m_headers.data();
    m_stream.pdata = 0;
    m_stream.ndata = this;
    m_stream.end = max(expectedContentLength, 0LL);
    m_stream.lastmodified = lastModifiedDateMS(m_resourceResponse);
    m_stream.notifyData = m_notifyData;

    m_transferMode = NP_NORMAL;
    m_offset = 0;
    m_reason = WebReasonNone;

    // Protect the stream if destroystream is called from within the newstream handler
    RefPtr<PluginStream> protect(this);

    // calling into a plug-in could result in re-entrance if the plug-in yields
    // control to the system (rdar://5744899). prevent this by deferring further
    // loading while calling into the plug-in.
    if (m_loader)
        m_loader->setDefersLoading(true);
    NPError npErr = m_pluginFuncs->newstream(m_instance, (NPMIMEType)mimeTypeStr.data(), &m_stream, false, &m_transferMode);
    if (m_loader)
        m_loader->setDefersLoading(false);
    
    // If the stream was destroyed in the call to newstream we return
    if (m_reason != WebReasonNone)
        return;
        
    if (npErr != NPERR_NO_ERROR) {
        cancelAndDestroyStream(npErr);
        return;
    }

    m_streamState = StreamStarted;

    if (m_transferMode == NP_NORMAL)
        return;

    m_path = FileSystem::openTemporaryFile("WKP", m_tempFileHandle);

    // Something went wrong, cancel loading the stream
    if (!FileSystem::isHandleValid(m_tempFileHandle))
        cancelAndDestroyStream(NPRES_NETWORK_ERR);
}

NPP PluginStream::ownerForStream(NPStream* stream)
{
    return streams().get(stream);
}

void PluginStream::cancelAndDestroyStream(NPReason reason)
{
    RefPtr<PluginStream> protect(this);

    destroyStream(reason);
    stop();
}

void PluginStream::destroyStream(NPReason reason)
{
    m_reason = reason;
    if (m_reason != NPRES_DONE) {
        // Stop any pending data from being streamed
        if (m_deliveryData)
            m_deliveryData->resize(0);
    } else if (m_deliveryData && m_deliveryData->size() > 0) {
        // There is more data to be streamed, don't destroy the stream now.
        return;
    }
    destroyStream();
}

void PluginStream::destroyStream()
{
    if (m_streamState == StreamStopped)
        return;

    ASSERT(m_reason != WebReasonNone);
    ASSERT(!m_deliveryData || m_deliveryData->size() == 0);

    FileSystem::closeFile(m_tempFileHandle);

    bool newStreamCalled = m_stream.ndata;

    // Protect from destruction if:
    //  NPN_DestroyStream is called from NPP_NewStream or
    //  PluginStreamClient::streamDidFinishLoading() removes the last reference
    RefPtr<PluginStream> protect(this);

    if (newStreamCalled) {
        if (m_reason == NPRES_DONE && (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY)) {
            ASSERT(!m_path.isNull());

            if (m_loader)
                m_loader->setDefersLoading(true);
            m_pluginFuncs->asfile(m_instance, &m_stream, m_path.utf8().data());
            if (m_loader)
                m_loader->setDefersLoading(false);
        }

        if (m_streamState != StreamBeforeStarted) {
            if (m_loader)
                m_loader->setDefersLoading(true);

            NPError npErr = m_pluginFuncs->destroystream(m_instance, &m_stream, m_reason);

            if (m_loader)
                m_loader->setDefersLoading(false);

            LOG_NPERROR(npErr);
        }

        m_stream.ndata = 0;
    }

    if (m_sendNotification) {
        // Flash 9 can dereference null if we call NPP_URLNotify without first calling NPP_NewStream
        // for requests made with NPN_PostURLNotify; see <rdar://5588807>
        if (m_loader)
            m_loader->setDefersLoading(true);
        if (!newStreamCalled && m_quirks.contains(PluginQuirkFlashURLNotifyBug) &&
            equalLettersIgnoringASCIICase(m_resourceRequest.httpMethod(), "post")) {
            m_transferMode = NP_NORMAL;
            m_stream.url = "";
            m_stream.notifyData = m_notifyData;

            static char emptyMimeType[] = "";
            m_pluginFuncs->newstream(m_instance, emptyMimeType, &m_stream, false, &m_transferMode);
            m_pluginFuncs->destroystream(m_instance, &m_stream, m_reason);

            // in successful requests, the URL is dynamically allocated and freed in our
            // destructor, so reset it to 0
            m_stream.url = 0;
        }
        m_pluginFuncs->urlnotify(m_instance, m_resourceRequest.url().string().utf8().data(), m_reason, m_notifyData);
        if (m_loader)
            m_loader->setDefersLoading(false);
    }

    m_streamState = StreamStopped;

    if (!m_loadManually && m_client)
        m_client->streamDidFinishLoading(this);

    if (!m_path.isNull())
        FileSystem::deleteFile(m_path);
}

void PluginStream::delayDeliveryTimerFired()
{
    deliverData();
}

void PluginStream::deliverData()
{
    ASSERT(m_deliveryData);
    
    if (m_streamState == StreamStopped)
        // FIXME: We should cancel our job in the SubresourceLoader on error so we don't reach this case
        return;

    ASSERT(m_streamState != StreamBeforeStarted);

    if (!m_stream.ndata || m_deliveryData->size() == 0)
        return;

    int32_t totalBytes = m_deliveryData->size();
    int32_t totalBytesDelivered = 0;

    if (m_loader)
        m_loader->setDefersLoading(true);
    while (totalBytesDelivered < totalBytes) {
        int32_t deliveryBytes = m_pluginFuncs->writeready(m_instance, &m_stream);

        if (deliveryBytes <= 0) {
            m_delayDeliveryTimer.startOneShot(0_s);
            break;
        } else {
            deliveryBytes = min(deliveryBytes, totalBytes - totalBytesDelivered);
            int32_t dataLength = deliveryBytes;
            char* data = m_deliveryData->data() + totalBytesDelivered;

            // Write the data
            deliveryBytes = m_pluginFuncs->write(m_instance, &m_stream, m_offset, dataLength, (void*)data);
            if (deliveryBytes < 0) {
                LOG_PLUGIN_NET_ERROR();
                if (m_loader)
                    m_loader->setDefersLoading(false);
                cancelAndDestroyStream(NPRES_NETWORK_ERR);
                return;
            }
            deliveryBytes = min(deliveryBytes, dataLength);
            m_offset += deliveryBytes;
            totalBytesDelivered += deliveryBytes;
        }
    }
    if (m_loader)
        m_loader->setDefersLoading(false);

    if (totalBytesDelivered > 0) {
        if (totalBytesDelivered < totalBytes) {
            int remainingBytes = totalBytes - totalBytesDelivered;
            memmove(m_deliveryData->data(), m_deliveryData->data() + totalBytesDelivered, remainingBytes);
            m_deliveryData->resize(remainingBytes);
        } else {
            m_deliveryData->resize(0);
            if (m_reason != WebReasonNone)
                destroyStream();
        }
    } 
}

void PluginStream::sendJavaScriptStream(const URL& requestURL, const CString& resultString)
{
    didReceiveResponse(0, ResourceResponse(requestURL, "text/plain", resultString.length(), ""));

    if (m_streamState == StreamStopped)
        return;

    if (!resultString.isNull()) {
        didReceiveData(0, resultString.data(), resultString.length());
        if (m_streamState == StreamStopped)
            return;
    }

    m_loader = nullptr;

    destroyStream(resultString.isNull() ? NPRES_NETWORK_ERR : NPRES_DONE);
}

void PluginStream::willSendRequest(NetscapePlugInStreamLoader*, ResourceRequest&& request, const ResourceResponse&, CompletionHandler<void(WebCore::ResourceRequest&&)>&& callback)
{
    // FIXME: We should notify the plug-in with NPP_URLRedirectNotify here.
    callback(WTFMove(request));
}

void PluginStream::didReceiveResponse(NetscapePlugInStreamLoader* loader, const ResourceResponse& response)
{
    ASSERT_UNUSED(loader, loader == m_loader);
    ASSERT(m_streamState == StreamBeforeStarted);

    m_resourceResponse = response;

    startStream();
}

void PluginStream::didReceiveData(NetscapePlugInStreamLoader* loader, const char* data, int length)
{
    ASSERT_UNUSED(loader, loader == m_loader);
    ASSERT(m_streamState == StreamStarted);

    // If the plug-in cancels the stream in deliverData it could be deleted, 
    // so protect it here.
    RefPtr<PluginStream> protect(this);

    if (m_transferMode != NP_ASFILEONLY) {
        if (!m_deliveryData)
            m_deliveryData = makeUnique<Vector<char>>();

        int oldSize = m_deliveryData->size();
        m_deliveryData->resize(oldSize + length);
        memcpy(m_deliveryData->data() + oldSize, data, length);

        deliverData();
    }

    if (m_streamState != StreamStopped && FileSystem::isHandleValid(m_tempFileHandle)) {
        int bytesWritten = FileSystem::writeToFile(m_tempFileHandle, data, length);
        if (bytesWritten != length)
            cancelAndDestroyStream(NPRES_NETWORK_ERR);
    }
}

void PluginStream::didFail(NetscapePlugInStreamLoader* loader, const ResourceError&)
{
    ASSERT_UNUSED(loader, loader == m_loader);

    LOG_PLUGIN_NET_ERROR();

    // destroyStream can result in our being deleted
    RefPtr<PluginStream> protect(this);

    destroyStream(NPRES_NETWORK_ERR);

    m_loader = nullptr;
}

void PluginStream::didFinishLoading(NetscapePlugInStreamLoader* loader)
{
    ASSERT_UNUSED(loader, loader == m_loader);
    ASSERT(m_streamState == StreamStarted);

    // destroyStream can result in our being deleted
    RefPtr<PluginStream> protect(this);

    destroyStream(NPRES_DONE);

    m_loader = nullptr;
}

bool PluginStream::wantsAllStreams() const
{
    if (!m_pluginFuncs->getvalue)
        return false;

    void* result = nullptr;
    if (m_pluginFuncs->getvalue(m_instance, NPPVpluginWantsAllNetworkStreams, &result) != NPERR_NO_ERROR)
        return false;

    return !!result;
}

}
