15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/ppb_flash_message_loop_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::thunk::PPB_Flash_MessageLoop_API;
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochnamespace content {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PPB_Flash_MessageLoop_Impl::State
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCounted<PPB_Flash_MessageLoop_Impl::State> {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
18a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  State() : result_(PP_OK), run_called_(false), quit_called_(false) {}
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result() const { return result_; }
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_result(int32_t result) { result_ = result; }
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool run_called() const { return run_called_; }
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_run_called() { run_called_ = true; }
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool quit_called() const { return quit_called_; }
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_quit_called() { quit_called_ = true; }
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const RunFromHostProxyCallback& run_callback() const { return run_callback_; }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_run_callback(const RunFromHostProxyCallback& run_callback) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run_callback_ = run_callback;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
35bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  friend class base::RefCounted<State>;
36bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual ~State() {}
37bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result_;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool run_called_;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool quit_called_;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunFromHostProxyCallback run_callback_;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_Flash_MessageLoop_Impl::PPB_Flash_MessageLoop_Impl(PP_Instance instance)
45a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : Resource(ppapi::OBJECT_IS_IMPL, instance), state_(new State()) {}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_Flash_MessageLoop_Impl::~PPB_Flash_MessageLoop_Impl() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is a no-op if either Run() hasn't been called or Quit() has been called
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to balance the call to Run().
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InternalQuit(PP_ERROR_ABORTED);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Resource PPB_Flash_MessageLoop_Impl::Create(PP_Instance instance) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (new PPB_Flash_MessageLoop_Impl(instance))->GetReference();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_Flash_MessageLoop_API*
59a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochPPB_Flash_MessageLoop_Impl::AsPPB_Flash_MessageLoop_API() {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t PPB_Flash_MessageLoop_Impl::Run() {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return InternalRun(RunFromHostProxyCallback());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Flash_MessageLoop_Impl::RunFromHostProxy(
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RunFromHostProxyCallback& callback) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InternalRun(callback);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid PPB_Flash_MessageLoop_Impl::Quit() { InternalQuit(PP_OK); }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t PPB_Flash_MessageLoop_Impl::InternalRun(
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RunFromHostProxyCallback& callback) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_->run_called()) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback.is_null())
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(PP_ERROR_FAILED);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_FAILED;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_->set_run_called();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_->set_run_callback(callback);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is possible that the PPB_Flash_MessageLoop_Impl object has been
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destroyed when the nested message loop exits.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<State> state_protector(state_);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::MessageLoop::ScopedNestableTaskAllower allow(
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        base::MessageLoop::current());
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::MessageLoop::current()->Run();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't access data members of the class below.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state_protector->result();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Flash_MessageLoop_Impl::InternalQuit(int32_t result) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!state_->run_called() || state_->quit_called())
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_->set_quit_called();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_->set_result(result);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->QuitNow();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!state_->run_callback().is_null())
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_->run_callback().Run(result);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}  // namespace content
110