OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/plugin_service.h" | 5 #include "chrome/browser/plugin_service.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
12 #include "base/threading/thread.h" | 12 #include "base/threading/thread.h" |
13 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
16 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
17 #include "chrome/browser/browser_thread.h" | 17 #include "chrome/browser/browser_thread.h" |
18 #include "chrome/browser/chrome_plugin_host.h" | 18 #include "chrome/browser/chrome_plugin_host.h" |
19 #include "chrome/browser/extensions/extension_service.h" | 19 #include "chrome/browser/extensions/extension_service.h" |
20 #include "chrome/browser/plugin_updater.h" | 20 #include "chrome/browser/plugin_updater.h" |
| 21 #include "chrome/browser/ppapi_plugin_process_host.h" |
21 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
22 #include "chrome/browser/renderer_host/render_process_host.h" | 23 #include "chrome/browser/renderer_host/render_process_host.h" |
23 #include "chrome/browser/renderer_host/render_view_host.h" | 24 #include "chrome/browser/renderer_host/render_view_host.h" |
24 #include "chrome/common/chrome_plugin_lib.h" | 25 #include "chrome/common/chrome_plugin_lib.h" |
25 #include "chrome/common/chrome_paths.h" | 26 #include "chrome/common/chrome_paths.h" |
26 #include "chrome/common/chrome_switches.h" | 27 #include "chrome/common/chrome_switches.h" |
27 #include "chrome/common/default_plugin.h" | 28 #include "chrome/common/default_plugin.h" |
28 #include "chrome/common/extensions/extension.h" | 29 #include "chrome/common/extensions/extension.h" |
29 #include "chrome/common/gpu_plugin.h" | 30 #include "chrome/common/gpu_plugin.h" |
30 #include "chrome/common/logging_chrome.h" | 31 #include "chrome/common/logging_chrome.h" |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 } | 234 } |
234 | 235 |
235 const FilePath& PluginService::GetChromePluginDataDir() { | 236 const FilePath& PluginService::GetChromePluginDataDir() { |
236 return chrome_plugin_data_dir_; | 237 return chrome_plugin_data_dir_; |
237 } | 238 } |
238 | 239 |
239 const std::string& PluginService::GetUILocale() { | 240 const std::string& PluginService::GetUILocale() { |
240 return ui_locale_; | 241 return ui_locale_; |
241 } | 242 } |
242 | 243 |
243 PluginProcessHost* PluginService::FindPluginProcess( | 244 PluginProcessHost* PluginService::FindNpapiPluginProcess( |
244 const FilePath& plugin_path) { | 245 const FilePath& plugin_path) { |
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
246 | 247 |
247 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); | 248 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); |
248 !iter.Done(); ++iter) { | 249 !iter.Done(); ++iter) { |
249 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); | 250 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); |
250 if (plugin->info().path == plugin_path) | 251 if (plugin->info().path == plugin_path) |
251 return plugin; | 252 return plugin; |
252 } | 253 } |
253 | 254 |
254 return NULL; | 255 return NULL; |
255 } | 256 } |
256 | 257 |
257 PluginProcessHost* PluginService::FindOrStartPluginProcess( | 258 PpapiPluginProcessHost* PluginService::FindPpapiPluginProcess( |
258 const FilePath& plugin_path) { | 259 const FilePath& plugin_path) { |
259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
260 | 261 |
261 PluginProcessHost* plugin_host = FindPluginProcess(plugin_path); | 262 for (BrowserChildProcessHost::Iterator iter( |
| 263 ChildProcessInfo::PPAPI_PLUGIN_PROCESS); |
| 264 !iter.Done(); ++iter) { |
| 265 PpapiPluginProcessHost* plugin = |
| 266 static_cast<PpapiPluginProcessHost*>(*iter); |
| 267 if (plugin->plugin_path() == plugin_path) |
| 268 return plugin; |
| 269 } |
| 270 |
| 271 return NULL; |
| 272 } |
| 273 |
| 274 PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess( |
| 275 const FilePath& plugin_path) { |
| 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 277 |
| 278 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path); |
262 if (plugin_host) | 279 if (plugin_host) |
263 return plugin_host; | 280 return plugin_host; |
264 | 281 |
265 webkit::npapi::WebPluginInfo info; | 282 webkit::npapi::WebPluginInfo info; |
266 if (!webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath( | 283 if (!webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath( |
267 plugin_path, &info)) { | 284 plugin_path, &info)) { |
268 return NULL; | 285 return NULL; |
269 } | 286 } |
270 | 287 |
271 // This plugin isn't loaded by any plugin process, so create a new process. | 288 // This plugin isn't loaded by any plugin process, so create a new process. |
272 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost()); | 289 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost()); |
273 if (!new_host->Init(info, ui_locale_)) { | 290 if (!new_host->Init(info, ui_locale_)) { |
274 NOTREACHED(); // Init is not expected to fail | 291 NOTREACHED(); // Init is not expected to fail. |
275 return NULL; | 292 return NULL; |
276 } | 293 } |
277 | |
278 return new_host.release(); | 294 return new_host.release(); |
279 } | 295 } |
280 | 296 |
281 void PluginService::OpenChannelToPlugin( | 297 PpapiPluginProcessHost* PluginService::FindOrStartPpapiPluginProcess( |
| 298 const FilePath& plugin_path) { |
| 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 300 |
| 301 PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path); |
| 302 if (plugin_host) |
| 303 return plugin_host; |
| 304 |
| 305 // Validate that the plugin is actually registered. There should generally |
| 306 // be very few plugins so a brute-force search is fine. |
| 307 PepperPluginInfo* info = NULL; |
| 308 for (size_t i = 0; i < ppapi_plugins_.size(); i++) { |
| 309 if (ppapi_plugins_[i].path == plugin_path) { |
| 310 info = &ppapi_plugins_[i]; |
| 311 break; |
| 312 } |
| 313 } |
| 314 if (!info) |
| 315 return NULL; |
| 316 |
| 317 // This plugin isn't loaded by any plugin process, so create a new process. |
| 318 scoped_ptr<PpapiPluginProcessHost> new_host(new PpapiPluginProcessHost); |
| 319 if (!new_host->Init(plugin_path)) { |
| 320 NOTREACHED(); // Init is not expected to fail. |
| 321 return NULL; |
| 322 } |
| 323 return new_host.release(); |
| 324 } |
| 325 |
| 326 void PluginService::OpenChannelToNpapiPlugin( |
282 int render_process_id, | 327 int render_process_id, |
283 int render_view_id, | 328 int render_view_id, |
284 const GURL& url, | 329 const GURL& url, |
285 const std::string& mime_type, | 330 const std::string& mime_type, |
286 PluginProcessHost::Client* client) { | 331 PluginProcessHost::Client* client) { |
287 // The PluginList::GetFirstAllowedPluginInfo may need to load the | 332 // The PluginList::GetFirstAllowedPluginInfo may need to load the |
288 // plugins. Don't do it on the IO thread. | 333 // plugins. Don't do it on the IO thread. |
289 BrowserThread::PostTask( | 334 BrowserThread::PostTask( |
290 BrowserThread::FILE, FROM_HERE, | 335 BrowserThread::FILE, FROM_HERE, |
291 NewRunnableMethod( | 336 NewRunnableMethod( |
292 this, &PluginService::GetAllowedPluginForOpenChannelToPlugin, | 337 this, &PluginService::GetAllowedPluginForOpenChannelToPlugin, |
293 render_process_id, render_view_id, url, mime_type, client)); | 338 render_process_id, render_view_id, url, mime_type, client)); |
294 } | 339 } |
295 | 340 |
| 341 void PluginService::OpenChannelToPpapiPlugin( |
| 342 const FilePath& path, |
| 343 PpapiPluginProcessHost::Client* client) { |
| 344 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(path); |
| 345 if (plugin_host) |
| 346 plugin_host->OpenChannelToPlugin(client); |
| 347 else // Send error. |
| 348 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle()); |
| 349 } |
| 350 |
296 void PluginService::GetAllowedPluginForOpenChannelToPlugin( | 351 void PluginService::GetAllowedPluginForOpenChannelToPlugin( |
297 int render_process_id, | 352 int render_process_id, |
298 int render_view_id, | 353 int render_view_id, |
299 const GURL& url, | 354 const GURL& url, |
300 const std::string& mime_type, | 355 const std::string& mime_type, |
301 PluginProcessHost::Client* client) { | 356 PluginProcessHost::Client* client) { |
302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
303 webkit::npapi::WebPluginInfo info; | 358 webkit::npapi::WebPluginInfo info; |
304 bool found = GetFirstAllowedPluginInfo( | 359 bool found = GetFirstAllowedPluginInfo( |
305 render_process_id, render_view_id, url, mime_type, &info, NULL); | 360 render_process_id, render_view_id, url, mime_type, &info, NULL); |
306 FilePath plugin_path; | 361 FilePath plugin_path; |
307 if (found && webkit::npapi::IsPluginEnabled(info)) | 362 if (found && webkit::npapi::IsPluginEnabled(info)) |
308 plugin_path = FilePath(info.path); | 363 plugin_path = FilePath(info.path); |
309 | 364 |
310 // Now we jump back to the IO thread to finish opening the channel. | 365 // Now we jump back to the IO thread to finish opening the channel. |
311 BrowserThread::PostTask( | 366 BrowserThread::PostTask( |
312 BrowserThread::IO, FROM_HERE, | 367 BrowserThread::IO, FROM_HERE, |
313 NewRunnableMethod( | 368 NewRunnableMethod( |
314 this, &PluginService::FinishOpenChannelToPlugin, | 369 this, &PluginService::FinishOpenChannelToPlugin, |
315 plugin_path, client)); | 370 plugin_path, client)); |
316 } | 371 } |
317 | 372 |
318 void PluginService::FinishOpenChannelToPlugin( | 373 void PluginService::FinishOpenChannelToPlugin( |
319 const FilePath& plugin_path, | 374 const FilePath& plugin_path, |
320 PluginProcessHost::Client* client) { | 375 PluginProcessHost::Client* client) { |
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
322 | 377 |
323 PluginProcessHost* plugin_host = FindOrStartPluginProcess(plugin_path); | 378 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path); |
324 if (plugin_host) | 379 if (plugin_host) |
325 plugin_host->OpenChannelToPlugin(client); | 380 plugin_host->OpenChannelToPlugin(client); |
326 else | 381 else |
327 client->OnError(); | 382 client->OnError(); |
328 } | 383 } |
329 | 384 |
330 bool PluginService::GetFirstAllowedPluginInfo( | 385 bool PluginService::GetFirstAllowedPluginInfo( |
331 int render_process_id, | 386 int render_process_id, |
332 int render_view_id, | 387 int render_view_id, |
333 const GURL& url, | 388 const GURL& url, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); | 440 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); |
386 PurgePluginListCache(true); | 441 PurgePluginListCache(true); |
387 #else | 442 #else |
388 // This event should only get signaled on a Windows machine. | 443 // This event should only get signaled on a Windows machine. |
389 NOTREACHED(); | 444 NOTREACHED(); |
390 #endif // defined(OS_WIN) | 445 #endif // defined(OS_WIN) |
391 } | 446 } |
392 | 447 |
393 static void ForceShutdownPlugin(const FilePath& plugin_path) { | 448 static void ForceShutdownPlugin(const FilePath& plugin_path) { |
394 PluginProcessHost* plugin = | 449 PluginProcessHost* plugin = |
395 PluginService::GetInstance()->FindPluginProcess(plugin_path); | 450 PluginService::GetInstance()->FindNpapiPluginProcess(plugin_path); |
396 if (plugin) | 451 if (plugin) |
397 plugin->ForceShutdown(); | 452 plugin->ForceShutdown(); |
398 } | 453 } |
399 | 454 |
400 void PluginService::Observe(NotificationType type, | 455 void PluginService::Observe(NotificationType type, |
401 const NotificationSource& source, | 456 const NotificationSource& source, |
402 const NotificationDetails& details) { | 457 const NotificationDetails& details) { |
403 switch (type.value) { | 458 switch (type.value) { |
404 case NotificationType::EXTENSION_LOADED: { | 459 case NotificationType::EXTENSION_LOADED: { |
405 const Extension* extension = Details<const Extension>(details).ptr(); | 460 const Extension* extension = Details<const Extension>(details).ptr(); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 return (url.scheme() == required_url.scheme() && | 538 return (url.scheme() == required_url.scheme() && |
484 url.host() == required_url.host()); | 539 url.host() == required_url.host()); |
485 } | 540 } |
486 | 541 |
487 void PluginService::OverridePluginForTab(OverriddenPlugin plugin) { | 542 void PluginService::OverridePluginForTab(OverriddenPlugin plugin) { |
488 base::AutoLock auto_lock(overridden_plugins_lock_); | 543 base::AutoLock auto_lock(overridden_plugins_lock_); |
489 overridden_plugins_.push_back(plugin); | 544 overridden_plugins_.push_back(plugin); |
490 } | 545 } |
491 | 546 |
492 void PluginService::RegisterPepperPlugins() { | 547 void PluginService::RegisterPepperPlugins() { |
493 std::vector<PepperPluginInfo> plugins; | 548 PepperPluginRegistry::ComputeList(&ppapi_plugins_); |
494 PepperPluginRegistry::ComputeList(&plugins); | 549 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) { |
495 for (size_t i = 0; i < plugins.size(); ++i) { | |
496 webkit::npapi::WebPluginInfo info; | 550 webkit::npapi::WebPluginInfo info; |
497 info.path = plugins[i].path; | 551 info.path = ppapi_plugins_[i].path; |
498 info.name = plugins[i].name.empty() ? | 552 info.name = ppapi_plugins_[i].name.empty() ? |
499 plugins[i].path.BaseName().LossyDisplayName() : | 553 ppapi_plugins_[i].path.BaseName().LossyDisplayName() : |
500 ASCIIToUTF16(plugins[i].name); | 554 ASCIIToUTF16(ppapi_plugins_[i].name); |
501 info.desc = ASCIIToUTF16(plugins[i].description); | 555 info.desc = ASCIIToUTF16(ppapi_plugins_[i].description); |
502 info.enabled = webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED; | 556 info.enabled = webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED; |
503 | 557 |
504 // TODO(evan): Pepper shouldn't require us to parse strings to get | 558 // TODO(evan): Pepper shouldn't require us to parse strings to get |
505 // the list of mime types out. | 559 // the list of mime types out. |
506 if (!webkit::npapi::PluginList::ParseMimeTypes( | 560 if (!webkit::npapi::PluginList::ParseMimeTypes( |
507 JoinString(plugins[i].mime_types, '|'), | 561 JoinString(ppapi_plugins_[i].mime_types, '|'), |
508 plugins[i].file_extensions, | 562 ppapi_plugins_[i].file_extensions, |
509 ASCIIToUTF16(plugins[i].type_descriptions), | 563 ASCIIToUTF16(ppapi_plugins_[i].type_descriptions), |
510 &info.mime_types)) { | 564 &info.mime_types)) { |
511 LOG(ERROR) << "Error parsing mime types for " | 565 LOG(ERROR) << "Error parsing mime types for " |
512 << plugins[i].path.LossyDisplayName(); | 566 << ppapi_plugins_[i].path.LossyDisplayName(); |
513 return; | 567 return; |
514 } | 568 } |
515 | 569 |
516 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info); | 570 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info); |
517 } | 571 } |
518 } | 572 } |
519 | 573 |
520 #if defined(OS_LINUX) | 574 #if defined(OS_LINUX) |
521 // static | 575 // static |
522 void PluginService::RegisterFilePathWatcher( | 576 void PluginService::RegisterFilePathWatcher( |
523 FilePathWatcher *watcher, | 577 FilePathWatcher *watcher, |
524 const FilePath& path, | 578 const FilePath& path, |
525 FilePathWatcher::Delegate* delegate) { | 579 FilePathWatcher::Delegate* delegate) { |
526 bool result = watcher->Watch(path, delegate); | 580 bool result = watcher->Watch(path, delegate); |
527 DCHECK(result); | 581 DCHECK(result); |
528 } | 582 } |
529 #endif | 583 #endif |
OLD | NEW |