1 // Copyright 2014 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/message_handler.h"
7 #include "ipc/ipc_message.h"
8 #include "ppapi/proxy/plugin_dispatcher.h"
9 #include "ppapi/proxy/ppapi_messages.h"
10 #include "ppapi/proxy/ppb_message_loop_proxy.h"
11 #include "ppapi/shared_impl/proxy_lock.h"
12 #include "ppapi/shared_impl/scoped_pp_var.h"
13 #include "ppapi/thunk/enter.h"
19 typedef void (*HandleMessageFunc
)(PP_Instance
, void*, PP_Var
);
20 typedef PP_Var (*HandleBlockingMessageFunc
)(PP_Instance
, void*, PP_Var
);
22 void HandleMessageWrapper(HandleMessageFunc function
,
25 ScopedPPVar message_data
) {
26 CallWhileUnlocked(function
, instance
, user_data
, message_data
.get());
29 void HandleBlockingMessageWrapper(HandleBlockingMessageFunc function
,
32 ScopedPPVar message_data
,
33 scoped_ptr
<IPC::Message
> reply_msg
) {
34 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
37 PP_Var return_value
= CallWhileUnlocked(function
,
41 PpapiMsg_PPPMessageHandler_HandleBlockingMessage::WriteReplyParams(
43 SerializedVarReturnValue::Convert(dispatcher
, return_value
),
44 true /* was_handled */);
45 dispatcher
->Send(reply_msg
.release());
51 scoped_ptr
<MessageHandler
> MessageHandler::Create(
53 const PPP_MessageHandler_0_1
* handler_if
,
55 PP_Resource message_loop
,
57 scoped_ptr
<MessageHandler
> result
;
58 // The interface and all function pointers must be valid.
60 !handler_if
->HandleMessage
||
61 !handler_if
->HandleBlockingMessage
||
62 !handler_if
->Destroy
) {
63 *error
= PP_ERROR_BADARGUMENT
;
66 thunk::EnterResourceNoLock
<thunk::PPB_MessageLoop_API
>
67 enter_loop(message_loop
, true);
68 if (enter_loop
.failed()) {
69 *error
= PP_ERROR_BADRESOURCE
;
72 scoped_refptr
<MessageLoopResource
> message_loop_resource(
73 static_cast<MessageLoopResource
*>(enter_loop
.object()));
74 if (message_loop_resource
->is_main_thread_loop()) {
75 *error
= PP_ERROR_WRONG_THREAD
;
79 result
.reset(new MessageHandler(
80 instance
, handler_if
, user_data
, message_loop_resource
));
85 MessageHandler::~MessageHandler() {
86 // It's possible the message_loop_proxy is NULL if that loop has been quit.
87 // In that case, we unfortunately just can't call Destroy.
88 if (message_loop_
->message_loop_proxy().get()) {
89 // The posted task won't have the proxy lock, but that's OK, it doesn't
90 // touch any internal state; it's a direct call on the plugin's function.
91 message_loop_
->message_loop_proxy()->PostTask(FROM_HERE
,
92 base::Bind(handler_if_
->Destroy
,
98 bool MessageHandler::LoopIsValid() const {
99 return !!message_loop_
->message_loop_proxy().get();
102 void MessageHandler::HandleMessage(ScopedPPVar var
) {
103 message_loop_
->message_loop_proxy()->PostTask(FROM_HERE
,
104 RunWhileLocked(base::Bind(&HandleMessageWrapper
,
105 handler_if_
->HandleMessage
,
111 void MessageHandler::HandleBlockingMessage(ScopedPPVar var
,
112 scoped_ptr
<IPC::Message
> reply_msg
) {
113 message_loop_
->message_loop_proxy()->PostTask(FROM_HERE
,
114 RunWhileLocked(base::Bind(&HandleBlockingMessageWrapper
,
115 handler_if_
->HandleBlockingMessage
,
119 base::Passed(reply_msg
.Pass()))));
122 MessageHandler::MessageHandler(
123 PP_Instance instance
,
124 const PPP_MessageHandler_0_1
* handler_if
,
126 scoped_refptr
<MessageLoopResource
> message_loop
)
127 : instance_(instance
),
128 handler_if_(handler_if
),
129 user_data_(user_data
),
130 message_loop_(message_loop
) {