OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "ppapi/proxy/message_handler.h" |
| 6 |
| 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" |
| 14 |
| 15 namespace ppapi { |
| 16 namespace proxy { |
| 17 namespace { |
| 18 |
| 19 typedef void (*HandleMessageFunc)(PP_Instance, void*, PP_Var); |
| 20 typedef PP_Var (*HandleBlockingMessageFunc)(PP_Instance, void*, PP_Var); |
| 21 |
| 22 void HandleMessageWrapper(HandleMessageFunc function, |
| 23 PP_Instance instance, |
| 24 void* user_data, |
| 25 ScopedPPVar message_data) { |
| 26 CallWhileUnlocked(function, instance, user_data, message_data.get()); |
| 27 } |
| 28 |
| 29 void HandleBlockingMessageWrapper(HandleBlockingMessageFunc function, |
| 30 PP_Instance instance, |
| 31 void* user_data, |
| 32 ScopedPPVar message_data, |
| 33 scoped_ptr<IPC::Message> reply_msg) { |
| 34 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); |
| 35 if (!dispatcher) |
| 36 return; |
| 37 PP_Var return_value = CallWhileUnlocked(function, |
| 38 instance, |
| 39 user_data, |
| 40 message_data.get()); |
| 41 PpapiMsg_PPPMessageHandler_HandleBlockingMessage::WriteReplyParams( |
| 42 reply_msg.get(), |
| 43 SerializedVarReturnValue::Convert(dispatcher, return_value), |
| 44 true /* was_handled */); |
| 45 dispatcher->Send(reply_msg.release()); |
| 46 } |
| 47 |
| 48 } // namespace |
| 49 |
| 50 // static |
| 51 scoped_ptr<MessageHandler> MessageHandler::Create( |
| 52 PP_Instance instance, |
| 53 const PPP_MessageHandler_0_1* handler_if, |
| 54 void* user_data, |
| 55 PP_Resource message_loop, |
| 56 int32_t* error) { |
| 57 scoped_ptr<MessageHandler> result; |
| 58 // The interface and all function pointers must be valid. |
| 59 if (!handler_if || |
| 60 !handler_if->HandleMessage || |
| 61 !handler_if->HandleBlockingMessage || |
| 62 !handler_if->Destroy) { |
| 63 *error = PP_ERROR_BADARGUMENT; |
| 64 return result.Pass(); |
| 65 } |
| 66 thunk::EnterResourceNoLock<thunk::PPB_MessageLoop_API> |
| 67 enter_loop(message_loop, true); |
| 68 if (enter_loop.failed()) { |
| 69 *error = PP_ERROR_BADRESOURCE; |
| 70 return result.Pass(); |
| 71 } |
| 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; |
| 76 return result.Pass(); |
| 77 } |
| 78 |
| 79 result.reset(new MessageHandler( |
| 80 instance, handler_if, user_data, message_loop_resource)); |
| 81 *error = PP_OK; |
| 82 return result.Pass(); |
| 83 } |
| 84 |
| 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()) { |
| 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, |
| 93 instance_, |
| 94 user_data_)); |
| 95 } |
| 96 } |
| 97 |
| 98 bool MessageHandler::LoopIsValid() const { |
| 99 return !!message_loop_->message_loop_proxy(); |
| 100 } |
| 101 |
| 102 void MessageHandler::HandleMessage(ScopedPPVar var) { |
| 103 message_loop_->message_loop_proxy()->PostTask(FROM_HERE, |
| 104 RunWhileLocked(base::Bind(&HandleMessageWrapper, |
| 105 handler_if_->HandleMessage, |
| 106 instance_, |
| 107 user_data_, |
| 108 var))); |
| 109 } |
| 110 |
| 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, |
| 116 instance_, |
| 117 user_data_, |
| 118 var, |
| 119 base::Passed(reply_msg.Pass())))); |
| 120 } |
| 121 |
| 122 MessageHandler::MessageHandler( |
| 123 PP_Instance instance, |
| 124 const PPP_MessageHandler_0_1* handler_if, |
| 125 void* user_data, |
| 126 scoped_refptr<MessageLoopResource> message_loop) |
| 127 : instance_(instance), |
| 128 handler_if_(handler_if), |
| 129 user_data_(user_data), |
| 130 message_loop_(message_loop) { |
| 131 } |
| 132 |
| 133 } // namespace proxy |
| 134 } // namespace ppapi |
OLD | NEW |