// 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 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