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

#include <stddef.h>

#include <memory>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "content/child/child_process.h"
#include "ppapi/c/pp_bool.h"
#include "ppapi/c/private/ppp_flash_browser_operations.h"
#include "ppapi/proxy/ppapi_messages.h"

namespace content {
namespace {

// How long we wait before releasing the broker process.
const int kBrokerReleaseTimeSeconds = 30;

std::string ConvertPluginDataPath(const base::FilePath& plugin_data_path) {
  // The string is always 8-bit, convert on Windows.
#if defined(OS_WIN)
  return base::WideToUTF8(plugin_data_path.value());
#else
  return plugin_data_path.value();
#endif
}

struct GetPermissionSettingsContext {
  GetPermissionSettingsContext(
      const base::WeakPtr<BrokerProcessDispatcher> in_dispatcher,
      uint32_t in_request_id)
      : dispatcher(in_dispatcher), request_id(in_request_id) {}

  base::WeakPtr<BrokerProcessDispatcher> dispatcher;
  uint32_t request_id;
};

void GetPermissionSettingsCallback(
    void* user_data,
    PP_Bool success,
    PP_Flash_BrowserOperations_Permission default_permission,
    uint32_t site_count,
    const PP_Flash_BrowserOperations_SiteSetting sites[]) {
  std::unique_ptr<GetPermissionSettingsContext> context(
      reinterpret_cast<GetPermissionSettingsContext*>(user_data));

  if (!context->dispatcher.get())
    return;

  ppapi::FlashSiteSettings site_vector;
  if (success) {
    site_vector.reserve(site_count);
    for (uint32_t i = 0; i < site_count; ++i) {
      if (!sites[i].site) {
        success = PP_FALSE;
        break;
      }
      site_vector.push_back(
          ppapi::FlashSiteSetting(sites[i].site, sites[i].permission));
    }

    if (!success)
      site_vector.clear();
  }
  context->dispatcher->OnGetPermissionSettingsCompleted(
      context->request_id, PP_ToBool(success), default_permission, site_vector);
}

}  // namespace

BrokerProcessDispatcher::BrokerProcessDispatcher(
    PP_GetInterface_Func get_plugin_interface,
    PP_ConnectInstance_Func connect_instance,
    bool peer_is_browser)
    : ppapi::proxy::BrokerSideDispatcher(connect_instance),
      get_plugin_interface_(get_plugin_interface),
      flash_browser_operations_1_3_(NULL),
      flash_browser_operations_1_2_(NULL),
      flash_browser_operations_1_0_(NULL),
      peer_is_browser_(peer_is_browser) {
  if (get_plugin_interface) {
    flash_browser_operations_1_0_ =
        static_cast<const PPP_Flash_BrowserOperations_1_0*>(
            get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_0));

    flash_browser_operations_1_2_ =
        static_cast<const PPP_Flash_BrowserOperations_1_2*>(
            get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_2));

    flash_browser_operations_1_3_ =
        static_cast<const PPP_Flash_BrowserOperations_1_3*>(
            get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_3));
  }
}

BrokerProcessDispatcher::~BrokerProcessDispatcher() {
  DVLOG(1) << "BrokerProcessDispatcher::~BrokerProcessDispatcher()";
  // Don't free the process right away. This timer allows the child process
  // to be re-used if the user rapidly goes to a new page that requires this
  // plugin. This is the case for common plugins where they may be used on a
  // source and destination page of a navigation. We don't want to tear down
  // and re-start processes each time in these cases.
  process_ref_.ReleaseWithDelay(
      base::TimeDelta::FromSeconds(kBrokerReleaseTimeSeconds));
}

bool BrokerProcessDispatcher::OnMessageReceived(const IPC::Message& msg) {
  if (BrokerSideDispatcher::OnMessageReceived(msg))
    return true;

  if (!peer_is_browser_) {
    // We might want to consider killing the peer instead is we see problems in
    // the future.
    return false;
  }

  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(BrokerProcessDispatcher, msg)
    IPC_MESSAGE_HANDLER(PpapiMsg_GetSitesWithData, OnGetSitesWithData)
    IPC_MESSAGE_HANDLER(PpapiMsg_ClearSiteData, OnClearSiteData)
    IPC_MESSAGE_HANDLER(PpapiMsg_DeauthorizeContentLicenses,
                        OnDeauthorizeContentLicenses)
    IPC_MESSAGE_HANDLER(PpapiMsg_GetPermissionSettings,
                        OnGetPermissionSettings)
    IPC_MESSAGE_HANDLER(PpapiMsg_SetDefaultPermission, OnSetDefaultPermission)
    IPC_MESSAGE_HANDLER(PpapiMsg_SetSitePermission, OnSetSitePermission)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void BrokerProcessDispatcher::OnGetPermissionSettingsCompleted(
    uint32_t request_id,
    bool success,
    PP_Flash_BrowserOperations_Permission default_permission,
    const ppapi::FlashSiteSettings& sites) {
  Send(new PpapiHostMsg_GetPermissionSettingsResult(
      request_id, success, default_permission, sites));
}

void BrokerProcessDispatcher::OnGetSitesWithData(
    uint32_t request_id,
    const base::FilePath& plugin_data_path) {
  std::vector<std::string> sites;
  GetSitesWithData(plugin_data_path, &sites);
  Send(new PpapiHostMsg_GetSitesWithDataResult(request_id, sites));
}

void BrokerProcessDispatcher::OnClearSiteData(
    uint32_t request_id,
    const base::FilePath& plugin_data_path,
    const std::string& site,
    uint64_t flags,
    uint64_t max_age) {
  Send(new PpapiHostMsg_ClearSiteDataResult(
      request_id, ClearSiteData(plugin_data_path, site, flags, max_age)));
}

void BrokerProcessDispatcher::OnDeauthorizeContentLicenses(
    uint32_t request_id,
    const base::FilePath& plugin_data_path) {
  Send(new PpapiHostMsg_DeauthorizeContentLicensesResult(
      request_id, DeauthorizeContentLicenses(plugin_data_path)));
}

void BrokerProcessDispatcher::OnGetPermissionSettings(
    uint32_t request_id,
    const base::FilePath& plugin_data_path,
    PP_Flash_BrowserOperations_SettingType setting_type) {
  if (flash_browser_operations_1_3_) {
    std::string data_str = ConvertPluginDataPath(plugin_data_path);
    // The GetPermissionSettingsContext object will be deleted in
    // GetPermissionSettingsCallback().
    flash_browser_operations_1_3_->GetPermissionSettings(
        data_str.c_str(), setting_type, &GetPermissionSettingsCallback,
        new GetPermissionSettingsContext(AsWeakPtr(), request_id));
    return;
  }

  if (flash_browser_operations_1_2_) {
    std::string data_str = ConvertPluginDataPath(plugin_data_path);
    // The GetPermissionSettingsContext object will be deleted in
    // GetPermissionSettingsCallback().
    flash_browser_operations_1_2_->GetPermissionSettings(
        data_str.c_str(), setting_type, &GetPermissionSettingsCallback,
        new GetPermissionSettingsContext(AsWeakPtr(), request_id));
    return;
  }

  OnGetPermissionSettingsCompleted(
      request_id, false, PP_FLASH_BROWSEROPERATIONS_PERMISSION_DEFAULT,
      ppapi::FlashSiteSettings());
  return;
}

void BrokerProcessDispatcher::OnSetDefaultPermission(
    uint32_t request_id,
    const base::FilePath& plugin_data_path,
    PP_Flash_BrowserOperations_SettingType setting_type,
    PP_Flash_BrowserOperations_Permission permission,
    bool clear_site_specific) {
  Send(new PpapiHostMsg_SetDefaultPermissionResult(
      request_id,
      SetDefaultPermission(plugin_data_path, setting_type, permission,
                           clear_site_specific)));
}

void BrokerProcessDispatcher::OnSetSitePermission(
    uint32_t request_id,
    const base::FilePath& plugin_data_path,
    PP_Flash_BrowserOperations_SettingType setting_type,
    const ppapi::FlashSiteSettings& sites) {
  Send(new PpapiHostMsg_SetSitePermissionResult(
      request_id, SetSitePermission(plugin_data_path, setting_type, sites)));
}

void BrokerProcessDispatcher::GetSitesWithData(
    const base::FilePath& plugin_data_path,
    std::vector<std::string>* site_vector) {
  std::string data_str = ConvertPluginDataPath(plugin_data_path);
  if (flash_browser_operations_1_3_) {
    char** sites = NULL;
    flash_browser_operations_1_3_->GetSitesWithData(data_str.c_str(), &sites);
    if (!sites)
      return;

    for (size_t i = 0; sites[i]; ++i)
      site_vector->push_back(sites[i]);

    flash_browser_operations_1_3_->FreeSiteList(sites);
  }
}

bool BrokerProcessDispatcher::ClearSiteData(
    const base::FilePath& plugin_data_path,
    const std::string& site,
    uint64_t flags,
    uint64_t max_age) {
  std::string data_str = ConvertPluginDataPath(plugin_data_path);
  if (flash_browser_operations_1_3_) {
    flash_browser_operations_1_3_->ClearSiteData(
        data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age);
    return true;
  }

  // TODO(viettrungluu): Remove this (and the 1.0 interface) sometime after M21
  // goes to Stable.
  if (flash_browser_operations_1_2_) {
    flash_browser_operations_1_2_->ClearSiteData(
        data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age);
    return true;
  }

  if (flash_browser_operations_1_0_) {
    flash_browser_operations_1_0_->ClearSiteData(
        data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age);
    return true;
  }

  return false;
}

bool BrokerProcessDispatcher::DeauthorizeContentLicenses(
    const base::FilePath& plugin_data_path) {
  if (flash_browser_operations_1_3_) {
    std::string data_str = ConvertPluginDataPath(plugin_data_path);
    return PP_ToBool(flash_browser_operations_1_3_->DeauthorizeContentLicenses(
        data_str.c_str()));
  }

  if (flash_browser_operations_1_2_) {
    std::string data_str = ConvertPluginDataPath(plugin_data_path);
    return PP_ToBool(flash_browser_operations_1_2_->DeauthorizeContentLicenses(
        data_str.c_str()));
  }

  return false;
}

bool BrokerProcessDispatcher::SetDefaultPermission(
    const base::FilePath& plugin_data_path,
    PP_Flash_BrowserOperations_SettingType setting_type,
    PP_Flash_BrowserOperations_Permission permission,
    bool clear_site_specific) {
  if (flash_browser_operations_1_3_) {
    std::string data_str = ConvertPluginDataPath(plugin_data_path);
    return PP_ToBool(flash_browser_operations_1_3_->SetDefaultPermission(
        data_str.c_str(), setting_type, permission,
        PP_FromBool(clear_site_specific)));
  }

  if (flash_browser_operations_1_2_) {
    std::string data_str = ConvertPluginDataPath(plugin_data_path);
    return PP_ToBool(flash_browser_operations_1_2_->SetDefaultPermission(
        data_str.c_str(), setting_type, permission,
        PP_FromBool(clear_site_specific)));
  }

  return false;
}

bool BrokerProcessDispatcher::SetSitePermission(
    const base::FilePath& plugin_data_path,
    PP_Flash_BrowserOperations_SettingType setting_type,
    const ppapi::FlashSiteSettings& sites) {
  if (sites.empty())
    return true;

  std::string data_str = ConvertPluginDataPath(plugin_data_path);
  std::unique_ptr<PP_Flash_BrowserOperations_SiteSetting[]> site_array(
      new PP_Flash_BrowserOperations_SiteSetting[sites.size()]);

  for (size_t i = 0; i < sites.size(); ++i) {
    site_array[i].site = sites[i].site.c_str();
    site_array[i].permission = sites[i].permission;
  }

  if (flash_browser_operations_1_3_) {
    PP_Bool result = flash_browser_operations_1_3_->SetSitePermission(
        data_str.c_str(), setting_type,
        static_cast<uint32_t>(sites.size()), site_array.get());

    return PP_ToBool(result);
  }

  if (flash_browser_operations_1_2_) {
    PP_Bool result = flash_browser_operations_1_2_->SetSitePermission(
        data_str.c_str(), setting_type,
        static_cast<uint32_t>(sites.size()), site_array.get());

    return PP_ToBool(result);
  }

  return false;
}

}  // namespace content
