[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc
andersca at apple.com
andersca at apple.com
Wed Dec 22 11:39:02 UTC 2010
The following commit has been merged in the debian/experimental branch:
commit acc1eeb1f0f926e851a0d5b131417c51cf94eccb
Author: andersca at apple.com <andersca at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Mon Aug 2 20:02:43 2010 +0000
Protect the plug-in from being destroyed while in plug-in code
https://bugs.webkit.org/show_bug.cgi?id=43370
Reviewed by Sam Weinig.
Add a PluginProtector to NPRuntimeObjectMap and use it in JSNPObject.
* WebProcess/Plugins/JSNPObject.cpp:
(WebKit::JSNPObject::callMethod):
(WebKit::JSNPObject::callObject):
(WebKit::JSNPObject::callConstructor):
(WebKit::JSNPObject::put):
(WebKit::JSNPObject::getOwnPropertyNames):
(WebKit::JSNPObject::propertyGetter):
Add PluginProtector declarations.
* WebProcess/Plugins/NPRuntimeObjectMap.cpp:
(WebKit::NPRuntimeObjectMap::PluginProtector::PluginProtector):
Ref the plug-in view (unless it's being destroyed).
(WebKit::NPRuntimeObjectMap::PluginProtector::~PluginProtector):
* WebProcess/Plugins/NPRuntimeObjectMap.h:
* WebProcess/Plugins/PluginView.cpp:
(WebKit::PluginView::PluginView):
Initialize m_isBeingDestroyed.
(WebKit::PluginView::~PluginView):
Set m_isBeingDestroyed to true.
(WebKit::PluginView::scriptObject):
Don't crash if the plug-in failed to initialize.
(WebKit::PluginView::evaluate):
Remove comment.
* WebProcess/Plugins/PluginView.h:
(WebKit::PluginView::isBeingDestroyed):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@64487 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebKit2/ChangeLog b/WebKit2/ChangeLog
index 35a3392..81836cc 100644
--- a/WebKit2/ChangeLog
+++ b/WebKit2/ChangeLog
@@ -62,6 +62,47 @@
Reviewed by Sam Weinig.
+ Protect the plug-in from being destroyed while in plug-in code
+ https://bugs.webkit.org/show_bug.cgi?id=43370
+
+ Add a PluginProtector to NPRuntimeObjectMap and use it in JSNPObject.
+
+ * WebProcess/Plugins/JSNPObject.cpp:
+ (WebKit::JSNPObject::callMethod):
+ (WebKit::JSNPObject::callObject):
+ (WebKit::JSNPObject::callConstructor):
+ (WebKit::JSNPObject::put):
+ (WebKit::JSNPObject::getOwnPropertyNames):
+ (WebKit::JSNPObject::propertyGetter):
+ Add PluginProtector declarations.
+
+ * WebProcess/Plugins/NPRuntimeObjectMap.cpp:
+ (WebKit::NPRuntimeObjectMap::PluginProtector::PluginProtector):
+ Ref the plug-in view (unless it's being destroyed).
+
+ (WebKit::NPRuntimeObjectMap::PluginProtector::~PluginProtector):
+ * WebProcess/Plugins/NPRuntimeObjectMap.h:
+
+ * WebProcess/Plugins/PluginView.cpp:
+ (WebKit::PluginView::PluginView):
+ Initialize m_isBeingDestroyed.
+
+ (WebKit::PluginView::~PluginView):
+ Set m_isBeingDestroyed to true.
+
+ (WebKit::PluginView::scriptObject):
+ Don't crash if the plug-in failed to initialize.
+
+ (WebKit::PluginView::evaluate):
+ Remove comment.
+
+ * WebProcess/Plugins/PluginView.h:
+ (WebKit::PluginView::isBeingDestroyed):
+
+2010-08-02 Anders Carlsson <andersca at apple.com>
+
+ Reviewed by Sam Weinig.
+
Cache JSNPObjects and fix bugs in the object map
https://bugs.webkit.org/show_bug.cgi?id=43368
diff --git a/WebKit2/WebProcess/Plugins/JSNPObject.cpp b/WebKit2/WebProcess/Plugins/JSNPObject.cpp
index e13e920..bd89b2e 100644
--- a/WebKit2/WebProcess/Plugins/JSNPObject.cpp
+++ b/WebKit2/WebProcess/Plugins/JSNPObject.cpp
@@ -88,6 +88,11 @@ JSValue JSNPObject::callMethod(ExecState* exec, NPIdentifier methodName)
for (size_t i = 0; i < argumentCount; ++i)
m_objectMap->convertJSValueToNPVariant(exec, exec->argument(i), arguments[i]);
+ // Calling NPClass::invoke will call into plug-in code, and there's no telling what the plug-in can do.
+ // (including destroying the plug-in). Because of this, we make sure to keep the plug-in alive until
+ // the call has finished.
+ NPRuntimeObjectMap::PluginProtector protector(m_objectMap);
+
bool returnValue;
NPVariant result;
VOID_TO_NPVARIANT(result);
@@ -95,9 +100,7 @@ JSValue JSNPObject::callMethod(ExecState* exec, NPIdentifier methodName)
{
JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
returnValue = m_npObject->_class->invoke(m_npObject, methodName, arguments.data(), argumentCount, &result);
-
- // FIXME: Handle invoke setting an exception.
- // FIXME: Find out what happens if calling invoke causes the plug-in to go away.
+ NPRuntimeObjectMap::moveGlobalExceptionToExecState(exec);
}
// Release all arguments;
@@ -123,6 +126,11 @@ JSC::JSValue JSNPObject::callObject(JSC::ExecState* exec)
// Convert all arguments to NPVariants.
for (size_t i = 0; i < argumentCount; ++i)
m_objectMap->convertJSValueToNPVariant(exec, exec->argument(i), arguments[i]);
+
+ // Calling NPClass::invokeDefault will call into plug-in code, and there's no telling what the plug-in can do.
+ // (including destroying the plug-in). Because of this, we make sure to keep the plug-in alive until
+ // the call has finished.
+ NPRuntimeObjectMap::PluginProtector protector(m_objectMap);
bool returnValue;
NPVariant result;
@@ -131,9 +139,7 @@ JSC::JSValue JSNPObject::callObject(JSC::ExecState* exec)
{
JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
returnValue = m_npObject->_class->invokeDefault(m_npObject, arguments.data(), argumentCount, &result);
-
- // FIXME: Handle invokeDefault setting an exception.
- // FIXME: Find out what happens if calling invokeDefault causes the plug-in to go away.
+ NPRuntimeObjectMap::moveGlobalExceptionToExecState(exec);
}
// Release all arguments;
@@ -160,6 +166,11 @@ JSValue JSNPObject::callConstructor(ExecState* exec)
for (size_t i = 0; i < argumentCount; ++i)
m_objectMap->convertJSValueToNPVariant(exec, exec->argument(i), arguments[i]);
+ // Calling NPClass::construct will call into plug-in code, and there's no telling what the plug-in can do.
+ // (including destroying the plug-in). Because of this, we make sure to keep the plug-in alive until
+ // the call has finished.
+ NPRuntimeObjectMap::PluginProtector protector(m_objectMap);
+
bool returnValue;
NPVariant result;
VOID_TO_NPVARIANT(result);
@@ -168,8 +179,6 @@ JSValue JSNPObject::callConstructor(ExecState* exec)
JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
returnValue = m_npObject->_class->construct(m_npObject, arguments.data(), argumentCount, &result);
NPRuntimeObjectMap::moveGlobalExceptionToExecState(exec);
-
- // FIXME: Find out what happens if calling construct causes the plug-in to go away.
}
if (!returnValue)
@@ -285,13 +294,18 @@ void JSNPObject::put(ExecState* exec, const Identifier& propertyName, JSValue va
NPVariant variant;
m_objectMap->convertJSValueToNPVariant(exec, value, variant);
+
+ // Calling NPClass::setProperty will call into plug-in code, and there's no telling what the plug-in can do.
+ // (including destroying the plug-in). Because of this, we make sure to keep the plug-in alive until
+ // the call has finished.
+ NPRuntimeObjectMap::PluginProtector protector(m_objectMap);
+
{
JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
m_npObject->_class->setProperty(m_npObject, npIdentifier, &variant);
NPRuntimeObjectMap::moveGlobalExceptionToExecState(exec);
- // FIXME: Find out what happens if calling setProperty causes the plug-in to go away.
// FIXME: Should we throw an exception if setProperty returns false?
}
@@ -311,10 +325,14 @@ void JSNPObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propert
NPIdentifier* identifiers = 0;
uint32_t identifierCount = 0;
+ // Calling NPClass::enumerate will call into plug-in code, and there's no telling what the plug-in can do.
+ // (including destroying the plug-in). Because of this, we make sure to keep the plug-in alive until
+ // the call has finished.
+ NPRuntimeObjectMap::PluginProtector protector(m_objectMap);
+
{
JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
- // FIXME: Find out what happens if calling enumerate causes the plug-in to go away.
// FIXME: Should we throw an exception if enumerate returns false?
if (!m_npObject->_class->enumerate(m_npObject, &identifiers, &identifierCount))
return;
@@ -354,6 +372,11 @@ JSValue JSNPObject::propertyGetter(ExecState* exec, JSValue slotBase, const Iden
NPVariant result;
VOID_TO_NPVARIANT(result);
+ // Calling NPClass::getProperty will call into plug-in code, and there's no telling what the plug-in can do.
+ // (including destroying the plug-in). Because of this, we make sure to keep the plug-in alive until
+ // the call has finished.
+ NPRuntimeObjectMap::PluginProtector protector(thisObj->m_objectMap);
+
bool returnValue;
{
JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
@@ -361,8 +384,6 @@ JSValue JSNPObject::propertyGetter(ExecState* exec, JSValue slotBase, const Iden
returnValue = thisObj->m_npObject->_class->getProperty(thisObj->m_npObject, npIdentifier, &result);
NPRuntimeObjectMap::moveGlobalExceptionToExecState(exec);
-
- // FIXME: Find out what happens if calling getProperty causes the plug-in to go away.
}
if (!returnValue)
diff --git a/WebKit2/WebProcess/Plugins/NPRuntimeObjectMap.cpp b/WebKit2/WebProcess/Plugins/NPRuntimeObjectMap.cpp
index bc61b44..bc09333 100644
--- a/WebKit2/WebProcess/Plugins/NPRuntimeObjectMap.cpp
+++ b/WebKit2/WebProcess/Plugins/NPRuntimeObjectMap.cpp
@@ -46,6 +46,17 @@ NPRuntimeObjectMap::NPRuntimeObjectMap(PluginView* pluginView)
{
}
+NPRuntimeObjectMap::PluginProtector::PluginProtector(NPRuntimeObjectMap* npRuntimeObjectMap)
+{
+ // If we're already in the plug-in view destructor, we shouldn't try to keep it alive.
+ if (!npRuntimeObjectMap->m_pluginView->isBeingDestroyed())
+ m_pluginView = npRuntimeObjectMap->m_pluginView;
+}
+
+NPRuntimeObjectMap::PluginProtector::~PluginProtector()
+{
+}
+
NPObject* NPRuntimeObjectMap::getOrCreateNPObject(JSObject* jsObject)
{
// If this is a JSNPObject, we can just get its underlying NPObject.
diff --git a/WebKit2/WebProcess/Plugins/NPRuntimeObjectMap.h b/WebKit2/WebProcess/Plugins/NPRuntimeObjectMap.h
index 51bd0c6..2b8e49f 100644
--- a/WebKit2/WebProcess/Plugins/NPRuntimeObjectMap.h
+++ b/WebKit2/WebProcess/Plugins/NPRuntimeObjectMap.h
@@ -53,6 +53,15 @@ class NPRuntimeObjectMap {
public:
explicit NPRuntimeObjectMap(PluginView*);
+ class PluginProtector {
+ public:
+ explicit PluginProtector(NPRuntimeObjectMap* npRuntimeObjectMap);
+ ~PluginProtector();
+
+ private:
+ RefPtr<PluginView> m_pluginView;
+ };
+
// Returns an NPObject that wraps the given JSObject object. If there is already an NPObject that wraps this JSObject, it will
// retain it and return it.
NPObject* getOrCreateNPObject(JSC::JSObject*);
diff --git a/WebKit2/WebProcess/Plugins/PluginView.cpp b/WebKit2/WebProcess/Plugins/PluginView.cpp
index d8a72ae..e51e8be 100644
--- a/WebKit2/WebProcess/Plugins/PluginView.cpp
+++ b/WebKit2/WebProcess/Plugins/PluginView.cpp
@@ -217,6 +217,7 @@ PluginView::PluginView(WebCore::HTMLPlugInElement* pluginElement, PassRefPtr<Plu
, m_parameters(parameters)
, m_isInitialized(false)
, m_isWaitingUntilMediaCanStart(false)
+ , m_isBeingDestroyed(false)
, m_pendingURLRequestsTimer(RunLoop::main(), this, &PluginView::pendingURLRequestsTimerFired)
, m_npRuntimeObjectMap(this)
{
@@ -224,6 +225,8 @@ PluginView::PluginView(WebCore::HTMLPlugInElement* pluginElement, PassRefPtr<Plu
PluginView::~PluginView()
{
+ ASSERT(!m_isBeingDestroyed);
+
if (m_isWaitingUntilMediaCanStart)
m_pluginElement->document()->removeMediaCanStartListener(this);
@@ -232,8 +235,11 @@ PluginView::~PluginView()
for (FrameLoadMap::iterator it = m_pendingFrameLoads.begin(), end = m_pendingFrameLoads.end(); it != end; ++it)
it->first->setLoadListener(0);
- if (m_plugin && m_isInitialized)
+ if (m_plugin && m_isInitialized) {
+ m_isBeingDestroyed = true;
m_plugin->destroy();
+ m_isBeingDestroyed = false;
+ }
// Invalidate the object map.
m_npRuntimeObjectMap.invalidate();
@@ -284,6 +290,10 @@ void PluginView::initializePlugin()
JSObject* PluginView::scriptObject(JSGlobalObject* globalObject)
{
+ // The plug-in can be null here if it failed to initialize.
+ if (!m_plugin)
+ return 0;
+
NPObject* scriptableNPObject = m_plugin->pluginScriptableNPObject();
if (!scriptableNPObject)
return 0;
@@ -644,7 +654,6 @@ bool PluginView::evaluate(NPObject* npObject, const String&scriptString, NPVaria
bool oldAllowPopups = frame()->script()->allowPopupsFromPlugin();
frame()->script()->setAllowPopupsFromPlugin(allowPopups);
- // FIXME: What happens if calling evaluate will cause the plug-in view to go away.
bool returnValue = m_npRuntimeObjectMap.evaluate(npObject, scriptString, result);
frame()->script()->setAllowPopupsFromPlugin(oldAllowPopups);
diff --git a/WebKit2/WebProcess/Plugins/PluginView.h b/WebKit2/WebProcess/Plugins/PluginView.h
index b39f6c2..c0e03f0 100644
--- a/WebKit2/WebProcess/Plugins/PluginView.h
+++ b/WebKit2/WebProcess/Plugins/PluginView.h
@@ -54,6 +54,8 @@ public:
WebCore::Frame* frame();
+ bool isBeingDestroyed() const { return m_isBeingDestroyed; }
+
private:
PluginView(WebCore::HTMLPlugInElement*, PassRefPtr<Plugin>, const Plugin::Parameters& parameters);
virtual ~PluginView();
@@ -116,6 +118,7 @@ private:
bool m_isInitialized;
bool m_isWaitingUntilMediaCanStart;
+ bool m_isBeingDestroyed;
// Pending URLRequests that the plug-in has made.
Deque<RefPtr<URLRequest> > m_pendingURLRequests;
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list