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. 4 5#include "content/renderer/pepper/ppb_flash_message_loop_impl.h" 6 7#include "base/callback.h" 8#include "base/message_loop/message_loop.h" 9#include "ppapi/c/pp_errors.h" 10 11using ppapi::thunk::PPB_Flash_MessageLoop_API; 12 13namespace content { 14 15class PPB_Flash_MessageLoop_Impl::State 16 : public base::RefCounted<PPB_Flash_MessageLoop_Impl::State> { 17 public: 18 State() : result_(PP_OK), run_called_(false), quit_called_(false) { 19 } 20 21 int32_t result() const { return result_; } 22 void set_result(int32_t result) { result_ = result; } 23 24 bool run_called() const { return run_called_; } 25 void set_run_called() { run_called_ = true; } 26 27 bool quit_called() const { return quit_called_; } 28 void set_quit_called() { quit_called_ = true; } 29 30 const RunFromHostProxyCallback& run_callback() const { return run_callback_; } 31 void set_run_callback(const RunFromHostProxyCallback& run_callback) { 32 run_callback_ = run_callback; 33 } 34 35 private: 36 friend class base::RefCounted<State>; 37 virtual ~State() {} 38 39 int32_t result_; 40 bool run_called_; 41 bool quit_called_; 42 RunFromHostProxyCallback run_callback_; 43}; 44 45PPB_Flash_MessageLoop_Impl::PPB_Flash_MessageLoop_Impl(PP_Instance instance) 46 : Resource(ppapi::OBJECT_IS_IMPL, instance), 47 state_(new State()) { 48} 49 50PPB_Flash_MessageLoop_Impl::~PPB_Flash_MessageLoop_Impl() { 51 // It is a no-op if either Run() hasn't been called or Quit() has been called 52 // to balance the call to Run(). 53 InternalQuit(PP_ERROR_ABORTED); 54} 55 56// static 57PP_Resource PPB_Flash_MessageLoop_Impl::Create(PP_Instance instance) { 58 return (new PPB_Flash_MessageLoop_Impl(instance))->GetReference(); 59} 60 61PPB_Flash_MessageLoop_API* 62 PPB_Flash_MessageLoop_Impl::AsPPB_Flash_MessageLoop_API() { 63 return this; 64} 65 66int32_t PPB_Flash_MessageLoop_Impl::Run() { 67 return InternalRun(RunFromHostProxyCallback()); 68} 69 70void PPB_Flash_MessageLoop_Impl::RunFromHostProxy( 71 const RunFromHostProxyCallback& callback) { 72 InternalRun(callback); 73} 74 75void PPB_Flash_MessageLoop_Impl::Quit() { 76 InternalQuit(PP_OK); 77} 78 79int32_t PPB_Flash_MessageLoop_Impl::InternalRun( 80 const RunFromHostProxyCallback& callback) { 81 if (state_->run_called()) { 82 if (!callback.is_null()) 83 callback.Run(PP_ERROR_FAILED); 84 return PP_ERROR_FAILED; 85 } 86 state_->set_run_called(); 87 state_->set_run_callback(callback); 88 89 // It is possible that the PPB_Flash_MessageLoop_Impl object has been 90 // destroyed when the nested message loop exits. 91 scoped_refptr<State> state_protector(state_); 92 { 93 base::MessageLoop::ScopedNestableTaskAllower allow( 94 base::MessageLoop::current()); 95 base::MessageLoop::current()->Run(); 96 } 97 // Don't access data members of the class below. 98 99 return state_protector->result(); 100} 101 102void PPB_Flash_MessageLoop_Impl::InternalQuit(int32_t result) { 103 if (!state_->run_called() || state_->quit_called()) 104 return; 105 state_->set_quit_called(); 106 state_->set_result(result); 107 108 base::MessageLoop::current()->QuitNow(); 109 110 if (!state_->run_callback().is_null()) 111 state_->run_callback().Run(result); 112} 113 114} // namespace content 115