summaryrefslogtreecommitdiff
path: root/Source/WebKit2/PluginProcess/PluginControllerProxy.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-01-06 14:44:00 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-01-06 14:44:00 +0100
commit40736c5763bf61337c8c14e16d8587db021a87d4 (patch)
treeb17a9c00042ad89cb1308e2484491799aa14e9f8 /Source/WebKit2/PluginProcess/PluginControllerProxy.cpp
downloadqtwebkit-40736c5763bf61337c8c14e16d8587db021a87d4.tar.gz
Imported WebKit commit 2ea9d364d0f6efa8fa64acf19f451504c59be0e4 (http://svn.webkit.org/repository/webkit/trunk@104285)
Diffstat (limited to 'Source/WebKit2/PluginProcess/PluginControllerProxy.cpp')
-rw-r--r--Source/WebKit2/PluginProcess/PluginControllerProxy.cpp626
1 files changed, 626 insertions, 0 deletions
diff --git a/Source/WebKit2/PluginProcess/PluginControllerProxy.cpp b/Source/WebKit2/PluginProcess/PluginControllerProxy.cpp
new file mode 100644
index 000000000..b548f8126
--- /dev/null
+++ b/Source/WebKit2/PluginProcess/PluginControllerProxy.cpp
@@ -0,0 +1,626 @@
+/*
+ * 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 "PluginControllerProxy.h"
+
+#if ENABLE(PLUGIN_PROCESS)
+
+#include "DataReference.h"
+#include "NPObjectProxy.h"
+#include "NPRemoteObjectMap.h"
+#include "NPRuntimeUtilities.h"
+#include "NPVariantData.h"
+#include "NetscapePlugin.h"
+#include "PluginCreationParameters.h"
+#include "PluginProcess.h"
+#include "PluginProxyMessages.h"
+#include "ShareableBitmap.h"
+#include "WebCoreArgumentCoders.h"
+#include "WebProcessConnection.h"
+#include <WebCore/GraphicsContext.h>
+#include <WebCore/IdentifierRep.h>
+#include <WebCore/NotImplemented.h>
+#include <wtf/text/WTFString.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+PassOwnPtr<PluginControllerProxy> PluginControllerProxy::create(WebProcessConnection* connection, const PluginCreationParameters& creationParameters)
+{
+ return adoptPtr(new PluginControllerProxy(connection, creationParameters));
+}
+
+PluginControllerProxy::PluginControllerProxy(WebProcessConnection* connection, const PluginCreationParameters& creationParameters)
+ : m_connection(connection)
+ , m_pluginInstanceID(creationParameters.pluginInstanceID)
+ , m_userAgent(creationParameters.userAgent)
+ , m_isPrivateBrowsingEnabled(creationParameters.isPrivateBrowsingEnabled)
+#if USE(ACCELERATED_COMPOSITING)
+ , m_isAcceleratedCompositingEnabled(creationParameters.isAcceleratedCompositingEnabled)
+#endif
+ , m_paintTimer(RunLoop::main(), this, &PluginControllerProxy::paint)
+ , m_pluginDestructionProtectCount(0)
+ , m_pluginDestroyTimer(RunLoop::main(), this, &PluginControllerProxy::destroy)
+ , m_pluginCreationParameters(0)
+ , m_waitingForDidUpdate(false)
+ , m_pluginCanceledManualStreamLoad(false)
+#if PLATFORM(MAC)
+ , m_isComplexTextInputEnabled(false)
+#endif
+ , m_contentsScaleFactor(creationParameters.contentsScaleFactor)
+ , m_windowNPObject(0)
+ , m_pluginElementNPObject(0)
+{
+}
+
+PluginControllerProxy::~PluginControllerProxy()
+{
+ ASSERT(!m_plugin);
+
+ if (m_windowNPObject)
+ releaseNPObject(m_windowNPObject);
+
+ if (m_pluginElementNPObject)
+ releaseNPObject(m_pluginElementNPObject);
+}
+
+bool PluginControllerProxy::initialize(const PluginCreationParameters& creationParameters)
+{
+ ASSERT(!m_plugin);
+
+ m_plugin = NetscapePlugin::create(PluginProcess::shared().netscapePluginModule());
+ if (!m_plugin) {
+ // This will delete the plug-in controller proxy object.
+ m_connection->removePluginControllerProxy(this, 0);
+ return false;
+ }
+
+ m_windowNPObject = m_connection->npRemoteObjectMap()->createNPObjectProxy(creationParameters.windowNPObjectID, m_plugin.get());
+ ASSERT(m_windowNPObject);
+
+ m_pluginCreationParameters = &creationParameters;
+ bool returnValue = m_plugin->initialize(this, creationParameters.parameters);
+ m_pluginCreationParameters = 0;
+
+ if (!returnValue) {
+ // Get the plug-in so we can pass it to removePluginControllerProxy. The pointer is only
+ // used as an identifier so it's OK to just get a weak reference.
+ Plugin* plugin = m_plugin.get();
+
+ m_plugin = 0;
+
+ // This will delete the plug-in controller proxy object.
+ m_connection->removePluginControllerProxy(this, plugin);
+ return false;
+ }
+
+ platformInitialize();
+
+ return true;
+}
+
+void PluginControllerProxy::destroy()
+{
+ ASSERT(m_plugin);
+
+ if (m_pluginDestructionProtectCount) {
+ // We have plug-in code on the stack so we can't destroy it right now.
+ // Destroy it later.
+ m_pluginDestroyTimer.startOneShot(0);
+ return;
+ }
+
+ // Get the plug-in so we can pass it to removePluginControllerProxy. The pointer is only
+ // used as an identifier so it's OK to just get a weak reference.
+ Plugin* plugin = m_plugin.get();
+
+ m_plugin->destroyPlugin();
+ m_plugin = 0;
+
+ platformDestroy();
+
+ // This will delete the plug-in controller proxy object.
+ m_connection->removePluginControllerProxy(this, plugin);
+}
+
+void PluginControllerProxy::paint()
+{
+ ASSERT(!m_dirtyRect.isEmpty());
+ m_paintTimer.stop();
+
+ if (!m_backingStore)
+ return;
+
+ IntRect dirtyRect = m_dirtyRect;
+ m_dirtyRect = IntRect();
+
+ ASSERT(m_plugin);
+
+ // Create a graphics context.
+ OwnPtr<GraphicsContext> graphicsContext = m_backingStore->createGraphicsContext();
+
+#if PLATFORM(MAC)
+ // FIXME: We should really call applyDeviceScaleFactor instead of scale, but that ends up calling into WKSI
+ // which we currently don't have initiated in the plug-in process.
+ graphicsContext->scale(FloatSize(m_contentsScaleFactor, m_contentsScaleFactor));
+#endif
+
+ if (m_plugin->isTransparent())
+ graphicsContext->clearRect(dirtyRect);
+
+ m_plugin->paint(graphicsContext.get(), dirtyRect);
+
+ m_connection->connection()->send(Messages::PluginProxy::Update(dirtyRect), m_pluginInstanceID);
+}
+
+void PluginControllerProxy::startPaintTimer()
+{
+ // Check if we should start the timer.
+
+ if (m_dirtyRect.isEmpty())
+ return;
+
+ // FIXME: Check clip rect.
+
+ if (m_paintTimer.isActive())
+ return;
+
+ if (m_waitingForDidUpdate)
+ return;
+
+ // Start the timer.
+ m_paintTimer.startOneShot(0);
+
+ m_waitingForDidUpdate = true;
+}
+
+bool PluginControllerProxy::isPluginVisible()
+{
+ // FIXME: Implement this.
+ notImplemented();
+ return false;
+}
+
+void PluginControllerProxy::invalidate(const IntRect& rect)
+{
+ IntRect dirtyRect = rect;
+
+ // Make sure that the dirty rect is not greater than the plug-in itself.
+ dirtyRect.intersect(IntRect(IntPoint(), m_pluginSize));
+ m_dirtyRect.unite(dirtyRect);
+
+ startPaintTimer();
+}
+
+String PluginControllerProxy::userAgent()
+{
+ return m_userAgent;
+}
+
+void PluginControllerProxy::loadURL(uint64_t requestID, const String& method, const String& urlString, const String& target, const HTTPHeaderMap& headerFields, const Vector<uint8_t>& httpBody, bool allowPopups)
+{
+ m_connection->connection()->send(Messages::PluginProxy::LoadURL(requestID, method, urlString, target, headerFields, httpBody, allowPopups), m_pluginInstanceID);
+}
+
+void PluginControllerProxy::cancelStreamLoad(uint64_t streamID)
+{
+ m_connection->connection()->send(Messages::PluginProxy::CancelStreamLoad(streamID), m_pluginInstanceID);
+}
+
+void PluginControllerProxy::cancelManualStreamLoad()
+{
+ m_pluginCanceledManualStreamLoad = true;
+
+ m_connection->connection()->send(Messages::PluginProxy::CancelManualStreamLoad(), m_pluginInstanceID);
+}
+
+NPObject* PluginControllerProxy::windowScriptNPObject()
+{
+ retainNPObject(m_windowNPObject);
+ return m_windowNPObject;
+}
+
+NPObject* PluginControllerProxy::pluginElementNPObject()
+{
+ if (!m_pluginElementNPObject) {
+ uint64_t pluginElementNPObjectID = 0;
+
+ if (!m_connection->connection()->sendSync(Messages::PluginProxy::GetPluginElementNPObject(), Messages::PluginProxy::GetPluginElementNPObject::Reply(pluginElementNPObjectID), m_pluginInstanceID))
+ return 0;
+
+ if (!pluginElementNPObjectID)
+ return 0;
+
+ m_pluginElementNPObject = m_connection->npRemoteObjectMap()->createNPObjectProxy(pluginElementNPObjectID, m_plugin.get());
+ ASSERT(m_pluginElementNPObject);
+ }
+
+ retainNPObject(m_pluginElementNPObject);
+ return m_pluginElementNPObject;
+}
+
+bool PluginControllerProxy::evaluate(NPObject* npObject, const String& scriptString, NPVariant* result, bool allowPopups)
+{
+ if (tryToShortCircuitEvaluate(npObject, scriptString, result))
+ return true;
+
+ PluginDestructionProtector protector(this);
+
+ NPVariant npObjectAsNPVariant;
+ OBJECT_TO_NPVARIANT(npObject, npObjectAsNPVariant);
+
+ // Send the NPObject over as an NPVariantData.
+ NPVariantData npObjectAsNPVariantData = m_connection->npRemoteObjectMap()->npVariantToNPVariantData(npObjectAsNPVariant, m_plugin.get());
+
+ bool returnValue = false;
+ NPVariantData resultData;
+
+ if (!m_connection->connection()->sendSync(Messages::PluginProxy::Evaluate(npObjectAsNPVariantData, scriptString, allowPopups), Messages::PluginProxy::Evaluate::Reply(returnValue, resultData), m_pluginInstanceID))
+ return false;
+
+ if (!returnValue)
+ return false;
+
+ *result = m_connection->npRemoteObjectMap()->npVariantDataToNPVariant(resultData, m_plugin.get());
+ return true;
+}
+
+bool PluginControllerProxy::tryToShortCircuitInvoke(NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, bool& returnValue, NPVariant& result)
+{
+ // Only try to short circuit evaluate for plug-ins that have the quirk specified.
+#if PLUGIN_ARCHITECTURE(MAC)
+ if (!PluginProcess::shared().netscapePluginModule()->pluginQuirks().contains(PluginQuirks::CanShortCircuitSomeNPRuntimeCallsDuringInitialization))
+ return false;
+#else
+ return false;
+#endif
+
+ // And only when we're in initialize.
+ if (!inInitialize())
+ return false;
+
+ // And only when the NPObject is the window NPObject.
+ if (npObject != m_windowNPObject)
+ return false;
+
+ // And only when we don't have any arguments.
+ if (argumentCount)
+ return false;
+
+ IdentifierRep* methodNameRep = static_cast<IdentifierRep*>(methodName);
+ if (!methodNameRep->isString())
+ return false;
+
+ if (!strcmp(methodNameRep->string(), "__flash_getWindowLocation")) {
+ result.type = NPVariantType_String;
+ result.value.stringValue = createNPString(m_pluginCreationParameters->parameters.documentURL.utf8());
+ returnValue = true;
+ return true;
+ }
+
+ if (!strcmp(methodNameRep->string(), "__flash_getTopLocation")) {
+ if (m_pluginCreationParameters->parameters.toplevelDocumentURL.isNull()) {
+ // If the toplevel document is URL it means that the frame that the plug-in is in doesn't have access to the toplevel document.
+ // In this case, just pass the string "[object]" to Flash.
+ result.type = NPVariantType_String;
+ result.value.stringValue = createNPString("[object]");
+ returnValue = true;
+ return true;
+ }
+
+ result.type = NPVariantType_String;
+ result.value.stringValue = createNPString(m_pluginCreationParameters->parameters.toplevelDocumentURL.utf8());
+ returnValue = true;
+ return true;
+ }
+
+ return false;
+}
+
+void PluginControllerProxy::setStatusbarText(const String& statusbarText)
+{
+ m_connection->connection()->send(Messages::PluginProxy::SetStatusbarText(statusbarText), m_pluginInstanceID);
+}
+
+bool PluginControllerProxy::isAcceleratedCompositingEnabled()
+{
+ return m_isAcceleratedCompositingEnabled;
+}
+
+void PluginControllerProxy::pluginProcessCrashed()
+{
+ // This should never be called from here.
+ ASSERT_NOT_REACHED();
+}
+
+void PluginControllerProxy::willSendEventToPlugin()
+{
+ // This is only used when running plugins in the web process.
+ ASSERT_NOT_REACHED();
+}
+
+float PluginControllerProxy::contentsScaleFactor()
+{
+ return m_contentsScaleFactor;
+}
+
+String PluginControllerProxy::proxiesForURL(const String& urlString)
+{
+ String proxyString;
+
+ if (!m_connection->connection()->sendSync(Messages::PluginProxy::ProxiesForURL(urlString), Messages::PluginProxy::ProxiesForURL::Reply(proxyString), m_pluginInstanceID))
+ return String();
+
+ return proxyString;
+}
+
+String PluginControllerProxy::cookiesForURL(const String& urlString)
+{
+ String cookieString;
+
+ if (!m_connection->connection()->sendSync(Messages::PluginProxy::CookiesForURL(urlString), Messages::PluginProxy::CookiesForURL::Reply(cookieString), m_pluginInstanceID))
+ return String();
+
+ return cookieString;
+}
+
+void PluginControllerProxy::setCookiesForURL(const String& urlString, const String& cookieString)
+{
+ m_connection->connection()->send(Messages::PluginProxy::SetCookiesForURL(urlString, cookieString), m_pluginInstanceID);
+}
+
+bool PluginControllerProxy::isPrivateBrowsingEnabled()
+{
+ return m_isPrivateBrowsingEnabled;
+}
+
+bool PluginControllerProxy::getAuthenticationInfo(const ProtectionSpace& protectionSpace, String& username, String& password)
+{
+ bool returnValue;
+ if (!m_connection->connection()->sendSync(Messages::PluginProxy::GetAuthenticationInfo(protectionSpace), Messages::PluginProxy::GetAuthenticationInfo::Reply(returnValue, username, password), m_pluginInstanceID))
+ return false;
+
+ return returnValue;
+}
+
+void PluginControllerProxy::protectPluginFromDestruction()
+{
+ m_pluginDestructionProtectCount++;
+}
+
+void PluginControllerProxy::unprotectPluginFromDestruction()
+{
+ ASSERT(m_pluginDestructionProtectCount);
+
+ m_pluginDestructionProtectCount--;
+}
+
+void PluginControllerProxy::frameDidFinishLoading(uint64_t requestID)
+{
+ m_plugin->frameDidFinishLoading(requestID);
+}
+
+void PluginControllerProxy::frameDidFail(uint64_t requestID, bool wasCancelled)
+{
+ m_plugin->frameDidFail(requestID, wasCancelled);
+}
+
+void PluginControllerProxy::geometryDidChange(const IntSize& pluginSize, const IntRect& clipRect, const AffineTransform& pluginToRootViewTransform, float contentsScaleFactor, const ShareableBitmap::Handle& backingStoreHandle)
+{
+ ASSERT(m_plugin);
+
+ m_pluginSize = pluginSize;
+
+ if (contentsScaleFactor != m_contentsScaleFactor) {
+ m_contentsScaleFactor = contentsScaleFactor;
+ m_plugin->contentsScaleFactorChanged(m_contentsScaleFactor);
+ }
+
+ platformGeometryDidChange();
+
+ if (!backingStoreHandle.isNull()) {
+ // Create a new backing store.
+ m_backingStore = ShareableBitmap::create(backingStoreHandle);
+ }
+
+ m_plugin->geometryDidChange(pluginSize, clipRect, pluginToRootViewTransform);
+}
+
+void PluginControllerProxy::didEvaluateJavaScript(uint64_t requestID, const String& result)
+{
+ m_plugin->didEvaluateJavaScript(requestID, result);
+}
+
+void PluginControllerProxy::streamDidReceiveResponse(uint64_t streamID, const String& responseURLString, uint32_t streamLength, uint32_t lastModifiedTime, const String& mimeType, const String& headers)
+{
+ m_plugin->streamDidReceiveResponse(streamID, KURL(ParsedURLString, responseURLString), streamLength, lastModifiedTime, mimeType, headers, String());
+}
+
+void PluginControllerProxy::streamDidReceiveData(uint64_t streamID, const CoreIPC::DataReference& data)
+{
+ m_plugin->streamDidReceiveData(streamID, reinterpret_cast<const char*>(data.data()), data.size());
+}
+
+void PluginControllerProxy::streamDidFinishLoading(uint64_t streamID)
+{
+ m_plugin->streamDidFinishLoading(streamID);
+}
+
+void PluginControllerProxy::streamDidFail(uint64_t streamID, bool wasCancelled)
+{
+ m_plugin->streamDidFail(streamID, wasCancelled);
+}
+
+void PluginControllerProxy::manualStreamDidReceiveResponse(const String& responseURLString, uint32_t streamLength, uint32_t lastModifiedTime, const String& mimeType, const String& headers)
+{
+ if (m_pluginCanceledManualStreamLoad)
+ return;
+
+ m_plugin->manualStreamDidReceiveResponse(KURL(ParsedURLString, responseURLString), streamLength, lastModifiedTime, mimeType, headers, String());
+}
+
+void PluginControllerProxy::manualStreamDidReceiveData(const CoreIPC::DataReference& data)
+{
+ if (m_pluginCanceledManualStreamLoad)
+ return;
+
+ m_plugin->manualStreamDidReceiveData(reinterpret_cast<const char*>(data.data()), data.size());
+}
+
+void PluginControllerProxy::manualStreamDidFinishLoading()
+{
+ if (m_pluginCanceledManualStreamLoad)
+ return;
+
+ m_plugin->manualStreamDidFinishLoading();
+}
+
+void PluginControllerProxy::manualStreamDidFail(bool wasCancelled)
+{
+ if (m_pluginCanceledManualStreamLoad)
+ return;
+
+ m_plugin->manualStreamDidFail(wasCancelled);
+}
+
+void PluginControllerProxy::handleMouseEvent(const WebMouseEvent& mouseEvent, PassRefPtr<Messages::PluginControllerProxy::HandleMouseEvent::DelayedReply> reply)
+{
+ // Always let the web process think that we've handled this mouse event, even before passing it along to the plug-in.
+ // This is a workaround for
+ // <rdar://problem/9299901> UI process thinks the page is unresponsive when a plug-in is showing a context menu.
+ // The web process sends a synchronous HandleMouseEvent message and the plug-in process spawns a nested
+ // run loop when showing the context menu, so eventually the unresponsiveness timer kicks in in the UI process.
+ // FIXME: We should come up with a better way to do this.
+ reply->send(true);
+
+ m_plugin->handleMouseEvent(mouseEvent);
+}
+
+void PluginControllerProxy::handleWheelEvent(const WebWheelEvent& wheelEvent, bool& handled)
+{
+ handled = m_plugin->handleWheelEvent(wheelEvent);
+}
+
+void PluginControllerProxy::handleMouseEnterEvent(const WebMouseEvent& mouseEnterEvent, bool& handled)
+{
+ handled = m_plugin->handleMouseEnterEvent(mouseEnterEvent);
+}
+
+void PluginControllerProxy::handleMouseLeaveEvent(const WebMouseEvent& mouseLeaveEvent, bool& handled)
+{
+ handled = m_plugin->handleMouseLeaveEvent(mouseLeaveEvent);
+}
+
+void PluginControllerProxy::handleKeyboardEvent(const WebKeyboardEvent& keyboardEvent, bool& handled)
+{
+ handled = m_plugin->handleKeyboardEvent(keyboardEvent);
+}
+
+void PluginControllerProxy::paintEntirePlugin()
+{
+ if (m_pluginSize.isEmpty())
+ return;
+
+ m_dirtyRect = IntRect(IntPoint(), m_pluginSize);
+ paint();
+}
+
+void PluginControllerProxy::snapshot(ShareableBitmap::Handle& backingStoreHandle)
+{
+ ASSERT(m_plugin);
+ RefPtr<ShareableBitmap> bitmap = m_plugin->snapshot();
+ if (!bitmap)
+ return;
+
+ bitmap->createHandle(backingStoreHandle);
+}
+
+void PluginControllerProxy::setFocus(bool hasFocus)
+{
+ m_plugin->setFocus(hasFocus);
+}
+
+void PluginControllerProxy::didUpdate()
+{
+ m_waitingForDidUpdate = false;
+ startPaintTimer();
+}
+
+void PluginControllerProxy::getPluginScriptableNPObject(uint64_t& pluginScriptableNPObjectID)
+{
+ NPObject* pluginScriptableNPObject = m_plugin->pluginScriptableNPObject();
+ if (!pluginScriptableNPObject) {
+ pluginScriptableNPObjectID = 0;
+ return;
+ }
+
+ pluginScriptableNPObjectID = m_connection->npRemoteObjectMap()->registerNPObject(pluginScriptableNPObject, m_plugin.get());
+ releaseNPObject(pluginScriptableNPObject);
+}
+
+void PluginControllerProxy::privateBrowsingStateChanged(bool isPrivateBrowsingEnabled)
+{
+ m_isPrivateBrowsingEnabled = isPrivateBrowsingEnabled;
+
+ m_plugin->privateBrowsingStateChanged(isPrivateBrowsingEnabled);
+}
+
+void PluginControllerProxy::getFormValue(bool& returnValue, String& formValue)
+{
+ returnValue = m_plugin->getFormValue(formValue);
+}
+
+bool PluginControllerProxy::tryToShortCircuitEvaluate(NPObject* npObject, const String& scriptString, NPVariant* result)
+{
+ // Only try to short circuit evaluate for plug-ins that have the quirk specified.
+#if PLUGIN_ARCHITECTURE(MAC)
+ if (!PluginProcess::shared().netscapePluginModule()->pluginQuirks().contains(PluginQuirks::CanShortCircuitSomeNPRuntimeCallsDuringInitialization))
+ return false;
+#else
+ return false;
+#endif
+
+ // And only when we're in initialize.
+ if (!inInitialize())
+ return false;
+
+ // And only when the NPObject is the window NPObject.
+ if (npObject != m_windowNPObject)
+ return false;
+
+ // Now, check for the right strings.
+ if (scriptString != "function __flash_getWindowLocation() { return window.location; }"
+ && scriptString != "function __flash_getTopLocation() { return top.location; }")
+ return false;
+
+ VOID_TO_NPVARIANT(*result);
+ return true;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(PLUGIN_PROCESS)