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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppb_message_loop_proxy.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/c/ppb_message_loop.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/plugin_dispatcher.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/plugin_globals.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/enter.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::thunk::PPB_MessageLoop_API;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace proxy {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef thunk::EnterResource<PPB_MessageLoop_API> EnterMessageLoop;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageLoopResource::MessageLoopResource(PP_Instance instance)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : MessageLoopShared(instance),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nested_invocations_(0),
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      destroyed_(false),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      should_destroy_(false),
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      is_main_thread_loop_(false),
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      currently_handling_blocking_message_(false) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageLoopResource::MessageLoopResource(ForMainThread for_main_thread)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : MessageLoopShared(for_main_thread),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nested_invocations_(0),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      destroyed_(false),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      should_destroy_(false),
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      is_main_thread_loop_(true),
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      currently_handling_blocking_message_(false) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We attach the main thread immediately. We can't use AttachToCurrentThread,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because the MessageLoop already exists.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This must be called only once, so the slot must be empty.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(!PluginGlobals::Get()->msg_loop_slot());
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We don't add a reference for TLS here, so we don't release it. Instead,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // this loop is owned by PluginGlobals. Contrast with AttachToCurrentThread
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // where we register ReleaseMessageLoop with TLS and call AddRef.
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadLocalStorage::Slot* slot = new base::ThreadLocalStorage::Slot();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginGlobals::Get()->set_msg_loop_slot(slot);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  slot->Set(this);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_proxy_ = base::MessageLoopProxy::current();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageLoopResource::~MessageLoopResource() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_MessageLoop_API* MessageLoopResource::AsPPB_MessageLoop_API() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t MessageLoopResource::AttachToCurrentThread() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_main_thread_loop_)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginGlobals* globals = PluginGlobals::Get();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadLocalStorage::Slot* slot = globals->msg_loop_slot();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!slot) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    slot = new base::ThreadLocalStorage::Slot(&ReleaseMessageLoop);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    globals->set_msg_loop_slot(slot);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (slot->Get())
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return PP_ERROR_INPROGRESS;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(dmichael) check that the current thread can support a message loop.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Take a ref to the MessageLoop on behalf of the TLS. Note that this is an
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // internal ref and not a plugin ref so the plugin can't accidentally
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // release it. This is released by ReleaseMessageLoop().
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  slot->Set(this);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  loop_.reset(new base::MessageLoop);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_proxy_ = base::MessageLoopProxy::current();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post all pending work to the message loop.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < pending_tasks_.size(); i++) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TaskInfo& info = pending_tasks_[i];
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostClosure(info.from_here, info.closure, info.delay_ms);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_tasks_.clear();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_OK;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t MessageLoopResource::Run() {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsCurrent())
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_WRONG_THREAD;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_main_thread_loop_)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nested_invocations_++;
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallWhileUnlocked(
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&base::MessageLoop::Run, base::Unretained(loop_.get())));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nested_invocations_--;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (should_destroy_ && nested_invocations_ == 0) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop_proxy_ = NULL;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop_.reset();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    destroyed_ = true;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_OK;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t MessageLoopResource::PostWork(PP_CompletionCallback callback,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int64_t delay_ms) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!callback.func)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (destroyed_)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_FAILED;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostClosure(FROM_HERE,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              base::Bind(callback.func, callback.user_data,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         static_cast<int32_t>(PP_OK)),
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              delay_ms);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_OK;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t MessageLoopResource::PostQuit(PP_Bool should_destroy) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_main_thread_loop_)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_WRONG_THREAD;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (PP_ToBool(should_destroy))
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    should_destroy_ = true;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsCurrent() && nested_invocations_ > 0)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop_->Quit();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PostClosure(FROM_HERE, base::MessageLoop::QuitClosure(), 0);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_OK;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageLoopResource* MessageLoopResource::GetCurrent() {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginGlobals* globals = PluginGlobals::Get();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!globals->msg_loop_slot())
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<MessageLoopResource*>(
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      globals->msg_loop_slot()->Get());
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageLoopResource::DetachFromThread() {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that the message loop must be destroyed on the thread it was created
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_proxy_ = NULL;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_.reset();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel out the AddRef in AttachToCurrentThread().
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DANGER: may delete this.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageLoopResource::IsCurrent() const {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginGlobals* globals = PluginGlobals::Get();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!globals->msg_loop_slot())
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // Can't be current if there's nothing in the slot.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<const void*>(globals->msg_loop_slot()->Get()) ==
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         static_cast<const void*>(this);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageLoopResource::PostClosure(
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& closure,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 delay_ms) {
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (loop_proxy_.get()) {
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    loop_proxy_->PostDelayedTask(
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        from_here, closure, base::TimeDelta::FromMilliseconds(delay_ms));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TaskInfo info;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.from_here = FROM_HERE;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.closure = closure;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.delay_ms = delay_ms;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_tasks_.push_back(info);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::MessageLoopProxy* MessageLoopResource::GetMessageLoopProxy() {
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return loop_proxy_.get();
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool MessageLoopResource::CurrentlyHandlingBlockingMessage() {
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return currently_handling_blocking_message_;
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageLoopResource::ReleaseMessageLoop(void* value) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static_cast<MessageLoopResource*>(value)->DetachFromThread();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Resource Create(PP_Instance instance) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyAutoLock lock;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate the instance.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dispatcher)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (new MessageLoopResource(instance))->GetReference();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Resource GetForMainThread() {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyAutoLock lock;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PluginGlobals::Get()->loop_for_main_thread()->GetReference();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Resource GetCurrent() {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyAutoLock lock;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Resource* resource = MessageLoopResource::GetCurrent();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (resource)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return resource->GetReference();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t AttachToCurrentThread(PP_Resource message_loop) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterMessageLoop enter(message_loop, true);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enter.succeeded())
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return enter.object()->AttachToCurrentThread();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_ERROR_BADRESOURCE;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t Run(PP_Resource message_loop) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterMessageLoop enter(message_loop, true);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enter.succeeded())
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return enter.object()->Run();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_ERROR_BADRESOURCE;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t PostWork(PP_Resource message_loop,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 PP_CompletionCallback callback,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 int64_t delay_ms) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterMessageLoop enter(message_loop, true);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enter.succeeded())
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return enter.object()->PostWork(callback, delay_ms);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_ERROR_BADRESOURCE;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t PostQuit(PP_Resource message_loop, PP_Bool should_destroy) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterMessageLoop enter(message_loop, true);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enter.succeeded())
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return enter.object()->PostQuit(should_destroy);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_ERROR_BADRESOURCE;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const PPB_MessageLoop_1_0 ppb_message_loop_interface = {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &Create,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetForMainThread,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &GetCurrent,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &AttachToCurrentThread,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &Run,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &PostWork,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  &PostQuit
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_MessageLoop_Proxy::PPB_MessageLoop_Proxy(Dispatcher* dispatcher)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterfaceProxy(dispatcher) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_MessageLoop_Proxy::~PPB_MessageLoop_Proxy() {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const PPB_MessageLoop_1_0* PPB_MessageLoop_Proxy::GetInterface() {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &ppb_message_loop_interface;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace proxy
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
285