// 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 "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.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 in_request_id)
: dispatcher(in_dispatcher),
request_id(in_request_id) {
}
base::WeakPtr<BrokerProcessDispatcher> dispatcher;
uint32 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[]) {
scoped_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)
: 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) {
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) {
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(return BrokerSideDispatcher::OnMessageReceived(msg))
IPC_END_MESSAGE_MAP()
return true;
}
void BrokerProcessDispatcher::OnGetPermissionSettingsCompleted(
uint32 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 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 request_id,
const base::FilePath& plugin_data_path,
const std::string& site,
uint64 flags,
uint64 max_age) {
Send(new PpapiHostMsg_ClearSiteDataResult(
request_id, ClearSiteData(plugin_data_path, site, flags, max_age)));
}
void BrokerProcessDispatcher::OnDeauthorizeContentLicenses(
uint32 request_id,
const base::FilePath& plugin_data_path) {
Send(new PpapiHostMsg_DeauthorizeContentLicensesResult(
request_id, DeauthorizeContentLicenses(plugin_data_path)));
}
void BrokerProcessDispatcher::OnGetPermissionSettings(
uint32 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 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 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 flags,
uint64 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);
scoped_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, 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, sites.size(), site_array.get());
return PP_ToBool(result);
}
return false;
}
} // namespace content