// 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/single_thread_task_runner.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::SingleThreadTaskRunner>& 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::SingleThreadTaskRunner>& 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
