Index: ppapi/proxy/ppp_messaging_proxy.cc |
diff --git a/ppapi/proxy/ppp_messaging_proxy.cc b/ppapi/proxy/ppp_messaging_proxy.cc |
index ba83ca7432b88fc829528ccc5c4abf754984f557..75614ae08b2266da602f448112e0bba83ac6e7b0 100644 |
--- a/ppapi/proxy/ppp_messaging_proxy.cc |
+++ b/ppapi/proxy/ppp_messaging_proxy.cc |
@@ -8,17 +8,53 @@ |
#include "ppapi/c/ppp_messaging.h" |
#include "ppapi/proxy/host_dispatcher.h" |
+#include "ppapi/proxy/message_handler.h" |
+#include "ppapi/proxy/plugin_dispatcher.h" |
#include "ppapi/proxy/plugin_resource_tracker.h" |
#include "ppapi/proxy/plugin_var_tracker.h" |
#include "ppapi/proxy/ppapi_messages.h" |
#include "ppapi/proxy/serialized_var.h" |
#include "ppapi/shared_impl/ppapi_globals.h" |
#include "ppapi/shared_impl/proxy_lock.h" |
+#include "ppapi/shared_impl/scoped_pp_var.h" |
#include "ppapi/shared_impl/var_tracker.h" |
namespace ppapi { |
namespace proxy { |
+namespace { |
+ |
+MessageHandler* GetMessageHandler(Dispatcher* dispatcher, |
+ PP_Instance instance) { |
+ if (!dispatcher || !dispatcher->IsPlugin()) { |
+ NOTREACHED(); |
+ return NULL; |
+ } |
+ PluginDispatcher* plugin_dispatcher = |
+ static_cast<PluginDispatcher*>(dispatcher); |
+ InstanceData* instance_data = plugin_dispatcher->GetInstanceData(instance); |
+ if (!instance_data) |
+ return NULL; |
+ |
+ return instance_data->message_handler.get(); |
+} |
+ |
+void ResetMessageHandler(Dispatcher* dispatcher, PP_Instance instance) { |
+ if (!dispatcher || !dispatcher->IsPlugin()) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ PluginDispatcher* plugin_dispatcher = |
+ static_cast<PluginDispatcher*>(dispatcher); |
+ InstanceData* instance_data = plugin_dispatcher->GetInstanceData(instance); |
+ if (!instance_data) |
+ return; |
+ |
+ instance_data->message_handler.reset(); |
+} |
+ |
+} // namespace |
+ |
PPP_Messaging_Proxy::PPP_Messaging_Proxy(Dispatcher* dispatcher) |
: InterfaceProxy(dispatcher), |
ppp_messaging_impl_(NULL) { |
@@ -39,6 +75,9 @@ bool PPP_Messaging_Proxy::OnMessageReceived(const IPC::Message& msg) { |
IPC_BEGIN_MESSAGE_MAP(PPP_Messaging_Proxy, msg) |
IPC_MESSAGE_HANDLER(PpapiMsg_PPPMessaging_HandleMessage, |
OnMsgHandleMessage) |
+ IPC_MESSAGE_HANDLER_DELAY_REPLY( |
+ PpapiMsg_PPPMessageHandler_HandleBlockingMessage, |
+ OnMsgHandleBlockingMessage) |
IPC_MESSAGE_UNHANDLED(handled = false) |
IPC_END_MESSAGE_MAP() |
return handled; |
@@ -47,13 +86,57 @@ bool PPP_Messaging_Proxy::OnMessageReceived(const IPC::Message& msg) { |
void PPP_Messaging_Proxy::OnMsgHandleMessage( |
PP_Instance instance, SerializedVarReceiveInput message_data) { |
PP_Var received_var(message_data.GetForInstance(dispatcher(), instance)); |
+ MessageHandler* message_handler = GetMessageHandler(dispatcher(), instance); |
+ if (message_handler) { |
+ if (message_handler->LoopIsValid()) { |
+ message_handler->HandleMessage(ScopedPPVar(received_var)); |
+ return; |
+ } else { |
+ // If the MessageHandler's loop has been quit, then we should treat it as |
+ // though it has been unregistered and start sending messages to the |
+ // default handler. This might mean the plugin has lost messages, but |
+ // there's not really anything sane we can do about it. They should have |
+ // used UnregisterMessageHandler. |
+ ResetMessageHandler(dispatcher(), instance); |
+ } |
+ } |
+ // If we reach this point, then there's no message handler registered, so |
+ // we send to the default PPP_Messaging one for the instance. |
+ |
// SerializedVarReceiveInput will decrement the reference count, but we want |
- // to give the recipient a reference. |
+ // to give the recipient a reference in the legacy API. |
PpapiGlobals::Get()->GetVarTracker()->AddRefVar(received_var); |
CallWhileUnlocked(ppp_messaging_impl_->HandleMessage, |
instance, |
received_var); |
} |
+void PPP_Messaging_Proxy::OnMsgHandleBlockingMessage( |
+ PP_Instance instance, |
+ SerializedVarReceiveInput message_data, |
+ IPC::Message* reply_msg) { |
+ ScopedPPVar received_var(message_data.GetForInstance(dispatcher(), instance)); |
+ MessageHandler* message_handler = GetMessageHandler(dispatcher(), instance); |
+ if (message_handler) { |
+ if (message_handler->LoopIsValid()) { |
+ message_handler->HandleBlockingMessage( |
+ received_var, scoped_ptr<IPC::Message>(reply_msg)); |
+ return; |
+ } else { |
+ // If the MessageHandler's loop has been quit, then we should treat it as |
+ // though it has been unregistered. Also see the note for PostMessage. |
+ ResetMessageHandler(dispatcher(), instance); |
+ } |
+ } |
+ // We have no handler, but we still need to respond to unblock the renderer |
+ // and inform the JavaScript caller. |
+ PpapiMsg_PPPMessageHandler_HandleBlockingMessage::WriteReplyParams( |
+ reply_msg, |
+ SerializedVarReturnValue::Convert(dispatcher(), PP_MakeUndefined()), |
+ false /* was_handled */); |
+ dispatcher()->Send(reply_msg); |
+} |
+ |
+ |
} // namespace proxy |
} // namespace ppapi |