165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch/*
265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * Copyright (C) 2010 Apple Inc. All rights reserved.
365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *
465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * Redistribution and use in source and binary forms, with or without
565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * modification, are permitted provided that the following conditions
665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * are met:
765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * 1. Redistributions of source code must retain the above copyright
865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *    notice, this list of conditions and the following disclaimer.
965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * 2. Redistributions in binary form must reproduce the above copyright
1065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *    notice, this list of conditions and the following disclaimer in the
1165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *    documentation and/or other materials provided with the distribution.
1265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch *
1365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
1465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
1765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THE POSSIBILITY OF SUCH DAMAGE.
2465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch */
2565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "config.h"
2765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "NetscapePluginStream.h"
2865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
2965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "NetscapePlugin.h"
3065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include <utility>
3165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
3265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochusing namespace WebCore;
3365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochusing namespace std;
3465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
3565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochnamespace WebKit {
3665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
3765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochNetscapePluginStream::NetscapePluginStream(PassRefPtr<NetscapePlugin> plugin, uint64_t streamID, bool sendNotification, void* notificationData)
3865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    : m_plugin(plugin)
3965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_streamID(streamID)
4065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_sendNotification(sendNotification)
4165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_notificationData(notificationData)
4265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_npStream()
4365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_transferMode(NP_NORMAL)
4465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_offset(0)
4565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_fileHandle(invalidPlatformFileHandle)
4665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_isStarted(false)
4765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#if !ASSERT_DISABLED
4865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_urlNotifyHasBeenCalled(false)
4965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#endif
5065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_deliveryDataTimer(RunLoop::main(), this, &NetscapePluginStream::deliverDataToPlugin)
5165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    , m_stopStreamWhenDoneDelivering(false)
5265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
5365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
5465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
5565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochNetscapePluginStream::~NetscapePluginStream()
5665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
5765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(!m_isStarted);
5865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(!m_sendNotification || m_urlNotifyHasBeenCalled);
5965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(m_fileHandle == invalidPlatformFileHandle);
6065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
6165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
6265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::didReceiveResponse(const KURL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const String& mimeType, const String& headers)
6365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
6465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Starting the stream could cause the plug-in stream to go away so we keep a reference to it here.
6565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    RefPtr<NetscapePluginStream> protect(this);
6665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
6765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    start(responseURL, streamLength, lastModifiedTime, mimeType, headers);
6865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
6965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
7065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::didReceiveData(const char* bytes, int length)
7165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
7265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Delivering the data could cause the plug-in stream to go away so we keep a reference to it here.
7365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    RefPtr<NetscapePluginStream> protect(this);
7465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
7565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    deliverData(bytes, length);
7665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
7765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
7865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::didFinishLoading()
7965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
8065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Stopping the stream could cause the plug-in stream to go away so we keep a reference to it here.
8165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    RefPtr<NetscapePluginStream> protect(this);
8265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
8365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    stop(NPRES_DONE);
8465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
8565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
8665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::didFail(bool wasCancelled)
8765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
8865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Stopping the stream could cause the plug-in stream to go away so we keep a reference to it here.
8965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    RefPtr<NetscapePluginStream> protect(this);
9065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
9165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    stop(wasCancelled ? NPRES_USER_BREAK : NPRES_NETWORK_ERR);
9265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
9365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
9465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::sendJavaScriptStream(const String& requestURLString, const String& result)
9565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
9665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // starting the stream or delivering the data to it might cause the plug-in stream to go away, so we keep
9765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // a reference to it here.
9865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    RefPtr<NetscapePluginStream> protect(this);
9965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
10065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    CString resultCString = requestURLString.utf8();
10165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (resultCString.isNull()) {
10265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // There was an error evaluating the JavaScript, call NPP_URLNotify if needed and then destroy the stream.
10365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        notifyAndDestroyStream(NPRES_NETWORK_ERR);
10465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
10565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
10665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
10765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!start(requestURLString, resultCString.length(), 0, "text/plain", ""))
10865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
10965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
11065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    deliverData(resultCString.data(), resultCString.length());
11165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    stop(NPRES_DONE);
11265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
11365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
11465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben MurdochNPError NetscapePluginStream::destroy(NPReason reason)
11565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
11665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // It doesn't make sense to call NPN_DestroyStream on a stream that hasn't been started yet.
11765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!m_isStarted)
11865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return NPERR_GENERIC_ERROR;
11965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
12065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // It isn't really valid for a plug-in to call NPN_DestroyStream with NPRES_DONE.
12165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // (At least not for browser initiated streams, and we don't support plug-in initiated streams).
12265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (reason == NPRES_DONE)
12365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return NPERR_INVALID_PARAM;
12465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
12565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    cancel();
12665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    stop(reason);
12765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return NPERR_NO_ERROR;
12865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
12965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
13065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic bool isSupportedTransferMode(uint16_t transferMode)
13165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
13265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    switch (transferMode) {
13365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    case NP_ASFILEONLY:
13465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    case NP_ASFILE:
13565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    case NP_NORMAL:
13665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return true;
13765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // FIXME: We don't support seekable streams.
13865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    case NP_SEEK:
13965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
14065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
14165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
14265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT_NOT_REACHED();
14365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return false;
14465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
14565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
14665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochbool NetscapePluginStream::start(const String& responseURLString, uint32_t streamLength, uint32_t lastModifiedTime, const String& mimeType, const String& headers)
14765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
14865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_responseURL = responseURLString.utf8();
14965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_mimeType = mimeType.utf8();
15065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_headers = headers.utf8();
15165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
15265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_npStream.ndata = this;
15365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_npStream.url = m_responseURL.data();
15465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_npStream.end = streamLength;
15565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_npStream.lastmodified = lastModifiedTime;
15665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_npStream.notifyData = m_notificationData;
15765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_npStream.headers = m_headers.length() == 0 ? 0 : m_headers.data();
15865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
15965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    NPError error = m_plugin->NPP_NewStream(const_cast<char*>(m_mimeType.data()), &m_npStream, false, &m_transferMode);
16065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (error != NPERR_NO_ERROR) {
16165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // We failed to start the stream, cancel the load and destroy it.
16265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        cancel();
16365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        notifyAndDestroyStream(NPRES_NETWORK_ERR);
16465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
16565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
16665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
16765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // We successfully started the stream.
16865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_isStarted = true;
16965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
17065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!isSupportedTransferMode(m_transferMode)) {
17165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Cancel the load and stop the stream.
17265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        cancel();
17365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        stop(NPRES_NETWORK_ERR);
17465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return false;
17565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
17665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
17765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return true;
17865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
17965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
18065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::deliverData(const char* bytes, int length)
18165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
18265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(m_isStarted);
18365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
18465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (m_transferMode != NP_ASFILEONLY) {
18565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (!m_deliveryData)
18665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            m_deliveryData.set(new Vector<uint8_t>);
18765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
18865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        m_deliveryData->reserveCapacity(m_deliveryData->size() + length);
18965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        m_deliveryData->append(bytes, length);
19065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
19165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        deliverDataToPlugin();
19265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
19365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
19465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY)
19565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        deliverDataToFile(bytes, length);
19665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
19765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
19865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::deliverDataToPlugin()
19965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
20065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(m_isStarted);
20165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
20265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    int32_t numBytesToDeliver = m_deliveryData->size();
20365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    int32_t numBytesDelivered = 0;
20465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
20565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    while (numBytesDelivered < numBytesToDeliver) {
20665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        int32_t numBytesPluginCanHandle = m_plugin->NPP_WriteReady(&m_npStream);
20765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
20865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // NPP_WriteReady could call NPN_DestroyStream and destroy the stream.
20965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (!m_isStarted)
21065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            return;
21165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
21265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (numBytesPluginCanHandle <= 0) {
21365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            // The plug-in can't handle more data, we'll send the rest later
21465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            m_deliveryDataTimer.startOneShot(0);
21565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            break;
21665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        }
21765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
21865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Figure out how much data to send to the plug-in.
21965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        int32_t dataLength = min(numBytesPluginCanHandle, numBytesToDeliver - numBytesDelivered);
22065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        uint8_t* data = m_deliveryData->data() + numBytesDelivered;
22165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
22265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        int32_t numBytesWritten = m_plugin->NPP_Write(&m_npStream, m_offset, dataLength, data);
22365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (numBytesWritten < 0) {
2242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            cancel();
22565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            stop(NPRES_NETWORK_ERR);
22665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            return;
22765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        }
22865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
22965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // NPP_Write could call NPN_DestroyStream and destroy the stream.
23065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (!m_isStarted)
23165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            return;
23265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
23365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        numBytesWritten = min(numBytesWritten, dataLength);
23465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        m_offset += numBytesWritten;
23565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        numBytesDelivered += numBytesWritten;
23665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
23765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
23865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // We didn't write anything.
23965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!numBytesDelivered)
24065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
24165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
24265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (numBytesDelivered < numBytesToDeliver) {
24365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Remove the bytes that we actually delivered.
24465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        m_deliveryData->remove(0, numBytesDelivered);
24565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    } else {
24665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        m_deliveryData->clear();
24765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
24865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (m_stopStreamWhenDoneDelivering)
24965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            stop(NPRES_DONE);
25065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
25165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
25265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
25365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::deliverDataToFile(const char* bytes, int length)
25465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
25565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (m_fileHandle == invalidPlatformFileHandle && m_filePath.isNull()) {
25665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Create a temporary file.
25765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        m_filePath = openTemporaryFile("WebKitPluginStream", m_fileHandle);
25865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
25965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // We failed to open the file, stop the stream.
26065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (m_fileHandle == invalidPlatformFileHandle) {
26165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            stop(NPRES_NETWORK_ERR);
26265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            return;
26365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        }
26465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
26565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
26665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!length)
26765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
26865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
26965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    int byteCount = writeToFile(m_fileHandle, bytes, length);
27065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (byteCount != length) {
27165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // This happens only rarely, when we are out of disk space or have a disk I/O error.
27265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        closeFile(m_fileHandle);
27365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
27465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        stop(NPRES_NETWORK_ERR);
27565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
27665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
27765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
27865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::stop(NPReason reason)
27965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
28065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // The stream was stopped before it got a chance to start. This can happen if a stream is cancelled by
28165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // WebKit before it received a response.
28265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!m_isStarted)
28365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
28465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
28565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (reason == NPRES_DONE && m_deliveryData && !m_deliveryData->isEmpty()) {
28665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // There is still data left that the plug-in hasn't been able to consume yet.
28765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        ASSERT(m_deliveryDataTimer.isActive());
28865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
28965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Set m_stopStreamWhenDoneDelivering to true so that the next time the delivery timer fires
29065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // and calls deliverDataToPlugin the stream will be closed if all the remaining data was
29165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // successfully delivered.
29265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        m_stopStreamWhenDoneDelivering = true;
29365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return;
29465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
29565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
29665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_deliveryData = 0;
29765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_deliveryDataTimer.stop();
29865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
29965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY) {
30065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (reason == NPRES_DONE) {
30165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            // Ensure that the file is created.
30265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            deliverDataToFile(0, 0);
30365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            if (m_fileHandle != invalidPlatformFileHandle)
30465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                closeFile(m_fileHandle);
30565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
30665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            ASSERT(!m_filePath.isNull());
30765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
3082bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_plugin->NPP_StreamAsFile(&m_npStream, m_filePath.utf8().data());
30965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        } else {
31065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            // Just close the file.
31165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            if (m_fileHandle != invalidPlatformFileHandle)
31265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                closeFile(m_fileHandle);
31365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        }
31465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
31565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Delete the file after calling NPP_StreamAsFile(), instead of in the destructor.  It should be OK
31665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // to delete the file here -- NPP_StreamAsFile() is always called immediately before NPP_DestroyStream()
31765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // (the stream destruction function), so there can be no expectation that a plugin will read the stream
31865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // file asynchronously after NPP_StreamAsFile() is called.
3192bde8e466a4451c7319e3a072d118917957d6554Steve Block        deleteFile(m_filePath);
3202bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_filePath = String();
32165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
32265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // NPP_StreamAsFile could call NPN_DestroyStream and destroy the stream.
32365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (!m_isStarted)
32465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            return;
32565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
32665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
32765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Set m_isStarted to false before calling NPP_DestroyStream in case NPP_DestroyStream calls NPN_DestroyStream.
32865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_isStarted = false;
32965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
33065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_plugin->NPP_DestroyStream(&m_npStream, reason);
33165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
33265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    notifyAndDestroyStream(reason);
33365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
33465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
33565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::cancel()
33665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
33765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_plugin->cancelStreamLoad(this);
33865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
33965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
34065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid NetscapePluginStream::notifyAndDestroyStream(NPReason reason)
34165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{
34265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(!m_isStarted);
34365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(!m_deliveryDataTimer.isActive());
34465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ASSERT(!m_urlNotifyHasBeenCalled);
34565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
34665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (m_sendNotification) {
34765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        m_plugin->NPP_URLNotify(m_responseURL.data(), reason, m_notificationData);
34865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
34965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#if !ASSERT_DISABLED
35065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        m_urlNotifyHasBeenCalled = true;
35165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#endif
35265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
35365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
35465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_plugin->removePluginStream(this);
35565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch}
35665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
35765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch} // namespace WebKit
358