diff -r 000000000000 -r 4f2f89ce4247 WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.cpp Fri Sep 17 09:02:29 2010 +0300 @@ -0,0 +1,416 @@ +/* + * 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 "NetscapePlugin.h" + +#include "NetscapePluginStream.h" +#include "PluginController.h" +#include +#include +#include +#include +#include +#include + +using namespace WebCore; +using namespace std; + +namespace WebKit { + +NetscapePlugin::NetscapePlugin(PassRefPtr pluginModule) + : m_pluginController(0) + , m_nextRequestID(0) + , m_pluginModule(pluginModule) + , m_npWindow() + , m_isStarted(false) + , m_inNPPNew(false) +#if PLATFORM(MAC) + , m_drawingModel(static_cast(-1)) + , m_eventModel(static_cast(-1)) +#endif +{ + m_npp.ndata = this; + m_npp.pdata = 0; + + m_pluginModule->pluginCreated(); +} + +NetscapePlugin::~NetscapePlugin() +{ + ASSERT(!m_isStarted); + + m_pluginModule->pluginDestroyed(); +} + +PassRefPtr NetscapePlugin::fromNPP(NPP npp) +{ + if (npp) { + NetscapePlugin* plugin = static_cast(npp->ndata); + ASSERT(npp == &plugin->m_npp); + + return plugin; + } + + // FIXME: Return the current NetscapePlugin here. + ASSERT_NOT_REACHED(); + return 0; +} + +void NetscapePlugin::invalidate(const NPRect* invalidRect) +{ + IntRect rect; + + if (!invalidRect) + rect = IntRect(0, 0, m_frameRect.width(), m_frameRect.height()); + else + rect = IntRect(invalidRect->left, invalidRect->top, + invalidRect->right - invalidRect->left, invalidRect->bottom - invalidRect->top); + + m_pluginController->invalidate(rect); +} + +const char* NetscapePlugin::userAgent() +{ + if (m_userAgent.isNull()) { + // FIXME: Pass the src URL. + m_userAgent = m_pluginController->userAgent(KURL()).utf8(); + ASSERT(!m_userAgent.isNull()); + } + + return m_userAgent.data(); +} + +void NetscapePlugin::loadURL(const String& method, const String& urlString, const String& target, const HTTPHeaderMap& headerFields, const Vector& httpBody, + bool sendNotification, void* notificationData) +{ + uint64_t requestID = ++m_nextRequestID; + + m_pluginController->loadURL(requestID, method, urlString, target, headerFields, httpBody, allowPopups()); + + if (target.isNull()) { + // The browser is going to send the data in a stream, create a plug-in stream. + RefPtr pluginStream = NetscapePluginStream::create(this, requestID, sendNotification, notificationData); + ASSERT(!m_streams.contains(requestID)); + + m_streams.set(requestID, pluginStream.release()); + return; + } + + if (sendNotification) { + // Eventually we are going to get a frameDidFinishLoading or frameDidFail call for this request. + // Keep track of the notification data so we can call NPP_URLNotify. + ASSERT(!m_pendingURLNotifications.contains(requestID)); + m_pendingURLNotifications.set(requestID, make_pair(urlString, notificationData)); + } +} + +NPError NetscapePlugin::destroyStream(NPStream* stream, NPReason reason) +{ + NetscapePluginStream* pluginStream = 0; + + for (StreamsMap::const_iterator it = m_streams.begin(), end = m_streams.end(); it != end; ++it) { + if (it->second->npStream() == stream) { + pluginStream = it->second.get(); + break; + } + } + + if (!pluginStream) + return NPERR_INVALID_INSTANCE_ERROR; + + return pluginStream->destroy(reason); +} + +NPObject* NetscapePlugin::windowScriptNPObject() +{ + return m_pluginController->windowScriptNPObject(); +} + +NPObject* NetscapePlugin::pluginElementNPObject() +{ + return m_pluginController->pluginElementNPObject(); +} + +void NetscapePlugin::cancelStreamLoad(NetscapePluginStream* pluginStream) +{ + // Ask the plug-in controller to cancel this stream load. + m_pluginController->cancelStreamLoad(pluginStream->streamID()); +} + +void NetscapePlugin::removePluginStream(NetscapePluginStream* pluginStream) +{ + ASSERT(m_streams.get(pluginStream->streamID()) == pluginStream); + m_streams.remove(pluginStream->streamID()); +} + +NPError NetscapePlugin::NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* savedData) +{ + return m_pluginModule->pluginFuncs().newp(pluginType, &m_npp, mode, argc, argn, argv, savedData); +} + +NPError NetscapePlugin::NPP_Destroy(NPSavedData** savedData) +{ + return m_pluginModule->pluginFuncs().destroy(&m_npp, savedData); +} + +NPError NetscapePlugin::NPP_SetWindow(NPWindow* npWindow) +{ + return m_pluginModule->pluginFuncs().setwindow(&m_npp, npWindow); +} + +NPError NetscapePlugin::NPP_NewStream(NPMIMEType mimeType, NPStream* stream, NPBool seekable, uint16_t* streamType) +{ + return m_pluginModule->pluginFuncs().newstream(&m_npp, mimeType, stream, seekable, streamType); +} + +NPError NetscapePlugin::NPP_DestroyStream(NPStream* stream, NPReason reason) +{ + return m_pluginModule->pluginFuncs().destroystream(&m_npp, stream, reason); +} + +void NetscapePlugin::NPP_StreamAsFile(NPStream* stream, const char* filename) +{ + return m_pluginModule->pluginFuncs().asfile(&m_npp, stream, filename); +} + +int32_t NetscapePlugin::NPP_WriteReady(NPStream* stream) +{ + return m_pluginModule->pluginFuncs().writeready(&m_npp, stream); +} + +int32_t NetscapePlugin::NPP_Write(NPStream* stream, int32_t offset, int32_t len, void* buffer) +{ + return m_pluginModule->pluginFuncs().write(&m_npp, stream, offset, len, buffer); +} + +void NetscapePlugin::NPP_URLNotify(const char* url, NPReason reason, void* notifyData) +{ + m_pluginModule->pluginFuncs().urlnotify(&m_npp, url, reason, notifyData); +} + +NPError NetscapePlugin::NPP_GetValue(NPPVariable variable, void *value) +{ + return m_pluginModule->pluginFuncs().getvalue(&m_npp, variable, value); +} + +void NetscapePlugin::callSetWindow() +{ + m_npWindow.x = m_frameRect.x(); + m_npWindow.y = m_frameRect.y(); + m_npWindow.width = m_frameRect.width(); + m_npWindow.height = m_frameRect.height(); + m_npWindow.clipRect.top = m_clipRect.y(); + m_npWindow.clipRect.left = m_clipRect.x(); + m_npWindow.clipRect.bottom = m_clipRect.bottom(); + m_npWindow.clipRect.right = m_clipRect.right(); + + NPP_SetWindow(&m_npWindow); +} + +bool NetscapePlugin::shouldLoadSrcURL() +{ + // Check if we should cancel the load + NPBool cancelSrcStream = false; + + if (NPP_GetValue(NPPVpluginCancelSrcStream, &cancelSrcStream) != NPERR_NO_ERROR) + return true; + + return !cancelSrcStream; +} + +NetscapePluginStream* NetscapePlugin::streamFromID(uint64_t streamID) +{ + return m_streams.get(streamID).get(); +} + +void NetscapePlugin::stopAllStreams() +{ + Vector > streams; + copyValuesToVector(m_streams, streams); + + for (size_t i = 0; i < streams.size(); ++i) + streams[i]->stop(NPRES_USER_BREAK); +} + +bool NetscapePlugin::allowPopups() const +{ + // FIXME: Handle popups. + return false; +} + +bool NetscapePlugin::initialize(PluginController* pluginController, const Parameters& parameters) +{ + ASSERT(!m_pluginController); + ASSERT(pluginController); + + m_pluginController = pluginController; + + uint16_t mode = parameters.loadManually ? NP_FULL : NP_EMBED; + + m_inNPPNew = true; + + CString mimeTypeCString = parameters.mimeType.utf8(); + + ASSERT(parameters.names.size() == parameters.values.size()); + + Vector paramNames; + Vector paramValues; + for (size_t i = 0; i < parameters.names.size(); ++i) { + paramNames.append(parameters.names[i].utf8()); + paramValues.append(parameters.values[i].utf8()); + } + + // The strings that these pointers point to are kept alive by paramNames and paramValues. + Vector names; + Vector values; + for (size_t i = 0; i < paramNames.size(); ++i) { + names.append(paramNames[i].data()); + values.append(paramValues[i].data()); + } + + NPError error = NPP_New(const_cast(mimeTypeCString.data()), mode, names.size(), + const_cast(names.data()), const_cast(values.data()), 0); + m_inNPPNew = false; + + if (error != NPERR_NO_ERROR) + return false; + + m_isStarted = true; + + // FIXME: This is not correct in all cases. + m_npWindow.type = NPWindowTypeDrawable; + + if (!platformPostInitialize()) { + destroy(); + return false; + } + + // Load the src URL if needed. + if (!parameters.url.isEmpty() && shouldLoadSrcURL()) + loadURL("GET", parameters.url.string(), String(), HTTPHeaderMap(), Vector(), false, 0); + + return true; +} + +void NetscapePlugin::destroy() +{ + ASSERT(m_isStarted); + + // Stop all streams. + stopAllStreams(); + + NPP_Destroy(0); + + m_isStarted = false; + m_pluginController = 0; +} + +void NetscapePlugin::paint(GraphicsContext* context, const IntRect& dirtyRect) +{ + ASSERT(m_isStarted); + + platformPaint(context, dirtyRect); +} + +void NetscapePlugin::geometryDidChange(const IntRect& frameRect, const IntRect& clipRect) +{ + ASSERT(m_isStarted); + + if (m_frameRect == frameRect && m_clipRect == clipRect) { + // Nothing to do. + return; + } + + m_frameRect = frameRect; + m_clipRect = clipRect; + + callSetWindow(); +} + +void NetscapePlugin::frameDidFinishLoading(uint64_t requestID) +{ + PendingURLNotifyMap::iterator it = m_pendingURLNotifications.find(requestID); + if (it == m_pendingURLNotifications.end()) + return; + + String url = it->second.first; + void* notificationData = it->second.second; + + m_pendingURLNotifications.remove(it); + + NPP_URLNotify(url.utf8().data(), NPRES_DONE, notificationData); +} + +void NetscapePlugin::frameDidFail(uint64_t requestID, bool wasCancelled) +{ + PendingURLNotifyMap::iterator it = m_pendingURLNotifications.find(requestID); + if (it == m_pendingURLNotifications.end()) + return; + + String url = it->second.first; + void* notificationData = it->second.second; + + m_pendingURLNotifications.remove(it); + + NPP_URLNotify(url.utf8().data(), wasCancelled ? NPRES_USER_BREAK : NPRES_NETWORK_ERR, notificationData); +} + +void NetscapePlugin::didEvaluateJavaScript(uint64_t requestID, const String& requestURLString, const String& result) +{ + if (NetscapePluginStream* pluginStream = streamFromID(requestID)) + pluginStream->sendJavaScriptStream(requestURLString, result); +} + +void NetscapePlugin::streamDidReceiveResponse(uint64_t streamID, const KURL& responseURL, uint32_t streamLength, + uint32_t lastModifiedTime, const String& mimeType, const String& headers) +{ + if (NetscapePluginStream* pluginStream = streamFromID(streamID)) + pluginStream->didReceiveResponse(responseURL, streamLength, lastModifiedTime, mimeType, headers); +} + +void NetscapePlugin::streamDidReceiveData(uint64_t streamID, const char* bytes, int length) +{ + if (NetscapePluginStream* pluginStream = streamFromID(streamID)) + pluginStream->didReceiveData(bytes, length); +} + +void NetscapePlugin::streamDidFinishLoading(uint64_t streamID) +{ + if (NetscapePluginStream* pluginStream = streamFromID(streamID)) + pluginStream->didFinishLoading(); +} + +void NetscapePlugin::streamDidFail(uint64_t streamID, bool wasCancelled) +{ + if (NetscapePluginStream* pluginStream = streamFromID(streamID)) + pluginStream->didFail(wasCancelled); +} + +PluginController* NetscapePlugin::controller() +{ + return m_pluginController; +} + +} // namespace WebKit