| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "ppapi/proxy/ppb_flash_message_loop_proxy.h" | 
 |  | 
 | #include "base/bind.h" | 
 | #include "base/macros.h" | 
 | #include "ppapi/c/pp_errors.h" | 
 | #include "ppapi/c/private/ppb_flash_message_loop.h" | 
 | #include "ppapi/proxy/enter_proxy.h" | 
 | #include "ppapi/proxy/plugin_dispatcher.h" | 
 | #include "ppapi/proxy/ppapi_messages.h" | 
 | #include "ppapi/shared_impl/resource.h" | 
 | #include "ppapi/thunk/enter.h" | 
 | #include "ppapi/thunk/ppb_flash_message_loop_api.h" | 
 | #include "ppapi/thunk/resource_creation_api.h" | 
 |  | 
 | using ppapi::thunk::PPB_Flash_MessageLoop_API; | 
 |  | 
 | namespace ppapi { | 
 | namespace proxy { | 
 | namespace { | 
 |  | 
 | class FlashMessageLoop : public PPB_Flash_MessageLoop_API, public Resource { | 
 |  public: | 
 |   explicit FlashMessageLoop(const HostResource& resource); | 
 |   ~FlashMessageLoop() override; | 
 |  | 
 |   // Resource overrides. | 
 |   PPB_Flash_MessageLoop_API* AsPPB_Flash_MessageLoop_API() override; | 
 |  | 
 |   // PPB_Flash_MesssageLoop_API implementation. | 
 |   int32_t Run() override; | 
 |   void Quit() override; | 
 |   void RunFromHostProxy(const RunFromHostProxyCallback& callback) override; | 
 |  | 
 |  private: | 
 |   DISALLOW_COPY_AND_ASSIGN(FlashMessageLoop); | 
 | }; | 
 |  | 
 | FlashMessageLoop::FlashMessageLoop(const HostResource& resource) | 
 |     : Resource(OBJECT_IS_PROXY, resource) { | 
 | } | 
 |  | 
 | FlashMessageLoop::~FlashMessageLoop() { | 
 | } | 
 |  | 
 | PPB_Flash_MessageLoop_API* FlashMessageLoop::AsPPB_Flash_MessageLoop_API() { | 
 |   return this; | 
 | } | 
 |  | 
 | int32_t FlashMessageLoop::Run() { | 
 |   int32_t result = PP_ERROR_FAILED; | 
 |   IPC::SyncMessage* msg = new PpapiHostMsg_PPBFlashMessageLoop_Run( | 
 |       API_ID_PPB_FLASH_MESSAGELOOP, host_resource(), &result); | 
 |   msg->EnableMessagePumping(); | 
 |   PluginDispatcher::GetForResource(this)->Send(msg); | 
 |   return result; | 
 | } | 
 |  | 
 | void FlashMessageLoop::Quit() { | 
 |   PluginDispatcher::GetForResource(this)->Send( | 
 |       new PpapiHostMsg_PPBFlashMessageLoop_Quit( | 
 |           API_ID_PPB_FLASH_MESSAGELOOP, host_resource())); | 
 | } | 
 |  | 
 | void FlashMessageLoop::RunFromHostProxy( | 
 |     const RunFromHostProxyCallback& callback) { | 
 |   // This should never be called on the plugin side. | 
 |   NOTREACHED(); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | PPB_Flash_MessageLoop_Proxy::PPB_Flash_MessageLoop_Proxy(Dispatcher* dispatcher) | 
 |     : InterfaceProxy(dispatcher) { | 
 | } | 
 |  | 
 | PPB_Flash_MessageLoop_Proxy::~PPB_Flash_MessageLoop_Proxy() { | 
 | } | 
 |  | 
 | // static | 
 | PP_Resource PPB_Flash_MessageLoop_Proxy::CreateProxyResource( | 
 |     PP_Instance instance) { | 
 |   PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); | 
 |   if (!dispatcher) | 
 |     return 0; | 
 |  | 
 |   HostResource result; | 
 |   dispatcher->Send(new PpapiHostMsg_PPBFlashMessageLoop_Create( | 
 |       API_ID_PPB_FLASH_MESSAGELOOP, instance, &result)); | 
 |   if (result.is_null()) | 
 |     return 0; | 
 |   return (new FlashMessageLoop(result))->GetReference(); | 
 | } | 
 |  | 
 | bool PPB_Flash_MessageLoop_Proxy::OnMessageReceived(const IPC::Message& msg) { | 
 |   if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH)) | 
 |     return false; | 
 |  | 
 |   bool handled = true; | 
 |   IPC_BEGIN_MESSAGE_MAP(PPB_Flash_MessageLoop_Proxy, msg) | 
 |     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashMessageLoop_Create, | 
 |                         OnMsgCreate) | 
 |     // We cannot use IPC_MESSAGE_HANDLER here. Because it tries to send the sync | 
 |     // message reply after the handler returns. However, in this case, the | 
 |     // PPB_Flash_MessageLoop_Proxy object may be destroyed before the handler | 
 |     // returns. | 
 |     IPC_MESSAGE_HANDLER_DELAY_REPLY(PpapiHostMsg_PPBFlashMessageLoop_Run, | 
 |                                     OnMsgRun) | 
 |     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashMessageLoop_Quit, | 
 |                         OnMsgQuit) | 
 |     IPC_MESSAGE_UNHANDLED(handled = false) | 
 |   IPC_END_MESSAGE_MAP() | 
 |   return handled; | 
 | } | 
 |  | 
 | void PPB_Flash_MessageLoop_Proxy::OnMsgCreate(PP_Instance instance, | 
 |                                               HostResource* result) { | 
 |   if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH)) | 
 |     return; | 
 |   thunk::EnterResourceCreation enter(instance); | 
 |   if (enter.succeeded()) { | 
 |     result->SetHostResource( | 
 |         instance, enter.functions()->CreateFlashMessageLoop(instance)); | 
 |   } | 
 | } | 
 |  | 
 | void PPB_Flash_MessageLoop_Proxy::OnMsgRun( | 
 |     const HostResource& flash_message_loop, | 
 |     IPC::Message* reply) { | 
 |   if (!dispatcher()->permissions().HasPermission(PERMISSION_FLASH)) | 
 |     return; | 
 |  | 
 |   PPB_Flash_MessageLoop_API::RunFromHostProxyCallback callback = | 
 |       base::Bind(&PPB_Flash_MessageLoop_Proxy::WillQuitSoon, AsWeakPtr(), | 
 |                  base::Passed(std::unique_ptr<IPC::Message>(reply))); | 
 |  | 
 |   EnterHostFromHostResource<PPB_Flash_MessageLoop_API> | 
 |       enter(flash_message_loop); | 
 |   if (enter.succeeded()) | 
 |     enter.object()->RunFromHostProxy(callback); | 
 |   else | 
 |     callback.Run(PP_ERROR_BADRESOURCE); | 
 | } | 
 |  | 
 | void PPB_Flash_MessageLoop_Proxy::OnMsgQuit( | 
 |     const ppapi::HostResource& flash_message_loop) { | 
 |   EnterHostFromHostResource<PPB_Flash_MessageLoop_API> | 
 |       enter(flash_message_loop); | 
 |   if (enter.succeeded()) | 
 |     enter.object()->Quit(); | 
 | } | 
 |  | 
 | void PPB_Flash_MessageLoop_Proxy::WillQuitSoon( | 
 |     std::unique_ptr<IPC::Message> reply_message, | 
 |     int32_t result) { | 
 |   PpapiHostMsg_PPBFlashMessageLoop_Run::WriteReplyParams(reply_message.get(), | 
 |                                                          result); | 
 |   Send(reply_message.release()); | 
 | } | 
 |  | 
 | }  // namespace proxy | 
 | }  // namespace ppapi |