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

#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "content/browser/utility_process_host_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/plugin_list.h"
#include "content/common/utility_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"

namespace content {

PluginLoaderPosix::PluginLoaderPosix()
    : next_load_index_(0) {
}

void PluginLoaderPosix::LoadPlugins(
    scoped_refptr<base::MessageLoopProxy> target_loop,
    const PluginService::GetPluginsCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  callbacks_.push_back(PendingCallback(target_loop, callback));

  if (callbacks_.size() == 1) {
    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
        base::Bind(&PluginLoaderPosix::GetPluginsToLoad, this));
  }
}

bool PluginLoaderPosix::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(PluginLoaderPosix, message)
    IPC_MESSAGE_HANDLER(UtilityHostMsg_LoadedPlugin, OnPluginLoaded)
    IPC_MESSAGE_HANDLER(UtilityHostMsg_LoadPluginFailed, OnPluginLoadFailed)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void PluginLoaderPosix::OnProcessCrashed(int exit_code) {
  if (next_load_index_ == canonical_list_.size()) {
    // How this case occurs is unknown. See crbug.com/111935.
    canonical_list_.clear();
  } else {
    canonical_list_.erase(canonical_list_.begin(),
                          canonical_list_.begin() + next_load_index_ + 1);
  }

  next_load_index_ = 0;

  LoadPluginsInternal();
}

bool PluginLoaderPosix::Send(IPC::Message* message) {
  if (process_host_.get())
    return process_host_->Send(message);
  return false;
}

PluginLoaderPosix::~PluginLoaderPosix() {
}

void PluginLoaderPosix::GetPluginsToLoad() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  base::TimeTicks start_time(base::TimeTicks::Now());

  loaded_plugins_.clear();
  next_load_index_ = 0;

  canonical_list_.clear();
  PluginList::Singleton()->GetPluginPathsToLoad(
      &canonical_list_,
      PluginService::GetInstance()->NPAPIPluginsSupported());

  internal_plugins_.clear();
  PluginList::Singleton()->GetInternalPlugins(&internal_plugins_);

  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
      base::Bind(&PluginLoaderPosix::LoadPluginsInternal,
                 make_scoped_refptr(this)));

  HISTOGRAM_TIMES("PluginLoaderPosix.GetPluginList",
                  (base::TimeTicks::Now() - start_time) *
                      base::Time::kMicrosecondsPerMillisecond);
}

void PluginLoaderPosix::LoadPluginsInternal() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  // Check if the list is empty or all plugins have already been loaded before
  // forking.
  if (MaybeRunPendingCallbacks())
    return;

  if (load_start_time_.is_null())
    load_start_time_ = base::TimeTicks::Now();

  UtilityProcessHostImpl* host = new UtilityProcessHostImpl(
      this,
      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get());
  process_host_ = host->AsWeakPtr();
  process_host_->DisableSandbox();
#if defined(OS_MACOSX)
  host->set_child_flags(ChildProcessHost::CHILD_ALLOW_HEAP_EXECUTION);
#endif

  process_host_->Send(new UtilityMsg_LoadPlugins(canonical_list_));
}

void PluginLoaderPosix::OnPluginLoaded(uint32 index,
                                       const WebPluginInfo& plugin) {
  if (index != next_load_index_) {
    LOG(ERROR) << "Received unexpected plugin load message for "
               << plugin.path.value() << "; index=" << index;
    return;
  }

  if (!MaybeAddInternalPlugin(plugin.path))
    loaded_plugins_.push_back(plugin);

  ++next_load_index_;

  MaybeRunPendingCallbacks();
}

void PluginLoaderPosix::OnPluginLoadFailed(uint32 index,
                                           const base::FilePath& plugin_path) {
  if (index != next_load_index_) {
    LOG(ERROR) << "Received unexpected plugin load failure message for "
               << plugin_path.value() << "; index=" << index;
    return;
  }

  ++next_load_index_;

  MaybeAddInternalPlugin(plugin_path);
  MaybeRunPendingCallbacks();
}

bool PluginLoaderPosix::MaybeAddInternalPlugin(
    const base::FilePath& plugin_path) {
  for (std::vector<WebPluginInfo>::iterator it = internal_plugins_.begin();
       it != internal_plugins_.end();
       ++it) {
    if (it->path == plugin_path) {
      loaded_plugins_.push_back(*it);
      internal_plugins_.erase(it);
      return true;
    }
  }
  return false;
}

bool PluginLoaderPosix::MaybeRunPendingCallbacks() {
  if (next_load_index_ < canonical_list_.size())
    return false;

  PluginList::Singleton()->SetPlugins(loaded_plugins_);

  // Only call the first callback with loaded plugins because there may be
  // some extra plugin paths added since the first callback is added.
  if (!callbacks_.empty()) {
    PendingCallback callback = callbacks_.front();
    callbacks_.pop_front();
    callback.target_loop->PostTask(
        FROM_HERE,
        base::Bind(callback.callback, loaded_plugins_));
  }

  HISTOGRAM_TIMES("PluginLoaderPosix.LoadDone",
                  (base::TimeTicks::Now() - load_start_time_)
                      * base::Time::kMicrosecondsPerMillisecond);
  load_start_time_ = base::TimeTicks();

  if (!callbacks_.empty()) {
    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
        base::Bind(&PluginLoaderPosix::GetPluginsToLoad, this));
    return false;
  }
  return true;
}

PluginLoaderPosix::PendingCallback::PendingCallback(
    scoped_refptr<base::MessageLoopProxy> loop,
    const PluginService::GetPluginsCallback& cb)
    : target_loop(loop),
      callback(cb) {
}

PluginLoaderPosix::PendingCallback::~PendingCallback() {
}

}  // namespace content
