Index: ppapi/proxy/host_dispatcher.cc |
=================================================================== |
--- ppapi/proxy/host_dispatcher.cc (revision 77850) |
+++ ppapi/proxy/host_dispatcher.cc (working copy) |
@@ -41,6 +41,20 @@ |
return BoolToPPBool(usable); |
} |
+// Saves the state of the given bool and puts it back when it goes out of |
+// scope. |
+class BoolRestorer { |
+ public: |
+ BoolRestorer(bool* var) : var_(var), old_value_(*var) { |
+ } |
+ ~BoolRestorer() { |
+ *var_ = old_value_; |
+ } |
+ private: |
+ bool* var_; |
+ bool old_value_; |
+}; |
+ |
} // namespace |
HostDispatcher::HostDispatcher(base::ProcessHandle remote_process_handle, |
@@ -105,7 +119,27 @@ |
return false; |
} |
+bool HostDispatcher::Send(IPC::Message* msg) { |
+ // Normal sync messages are set to unblock, which would normally cause the |
+ // plugin to be reentered to process them. We only want to do this when we |
+ // know the plugin is in a state to accept reentrancy. Since the plugin side |
+ // never clears this flag on messages it sends, we can't get deadlock, but we |
+ // may still get reentrancy in the host as a result. |
+ if (!allow_plugin_reentrancy_) |
+ msg->set_unblock(false); |
+ return Dispatcher::Send(msg); |
+} |
+ |
bool HostDispatcher::OnMessageReceived(const IPC::Message& msg) { |
+ // We only want to allow reentrancy when the most recent message from the |
+ // plugin was a scripting message. We save the old state of the flag on the |
+ // stack in case we're (we are the host) being reentered ourselves. The flag |
+ // is set to false here for all messages, and then the scripting API will |
+ // explicitly set it to true during processing of those messages that can be |
+ // reentered. |
+ BoolRestorer restorer(&allow_plugin_reentrancy_); |
+ allow_plugin_reentrancy_ = false; |
+ |
// Handle common control messages. |
if (Dispatcher::OnMessageReceived(msg)) |
return true; |