// 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 "content/renderer/pepper/ppb_flash_message_loop_impl.h"

#include "base/callback.h"
#include "base/run_loop.h"
#include "ppapi/c/pp_errors.h"
#include "third_party/blink/public/web/web_view.h"

using ppapi::thunk::PPB_Flash_MessageLoop_API;

namespace content {

class PPB_Flash_MessageLoop_Impl::State
    : public base::RefCounted<PPB_Flash_MessageLoop_Impl::State> {
 public:
  explicit State() : result_(PP_OK), run_called_(false) {}

  int32_t result() const { return result_; }
  void set_result(int32_t result) { result_ = result; }

  bool run_called() const { return run_called_; }
  void set_run_called() { run_called_ = true; }

  void set_quit_closure(base::OnceClosure quit_closure) {
    quit_closure_ = std::move(quit_closure);
  }
  base::OnceClosure& quit_closure() { return quit_closure_; }

  const RunFromHostProxyCallback& run_callback() const { return run_callback_; }
  void set_run_callback(const RunFromHostProxyCallback& run_callback) {
    run_callback_ = run_callback;
  }

 private:
  friend class base::RefCounted<State>;
  virtual ~State() {}

  int32_t result_;
  bool run_called_;
  base::OnceClosure quit_closure_;
  RunFromHostProxyCallback run_callback_;
};

PPB_Flash_MessageLoop_Impl::PPB_Flash_MessageLoop_Impl(PP_Instance instance)
    : Resource(ppapi::OBJECT_IS_IMPL, instance), state_(new State()) {}

PPB_Flash_MessageLoop_Impl::~PPB_Flash_MessageLoop_Impl() {
  // It is a no-op if either Run() hasn't been called or Quit() has been called
  // to balance the call to Run().
  InternalQuit(PP_ERROR_ABORTED);
}

// static
PP_Resource PPB_Flash_MessageLoop_Impl::Create(PP_Instance instance) {
  return (new PPB_Flash_MessageLoop_Impl(instance))->GetReference();
}

PPB_Flash_MessageLoop_API*
PPB_Flash_MessageLoop_Impl::AsPPB_Flash_MessageLoop_API() {
  return this;
}

int32_t PPB_Flash_MessageLoop_Impl::Run() {
  return InternalRun(RunFromHostProxyCallback());
}

void PPB_Flash_MessageLoop_Impl::RunFromHostProxy(
    const RunFromHostProxyCallback& callback) {
  InternalRun(callback);
}

void PPB_Flash_MessageLoop_Impl::Quit() { InternalQuit(PP_OK); }

int32_t PPB_Flash_MessageLoop_Impl::InternalRun(
    const RunFromHostProxyCallback& callback) {
  if (state_->run_called()) {
    if (!callback.is_null())
      callback.Run(PP_ERROR_FAILED);
    return PP_ERROR_FAILED;
  }
  state_->set_run_called();
  state_->set_run_callback(callback);

  base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
  state_->set_quit_closure(run_loop.QuitClosure());

  // It is possible that the PPB_Flash_MessageLoop_Impl object has been
  // destroyed when the nested run loop exits.
  scoped_refptr<State> state_protector(state_);
  {
    blink::WebView::WillEnterModalLoop();

    run_loop.Run();

    blink::WebView::DidExitModalLoop();
  }
  // Don't access data members of the class below.

  return state_protector->result();
}

void PPB_Flash_MessageLoop_Impl::InternalQuit(int32_t result) {
  if (!state_->run_called() || state_->quit_closure().is_null())
    return;
  state_->set_result(result);

  std::move(state_->quit_closure()).Run();

  if (!state_->run_callback().is_null())
    state_->run_callback().Run(result);
}

}  // namespace content
