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 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 ChildProcess::current()->AddRefProcess(); 85 86 if (get_plugin_interface) { 87 flash_browser_operations_1_0_ = 88 static_cast<const PPP_Flash_BrowserOperations_1_0*>( 89 get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_0)); 90 91 flash_browser_operations_1_2_ = 92 static_cast<const PPP_Flash_BrowserOperations_1_2*>( 93 get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_2)); 94 95 flash_browser_operations_1_3_ = 96 static_cast<const PPP_Flash_BrowserOperations_1_3*>( 97 get_plugin_interface_(PPP_FLASH_BROWSEROPERATIONS_INTERFACE_1_3)); 98 } 99 } 100 101 BrokerProcessDispatcher::~BrokerProcessDispatcher() { 102 DVLOG(1) << "BrokerProcessDispatcher::~BrokerProcessDispatcher()"; 103 // Don't free the process right away. This timer allows the child process 104 // to be re-used if the user rapidly goes to a new page that requires this 105 // plugin. This is the case for common plugins where they may be used on a 106 // source and destination page of a navigation. We don't want to tear down 107 // and re-start processes each time in these cases. 108 base::MessageLoop::current()->PostDelayedTask( 109 FROM_HERE, 110 base::Bind(&ChildProcess::ReleaseProcess, 111 base::Unretained(ChildProcess::current())), 112 base::TimeDelta::FromSeconds(kBrokerReleaseTimeSeconds)); 113 } 114 115 bool BrokerProcessDispatcher::OnMessageReceived(const IPC::Message& msg) { 116 IPC_BEGIN_MESSAGE_MAP(BrokerProcessDispatcher, msg) 117 IPC_MESSAGE_HANDLER(PpapiMsg_GetSitesWithData, OnGetSitesWithData) 118 IPC_MESSAGE_HANDLER(PpapiMsg_ClearSiteData, OnClearSiteData) 119 IPC_MESSAGE_HANDLER(PpapiMsg_DeauthorizeContentLicenses, 120 OnDeauthorizeContentLicenses) 121 IPC_MESSAGE_HANDLER(PpapiMsg_GetPermissionSettings, OnGetPermissionSettings) 122 IPC_MESSAGE_HANDLER(PpapiMsg_SetDefaultPermission, OnSetDefaultPermission) 123 IPC_MESSAGE_HANDLER(PpapiMsg_SetSitePermission, OnSetSitePermission) 124 IPC_MESSAGE_UNHANDLED(return BrokerSideDispatcher::OnMessageReceived(msg)) 125 IPC_END_MESSAGE_MAP() 126 return true; 127 } 128 129 void BrokerProcessDispatcher::OnGetPermissionSettingsCompleted( 130 uint32 request_id, 131 bool success, 132 PP_Flash_BrowserOperations_Permission default_permission, 133 const ppapi::FlashSiteSettings& sites) { 134 Send(new PpapiHostMsg_GetPermissionSettingsResult( 135 request_id, success, default_permission, sites)); 136 } 137 138 void BrokerProcessDispatcher::OnGetSitesWithData( 139 uint32 request_id, 140 const base::FilePath& plugin_data_path) { 141 std::vector<std::string> sites; 142 GetSitesWithData(plugin_data_path, &sites); 143 Send(new PpapiHostMsg_GetSitesWithDataResult(request_id, sites)); 144 } 145 146 void BrokerProcessDispatcher::OnClearSiteData( 147 uint32 request_id, 148 const base::FilePath& plugin_data_path, 149 const std::string& site, 150 uint64 flags, 151 uint64 max_age) { 152 Send(new PpapiHostMsg_ClearSiteDataResult( 153 request_id, ClearSiteData(plugin_data_path, site, flags, max_age))); 154 } 155 156 void BrokerProcessDispatcher::OnDeauthorizeContentLicenses( 157 uint32 request_id, 158 const base::FilePath& plugin_data_path) { 159 Send(new PpapiHostMsg_DeauthorizeContentLicensesResult( 160 request_id, DeauthorizeContentLicenses(plugin_data_path))); 161 } 162 163 void BrokerProcessDispatcher::OnGetPermissionSettings( 164 uint32 request_id, 165 const base::FilePath& plugin_data_path, 166 PP_Flash_BrowserOperations_SettingType setting_type) { 167 if (flash_browser_operations_1_3_) { 168 std::string data_str = ConvertPluginDataPath(plugin_data_path); 169 // The GetPermissionSettingsContext object will be deleted in 170 // GetPermissionSettingsCallback(). 171 flash_browser_operations_1_3_->GetPermissionSettings( 172 data_str.c_str(), setting_type, &GetPermissionSettingsCallback, 173 new GetPermissionSettingsContext(AsWeakPtr(), request_id)); 174 return; 175 } 176 177 if (flash_browser_operations_1_2_) { 178 std::string data_str = ConvertPluginDataPath(plugin_data_path); 179 // The GetPermissionSettingsContext object will be deleted in 180 // GetPermissionSettingsCallback(). 181 flash_browser_operations_1_2_->GetPermissionSettings( 182 data_str.c_str(), setting_type, &GetPermissionSettingsCallback, 183 new GetPermissionSettingsContext(AsWeakPtr(), request_id)); 184 return; 185 } 186 187 OnGetPermissionSettingsCompleted( 188 request_id, false, PP_FLASH_BROWSEROPERATIONS_PERMISSION_DEFAULT, 189 ppapi::FlashSiteSettings()); 190 return; 191 } 192 193 void BrokerProcessDispatcher::OnSetDefaultPermission( 194 uint32 request_id, 195 const base::FilePath& plugin_data_path, 196 PP_Flash_BrowserOperations_SettingType setting_type, 197 PP_Flash_BrowserOperations_Permission permission, 198 bool clear_site_specific) { 199 Send(new PpapiHostMsg_SetDefaultPermissionResult( 200 request_id, 201 SetDefaultPermission(plugin_data_path, setting_type, permission, 202 clear_site_specific))); 203 } 204 205 void BrokerProcessDispatcher::OnSetSitePermission( 206 uint32 request_id, 207 const base::FilePath& plugin_data_path, 208 PP_Flash_BrowserOperations_SettingType setting_type, 209 const ppapi::FlashSiteSettings& sites) { 210 Send(new PpapiHostMsg_SetSitePermissionResult( 211 request_id, SetSitePermission(plugin_data_path, setting_type, sites))); 212 } 213 214 void BrokerProcessDispatcher::GetSitesWithData( 215 const base::FilePath& plugin_data_path, 216 std::vector<std::string>* site_vector) { 217 std::string data_str = ConvertPluginDataPath(plugin_data_path); 218 if (flash_browser_operations_1_3_) { 219 char** sites = NULL; 220 flash_browser_operations_1_3_->GetSitesWithData(data_str.c_str(), &sites); 221 if (!sites) 222 return; 223 224 for (size_t i = 0; sites[i]; ++i) 225 site_vector->push_back(sites[i]); 226 227 flash_browser_operations_1_3_->FreeSiteList(sites); 228 } 229 } 230 231 bool BrokerProcessDispatcher::ClearSiteData( 232 const base::FilePath& plugin_data_path, 233 const std::string& site, 234 uint64 flags, 235 uint64 max_age) { 236 std::string data_str = ConvertPluginDataPath(plugin_data_path); 237 if (flash_browser_operations_1_3_) { 238 flash_browser_operations_1_3_->ClearSiteData( 239 data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age); 240 return true; 241 } 242 243 // TODO(viettrungluu): Remove this (and the 1.0 interface) sometime after M21 244 // goes to Stable. 245 if (flash_browser_operations_1_2_) { 246 flash_browser_operations_1_2_->ClearSiteData( 247 data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age); 248 return true; 249 } 250 251 if (flash_browser_operations_1_0_) { 252 flash_browser_operations_1_0_->ClearSiteData( 253 data_str.c_str(), site.empty() ? NULL : site.c_str(), flags, max_age); 254 return true; 255 } 256 257 return false; 258 } 259 260 bool BrokerProcessDispatcher::DeauthorizeContentLicenses( 261 const base::FilePath& plugin_data_path) { 262 if (flash_browser_operations_1_3_) { 263 std::string data_str = ConvertPluginDataPath(plugin_data_path); 264 return PP_ToBool(flash_browser_operations_1_3_->DeauthorizeContentLicenses( 265 data_str.c_str())); 266 } 267 268 if (flash_browser_operations_1_2_) { 269 std::string data_str = ConvertPluginDataPath(plugin_data_path); 270 return PP_ToBool(flash_browser_operations_1_2_->DeauthorizeContentLicenses( 271 data_str.c_str())); 272 } 273 274 return false; 275 } 276 277 bool BrokerProcessDispatcher::SetDefaultPermission( 278 const base::FilePath& plugin_data_path, 279 PP_Flash_BrowserOperations_SettingType setting_type, 280 PP_Flash_BrowserOperations_Permission permission, 281 bool clear_site_specific) { 282 if (flash_browser_operations_1_3_) { 283 std::string data_str = ConvertPluginDataPath(plugin_data_path); 284 return PP_ToBool(flash_browser_operations_1_3_->SetDefaultPermission( 285 data_str.c_str(), setting_type, permission, 286 PP_FromBool(clear_site_specific))); 287 } 288 289 if (flash_browser_operations_1_2_) { 290 std::string data_str = ConvertPluginDataPath(plugin_data_path); 291 return PP_ToBool(flash_browser_operations_1_2_->SetDefaultPermission( 292 data_str.c_str(), setting_type, permission, 293 PP_FromBool(clear_site_specific))); 294 } 295 296 return false; 297 } 298 299 bool BrokerProcessDispatcher::SetSitePermission( 300 const base::FilePath& plugin_data_path, 301 PP_Flash_BrowserOperations_SettingType setting_type, 302 const ppapi::FlashSiteSettings& sites) { 303 if (sites.empty()) 304 return true; 305 306 std::string data_str = ConvertPluginDataPath(plugin_data_path); 307 scoped_ptr<PP_Flash_BrowserOperations_SiteSetting[]> site_array( 308 new PP_Flash_BrowserOperations_SiteSetting[sites.size()]); 309 310 for (size_t i = 0; i < sites.size(); ++i) { 311 site_array[i].site = sites[i].site.c_str(); 312 site_array[i].permission = sites[i].permission; 313 } 314 315 if (flash_browser_operations_1_3_) { 316 PP_Bool result = flash_browser_operations_1_3_->SetSitePermission( 317 data_str.c_str(), setting_type, sites.size(), site_array.get()); 318 319 return PP_ToBool(result); 320 } 321 322 if (flash_browser_operations_1_2_) { 323 PP_Bool result = flash_browser_operations_1_2_->SetSitePermission( 324 data_str.c_str(), setting_type, sites.size(), site_array.get()); 325 326 return PP_ToBool(result); 327 } 328 329 return false; 330 } 331 332 } // namespace content 333