From 2a273c0016924b9b8b7b8e7e14937601867c4f79 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Tue, 16 Feb 2010 12:44:25 -0600 Subject: [PATCH] Bug 544945, part 2: Periodically unblock the parent to allow it to process events while the plugin subprocess is in a nested event loop. r=karlt --HG-- extra : rebase_source : bf9a2df9d7d6b420fb93d11dc5abaeb4be1214db --- dom/plugins/PPluginModule.ipdl | 6 ++++++ dom/plugins/PluginModuleChild.cpp | 2 +- dom/plugins/PluginModuleParent.cpp | 33 ++++++++++++++++++++++++++++++ dom/plugins/PluginModuleParent.h | 3 +++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/dom/plugins/PPluginModule.ipdl b/dom/plugins/PPluginModule.ipdl index 6c7e757d2ce1..2b0e73cc8c97 100644 --- a/dom/plugins/PPluginModule.ipdl +++ b/dom/plugins/PPluginModule.ipdl @@ -93,6 +93,12 @@ parent: rpc NPN_GetValue_WithBoolReturn(NPNVariable aVariable) returns (NPError aError, bool aBoolVal); + + // Wake up and process a few native events. Periodically called by + // Gtk-specific code upon detecting that the plugin process has + // entered a nested event loop. If the browser doesn't process + // native events, then "livelock" and some other glitches can occur. + rpc ProcessSomeEvents(); }; } // namespace plugins diff --git a/dom/plugins/PluginModuleChild.cpp b/dom/plugins/PluginModuleChild.cpp index 24b86eb6471d..2242fdc98818 100644 --- a/dom/plugins/PluginModuleChild.cpp +++ b/dom/plugins/PluginModuleChild.cpp @@ -290,7 +290,7 @@ PluginModuleChild::ProcessBrowserEvents(gpointer data) PluginModuleChild* pmc = static_cast(data); - PLUGIN_LOG_DEBUG(("FIXME/bug 544945: rpc-call to browser to process a few events")); + pmc->CallProcessSomeEvents(); return TRUE; } diff --git a/dom/plugins/PluginModuleParent.cpp b/dom/plugins/PluginModuleParent.cpp index 6bf3fa642890..ebd0e99e8752 100644 --- a/dom/plugins/PluginModuleParent.cpp +++ b/dom/plugins/PluginModuleParent.cpp @@ -45,6 +45,7 @@ #include "nsContentUtils.h" #include "nsCRT.h" #include "nsNPAPIPlugin.h" +#include "nsThreadUtils.h" using base::KillProcess; @@ -837,3 +838,35 @@ PluginModuleParent::AnswerNPN_GetValue_WithBoolReturn(const NPNVariable& aVariab *aBoolVal = boolVal ? true : false; return true; } + +#if !defined(MOZ_WIDGET_GTK2) +bool +PluginModuleParent::AnswerProcessSomeEvents() +{ + NS_RUNTIMEABORT("unreached"); + return false; +} + +#else +static const int kMaxChancesToProcessEvents = 20; + +bool +PluginModuleParent::AnswerProcessSomeEvents() +{ + PLUGIN_LOG_DEBUG(("Spinning mini nested loop ...")); + + // XXX it would seem sensical to make the condition be + // |NS_HasPendingEvents() && i < kMaxEventsToProcess|. The + // problem is, the native appshell is just an observer of our + // nsThread, and processes native events as a side effect of + // nsThread::ProcessNextEvent(). Since native events are the ones + // we really care about here, we need to go straight to + // NS_ProcessNextEvent(). + for (int i = 0; i < kMaxChancesToProcessEvents; ++i) + NS_ProcessNextEvent(nsnull, PR_FALSE); + + PLUGIN_LOG_DEBUG(("... quitting mini nested loop")); + + return true; +} +#endif diff --git a/dom/plugins/PluginModuleParent.h b/dom/plugins/PluginModuleParent.h index f3319d7e9430..d20baff91d1b 100644 --- a/dom/plugins/PluginModuleParent.h +++ b/dom/plugins/PluginModuleParent.h @@ -154,6 +154,9 @@ protected: NPError* aError, bool* aBoolVal); + NS_OVERRIDE + virtual bool AnswerProcessSomeEvents(); + static PluginInstanceParent* InstCast(NPP instance); static BrowserStreamParent* StreamCast(NPP instance, NPStream* s);