Reviewed by Kevin Decker.
<rdar://problem/
6584834> ESPN radio live stream link hangs Safari
When a plug-in invokes JavaScript code that will destroy the plug-in, we need to
defer destruction until we're done executing the script.
* Plugins/Hosted/NetscapePluginHostProxy.mm:
(WebKit::PluginDestroyDeferrer::PluginDestroyDeferrer):
(WebKit::PluginDestroyDeferrer::~PluginDestroyDeferrer):
Add a simple RAII object for deferring destruction of the plug-in instance.
(WKPCEvaluate):
(WKPCInvoke):
(WKPCInvokeDefault):
(WKPCConstruct):
(WKPCGetProperty):
(WKPCSetProperty):
(WKPCRemoveProperty):
(WKPCHasProperty):
(WKPCHasMethod):
Use the PluginDestroyDeferrer.
* Plugins/Hosted/NetscapePluginInstanceProxy.h:
(WebKit::NetscapePluginInstanceProxy::pluginID):
Assert that the plug-in ID is not 0 here.
* Plugins/Hosted/NetscapePluginInstanceProxy.mm:
(WebKit::NetscapePluginInstanceProxy::NetscapePluginInstanceProxy):
Initialize the call depth.
(WebKit::NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy):
Set the plug-in ID to 0 to aid debugging.
(WebKit::NetscapePluginInstanceProxy::willCallPluginFunction):
Increment the call depth.
(WebKit::NetscapePluginInstanceProxy::didCallPluginFunction):
Decrement the call depth, if it's 0 and we should stop the plug-in, do so.
(WebKit::NetscapePluginInstanceProxy::shouldStop):
If we're called this with a non-zero call depth, set shouldStopSoon to true.
* Plugins/Hosted/WebHostedNetscapePluginView.mm:
(-[WebHostedNetscapePluginView shouldStop]):
Call the proxy.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@40996
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2009-02-13 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Kevin Decker.
+
+ <rdar://problem/6584834> ESPN radio live stream link hangs Safari
+
+ When a plug-in invokes JavaScript code that will destroy the plug-in, we need to
+ defer destruction until we're done executing the script.
+
+ * Plugins/Hosted/NetscapePluginHostProxy.mm:
+ (WebKit::PluginDestroyDeferrer::PluginDestroyDeferrer):
+ (WebKit::PluginDestroyDeferrer::~PluginDestroyDeferrer):
+ Add a simple RAII object for deferring destruction of the plug-in instance.
+
+ (WKPCEvaluate):
+ (WKPCInvoke):
+ (WKPCInvokeDefault):
+ (WKPCConstruct):
+ (WKPCGetProperty):
+ (WKPCSetProperty):
+ (WKPCRemoveProperty):
+ (WKPCHasProperty):
+ (WKPCHasMethod):
+ Use the PluginDestroyDeferrer.
+
+ * Plugins/Hosted/NetscapePluginInstanceProxy.h:
+ (WebKit::NetscapePluginInstanceProxy::pluginID):
+ Assert that the plug-in ID is not 0 here.
+
+ * Plugins/Hosted/NetscapePluginInstanceProxy.mm:
+ (WebKit::NetscapePluginInstanceProxy::NetscapePluginInstanceProxy):
+ Initialize the call depth.
+
+ (WebKit::NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy):
+ Set the plug-in ID to 0 to aid debugging.
+
+ (WebKit::NetscapePluginInstanceProxy::willCallPluginFunction):
+ Increment the call depth.
+
+ (WebKit::NetscapePluginInstanceProxy::didCallPluginFunction):
+ Decrement the call depth, if it's 0 and we should stop the plug-in, do so.
+
+ (WebKit::NetscapePluginInstanceProxy::shouldStop):
+ If we're called this with a non-zero call depth, set shouldStopSoon to true.
+
+ * Plugins/Hosted/WebHostedNetscapePluginView.mm:
+ (-[WebHostedNetscapePluginView shouldStop]):
+ Call the proxy.
+
2009-02-12 Brady Eidson <beidson@apple.com>
Reviewed by Kevin Decker
namespace WebKit {
+class PluginDestroyDeferrer {
+public:
+ PluginDestroyDeferrer(NetscapePluginInstanceProxy* proxy)
+ : m_proxy(proxy)
+ {
+ m_proxy->willCallPluginFunction();
+ }
+
+ ~PluginDestroyDeferrer()
+ {
+ m_proxy->didCallPluginFunction();
+ }
+
+private:
+ NetscapePluginInstanceProxy* m_proxy;
+};
+
typedef HashMap<mach_port_t, NetscapePluginHostProxy*> PluginProxyMap;
static PluginProxyMap& pluginProxyMap()
{
if (!instanceProxy)
return KERN_FAILURE;
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
String script = String::fromUTF8WithLatin1Fallback(scriptData, scriptLength);
data_t resultData;
if (!instanceProxy)
return KERN_FAILURE;
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
if (!IdentifierRep::isValid(identifier)) {
_WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), false, 0, 0);
if (!instanceProxy)
return KERN_FAILURE;
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
*returnValue = instanceProxy->invokeDefault(objectID, argumentsData, argumentsLength, *resultData, *resultLength);
return KERN_SUCCESS;
if (!instanceProxy)
return KERN_FAILURE;
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
*returnValue = instanceProxy->construct(objectID, argumentsData, argumentsLength, *resultData, *resultLength);
return KERN_SUCCESS;
if (!IdentifierRep::isValid(identifier))
return KERN_FAILURE;
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
data_t resultData;
mach_msg_type_number_t resultLength;
boolean_t returnValue;
if (!instanceProxy)
return KERN_FAILURE;
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
if (!IdentifierRep::isValid(identifier))
*returnValue = false;
if (!instanceProxy)
return KERN_FAILURE;
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
if (!IdentifierRep::isValid(identifier))
return KERN_FAILURE;
if (!instanceProxy)
return KERN_FAILURE;
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
if (!IdentifierRep::isValid(identifier)) {
_WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), false);
if (!instanceProxy)
return KERN_FAILURE;
+ PluginDestroyDeferrer deferrer(instanceProxy);
+
IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier);
if (!IdentifierRep::isValid(identifier)) {
_WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), false);
}
~NetscapePluginInstanceProxy();
- uint32_t pluginID() const { return m_pluginID; }
+ uint32_t pluginID() const
+ {
+ ASSERT(m_pluginID);
+
+ return m_pluginID;
+ }
uint32_t renderContextID() const { return m_renderContextID; }
void setRenderContextID(uint32_t renderContextID) { m_renderContextID = renderContextID; }
void invalidate();
+ void willCallPluginFunction();
+ void didCallPluginFunction();
+ bool shouldStop();
+
// Reply structs
struct Reply {
enum Type {
typedef HashSet<ProxyInstance*> ProxyInstanceSet;
ProxyInstanceSet m_instances;
+
+ unsigned m_pluginFunctionCallDepth;
+ bool m_shouldStopSoon;
};
} // namespace WebKit
, m_useSoftwareRenderer(false)
, m_waitingForReply(false)
, m_objectIDCounter(0)
+ , m_pluginFunctionCallDepth(0)
+ , m_shouldStopSoon(false)
{
ASSERT(m_pluginView);
NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy()
{
ASSERT(!m_pluginHostProxy);
+
+ m_pluginID = 0;
}
void NetscapePluginInstanceProxy::resize(NSRect size, NSRect clipRect)
m_instances.remove(instance);
}
+
+void NetscapePluginInstanceProxy::willCallPluginFunction()
+{
+ m_pluginFunctionCallDepth++;
+}
+
+void NetscapePluginInstanceProxy::didCallPluginFunction()
+{
+ ASSERT(m_pluginFunctionCallDepth > 0);
+ m_pluginFunctionCallDepth--;
+
+ // If -stop was called while we were calling into a plug-in function, and we're no longer
+ // inside a plug-in function, stop now.
+ if (!m_pluginFunctionCallDepth && m_shouldStopSoon) {
+ m_shouldStopSoon = false;
+ [m_pluginView stop];
+ }
+}
+bool NetscapePluginInstanceProxy::shouldStop()
+{
+ if (m_pluginFunctionCallDepth) {
+ m_shouldStopSoon = true;
+ return false;
+ }
+
+ return true;
+}
+
} // namespace WebKit
#endif // USE(PLUGIN_HOST_PROCESS)
- (BOOL)shouldStop
{
- return YES;
+ if (!_proxy)
+ return YES;
+
+ return _proxy->shouldStop();
}
- (void)destroyPlugin