// 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/macros.h"
#include "base/message_loop/message_pump_type.h"
#include "base/task_runner.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_message_filter.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/proxy/udp_socket_filter.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) {
  }

  ~BrowserSender() override {}

  // IPC::Sender implementation.
  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(
    const scoped_refptr<base::TaskRunner>& ipc_task_runner)
    : ppapi::PpapiGlobals(),
      plugin_proxy_delegate_(NULL),
      callback_tracker_(new CallbackTracker),
      ipc_task_runner_(ipc_task_runner),
      resource_reply_thread_registrar_(
          new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())),
      udp_socket_filter_(new UDPSocketFilter()) {
  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,
    const scoped_refptr<base::TaskRunner>& ipc_task_runner)
    : ppapi::PpapiGlobals(per_thread_for_test),
      plugin_proxy_delegate_(NULL),
      callback_tracker_(new CallbackTracker),
      ipc_task_runner_(ipc_task_runner),
      resource_reply_thread_registrar_(
          new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())) {
  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_.reset();
  }
  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_->PreCacheFontForFlash(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_pump_type = base::MessagePumpType::IO;
    file_thread_->StartWithOptions(options);
  }
  return file_thread_->task_runner().get();
}

IPC::Sender* PluginGlobals::GetBrowserSender() {
  // CAUTION: This function is called without the ProxyLock. See also
  // InterfaceList::GetInterfaceForPPB.
  //
  // See also SetPluginProxyDelegate. That initializes browser_sender_ before
  // the plugin can start threads, and it may be cleared after the
  // plugin has torn down threads. So this pointer is expected to remain valid
  // during the lifetime of the plugin.
  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);
}

void PluginGlobals::SetPluginProxyDelegate(PluginProxyDelegate* delegate) {
  DCHECK(delegate && !plugin_proxy_delegate_);
  plugin_proxy_delegate_ = delegate;
  browser_sender_.reset(
      new BrowserSender(plugin_proxy_delegate_->GetBrowserSender()));
}

void PluginGlobals::ResetPluginProxyDelegate() {
  DCHECK(plugin_proxy_delegate_);
  plugin_proxy_delegate_ = NULL;
  browser_sender_.reset();
}

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

void PluginGlobals::RegisterResourceMessageFilters(
    ppapi::proxy::PluginMessageFilter* plugin_filter) {
  plugin_filter->AddResourceMessageFilter(udp_socket_filter_.get());
}

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

}  // namespace proxy
}  // namespace ppapi
