diff --git a/dom/plugins/PPluginModule.ipdl b/dom/plugins/PPluginModule.ipdl index 6c7e757d2ce..2b0e73cc8c9 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 0c7fcf2a960..2c2337583fa 100644 --- a/dom/plugins/PluginModuleChild.cpp +++ b/dom/plugins/PluginModuleChild.cpp @@ -278,7 +278,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 7123414e2bb..359f8def1b2 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; @@ -840,3 +841,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 f3319d7e943..d20baff91d1 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);