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

#include "NetscapePlugin.h"
#include <utility>

using namespace WebCore;
using namespace std;

namespace WebKit {

NetscapePluginStream::NetscapePluginStream(PassRefPtr<NetscapePlugin> plugin, uint64_t streamID, bool sendNotification, void* notificationData)
    : m_plugin(plugin)
    , m_streamID(streamID)
    , m_sendNotification(sendNotification)
    , m_notificationData(notificationData)
    , m_npStream()
    , m_transferMode(NP_NORMAL)
    , m_offset(0)
    , m_fileHandle(invalidPlatformFileHandle)
    , m_isStarted(false)
#if !ASSERT_DISABLED
    , m_urlNotifyHasBeenCalled(false)
#endif    
    , m_deliveryDataTimer(RunLoop::main(), this, &NetscapePluginStream::deliverDataToPlugin)
    , m_stopStreamWhenDoneDelivering(false)
{
}

NetscapePluginStream::~NetscapePluginStream()
{
    ASSERT(!m_isStarted);
    ASSERT(!m_sendNotification || m_urlNotifyHasBeenCalled);
    ASSERT(m_fileHandle == invalidPlatformFileHandle);
}

void NetscapePluginStream::didReceiveResponse(const KURL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const String& mimeType, const String& headers)
{
    // Starting the stream could cause the plug-in stream to go away so we keep a reference to it here.
    RefPtr<NetscapePluginStream> protect(this);

    start(responseURL, streamLength, lastModifiedTime, mimeType, headers);
}

void NetscapePluginStream::didReceiveData(const char* bytes, int length)
{
    // Delivering the data could cause the plug-in stream to go away so we keep a reference to it here.
    RefPtr<NetscapePluginStream> protect(this);

    deliverData(bytes, length);
}

void NetscapePluginStream::didFinishLoading()
{
    // Stopping the stream could cause the plug-in stream to go away so we keep a reference to it here.
    RefPtr<NetscapePluginStream> protect(this);

    stop(NPRES_DONE);
}

void NetscapePluginStream::didFail(bool wasCancelled)
{
    // Stopping the stream could cause the plug-in stream to go away so we keep a reference to it here.
    RefPtr<NetscapePluginStream> protect(this);

    stop(wasCancelled ? NPRES_USER_BREAK : NPRES_NETWORK_ERR);
}
    
void NetscapePluginStream::sendJavaScriptStream(const String& requestURLString, const String& result)
{
    // starting the stream or delivering the data to it might cause the plug-in stream to go away, so we keep
    // a reference to it here.
    RefPtr<NetscapePluginStream> protect(this);

    CString resultCString = requestURLString.utf8();
    if (resultCString.isNull()) {
        // There was an error evaluating the JavaScript, call NPP_URLNotify if needed and then destroy the stream.
        notifyAndDestroyStream(NPRES_NETWORK_ERR);
        return;
    }

    if (!start(requestURLString, resultCString.length(), 0, "text/plain", ""))
        return;

    deliverData(resultCString.data(), resultCString.length());
    stop(NPRES_DONE);
}

NPError NetscapePluginStream::destroy(NPReason reason)
{
    // It doesn't make sense to call NPN_DestroyStream on a stream that hasn't been started yet.
    if (!m_isStarted)
        return NPERR_GENERIC_ERROR;

    // It isn't really valid for a plug-in to call NPN_DestroyStream with NPRES_DONE.
    // (At least not for browser initiated streams, and we don't support plug-in initiated streams).
    if (reason == NPRES_DONE)
        return NPERR_INVALID_PARAM;

    cancel();
    stop(reason);
    return NPERR_NO_ERROR;
}

static bool isSupportedTransferMode(uint16_t transferMode)
{
    switch (transferMode) {
    case NP_ASFILEONLY:
    case NP_ASFILE:
    case NP_NORMAL:
        return true;
    // FIXME: We don't support seekable streams.
    case NP_SEEK:
        return false;
    }

    ASSERT_NOT_REACHED();
    return false;
}
    
bool NetscapePluginStream::start(const String& responseURLString, uint32_t streamLength, uint32_t lastModifiedTime, const String& mimeType, const String& headers)
{
    m_responseURL = responseURLString.utf8();
    m_mimeType = mimeType.utf8();
    m_headers = headers.utf8();

    m_npStream.ndata = this;
    m_npStream.url = m_responseURL.data();
    m_npStream.end = streamLength;
    m_npStream.lastmodified = lastModifiedTime;
    m_npStream.notifyData = m_notificationData;
    m_npStream.headers = m_headers.length() == 0 ? 0 : m_headers.data();

    NPError error = m_plugin->NPP_NewStream(const_cast<char*>(m_mimeType.data()), &m_npStream, false, &m_transferMode);
    if (error != NPERR_NO_ERROR) {
        // We failed to start the stream, cancel the load and destroy it.
        cancel();
        notifyAndDestroyStream(NPRES_NETWORK_ERR);
        return false;
    }

    // We successfully started the stream.
    m_isStarted = true;

    if (!isSupportedTransferMode(m_transferMode)) {
        // Cancel the load and stop the stream.
        cancel();
        stop(NPRES_NETWORK_ERR);
        return false;
    }

    return true;
}

void NetscapePluginStream::deliverData(const char* bytes, int length)
{
    ASSERT(m_isStarted);

    if (m_transferMode != NP_ASFILEONLY) {
        if (!m_deliveryData)
            m_deliveryData.set(new Vector<uint8_t>);

        m_deliveryData->reserveCapacity(m_deliveryData->size() + length);
        m_deliveryData->append(bytes, length);
        
        deliverDataToPlugin();
    }

    if (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY)
        deliverDataToFile(bytes, length);
}

void NetscapePluginStream::deliverDataToPlugin()
{
    ASSERT(m_isStarted);

    int32_t numBytesToDeliver = m_deliveryData->size();
    int32_t numBytesDelivered = 0;

    while (numBytesDelivered < numBytesToDeliver) {
        int32_t numBytesPluginCanHandle = m_plugin->NPP_WriteReady(&m_npStream);
        
        // NPP_WriteReady could call NPN_DestroyStream and destroy the stream.
        if (!m_isStarted)
            return;

        if (numBytesPluginCanHandle <= 0) {
            // The plug-in can't handle more data, we'll send the rest later
            m_deliveryDataTimer.startOneShot(0);
            break;
        }

        // Figure out how much data to send to the plug-in.
        int32_t dataLength = min(numBytesPluginCanHandle, numBytesToDeliver - numBytesDelivered);
        uint8_t* data = m_deliveryData->data() + numBytesDelivered;

        int32_t numBytesWritten = m_plugin->NPP_Write(&m_npStream, m_offset, dataLength, data);
        if (numBytesWritten < 0) {
            cancel();
            stop(NPRES_NETWORK_ERR);
            return;
        }

        // NPP_Write could call NPN_DestroyStream and destroy the stream.
        if (!m_isStarted)
            return;

        numBytesWritten = min(numBytesWritten, dataLength);
        m_offset += numBytesWritten;
        numBytesDelivered += numBytesWritten;
    }

    // We didn't write anything.
    if (!numBytesDelivered)
        return;

    if (numBytesDelivered < numBytesToDeliver) {
        // Remove the bytes that we actually delivered.
        m_deliveryData->remove(0, numBytesDelivered);
    } else {
        m_deliveryData->clear();

        if (m_stopStreamWhenDoneDelivering)
            stop(NPRES_DONE);
    }
}

void NetscapePluginStream::deliverDataToFile(const char* bytes, int length)
{
    if (m_fileHandle == invalidPlatformFileHandle && m_filePath.isNull()) {
        // Create a temporary file.
        m_filePath = openTemporaryFile("WebKitPluginStream", m_fileHandle);

        // We failed to open the file, stop the stream.
        if (m_fileHandle == invalidPlatformFileHandle) {
            stop(NPRES_NETWORK_ERR);
            return;
        }
    }

    if (!length)
        return;

    int byteCount = writeToFile(m_fileHandle, bytes, length);
    if (byteCount != length) {
        // This happens only rarely, when we are out of disk space or have a disk I/O error.
        closeFile(m_fileHandle);

        stop(NPRES_NETWORK_ERR);
    }
}

void NetscapePluginStream::stop(NPReason reason)
{
    // The stream was stopped before it got a chance to start. This can happen if a stream is cancelled by
    // WebKit before it received a response.
    if (!m_isStarted)
        return;

    if (reason == NPRES_DONE && m_deliveryData && !m_deliveryData->isEmpty()) {
        // There is still data left that the plug-in hasn't been able to consume yet.
        ASSERT(m_deliveryDataTimer.isActive());
        
        // Set m_stopStreamWhenDoneDelivering to true so that the next time the delivery timer fires
        // and calls deliverDataToPlugin the stream will be closed if all the remaining data was
        // successfully delivered.
        m_stopStreamWhenDoneDelivering = true;
        return;
    }

    m_deliveryData = 0;
    m_deliveryDataTimer.stop();

    if (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY) {
        if (reason == NPRES_DONE) {
            // Ensure that the file is created.
            deliverDataToFile(0, 0);
            if (m_fileHandle != invalidPlatformFileHandle)
                closeFile(m_fileHandle);
            
            ASSERT(!m_filePath.isNull());
            
            m_plugin->NPP_StreamAsFile(&m_npStream, m_filePath.utf8().data());
        } else {
            // Just close the file.
            if (m_fileHandle != invalidPlatformFileHandle)
                closeFile(m_fileHandle);
        }

        // Delete the file after calling NPP_StreamAsFile(), instead of in the destructor.  It should be OK
        // to delete the file here -- NPP_StreamAsFile() is always called immediately before NPP_DestroyStream()
        // (the stream destruction function), so there can be no expectation that a plugin will read the stream
        // file asynchronously after NPP_StreamAsFile() is called.
        deleteFile(m_filePath);
        m_filePath = String();

        // NPP_StreamAsFile could call NPN_DestroyStream and destroy the stream.
        if (!m_isStarted)
            return;
    }

    // Set m_isStarted to false before calling NPP_DestroyStream in case NPP_DestroyStream calls NPN_DestroyStream.
    m_isStarted = false;

    m_plugin->NPP_DestroyStream(&m_npStream, reason);

    notifyAndDestroyStream(reason);
}

void NetscapePluginStream::cancel()
{
    m_plugin->cancelStreamLoad(this);
}

void NetscapePluginStream::notifyAndDestroyStream(NPReason reason)
{
    ASSERT(!m_isStarted);
    ASSERT(!m_deliveryDataTimer.isActive());
    ASSERT(!m_urlNotifyHasBeenCalled);
    
    if (m_sendNotification) {
        m_plugin->NPP_URLNotify(m_responseURL.data(), reason, m_notificationData);
    
#if !ASSERT_DISABLED
        m_urlNotifyHasBeenCalled = true;
#endif    
    }

    m_plugin->removePluginStream(this);
}

} // namespace WebKit
