1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/proxy/ppp_messaging_proxy.h"
9 #include "ppapi/c/ppp_messaging.h"
10 #include "ppapi/proxy/host_dispatcher.h"
11 #include "ppapi/proxy/message_handler.h"
12 #include "ppapi/proxy/plugin_dispatcher.h"
13 #include "ppapi/proxy/plugin_resource_tracker.h"
14 #include "ppapi/proxy/plugin_var_tracker.h"
15 #include "ppapi/proxy/ppapi_messages.h"
16 #include "ppapi/proxy/serialized_var.h"
17 #include "ppapi/shared_impl/ppapi_globals.h"
18 #include "ppapi/shared_impl/proxy_lock.h"
19 #include "ppapi/shared_impl/scoped_pp_var.h"
20 #include "ppapi/shared_impl/var_tracker.h"
27 MessageHandler
* GetMessageHandler(Dispatcher
* dispatcher
,
28 PP_Instance instance
) {
29 if (!dispatcher
|| !dispatcher
->IsPlugin()) {
33 PluginDispatcher
* plugin_dispatcher
=
34 static_cast<PluginDispatcher
*>(dispatcher
);
35 InstanceData
* instance_data
= plugin_dispatcher
->GetInstanceData(instance
);
39 return instance_data
->message_handler
.get();
42 void ResetMessageHandler(Dispatcher
* dispatcher
, PP_Instance instance
) {
43 if (!dispatcher
|| !dispatcher
->IsPlugin()) {
47 PluginDispatcher
* plugin_dispatcher
=
48 static_cast<PluginDispatcher
*>(dispatcher
);
49 InstanceData
* instance_data
= plugin_dispatcher
->GetInstanceData(instance
);
53 instance_data
->message_handler
.reset();
58 PPP_Messaging_Proxy::PPP_Messaging_Proxy(Dispatcher
* dispatcher
)
59 : InterfaceProxy(dispatcher
),
60 ppp_messaging_impl_(NULL
) {
61 if (dispatcher
->IsPlugin()) {
62 ppp_messaging_impl_
= static_cast<const PPP_Messaging
*>(
63 dispatcher
->local_get_interface()(PPP_MESSAGING_INTERFACE
));
67 PPP_Messaging_Proxy::~PPP_Messaging_Proxy() {
70 bool PPP_Messaging_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
71 if (!dispatcher()->IsPlugin())
75 IPC_BEGIN_MESSAGE_MAP(PPP_Messaging_Proxy
, msg
)
76 IPC_MESSAGE_HANDLER(PpapiMsg_PPPMessaging_HandleMessage
,
78 IPC_MESSAGE_HANDLER_DELAY_REPLY(
79 PpapiMsg_PPPMessageHandler_HandleBlockingMessage
,
80 OnMsgHandleBlockingMessage
)
81 IPC_MESSAGE_UNHANDLED(handled
= false)
86 void PPP_Messaging_Proxy::OnMsgHandleMessage(
87 PP_Instance instance
, SerializedVarReceiveInput message_data
) {
88 PP_Var
received_var(message_data
.GetForInstance(dispatcher(), instance
));
89 MessageHandler
* message_handler
= GetMessageHandler(dispatcher(), instance
);
90 if (message_handler
) {
91 if (message_handler
->LoopIsValid()) {
92 message_handler
->HandleMessage(ScopedPPVar(received_var
));
95 // If the MessageHandler's loop has been quit, then we should treat it as
96 // though it has been unregistered and start sending messages to the
97 // default handler. This might mean the plugin has lost messages, but
98 // there's not really anything sane we can do about it. They should have
99 // used UnregisterMessageHandler.
100 ResetMessageHandler(dispatcher(), instance
);
103 // If we reach this point, then there's no message handler registered, so
104 // we send to the default PPP_Messaging one for the instance.
106 // SerializedVarReceiveInput will decrement the reference count, but we want
107 // to give the recipient a reference in the legacy API.
108 PpapiGlobals::Get()->GetVarTracker()->AddRefVar(received_var
);
109 CallWhileUnlocked(ppp_messaging_impl_
->HandleMessage
,
114 void PPP_Messaging_Proxy::OnMsgHandleBlockingMessage(
115 PP_Instance instance
,
116 SerializedVarReceiveInput message_data
,
117 IPC::Message
* reply_msg
) {
118 ScopedPPVar
received_var(message_data
.GetForInstance(dispatcher(), instance
));
119 MessageHandler
* message_handler
= GetMessageHandler(dispatcher(), instance
);
120 if (message_handler
) {
121 if (message_handler
->LoopIsValid()) {
122 message_handler
->HandleBlockingMessage(
123 received_var
, scoped_ptr
<IPC::Message
>(reply_msg
));
126 // If the MessageHandler's loop has been quit, then we should treat it as
127 // though it has been unregistered. Also see the note for PostMessage.
128 ResetMessageHandler(dispatcher(), instance
);
131 // We have no handler, but we still need to respond to unblock the renderer
132 // and inform the JavaScript caller.
133 PpapiMsg_PPPMessageHandler_HandleBlockingMessage::WriteReplyParams(
135 SerializedVarReturnValue::Convert(dispatcher(), PP_MakeUndefined()),
136 false /* was_handled */);
137 dispatcher()->Send(reply_msg
);