OLD | NEW |
1 // Copyright (c) 2011 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 "content/browser/plugin_service.h" | 5 #include "content/browser/plugin_service.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 std::vector<webkit::npapi::PluginGroup> groups; | 60 std::vector<webkit::npapi::PluginGroup> groups; |
61 webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, &groups); | 61 webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, &groups); |
62 callback.Run(groups); | 62 callback.Run(groups); |
63 } | 63 } |
64 | 64 |
65 // Callback set on the PluginList to assert that plugin loading happens on the | 65 // Callback set on the PluginList to assert that plugin loading happens on the |
66 // correct thread. | 66 // correct thread. |
67 void WillLoadPluginsCallback() { | 67 void WillLoadPluginsCallback() { |
68 // TODO(rsesek): Change these to CHECKs. | 68 // TODO(rsesek): Change these to CHECKs. |
69 #if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX)) | 69 #if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX)) |
70 LOG_IF(ERROR, !BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 70 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
71 #else | 71 #else |
72 LOG(ERROR) << "Plugin loading should happen out-of-process."; | 72 CHECK(false) << "Plugin loading should happen out-of-process."; |
73 #endif | 73 #endif |
74 } | 74 } |
75 | 75 |
| 76 struct ForwardOpenChannelParams { |
| 77 int render_process_id; |
| 78 int render_view_id; |
| 79 PluginProcessHost::Client* client; |
| 80 const content::ResourceContext* resource_context; |
| 81 }; |
| 82 |
76 #if defined(OS_POSIX) | 83 #if defined(OS_POSIX) |
77 // Utility child process client that manages the IPC for loading plugins out of | 84 // Utility child process client that manages the IPC for loading plugins out of |
78 // process. | 85 // process. |
79 class PluginLoaderClient : public UtilityProcessHost::Client { | 86 class PluginLoaderClient : public UtilityProcessHost::Client { |
80 public: | 87 public: |
81 // Meant to be called on the IO thread. Will invoke the callback on the target | 88 // Meant to be called on the IO thread. Will invoke the callback on the target |
82 // loop when the plugins have been loaded. | 89 // loop when the plugins have been loaded. |
83 static void LoadPluginsOutOfProcess( | 90 static void LoadPluginsOutOfProcess( |
84 base::MessageLoopProxy* target_loop, | 91 base::MessageLoopProxy* target_loop, |
85 const PluginService::GetPluginsCallback& callback) { | 92 const PluginService::GetPluginsCallback& callback) { |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 | 324 |
318 PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess( | 325 PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess( |
319 const FilePath& plugin_path) { | 326 const FilePath& plugin_path) { |
320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
321 | 328 |
322 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path); | 329 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path); |
323 if (plugin_host) | 330 if (plugin_host) |
324 return plugin_host; | 331 return plugin_host; |
325 | 332 |
326 webkit::WebPluginInfo info; | 333 webkit::WebPluginInfo info; |
327 if (!webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath( | 334 if (!GetPluginInfoByPath(plugin_path, &info)) { |
328 plugin_path, &info)) { | |
329 return NULL; | 335 return NULL; |
330 } | 336 } |
331 | 337 |
332 // This plugin isn't loaded by any plugin process, so create a new process. | 338 // This plugin isn't loaded by any plugin process, so create a new process. |
333 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost()); | 339 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost()); |
334 if (!new_host->Init(info, ui_locale_)) { | 340 if (!new_host->Init(info, ui_locale_)) { |
335 NOTREACHED(); // Init is not expected to fail. | 341 NOTREACHED(); // Init is not expected to fail. |
336 return NULL; | 342 return NULL; |
337 } | 343 } |
338 return new_host.release(); | 344 return new_host.release(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 | 386 |
381 void PluginService::OpenChannelToNpapiPlugin( | 387 void PluginService::OpenChannelToNpapiPlugin( |
382 int render_process_id, | 388 int render_process_id, |
383 int render_view_id, | 389 int render_view_id, |
384 const GURL& url, | 390 const GURL& url, |
385 const GURL& page_url, | 391 const GURL& page_url, |
386 const std::string& mime_type, | 392 const std::string& mime_type, |
387 PluginProcessHost::Client* client) { | 393 PluginProcessHost::Client* client) { |
388 DCHECK(!ContainsKey(pending_plugin_clients_, client)); | 394 DCHECK(!ContainsKey(pending_plugin_clients_, client)); |
389 pending_plugin_clients_.insert(client); | 395 pending_plugin_clients_.insert(client); |
390 // The PluginList::GetPluginInfo may need to load the plugins. Don't do it on | 396 |
391 // the IO thread. | 397 // Make sure plugins are loaded if necessary. |
392 BrowserThread::PostTask( | 398 ForwardOpenChannelParams params = { |
393 BrowserThread::FILE, FROM_HERE, | 399 render_process_id, |
394 NewRunnableMethod( | 400 render_view_id, |
395 this, &PluginService::GetAllowedPluginForOpenChannelToPlugin, | 401 client, |
396 render_process_id, render_view_id, url, page_url, mime_type, | 402 &client->GetResourceContext() |
397 client, &client->GetResourceContext())); | 403 }; |
| 404 GetPlugins( |
| 405 base::Bind(&PluginService::ForwardGetAllowedPluginForOpenChannelToPlugin, |
| 406 base::Unretained(this), params, url, page_url, mime_type)); |
398 } | 407 } |
399 | 408 |
400 void PluginService::OpenChannelToPpapiPlugin( | 409 void PluginService::OpenChannelToPpapiPlugin( |
401 const FilePath& path, | 410 const FilePath& path, |
402 PpapiPluginProcessHost::PluginClient* client) { | 411 PpapiPluginProcessHost::PluginClient* client) { |
403 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess( | 412 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess( |
404 path, client); | 413 path, client); |
405 if (plugin_host) | 414 if (plugin_host) |
406 plugin_host->OpenChannelToPlugin(client); | 415 plugin_host->OpenChannelToPlugin(client); |
407 else // Send error. | 416 else // Send error. |
(...skipping 10 matching lines...) Expand all Loading... |
418 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle()); | 427 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle()); |
419 } | 428 } |
420 | 429 |
421 void PluginService::CancelOpenChannelToNpapiPlugin( | 430 void PluginService::CancelOpenChannelToNpapiPlugin( |
422 PluginProcessHost::Client* client) { | 431 PluginProcessHost::Client* client) { |
423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
424 DCHECK(ContainsKey(pending_plugin_clients_, client)); | 433 DCHECK(ContainsKey(pending_plugin_clients_, client)); |
425 pending_plugin_clients_.erase(client); | 434 pending_plugin_clients_.erase(client); |
426 } | 435 } |
427 | 436 |
| 437 void PluginService::ForwardGetAllowedPluginForOpenChannelToPlugin( |
| 438 const ForwardOpenChannelParams& params, |
| 439 const GURL& url, |
| 440 const GURL& page_url, |
| 441 const std::string& mime_type, |
| 442 const std::vector<webkit::WebPluginInfo>&) { |
| 443 GetAllowedPluginForOpenChannelToPlugin(params.render_process_id, |
| 444 params.render_view_id, url, page_url, mime_type, params.client, |
| 445 params.resource_context); |
| 446 } |
| 447 |
428 void PluginService::GetAllowedPluginForOpenChannelToPlugin( | 448 void PluginService::GetAllowedPluginForOpenChannelToPlugin( |
429 int render_process_id, | 449 int render_process_id, |
430 int render_view_id, | 450 int render_view_id, |
431 const GURL& url, | 451 const GURL& url, |
432 const GURL& page_url, | 452 const GURL& page_url, |
433 const std::string& mime_type, | 453 const std::string& mime_type, |
434 PluginProcessHost::Client* client, | 454 PluginProcessHost::Client* client, |
435 const content::ResourceContext* resource_context) { | 455 const content::ResourceContext* resource_context) { |
436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
437 DCHECK(resource_context); | |
438 webkit::WebPluginInfo info; | 456 webkit::WebPluginInfo info; |
439 bool allow_wildcard = true; | 457 bool allow_wildcard = true; |
440 bool found = GetPluginInfo( | 458 bool found = GetPluginInfo( |
441 render_process_id, render_view_id, *resource_context, | 459 render_process_id, render_view_id, *resource_context, |
442 url, page_url, mime_type, allow_wildcard, | 460 url, page_url, mime_type, allow_wildcard, |
443 NULL, &info, NULL); | 461 NULL, &info, NULL); |
444 FilePath plugin_path; | 462 FilePath plugin_path; |
445 if (found) | 463 if (found) |
446 plugin_path = info.path; | 464 plugin_path = info.path; |
447 | 465 |
448 // Now we jump back to the IO thread to finish opening the channel. | 466 // Now we jump back to the IO thread to finish opening the channel. |
449 BrowserThread::PostTask( | 467 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
450 BrowserThread::IO, FROM_HERE, | 468 base::Bind(&PluginService::FinishOpenChannelToPlugin, |
451 NewRunnableMethod( | 469 base::Unretained(this), plugin_path, client)); |
452 this, &PluginService::FinishOpenChannelToPlugin, | |
453 plugin_path, client)); | |
454 } | 470 } |
455 | 471 |
456 void PluginService::FinishOpenChannelToPlugin( | 472 void PluginService::FinishOpenChannelToPlugin( |
457 const FilePath& plugin_path, | 473 const FilePath& plugin_path, |
458 PluginProcessHost::Client* client) { | 474 PluginProcessHost::Client* client) { |
459 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
460 | 476 |
461 // Make sure it hasn't been canceled yet. | 477 // Make sure it hasn't been canceled yet. |
462 if (!ContainsKey(pending_plugin_clients_, client)) | 478 if (!ContainsKey(pending_plugin_clients_, client)) |
463 return; | 479 return; |
464 pending_plugin_clients_.erase(client); | 480 pending_plugin_clients_.erase(client); |
465 | 481 |
466 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path); | 482 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path); |
467 if (plugin_host) { | 483 if (plugin_host) { |
468 client->OnFoundPluginProcessHost(plugin_host); | 484 client->OnFoundPluginProcessHost(plugin_host); |
469 plugin_host->OpenChannelToPlugin(client); | 485 plugin_host->OpenChannelToPlugin(client); |
470 } else { | 486 } else { |
471 client->OnError(); | 487 client->OnError(); |
472 } | 488 } |
473 } | 489 } |
474 | 490 |
| 491 bool PluginService::GetPluginInfoArray( |
| 492 const GURL& url, |
| 493 const std::string& mime_type, |
| 494 bool allow_wildcard, |
| 495 std::vector<webkit::WebPluginInfo>* plugins, |
| 496 std::vector<std::string>* actual_mime_types) { |
| 497 bool use_stale = false; |
| 498 webkit::npapi::PluginList::Singleton()->GetPluginInfoArray( |
| 499 url, mime_type, allow_wildcard, &use_stale, plugins, actual_mime_types); |
| 500 return use_stale; |
| 501 } |
| 502 |
475 bool PluginService::GetPluginInfo(int render_process_id, | 503 bool PluginService::GetPluginInfo(int render_process_id, |
476 int render_view_id, | 504 int render_view_id, |
477 const content::ResourceContext& context, | 505 const content::ResourceContext& context, |
478 const GURL& url, | 506 const GURL& url, |
479 const GURL& page_url, | 507 const GURL& page_url, |
480 const std::string& mime_type, | 508 const std::string& mime_type, |
481 bool allow_wildcard, | 509 bool allow_wildcard, |
482 bool* use_stale, | 510 bool* is_stale, |
483 webkit::WebPluginInfo* info, | 511 webkit::WebPluginInfo* info, |
484 std::string* actual_mime_type) { | 512 std::string* actual_mime_type) { |
485 webkit::npapi::PluginList* plugin_list = | |
486 webkit::npapi::PluginList::Singleton(); | |
487 // GetPluginInfoArray may need to load the plugins, so we need to be | |
488 // on the FILE thread. | |
489 DCHECK(use_stale || BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
490 std::vector<webkit::WebPluginInfo> plugins; | 513 std::vector<webkit::WebPluginInfo> plugins; |
491 std::vector<std::string> mime_types; | 514 std::vector<std::string> mime_types; |
492 plugin_list->GetPluginInfoArray( | 515 bool stale = GetPluginInfoArray( |
493 url, mime_type, allow_wildcard, use_stale, &plugins, &mime_types); | 516 url, mime_type, allow_wildcard, &plugins, &mime_types); |
| 517 if (is_stale) |
| 518 *is_stale = stale; |
494 if (plugins.size() > 1 && | 519 if (plugins.size() > 1 && |
495 plugins.back().path == | 520 plugins.back().path == |
496 FilePath(webkit::npapi::kDefaultPluginLibraryName)) { | 521 FilePath(webkit::npapi::kDefaultPluginLibraryName)) { |
497 // If there is at least one plug-in handling the required MIME type (apart | 522 // If there is at least one plug-in handling the required MIME type (apart |
498 // from the default plug-in), we don't need the default plug-in. | 523 // from the default plug-in), we don't need the default plug-in. |
499 plugins.pop_back(); | 524 plugins.pop_back(); |
500 } | 525 } |
501 | 526 |
502 for (size_t i = 0; i < plugins.size(); ++i) { | 527 for (size_t i = 0; i < plugins.size(); ++i) { |
503 if (!filter_ || filter_->ShouldUsePlugin(render_process_id, | 528 if (!filter_ || filter_->ShouldUsePlugin(render_process_id, |
504 render_view_id, | 529 render_view_id, |
505 &context, | 530 &context, |
506 url, | 531 url, |
507 page_url, | 532 page_url, |
508 &plugins[i])) { | 533 &plugins[i])) { |
509 *info = plugins[i]; | 534 *info = plugins[i]; |
510 if (actual_mime_type) | 535 if (actual_mime_type) |
511 *actual_mime_type = mime_types[i]; | 536 *actual_mime_type = mime_types[i]; |
512 return true; | 537 return true; |
513 } | 538 } |
514 } | 539 } |
515 return false; | 540 return false; |
516 } | 541 } |
517 | 542 |
| 543 bool PluginService::GetPluginInfoByPath(const FilePath& plugin_path, |
| 544 webkit::WebPluginInfo* info) { |
| 545 std::vector<webkit::WebPluginInfo> plugins; |
| 546 webkit::npapi::PluginList::Singleton()->GetPluginsIfNoRefreshNeeded( |
| 547 &plugins); |
| 548 |
| 549 for (std::vector<webkit::WebPluginInfo>::iterator it = plugins.begin(); |
| 550 it != plugins.end(); |
| 551 ++it) { |
| 552 if (it->path == plugin_path) { |
| 553 *info = *it; |
| 554 return true; |
| 555 } |
| 556 } |
| 557 |
| 558 return false; |
| 559 } |
| 560 |
518 void PluginService::RefreshPluginList() { | 561 void PluginService::RefreshPluginList() { |
519 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); | 562 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); |
520 } | 563 } |
521 | 564 |
522 void PluginService::GetPlugins(const GetPluginsCallback& callback) { | 565 void PluginService::GetPlugins(const GetPluginsCallback& callback) { |
523 scoped_refptr<base::MessageLoopProxy> target_loop( | 566 scoped_refptr<base::MessageLoopProxy> target_loop( |
524 MessageLoop::current()->message_loop_proxy()); | 567 MessageLoop::current()->message_loop_proxy()); |
525 | 568 |
526 #if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX)) | 569 #if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX)) |
527 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 570 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 } | 658 } |
616 } | 659 } |
617 if (info) | 660 if (info) |
618 return info; | 661 return info; |
619 // We did not find the plugin in our list. But wait! the plugin can also | 662 // We did not find the plugin in our list. But wait! the plugin can also |
620 // be a latecomer, as it happens with pepper flash. This information | 663 // be a latecomer, as it happens with pepper flash. This information |
621 // can be obtained from the PluginList singleton and we can use it to | 664 // can be obtained from the PluginList singleton and we can use it to |
622 // construct it and add it to the list. This same deal needs to be done | 665 // construct it and add it to the list. This same deal needs to be done |
623 // in the renderer side in PepperPluginRegistry. | 666 // in the renderer side in PepperPluginRegistry. |
624 webkit::WebPluginInfo webplugin_info; | 667 webkit::WebPluginInfo webplugin_info; |
625 if (!webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath( | 668 if (!GetPluginInfoByPath(plugin_path, &webplugin_info)) |
626 plugin_path, &webplugin_info)) | |
627 return NULL; | 669 return NULL; |
628 PepperPluginInfo new_pepper_info; | 670 PepperPluginInfo new_pepper_info; |
629 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info)) | 671 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info)) |
630 return NULL; | 672 return NULL; |
631 ppapi_plugins_.push_back(new_pepper_info); | 673 ppapi_plugins_.push_back(new_pepper_info); |
632 return &ppapi_plugins_[ppapi_plugins_.size() - 1]; | 674 return &ppapi_plugins_[ppapi_plugins_.size() - 1]; |
633 } | 675 } |
634 | 676 |
635 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 677 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
636 // static | 678 // static |
637 void PluginService::RegisterFilePathWatcher( | 679 void PluginService::RegisterFilePathWatcher( |
638 FilePathWatcher *watcher, | 680 FilePathWatcher *watcher, |
639 const FilePath& path, | 681 const FilePath& path, |
640 FilePathWatcher::Delegate* delegate) { | 682 FilePathWatcher::Delegate* delegate) { |
641 bool result = watcher->Watch(path, delegate); | 683 bool result = watcher->Watch(path, delegate); |
642 DCHECK(result); | 684 DCHECK(result); |
643 } | 685 } |
644 #endif | 686 #endif |
OLD | NEW |