Diff
Modified: trunk/Source/WebCore/ChangeLog (96990 => 96991)
--- trunk/Source/WebCore/ChangeLog 2011-10-07 23:38:39 UTC (rev 96990)
+++ trunk/Source/WebCore/ChangeLog 2011-10-07 23:58:42 UTC (rev 96991)
@@ -1,3 +1,46 @@
+2011-10-07 Anantanarayanan G Iyengar <[email protected]>
+
+ https://bugs.webkit.org/show_bug.cgi?id=69471
+
+ We now wrap the window script NPObject which is requested by NPAPI plugins for
+ scripting. The wrapped NPObject pointer maintains a weak reference to the
+ window script NPObject and is cleared out when the window script object is destroyed.
+ The NPObject wrapper is destroyed when the last outstanding reference is released.
+
+ Reviewed by Nate Chapin.
+
+ No tests added as there is no change in functionality.
+
+ * WebCore.gypi:
+ * bindings/v8/NPObjectWrapper.cpp: Added.
+ (WebCore::NPObjectWrapper::NPObjectWrapper):
+ (WebCore::NPObjectWrapper::create):
+ (WebCore::NPObjectWrapper::clear):
+ (WebCore::NPObjectWrapper::getWrapper):
+ (WebCore::NPObjectWrapper::getUnderlyingNPObject):
+ (WebCore::NPObjectWrapper::getObjectForCall):
+ (WebCore::NPObjectWrapper::NPAllocate):
+ (WebCore::NPObjectWrapper::NPDeallocate):
+ (WebCore::NPObjectWrapper::NPPInvalidate):
+ (WebCore::NPObjectWrapper::NPHasMethod):
+ (WebCore::NPObjectWrapper::NPInvoke):
+ (WebCore::NPObjectWrapper::NPInvokeDefault):
+ (WebCore::NPObjectWrapper::NPHasProperty):
+ (WebCore::NPObjectWrapper::NPGetProperty):
+ (WebCore::NPObjectWrapper::NPSetProperty):
+ (WebCore::NPObjectWrapper::NPRemoveProperty):
+ (WebCore::NPObjectWrapper::NPNEnumerate):
+ (WebCore::NPObjectWrapper::NPNConstruct):
+ (WebCore::NPObjectWrapper::NPInvokePrivate):
+ * bindings/v8/NPObjectWrapper.h: Added.
+ * bindings/v8/NPV8Object.cpp:
+ (_NPN_EvaluateHelper):
+ * bindings/v8/ScriptController.cpp:
+ (WebCore::ScriptController::ScriptController):
+ (WebCore::ScriptController::clearScriptObjects):
+ (WebCore::ScriptController::windowScriptNPObject):
+ * bindings/v8/ScriptController.h:
+
2011-10-07 Antoine Labour <[email protected]>
Webkit API for compositor
Modified: trunk/Source/WebCore/WebCore.gypi (96990 => 96991)
--- trunk/Source/WebCore/WebCore.gypi 2011-10-07 23:38:39 UTC (rev 96990)
+++ trunk/Source/WebCore/WebCore.gypi 2011-10-07 23:58:42 UTC (rev 96991)
@@ -2016,6 +2016,8 @@
'bindings/v8/IsolatedWorld.h',
'bindings/v8/_javascript_CallFrame.cpp',
'bindings/v8/_javascript_CallFrame.h',
+ 'bindings/v8/NPObjectWrapper.cpp',
+ 'bindings/v8/NPObjectWrapper.h',
'bindings/v8/NPV8Object.cpp',
'bindings/v8/NPV8Object.h',
'bindings/v8/OptionsObject.cpp',
Added: trunk/Source/WebCore/bindings/v8/NPObjectWrapper.cpp (0 => 96991)
--- trunk/Source/WebCore/bindings/v8/NPObjectWrapper.cpp (rev 0)
+++ trunk/Source/WebCore/bindings/v8/NPObjectWrapper.cpp 2011-10-07 23:58:42 UTC (rev 96991)
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "config.h"
+#include "NPObjectWrapper.h"
+
+namespace WebCore {
+
+struct NPProxyObject {
+ NPObject object;
+ NPObjectWrapper* wrapper;
+};
+
+NPClass NPObjectWrapper::m_npClassWrapper = {
+ NP_CLASS_STRUCT_VERSION,
+ NPObjectWrapper::NPAllocate,
+ NPObjectWrapper::NPDeallocate,
+ NPObjectWrapper::NPPInvalidate,
+ NPObjectWrapper::NPHasMethod,
+ NPObjectWrapper::NPInvoke,
+ NPObjectWrapper::NPInvokeDefault,
+ NPObjectWrapper::NPHasProperty,
+ NPObjectWrapper::NPGetProperty,
+ NPObjectWrapper::NPSetProperty,
+ NPObjectWrapper::NPRemoveProperty,
+ NPObjectWrapper::NPNEnumerate,
+ NPObjectWrapper::NPNConstruct
+};
+
+NPObjectWrapper::NPObjectWrapper(NPObject* obj)
+ : m_wrappedNPObject(obj) {
+}
+
+NPObject* NPObjectWrapper::create(NPObject* object) {
+ ASSERT(object);
+ NPProxyObject* proxyObject = reinterpret_cast<NPProxyObject*>(_NPN_CreateObject(0, &m_npClassWrapper));
+ proxyObject->wrapper = new NPObjectWrapper(object);
+ return reinterpret_cast<NPObject*>(proxyObject);
+}
+
+void NPObjectWrapper::clear() {
+ m_wrappedNPObject = 0;
+}
+
+NPObjectWrapper* NPObjectWrapper::getWrapper(NPObject* obj) {
+ if (&m_npClassWrapper == obj->_class) {
+ NPProxyObject* proxyObject = reinterpret_cast<NPProxyObject*>(obj);
+ return proxyObject->wrapper;
+ }
+ return 0;
+}
+
+NPObject* NPObjectWrapper::getUnderlyingNPObject(NPObject* obj) {
+ NPObjectWrapper* wrapper = getWrapper(obj);
+ return wrapper ? wrapper->m_wrappedNPObject : 0;
+}
+
+NPObject* NPObjectWrapper::getObjectForCall(NPObject* obj) {
+ NPObject* actualObject = getUnderlyingNPObject(obj);
+ return actualObject ? actualObject : obj;
+}
+
+NPObject* NPObjectWrapper::NPAllocate(NPP, NPClass*) {
+ return reinterpret_cast<NPObject*>(new NPObjectWrapper(0));
+}
+
+void NPObjectWrapper::NPDeallocate(NPObject* obj) {
+ NPProxyObject* proxyObject = reinterpret_cast<NPProxyObject*>(obj);
+ delete proxyObject->wrapper;
+ delete proxyObject;
+}
+
+void NPObjectWrapper::NPPInvalidate(NPObject* obj) {
+ NPObject* actualObject = getObjectForCall(obj);
+ if (actualObject && actualObject->_class->invalidate)
+ actualObject->_class->invalidate(actualObject);
+}
+
+bool NPObjectWrapper::NPHasMethod(NPObject* obj, NPIdentifier name) {
+ NPObject* actualObject = getObjectForCall(obj);
+ return actualObject ? _NPN_HasMethod(0, actualObject, name) : false;
+}
+
+bool NPObjectWrapper::NPInvoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result) {
+ NPObject* actualObject = getObjectForCall(obj);
+ return actualObject ? _NPN_Invoke(0, actualObject, name, args, argCount, result) : false;
+}
+
+bool NPObjectWrapper::NPInvokeDefault(NPObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) {
+ NPObject* actualObject = getObjectForCall(obj);
+ return actualObject ? _NPN_InvokeDefault(0, actualObject, args, argCount, result) : false;
+}
+
+bool NPObjectWrapper::NPHasProperty(NPObject* obj, NPIdentifier name) {
+ NPObject* actualObject = getObjectForCall(obj);
+ return actualObject ? _NPN_HasProperty(0, actualObject, name) : false;
+}
+
+bool NPObjectWrapper::NPGetProperty(NPObject* obj, NPIdentifier name, NPVariant* result) {
+ NPObject* actualObject = getObjectForCall(obj);
+ return actualObject ? _NPN_GetProperty(0, actualObject, name, result) : false;
+}
+
+bool NPObjectWrapper::NPSetProperty(NPObject* obj, NPIdentifier name, const NPVariant* value) {
+ NPObject* actualObject = getObjectForCall(obj);
+ return actualObject ? _NPN_SetProperty(0, actualObject, name, value) : false;
+}
+
+bool NPObjectWrapper::NPRemoveProperty(NPObject* obj, NPIdentifier name) {
+ NPObject* actualObject = getObjectForCall(obj);
+ return actualObject ? _NPN_RemoveProperty(0, actualObject, name) : false;
+}
+
+bool NPObjectWrapper::NPNEnumerate(NPObject* obj, NPIdentifier** value, uint32_t* count) {
+ NPObject* actualObject = getObjectForCall(obj);
+ return actualObject ? _NPN_Enumerate(0, actualObject, value, count) : false;
+}
+
+bool NPObjectWrapper::NPNConstruct(NPObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) {
+ NPObject* actualObject = getObjectForCall(obj);
+ return actualObject ? _NPN_Construct(0, actualObject, args, argCount, result) : false;
+}
+
+bool NPObjectWrapper::NPInvokePrivate(NPP npp, NPObject* obj, bool isDefault, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result) {
+ NPObject* actualObject = getObjectForCall(obj);
+ if (!actualObject)
+ return false;
+
+ if (isDefault) {
+ return _NPN_InvokeDefault(0, actualObject, args, argCount, result);
+ } else {
+ return _NPN_Invoke(0, actualObject, name, args, argCount, result);
+ }
+}
+
+} // namespace WebCore
Added: trunk/Source/WebCore/bindings/v8/NPObjectWrapper.h (0 => 96991)
--- trunk/Source/WebCore/bindings/v8/NPObjectWrapper.h (rev 0)
+++ trunk/Source/WebCore/bindings/v8/NPObjectWrapper.h 2011-10-07 23:58:42 UTC (rev 96991)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+#ifndef NPObjectWrapper_h
+#define NPObjectWrapper_h
+
+#include "npruntime_impl.h"
+
+namespace WebCore {
+
+// This class wraps a NPObject and provides functionality for the wrapped
+// object to be cleared out when this object is destroyed. This is to ensure
+// that callers trying to access the underlying object don't crash while
+// invoking methods on the NPObject.
+class NPObjectWrapper : public NPObject {
+public:
+ // Creates an instance of the NPObjectWrapper class and wraps the object
+ // passed in.
+ static NPObject* create(NPObject* object);
+
+ // This method should be called to invalidate the underlying NPObject pointer.
+ void clear();
+
+ // Returns a pointer to NPObjectWrapper if the object passed in was wrapped by us.
+ static NPObjectWrapper* getWrapper(NPObject* obj);
+
+ // Returns a pointer to the underlying raw NPObject pointer or 0 if the object
+ // passed in was not wrapped.
+ static NPObject* getUnderlyingNPObject(NPObject* obj);
+
+ // NPObject functions implemented by the wrapper.
+ static NPObject* NPAllocate(NPP, NPClass*);
+ static void NPDeallocate(NPObject* obj);
+ static void NPPInvalidate(NPObject *obj);
+ static bool NPHasMethod(NPObject* obj, NPIdentifier name);
+ static bool NPInvoke(NPObject* obj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool NPInvokeDefault(NPObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool NPHasProperty(NPObject* obj, NPIdentifier name);
+ static bool NPGetProperty(NPObject* obj, NPIdentifier name, NPVariant* result);
+ static bool NPSetProperty(NPObject* obj, NPIdentifier name, const NPVariant *value);
+ static bool NPRemoveProperty(NPObject* obj, NPIdentifier name);
+ static bool NPNEnumerate(NPObject* obj, NPIdentifier **value, uint32_t* count);
+ static bool NPNConstruct(NPObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool NPInvokePrivate(NPP npp, NPObject* obj,bool isDefault, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result);
+
+private:
+ NPObjectWrapper(NPObject* obj);
+
+ // Returns the underlying NPObject if the object passed in was wrapped. Otherwise
+ // just returns the object passed in.
+ static NPObject* getObjectForCall(NPObject* obj);
+
+ static NPClass m_npClassWrapper;
+ // Weak NPObject poointer.
+ NPObject* m_wrappedNPObject;
+};
+
+} // namespace WebCore
+
+#endif // NPObjectWrapper_h
+
Modified: trunk/Source/WebCore/bindings/v8/NPV8Object.cpp (96990 => 96991)
--- trunk/Source/WebCore/bindings/v8/NPV8Object.cpp 2011-10-07 23:38:39 UTC (rev 96990)
+++ trunk/Source/WebCore/bindings/v8/NPV8Object.cpp 2011-10-07 23:58:42 UTC (rev 96991)
@@ -31,6 +31,7 @@
#include "PlatformSupport.h"
#include "DOMWindow.h"
#include "Frame.h"
+#include "NPObjectWrapper.h"
#include "OwnArrayPtr.h"
#include "PlatformString.h"
#include "ScriptSourceCode.h"
@@ -283,8 +284,13 @@
if (!npObject)
return false;
- if (npObject->_class != npScriptObjectClass)
- return false;
+ if (npObject->_class != npScriptObjectClass) {
+ // Check if the object passed in is wrapped. If yes, then we need to invoke on the underlying object.
+ NPObject* actualObject = NPObjectWrapper::getUnderlyingNPObject(npObject);
+ if (!actualObject)
+ return false;
+ npObject = actualObject;
+ }
v8::HandleScope handleScope;
v8::Handle<v8::Context> context = toV8Context(npp, npObject);
Modified: trunk/Source/WebCore/bindings/v8/ScriptController.cpp (96990 => 96991)
--- trunk/Source/WebCore/bindings/v8/ScriptController.cpp 2011-10-07 23:38:39 UTC (rev 96990)
+++ trunk/Source/WebCore/bindings/v8/ScriptController.cpp 2011-10-07 23:58:42 UTC (rev 96991)
@@ -45,6 +45,7 @@
#include "FrameLoaderClient.h"
#include "Node.h"
#include "NotImplemented.h"
+#include "NPObjectWrapper.h"
#include "npruntime_impl.h"
#include "npruntime_priv.h"
#include "NPV8Object.h"
@@ -113,7 +114,7 @@
, m_paused(false)
, m_proxy(adoptPtr(new V8Proxy(frame)))
#if ENABLE(NETSCAPE_PLUGIN_API)
- , m_windowScriptNPObject(0)
+ , m_wrappedWindowScriptNPObject(0)
#endif
{
}
@@ -132,12 +133,21 @@
m_pluginObjects.clear();
#if ENABLE(NETSCAPE_PLUGIN_API)
- if (m_windowScriptNPObject) {
+ if (m_wrappedWindowScriptNPObject) {
+ NPObjectWrapper* windowScriptObjectWrapper = NPObjectWrapper::getWrapper(m_wrappedWindowScriptNPObject);
+ ASSERT(windowScriptObjectWrapper);
+
+ NPObject* windowScriptNPObject = NPObjectWrapper::getUnderlyingNPObject(m_wrappedWindowScriptNPObject);
+ ASSERT(windowScriptNPObject);
// Call _NPN_DeallocateObject() instead of _NPN_ReleaseObject() so that we don't leak if a plugin fails to release the window
// script object properly.
// This shouldn't cause any problems for plugins since they should have already been stopped and destroyed at this point.
- _NPN_DeallocateObject(m_windowScriptNPObject);
- m_windowScriptNPObject = 0;
+ _NPN_DeallocateObject(windowScriptNPObject);
+
+ // Clear out the wrapped window script object pointer held by the wrapper.
+ windowScriptObjectWrapper->clear();
+ _NPN_ReleaseObject(m_wrappedWindowScriptNPObject);
+ m_wrappedWindowScriptNPObject = 0;
}
#endif
}
@@ -359,21 +369,24 @@
NPObject* ScriptController::windowScriptNPObject()
{
- if (m_windowScriptNPObject)
- return m_windowScriptNPObject;
+ if (m_wrappedWindowScriptNPObject)
+ return m_wrappedWindowScriptNPObject;
+ NPObject* windowScriptNPObject = 0;
if (canExecuteScripts(NotAboutToExecuteScript)) {
// _javascript_ is enabled, so there is a _javascript_ window object.
// Return an NPObject bound to the window object.
- m_windowScriptNPObject = createScriptObject(m_frame);
- _NPN_RegisterObject(m_windowScriptNPObject, 0);
+ windowScriptNPObject = createScriptObject(m_frame);
+ _NPN_RegisterObject(windowScriptNPObject, 0);
} else {
// _javascript_ is not enabled, so we cannot bind the NPObject to the
// _javascript_ window object. Instead, we create an NPObject of a
// different class, one which is not bound to a _javascript_ object.
- m_windowScriptNPObject = createNoScriptObject();
+ windowScriptNPObject = createNoScriptObject();
}
- return m_windowScriptNPObject;
+
+ m_wrappedWindowScriptNPObject = NPObjectWrapper::create(windowScriptNPObject);
+ return m_wrappedWindowScriptNPObject;
}
NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin)
Modified: trunk/Source/WebCore/bindings/v8/ScriptController.h (96990 => 96991)
--- trunk/Source/WebCore/bindings/v8/ScriptController.h 2011-10-07 23:38:39 UTC (rev 96990)
+++ trunk/Source/WebCore/bindings/v8/ScriptController.h 2011-10-07 23:58:42 UTC (rev 96991)
@@ -208,7 +208,14 @@
// The frame keeps a NPObject reference for each item on the list.
PluginObjectMap m_pluginObjects;
#if ENABLE(NETSCAPE_PLUGIN_API)
- NPObject* m_windowScriptNPObject;
+ // The window script object can get destroyed while there are outstanding
+ // references to it. Please refer to ScriptController::clearScriptObjects
+ // for more information as to why this is necessary. To avoid crashes due
+ // to calls on the destroyed window object, we return a proxy NPObject
+ // which wraps the underlying window object. The wrapped window object
+ // pointer in this object is cleared out when the window object is
+ // destroyed.
+ NPObject* m_wrappedWindowScriptNPObject;
#endif
};