root/ppapi/proxy/plugin_globals.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. BrowserSender
  2. BrowserSender
  3. Send
  4. weak_factory_
  5. weak_factory_
  6. GetResourceTracker
  7. GetVarTracker
  8. GetCallbackTrackerForInstance
  9. GetInstanceAPI
  10. GetResourceCreationAPI
  11. GetModuleForInstance
  12. GetCmdLine
  13. PreCacheFontForFlash
  14. LogWithSource
  15. BroadcastLogWithSource
  16. GetCurrentMessageLoop
  17. GetFileTaskRunner
  18. MarkPluginIsActive
  19. GetBrowserSender
  20. GetUILanguage
  21. SetActiveURL
  22. CreateBrowserFont
  23. loop_for_main_thread
  24. set_keepalive_throttle_interval_milliseconds
  25. IsPluginGlobals
  26. OnReleaseKeepaliveThrottle

// 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/plugin_globals.h"

#include "base/task_runner.h"
#include "base/threading/thread.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_proxy_delegate.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_message_loop_proxy.h"
#include "ppapi/proxy/resource_reply_thread_registrar.h"
#include "ppapi/shared_impl/ppapi_constants.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/thunk/enter.h"

namespace ppapi {
namespace proxy {

// It performs necessary locking/unlocking of the proxy lock, and forwards all
// messages to the underlying sender.
class PluginGlobals::BrowserSender : public IPC::Sender {
 public:
  // |underlying_sender| must outlive this object.
  explicit BrowserSender(IPC::Sender* underlying_sender)
      : underlying_sender_(underlying_sender) {
  }

  virtual ~BrowserSender() {}

  // IPC::Sender implementation.
  virtual bool Send(IPC::Message* msg) OVERRIDE {
    if (msg->is_sync()) {
      // Synchronous messages might be re-entrant, so we need to drop the lock.
      ProxyAutoUnlock unlock;
      return underlying_sender_->Send(msg);
    }

    return underlying_sender_->Send(msg);
  }

 private:
  // Non-owning pointer.
  IPC::Sender* underlying_sender_;

  DISALLOW_COPY_AND_ASSIGN(BrowserSender);
};

PluginGlobals* PluginGlobals::plugin_globals_ = NULL;

PluginGlobals::PluginGlobals()
    : ppapi::PpapiGlobals(),
      plugin_proxy_delegate_(NULL),
      callback_tracker_(new CallbackTracker),
      resource_reply_thread_registrar_(
          new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())),
      plugin_recently_active_(false),
      keepalive_throttle_interval_milliseconds_(
          ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds),
      weak_factory_(this) {
  DCHECK(!plugin_globals_);
  plugin_globals_ = this;

  // ResourceTracker asserts that we have the lock when we add new resources,
  // so we lock when creating the MessageLoopResource even though there is no
  // chance of race conditions.
  ProxyAutoLock lock;
  loop_for_main_thread_ =
      new MessageLoopResource(MessageLoopResource::ForMainThread());
}

PluginGlobals::PluginGlobals(PerThreadForTest per_thread_for_test)
    : ppapi::PpapiGlobals(per_thread_for_test),
      plugin_proxy_delegate_(NULL),
      callback_tracker_(new CallbackTracker),
      resource_reply_thread_registrar_(
          new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())),
      plugin_recently_active_(false),
      keepalive_throttle_interval_milliseconds_(
          kKeepaliveThrottleIntervalDefaultMilliseconds),
      weak_factory_(this) {
  DCHECK(!plugin_globals_);
}

PluginGlobals::~PluginGlobals() {
  DCHECK(plugin_globals_ == this || !plugin_globals_);
  {
    ProxyAutoLock lock;
    // Release the main-thread message loop. We should have the last reference
    // count, so this will delete the MessageLoop resource. We do this before
    // we clear plugin_globals_, because the Resource destructor tries to access
    // this PluginGlobals.
    DCHECK(!loop_for_main_thread_.get() || loop_for_main_thread_->HasOneRef());
    loop_for_main_thread_ = NULL;
  }
  plugin_globals_ = NULL;
}

ResourceTracker* PluginGlobals::GetResourceTracker() {
  return &plugin_resource_tracker_;
}

VarTracker* PluginGlobals::GetVarTracker() {
  return &plugin_var_tracker_;
}

CallbackTracker* PluginGlobals::GetCallbackTrackerForInstance(
    PP_Instance instance) {
  // In the plugin process, the callback tracker is always the same, regardless
  // of the instance.
  return callback_tracker_.get();
}

thunk::PPB_Instance_API* PluginGlobals::GetInstanceAPI(PP_Instance instance) {
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
  if (dispatcher)
    return dispatcher->GetInstanceAPI();
  return NULL;
}

thunk::ResourceCreationAPI* PluginGlobals::GetResourceCreationAPI(
    PP_Instance instance) {
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
  if (dispatcher)
    return dispatcher->GetResourceCreationAPI();
  return NULL;
}

PP_Module PluginGlobals::GetModuleForInstance(PP_Instance instance) {
  // Currently proxied plugins don't use the PP_Module for anything useful.
  return 0;
}

std::string PluginGlobals::GetCmdLine() {
  return command_line_;
}

void PluginGlobals::PreCacheFontForFlash(const void* logfontw) {
  ProxyAutoUnlock unlock;
  plugin_proxy_delegate_->PreCacheFont(logfontw);
}

void PluginGlobals::LogWithSource(PP_Instance instance,
                                  PP_LogLevel level,
                                  const std::string& source,
                                  const std::string& value) {
  const std::string& fixed_up_source = source.empty() ? plugin_name_ : source;
  PluginDispatcher::LogWithSource(instance, level, fixed_up_source, value);
}

void PluginGlobals::BroadcastLogWithSource(PP_Module /* module */,
                                           PP_LogLevel level,
                                           const std::string& source,
                                           const std::string& value) {
  // Since we have only one module in a plugin process, broadcast is always
  // the same as "send to everybody" which is what the dispatcher implements
  // for the "instance = 0" case.
  LogWithSource(0, level, source, value);
}

MessageLoopShared* PluginGlobals::GetCurrentMessageLoop() {
  return MessageLoopResource::GetCurrent();
}

base::TaskRunner* PluginGlobals::GetFileTaskRunner() {
  if (!file_thread_.get()) {
    file_thread_.reset(new base::Thread("Plugin::File"));
    base::Thread::Options options;
    options.message_loop_type = base::MessageLoop::TYPE_IO;
    file_thread_->StartWithOptions(options);
  }
  return file_thread_->message_loop_proxy();
}

void PluginGlobals::MarkPluginIsActive() {
  if (!plugin_recently_active_) {
    plugin_recently_active_ = true;
    if (!GetBrowserSender() || !base::MessageLoop::current())
      return;
    GetBrowserSender()->Send(new PpapiHostMsg_Keepalive());
    DCHECK(keepalive_throttle_interval_milliseconds_);
    GetMainThreadMessageLoop()->PostDelayedTask(
        FROM_HERE,
        RunWhileLocked(base::Bind(&PluginGlobals::OnReleaseKeepaliveThrottle,
                                  weak_factory_.GetWeakPtr())),
        base::TimeDelta::FromMilliseconds(
            keepalive_throttle_interval_milliseconds_));
  }
}

IPC::Sender* PluginGlobals::GetBrowserSender() {
  if (!browser_sender_.get()) {
    browser_sender_.reset(
        new BrowserSender(plugin_proxy_delegate_->GetBrowserSender()));
  }

  return browser_sender_.get();
}

std::string PluginGlobals::GetUILanguage() {
  return plugin_proxy_delegate_->GetUILanguage();
}

void PluginGlobals::SetActiveURL(const std::string& url) {
  plugin_proxy_delegate_->SetActiveURL(url);
}

PP_Resource PluginGlobals::CreateBrowserFont(
    Connection connection,
    PP_Instance instance,
    const PP_BrowserFont_Trusted_Description& desc,
    const ppapi::Preferences& prefs) {
  return plugin_proxy_delegate_->CreateBrowserFont(
      connection, instance, desc, prefs);
}

MessageLoopResource* PluginGlobals::loop_for_main_thread() {
  return loop_for_main_thread_.get();
}

void PluginGlobals::set_keepalive_throttle_interval_milliseconds(unsigned i) {
  keepalive_throttle_interval_milliseconds_ = i;
}

bool PluginGlobals::IsPluginGlobals() const {
  return true;
}

void PluginGlobals::OnReleaseKeepaliveThrottle() {
  ppapi::ProxyLock::AssertAcquiredDebugOnly();
  plugin_recently_active_ = false;
}

}  // namespace proxy
}  // namespace ppapi

/* [<][>][^][v][top][bottom][index][help] */