Title: [97019] branches/chromium/874/Source/WebCore

Diff

Modified: branches/chromium/874/Source/WebCore/WebCore.gypi (97018 => 97019)


--- branches/chromium/874/Source/WebCore/WebCore.gypi	2011-10-09 01:20:00 UTC (rev 97018)
+++ branches/chromium/874/Source/WebCore/WebCore.gypi	2011-10-09 04:19:01 UTC (rev 97019)
@@ -2006,6 +2006,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',

Copied: branches/chromium/874/Source/WebCore/bindings/v8/NPObjectWrapper.cpp (from rev 96991, trunk/Source/WebCore/bindings/v8/NPObjectWrapper.cpp) (0 => 97019)


--- branches/chromium/874/Source/WebCore/bindings/v8/NPObjectWrapper.cpp	                        (rev 0)
+++ branches/chromium/874/Source/WebCore/bindings/v8/NPObjectWrapper.cpp	2011-10-09 04:19:01 UTC (rev 97019)
@@ -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

Copied: branches/chromium/874/Source/WebCore/bindings/v8/NPObjectWrapper.h (from rev 96991, trunk/Source/WebCore/bindings/v8/NPObjectWrapper.h) (0 => 97019)


--- branches/chromium/874/Source/WebCore/bindings/v8/NPObjectWrapper.h	                        (rev 0)
+++ branches/chromium/874/Source/WebCore/bindings/v8/NPObjectWrapper.h	2011-10-09 04:19:01 UTC (rev 97019)
@@ -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: branches/chromium/874/Source/WebCore/bindings/v8/NPV8Object.cpp (97018 => 97019)


--- branches/chromium/874/Source/WebCore/bindings/v8/NPV8Object.cpp	2011-10-09 01:20:00 UTC (rev 97018)
+++ branches/chromium/874/Source/WebCore/bindings/v8/NPV8Object.cpp	2011-10-09 04:19:01 UTC (rev 97019)
@@ -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: branches/chromium/874/Source/WebCore/bindings/v8/ScriptController.cpp (97018 => 97019)


--- branches/chromium/874/Source/WebCore/bindings/v8/ScriptController.cpp	2011-10-09 01:20:00 UTC (rev 97018)
+++ branches/chromium/874/Source/WebCore/bindings/v8/ScriptController.cpp	2011-10-09 04:19:01 UTC (rev 97019)
@@ -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: branches/chromium/874/Source/WebCore/bindings/v8/ScriptController.h (97018 => 97019)


--- branches/chromium/874/Source/WebCore/bindings/v8/ScriptController.h	2011-10-09 01:20:00 UTC (rev 97018)
+++ branches/chromium/874/Source/WebCore/bindings/v8/ScriptController.h	2011-10-09 04:19:01 UTC (rev 97019)
@@ -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
 };
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to