1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/ppapi_plugin/broker_process_dispatcher.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "content/child/child_process.h" 12 #include "ppapi/c/pp_bool.h" 13 #include "ppapi/c/private/ppp_flash_browser_operations.h" 14 #include "ppapi/proxy/ppapi_messages.h" 15 16 namespace content { 17 namespace { 18 19 // How long we wait before releasing the broker process. 20 const int kBrokerReleaseTimeSeconds = 30; 21 22 std::string ConvertPluginDataPath(const base::FilePath& plugin_data_path) { 23 // The string is always 8-bit, convert on Windows. 24 #if defined(OS_WIN) 25 return base::WideToUTF8(plugin_data_path.value()); 26 #else 27 return plugin_data_path.value(); 28 #endif 29 } 30 31 struct GetPermissionSettingsContext { 32 GetPermissionSettingsContext( 33 const base::WeakPtr<BrokerProcessDispatcher> in_dispatcher, 34 uint32 in_request_id) 35 : dispatcher(in_dispatcher), 36 request_id(in_request_id) { 37 } 38 39 base::WeakPtr<BrokerProcessDispatcher> dispatcher; 40 uint32 request_id; 41 }; 42 43 void GetPermissionSettingsCallback( 44 void* user_data, 45 PP_Bool success, 46 PP_Flash_BrowserOperations_Permission default_permission, 47 uint32_t site_count, 48 const PP_Flash_BrowserOperations_SiteSetting sites[]) { 49 scoped_ptr<GetPermissionSettingsContext> context( 50 reinterpret_cast<GetPermissionSettingsContext*>(user_data)); 51 52 if (!context->dispatcher.get()) 53 return; 54 55 ppapi::FlashSiteSettings site_vector; 56 if (success) { 57 site_vector.reserve(site_count); 58 for (uint32_t i = 0; i < site_count; ++i) { 59 if (!sites[i].site) { 60 success = PP_FALSE; 61 break; 62 } 63 site_vector.push_back( 64 ppapi::FlashSiteSetting(sites[i].site, sites[i].permission)); 65 } 66 67 if (!success) 68 site_vector.clear(); 69 } 70 context->dispatcher->OnGetPermissionSettingsCompleted( 71 context->request_id, PP_ToBool(success), default_permission, site_vector); 72 } 73 74 } // namespace 75 76 BrokerProcessDispatcher::BrokerProcessDispatcher( 77 PP_GetInterface_Func get_plugin_interface, 78 PP_ConnectInstance_Func connect_instance) 79 : ppapi::proxy::BrokerSideDispatcher(connect_instance), 80 get_plugin_interface_(get_plugin_interface), 81 flash_browser_operations_1_3_(NULL), 82 flash_browser_operations_1_2_(NULL), 83 flash_browser_operations_1_0_(NULL) { 84 if (get_plugin_interface) { 85 flash_browser_operations_1_0_ = 86 static_cast<const PPP_Flash_BrowserOperations_1_0*>( 87 get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_0)); 88 89 flash_browser_operations_1_2_ = 90 static_cast<const PPP_Flash_BrowserOperations_1_2*>( 91 get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_2)); 92 93 flash_browser_operations_1_3_ = 94 static_cast<const PPP_Flash_BrowserOperations_1_3*>( 95 get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_3)); 96 } 97 } 98 99 BrokerProcessDispatcher::~BrokerProcessDispatcher() { 100 DVLOG(1) << "BrokerProcessDispatcher::~BrokerProcessDispatcher()"; 101 // Don't free the process right away. This timer allows the child process 102 // to be re-used if the user rapidly goes to a new page that requires this 103 // plugin. This is the case for common plugins where they may be used on a 104 // source and destination page of a navigation. We don't want to tear down 105 // and re-start processes each time in these cases. 106 process_ref_.ReleaseWithDelay( 107 base::TimeDelta::FromSeconds(kBrokerReleaseTimeSeconds)); 108 } 109 110 bool BrokerProcessDispatcher::OnMessageReceived(const IPC::Message& msg) { 111 IPC_BEGIN_MESSAGE_MAP(BrokerProcessDispatcher, msg) 112 IPC_MESSAGE_HANDLER(PpapiMsg_GetSitesWithData, OnGetSitesWithData) 113 IPC_MESSAGE_HANDLER(PpapiMsg_ClearSiteData, OnClearSiteData) 114 IPC_MESSAGE_HANDLER(PpapiMsg_DeauthorizeContentLicenses, 115 OnDeauthorizeContentLicenses) 116 IPC_MESSAGE_HANDLER(PpapiMsg_GetPermissionSettings, OnGetPermissionSettings) 117 IPC_MESSAGE_HANDLER(PpapiMsg_SetDefaultPermission, OnSetDefaultPermission) 118 IPC_MESSAGE_HANDLER(PpapiMsg_SetSitePermission, OnSetSitePermission) 119 IPC_MESSAGE_UNHANDLED(return BrokerSideDispatcher::OnMessageReceived(msg)) 120 IPC_END_MESSAGE_MAP() 121 return true; 122 } 123 124 void BrokerProcessDispatcher::OnGetPermissionSettingsCompleted( 125 uint32 request_id, 126 bool success, 127 PP_Flash_BrowserOperations_Permission default_permission, 128 const ppapi::FlashSiteSettings& sites) { 129 Send(new PpapiHostMsg_GetPermissionSettingsResult( 130 request_id, success, default_permission, sites)); 131 } 132 133 void BrokerProcessDispatcher::OnGetSitesWithData( 134 uint32 request_id, 135 const base::FilePath& plugin_data_path) { 136 std::vector<std::string> sites; 137 GetSitesWithData(plugin_data_path, &sites); 138 Send(new PpapiHostMsg_GetSitesWithDataResult(request_id, sites)); 139 } 140 141 void BrokerProcessDispatcher::OnClearSiteData( 142 uint32 request_id, 143 const base::FilePath& plugin_data_path, 144 const std::string& site, 145 uint64 flags, 146 uint64 max_age) { 147 Send(new PpapiHostMsg_ClearSiteDataResult( 148 request_id, ClearSiteData(plugin_data_path, site, flags, max_age))); 149 } 150 151 void BrokerProcessDispatcher::OnDeauthorizeContentLicenses( 152 uint32 request_id, 153 const base::FilePath& plugin_data_path) { 154 Send(new PpapiHostMsg_DeauthorizeContentLicensesResult( 155 request_id, DeauthorizeContentLicenses(plugin_data_path))); 156 } 157 158 void BrokerProcessDispatcher::OnGetPermissionSettings( 159 uint32 request_id, 160 const base::FilePath& plugin_data_path, 161 PP_Flash_BrowserOperations_SettingType setting_type) { 162 if (flash_browser_operations_1_3_) { 163 std::string data_str = ConvertPluginDataPath(plugin_data_path); 164 // The GetPermissionSettingsContext object will be deleted in 165 // GetPermissionSettingsCallback(). 166 flash_browser_operations_1_3_->GetPermissionSettings( 167 data_str.c_str(), setting_type, &GetPermissionSettingsCallback, 168 new GetPermissionSettingsContext(AsWeakPtr(), request_id)); 169 return; 170 } 171 172 if (flash_browser_operations_1_2_) { 173 std::string data_str = ConvertPluginDataPath(plugin_data_path); 174 // The GetPermissionSettingsContext object will be deleted in 175 // GetPermissionSettingsCallback(). 176 flash_browser_operations_1_2_->GetPermissionSettings( 177 data_str.c_str(), setting_type, &GetPermissionSettingsCallback, 178 new GetPermissionSettingsContext(AsWeakPtr(), request_id)); 179 return; 180 } 181 182 OnGetPermissionSettingsCompleted( 183 request_id, false, PP_FLASH_BROWSEROPERATIONS_PERMISSION_DEFAULT, 184 ppapi::FlashSiteSettings()); 185 return; 186 } 187 188 void BrokerProcessDispatcher::OnSetDefaultPermission( 189 uint32 request_id, 190 const base::FilePath& plugin_data_path, 191 PP_Flash_BrowserOperations_SettingType setting_type, 192 PP_Flash_BrowserOperations_Permission permission, 193 bool clear_site_specific) { 194 Send(new PpapiHostMsg_SetDefaultPermissionResult( 195 request_id, 196 SetDefaultPermission(plugin_data_path, setting_type, permission, 197 clear_site_specific))); 198 } 199 200 void BrokerProcessDispatcher::OnSetSitePermission( 201 uint32 request_id, 202 const base::FilePath& plugin_data_path, 203 PP_Flash_BrowserOperations_SettingType setting_type, 204 const ppapi::FlashSiteSettings& sites) { 205 Send(new PpapiHostMsg_SetSitePermissionResult( 206 request_id, SetSitePermission(plugin_data_path, setting_type, sites))); 207 } 208 209 void BrokerProcessDispatcher::GetSitesWithData( 210 const base::FilePath& plugin_data_path, 211 std::vector<std::string>* site_vector) { 212 std::string data_str = ConvertPluginDataPath(plugin_data_path); 213 if (flash_browser_operations_1_3_) { 214 char** sites = NULL; 215 flash_browser_operations_1_3_->GetSitesWithData(data_str.c_str(), &sites); 216 if (!sites) 217 return; 218 219 for (size_t i = 0; sites[i]; ++i) 220 site_vector->push_back(sites[i]); 221 222 flash_browser_operations_1_3_->FreeSiteList(sites); 223 } 224 } 225 226 bool BrokerProcessDispatcher::ClearSiteData( 227 const base::FilePath& plugin_data_path, 228 const std::string& site, 229 uint64 flags, 230 uint64 max_age) { 231 std::string data_str = ConvertPluginDataPath(plugin_data_path); 232 if (flash_browser_operations_1_3_) { 233 flash_browser_operations_1_3_->ClearSiteData( 234 data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age); 235 return true; 236 } 237 238 // TODO(viettrungluu): Remove this (and the 1.0 interface) sometime after M21 239 // goes to Stable. 240 if (flash_browser_operations_1_2_) { 241 flash_browser_operations_1_2_->ClearSiteData( 242 data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age); 243 return true; 244 } 245 246 if (flash_browser_operations_1_0_) { 247 flash_browser_operations_1_0_->ClearSiteData( 248 data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age); 249 return true; 250 } 251 252 return false; 253 } 254 255 bool BrokerProcessDispatcher::DeauthorizeContentLicenses( 256 const base::FilePath& plugin_data_path) { 257 if (flash_browser_operations_1_3_) { 258 std::string data_str = ConvertPluginDataPath(plugin_data_path); 259 return PP_ToBool(flash_browser_operations_1_3_->DeauthorizeContentLicenses( 260 data_str.c_str())); 261 } 262 263 if (flash_browser_operations_1_2_) { 264 std::string data_str = ConvertPluginDataPath(plugin_data_path); 265 return PP_ToBool(flash_browser_operations_1_2_->DeauthorizeContentLicenses( 266 data_str.c_str())); 267 } 268 269 return false; 270 } 271 272 bool BrokerProcessDispatcher::SetDefaultPermission( 273 const base::FilePath& plugin_data_path, 274 PP_Flash_BrowserOperations_SettingType setting_type, 275 PP_Flash_BrowserOperations_Permission permission, 276 bool clear_site_specific) { 277 if (flash_browser_operations_1_3_) { 278 std::string data_str = ConvertPluginDataPath(plugin_data_path); 279 return PP_ToBool(flash_browser_operations_1_3_->SetDefaultPermission( 280 data_str.c_str(), setting_type, permission, 281 PP_FromBool(clear_site_specific))); 282 } 283 284 if (flash_browser_operations_1_2_) { 285 std::string data_str = ConvertPluginDataPath(plugin_data_path); 286 return PP_ToBool(flash_browser_operations_1_2_->SetDefaultPermission( 287 data_str.c_str(), setting_type, permission, 288 PP_FromBool(clear_site_specific))); 289 } 290 291 return false; 292 } 293 294 bool BrokerProcessDispatcher::SetSitePermission( 295 const base::FilePath& plugin_data_path, 296 PP_Flash_BrowserOperations_SettingType setting_type, 297 const ppapi::FlashSiteSettings& sites) { 298 if (sites.empty()) 299 return true; 300 301 std::string data_str = ConvertPluginDataPath(plugin_data_path); 302 scoped_ptr<PP_Flash_BrowserOperations_SiteSetting[]> site_array( 303 new PP_Flash_BrowserOperations_SiteSetting[sites.size()]); 304 305 for (size_t i = 0; i < sites.size(); ++i) { 306 site_array[i].site = sites[i].site.c_str(); 307 site_array[i].permission = sites[i].permission; 308 } 309 310 if (flash_browser_operations_1_3_) { 311 PP_Bool result = flash_browser_operations_1_3_->SetSitePermission( 312 data_str.c_str(), setting_type, sites.size(), site_array.get()); 313 314 return PP_ToBool(result); 315 } 316 317 if (flash_browser_operations_1_2_) { 318 PP_Bool result = flash_browser_operations_1_2_->SetSitePermission( 319 data_str.c_str(), setting_type, sites.size(), site_array.get()); 320 321 return PP_ToBool(result); 322 } 323 324 return false; 325 } 326 327 } // namespace content 328