Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: content/browser/plugin_service.cc

Issue 7980011: Convert the PluginService interface to be an async wrapper around PluginList. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/command_line.h" 8 #include "base/command_line.h"
8 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
9 #include "base/file_path.h" 10 #include "base/file_path.h"
11 #include "base/message_loop.h"
12 #include "base/message_loop_proxy.h"
10 #include "base/path_service.h" 13 #include "base/path_service.h"
11 #include "base/string_util.h" 14 #include "base/string_util.h"
12 #include "base/synchronization/waitable_event.h" 15 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread.h" 16 #include "base/threading/thread.h"
14 #include "base/utf_string_conversions.h" 17 #include "base/utf_string_conversions.h"
15 #include "base/values.h" 18 #include "base/values.h"
16 #include "content/browser/browser_thread.h" 19 #include "content/browser/browser_thread.h"
17 #include "content/browser/content_browser_client.h" 20 #include "content/browser/content_browser_client.h"
18 #include "content/browser/plugin_service_filter.h" 21 #include "content/browser/plugin_service_filter.h"
19 #include "content/browser/ppapi_plugin_process_host.h" 22 #include "content/browser/ppapi_plugin_process_host.h"
20 #include "content/browser/renderer_host/render_process_host.h" 23 #include "content/browser/renderer_host/render_process_host.h"
21 #include "content/browser/renderer_host/render_view_host.h" 24 #include "content/browser/renderer_host/render_view_host.h"
22 #include "content/browser/resource_context.h" 25 #include "content/browser/resource_context.h"
23 #include "content/common/content_notification_types.h" 26 #include "content/common/content_notification_types.h"
24 #include "content/common/content_switches.h" 27 #include "content/common/content_switches.h"
25 #include "content/common/notification_service.h" 28 #include "content/common/notification_service.h"
26 #include "content/common/pepper_plugin_registry.h" 29 #include "content/common/pepper_plugin_registry.h"
27 #include "content/common/plugin_messages.h" 30 #include "content/common/plugin_messages.h"
28 #include "content/common/view_messages.h" 31 #include "content/common/view_messages.h"
32 #include "webkit/plugins/npapi/mock_plugin_list.h"
29 #include "webkit/plugins/npapi/plugin_constants_win.h" 33 #include "webkit/plugins/npapi/plugin_constants_win.h"
34 #include "webkit/plugins/npapi/plugin_group.h"
30 #include "webkit/plugins/npapi/plugin_list.h" 35 #include "webkit/plugins/npapi/plugin_list.h"
31 #include "webkit/plugins/webplugininfo.h" 36 #include "webkit/plugins/webplugininfo.h"
32 37
33 #if defined(OS_POSIX) && !defined(OS_MACOSX) 38 #if defined(OS_POSIX) && !defined(OS_MACOSX)
34 using ::base::files::FilePathWatcher; 39 using ::base::files::FilePathWatcher;
35 #endif 40 #endif
36 41
37 using content::PluginServiceFilter; 42 using content::PluginServiceFilter;
38 43
44 namespace {
45
46 // Helper function that merely runs the callback with the result. Called on the
47 // thread on which the original GetPlugins() call was made.
48 static void RunGetPluginsCallback(
49 const PluginService::GetPluginsCallback& callback,
50 std::vector<webkit::WebPluginInfo> result) {
Bernhard Bauer 2011/09/21 14:31:26 Nit: This should probably be const ref as well?
Robert Sesek 2011/09/21 16:46:52 Done.
51 callback.Run(result);
52 }
53
54 // A callback for GetPlugins() that then gets the freshly loaded plugin groups
55 // and runs the callback for GetPluginGroups().
56 static void GetPluginsForGroupsCallback(
57 const PluginService::GetPluginGroupsCallback& callback,
58 const std::vector<webkit::WebPluginInfo>& plugins) {
59 std::vector<webkit::npapi::PluginGroup> groups;
60 PluginService::GetInstance()->GetCachedPluginGroups(&groups);
61 callback.Run(groups);
62 }
63
64 } // namespace
65
39 #if defined(OS_MACOSX) 66 #if defined(OS_MACOSX)
40 static void NotifyPluginsOfActivation() { 67 static void NotifyPluginsOfActivation() {
41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
42 69
43 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); 70 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS);
44 !iter.Done(); ++iter) { 71 !iter.Done(); ++iter) {
45 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); 72 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
46 plugin->OnAppActivation(); 73 plugin->OnAppActivation();
47 } 74 }
48 } 75 }
(...skipping 14 matching lines...) Expand all
63 #endif 90 #endif
64 91
65 // static 92 // static
66 PluginService* PluginService::GetInstance() { 93 PluginService* PluginService::GetInstance() {
67 return Singleton<PluginService>::get(); 94 return Singleton<PluginService>::get();
68 } 95 }
69 96
70 PluginService::PluginService() 97 PluginService::PluginService()
71 : ui_locale_( 98 : ui_locale_(
72 content::GetContentClient()->browser()->GetApplicationLocale()), 99 content::GetContentClient()->browser()->GetApplicationLocale()),
73 filter_(NULL) { 100 filter_(NULL),
101 plugin_list_(NULL) {
74 RegisterPepperPlugins(); 102 RegisterPepperPlugins();
75 103
76 // Load any specified on the command line as well. 104 // Load any specified on the command line as well.
77 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 105 const CommandLine* command_line = CommandLine::ForCurrentProcess();
78 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin); 106 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin);
79 if (!path.empty()) 107 if (!path.empty())
80 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path); 108 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path);
81 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir); 109 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
82 if (!path.empty()) 110 if (!path.empty())
83 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(path); 111 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(path);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 } 155 }
128 #elif defined(OS_POSIX) && !defined(OS_MACOSX) 156 #elif defined(OS_POSIX) && !defined(OS_MACOSX)
129 // The FilePathWatcher produces too many false positives on MacOS (access time 157 // The FilePathWatcher produces too many false positives on MacOS (access time
130 // updates?) which will lead to enforcing updates of the plugins way too often. 158 // updates?) which will lead to enforcing updates of the plugins way too often.
131 // On ChromeOS the user can't install plugins anyway and on Windows all 159 // On ChromeOS the user can't install plugins anyway and on Windows all
132 // important plugins register themselves in the registry so no need to do that. 160 // important plugins register themselves in the registry so no need to do that.
133 file_watcher_delegate_ = new PluginDirWatcherDelegate(); 161 file_watcher_delegate_ = new PluginDirWatcherDelegate();
134 // Get the list of all paths for registering the FilePathWatchers 162 // Get the list of all paths for registering the FilePathWatchers
135 // that will track and if needed reload the list of plugins on runtime. 163 // that will track and if needed reload the list of plugins on runtime.
136 std::vector<FilePath> plugin_dirs; 164 std::vector<FilePath> plugin_dirs;
137 webkit::npapi::PluginList::Singleton()->GetPluginDirectories( 165 GetPluginList()->GetPluginDirectories(&plugin_dirs);
138 &plugin_dirs);
139 166
140 for (size_t i = 0; i < plugin_dirs.size(); ++i) { 167 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
141 // FilePathWatcher can not handle non-absolute paths under windows. 168 // FilePathWatcher can not handle non-absolute paths under windows.
142 // We don't watch for file changes in windows now but if this should ever 169 // We don't watch for file changes in windows now but if this should ever
143 // be extended to Windows these lines might save some time of debugging. 170 // be extended to Windows these lines might save some time of debugging.
144 #if defined(OS_WIN) 171 #if defined(OS_WIN)
145 if (!plugin_dirs[i].IsAbsolute()) 172 if (!plugin_dirs[i].IsAbsolute())
146 continue; 173 continue;
147 #endif 174 #endif
148 FilePathWatcher* watcher = new FilePathWatcher(); 175 FilePathWatcher* watcher = new FilePathWatcher();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 236
210 PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess( 237 PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess(
211 const FilePath& plugin_path) { 238 const FilePath& plugin_path) {
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
213 240
214 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path); 241 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
215 if (plugin_host) 242 if (plugin_host)
216 return plugin_host; 243 return plugin_host;
217 244
218 webkit::WebPluginInfo info; 245 webkit::WebPluginInfo info;
219 if (!webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath( 246 if (!GetPluginList()->GetPluginInfoByPath(plugin_path, &info)) {
220 plugin_path, &info)) {
221 return NULL; 247 return NULL;
222 } 248 }
223 249
224 // This plugin isn't loaded by any plugin process, so create a new process. 250 // This plugin isn't loaded by any plugin process, so create a new process.
225 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost()); 251 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
226 if (!new_host->Init(info, ui_locale_)) { 252 if (!new_host->Init(info, ui_locale_)) {
227 NOTREACHED(); // Init is not expected to fail. 253 NOTREACHED(); // Init is not expected to fail.
228 return NULL; 254 return NULL;
229 } 255 }
230 return new_host.release(); 256 return new_host.release();
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 bool PluginService::GetPluginInfo(int render_process_id, 403 bool PluginService::GetPluginInfo(int render_process_id,
378 int render_view_id, 404 int render_view_id,
379 const content::ResourceContext& context, 405 const content::ResourceContext& context,
380 const GURL& url, 406 const GURL& url,
381 const GURL& page_url, 407 const GURL& page_url,
382 const std::string& mime_type, 408 const std::string& mime_type,
383 bool allow_wildcard, 409 bool allow_wildcard,
384 bool* use_stale, 410 bool* use_stale,
385 webkit::WebPluginInfo* info, 411 webkit::WebPluginInfo* info,
386 std::string* actual_mime_type) { 412 std::string* actual_mime_type) {
387 webkit::npapi::PluginList* plugin_list = 413 webkit::npapi::PluginList* plugin_list = GetPluginList();
388 webkit::npapi::PluginList::Singleton();
389 // GetPluginInfoArray may need to load the plugins, so we need to be 414 // GetPluginInfoArray may need to load the plugins, so we need to be
390 // on the FILE thread. 415 // on the FILE thread.
391 DCHECK(use_stale || BrowserThread::CurrentlyOn(BrowserThread::FILE)); 416 DCHECK(use_stale || BrowserThread::CurrentlyOn(BrowserThread::FILE));
392 std::vector<webkit::WebPluginInfo> plugins; 417 std::vector<webkit::WebPluginInfo> plugins;
393 std::vector<std::string> mime_types; 418 std::vector<std::string> mime_types;
394 plugin_list->GetPluginInfoArray( 419 plugin_list->GetPluginInfoArray(
395 url, mime_type, allow_wildcard, use_stale, &plugins, &mime_types); 420 url, mime_type, allow_wildcard, use_stale, &plugins, &mime_types);
396 if (plugins.size() > 1 && 421 if (plugins.size() > 1 &&
397 plugins.back().path == 422 plugins.back().path ==
398 FilePath(webkit::npapi::kDefaultPluginLibraryName)) { 423 FilePath(webkit::npapi::kDefaultPluginLibraryName)) {
(...skipping 11 matching lines...) Expand all
410 &plugins[i])) { 435 &plugins[i])) {
411 *info = plugins[i]; 436 *info = plugins[i];
412 if (actual_mime_type) 437 if (actual_mime_type)
413 *actual_mime_type = mime_types[i]; 438 *actual_mime_type = mime_types[i];
414 return true; 439 return true;
415 } 440 }
416 } 441 }
417 return false; 442 return false;
418 } 443 }
419 444
420 void PluginService::GetPlugins( 445 void PluginService::RefreshPluginList() {
421 const content::ResourceContext& context, 446 GetPluginList()->RefreshPlugins();
422 std::vector<webkit::WebPluginInfo>* plugins) { 447 }
423 // GetPlugins may need to load the plugins, so we need to be 448
424 // on the FILE thread. 449 void PluginService::GetPlugins(const content::ResourceContext& context,
425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 450 const PluginService::GetPluginsCallback& callback) {
426 webkit::npapi::PluginList* plugin_list = 451 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
427 webkit::npapi::PluginList::Singleton(); 452 base::Bind(&PluginService::GetPluginsInternal, base::Unretained(this),
453 base::Unretained(&context),
454 MessageLoop::current()->message_loop_proxy(),
455 callback));
456 }
457
458 void PluginService::GetPlugins(const GetPluginsCallback& callback) {
459 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
460 base::Bind(&PluginService::GetPluginsInternal, base::Unretained(this),
461 base::Unretained(static_cast<content::ResourceContext*>(NULL)),
462 MessageLoop::current()->message_loop_proxy(),
463 callback));
464 }
465
466 void PluginService::GetCachedPluginGroups(
467 std::vector<webkit::npapi::PluginGroup>* groups) {
468 GetPluginList()->GetPluginGroups(false, groups);
469 }
470
471 void PluginService::GetPluginGroups(const GetPluginGroupsCallback& callback) {
472 GetPlugins(base::Bind(&GetPluginsForGroupsCallback, callback));
473 }
474
475 void PluginService::GetPluginsInternal(const content::ResourceContext* context,
476 base::MessageLoopProxy* target_loop,
477 const PluginService::GetPluginsCallback& callback) {
478 // Load all the plugins synchronously.
479 webkit::npapi::PluginList* plugin_list = GetPluginList();
428 std::vector<webkit::WebPluginInfo> all_plugins; 480 std::vector<webkit::WebPluginInfo> all_plugins;
429 plugin_list->GetPlugins(&all_plugins); 481 plugin_list->GetPlugins(&all_plugins);
430 482
431 int child_process_id = -1; 483 if (context) {
432 int routing_id = MSG_ROUTING_NONE; 484 // If there is a context, filter plugins.
433 for (size_t i = 0; i < all_plugins.size(); ++i) { 485 std::vector<webkit::WebPluginInfo> plugins;
434 if (!filter_ || filter_->ShouldUsePlugin(child_process_id, 486
435 routing_id, 487 int child_process_id = -1;
436 &context, 488 int routing_id = MSG_ROUTING_NONE;
437 GURL(), 489 for (size_t i = 0; i < all_plugins.size(); ++i) {
438 GURL(), 490 if (!filter_ || filter_->ShouldUsePlugin(child_process_id,
439 &all_plugins[i])) { 491 routing_id,
440 plugins->push_back(all_plugins[i]); 492 context,
493 GURL(),
494 GURL(),
495 &all_plugins[i])) {
496 plugins.push_back(all_plugins[i]);
497 }
441 } 498 }
499
500 target_loop->PostTask(FROM_HERE,
501 base::Bind(&RunGetPluginsCallback, callback, plugins));
502 } else {
503 // Otherwise, return all plugins.
504 target_loop->PostTask(FROM_HERE,
505 base::Bind(&RunGetPluginsCallback, callback, all_plugins));
442 } 506 }
443 } 507 }
444 508
509 void PluginService::SetPluginListForTesting(
510 webkit::npapi::MockPluginList* plugin_list) {
511 plugin_list_ = plugin_list;
512 }
513
514 webkit::npapi::PluginList* PluginService::GetPluginList() {
515 if (plugin_list_)
516 return plugin_list_;
517 return webkit::npapi::PluginList::Singleton();
518 }
519
445 void PluginService::OnWaitableEventSignaled( 520 void PluginService::OnWaitableEventSignaled(
446 base::WaitableEvent* waitable_event) { 521 base::WaitableEvent* waitable_event) {
447 #if defined(OS_WIN) 522 #if defined(OS_WIN)
448 if (waitable_event == hkcu_event_.get()) { 523 if (waitable_event == hkcu_event_.get()) {
449 hkcu_key_.StartWatching(); 524 hkcu_key_.StartWatching();
450 } else { 525 } else {
451 hklm_key_.StartWatching(); 526 hklm_key_.StartWatching();
452 } 527 }
453 528
454 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); 529 GetPluginList()->RefreshPlugins();
455 PurgePluginListCache(true); 530 PurgePluginListCache(true);
456 #else 531 #else
457 // This event should only get signaled on a Windows machine. 532 // This event should only get signaled on a Windows machine.
458 NOTREACHED(); 533 NOTREACHED();
459 #endif // defined(OS_WIN) 534 #endif // defined(OS_WIN)
460 } 535 }
461 536
462 void PluginService::Observe(int type, 537 void PluginService::Observe(int type,
463 const NotificationSource& source, 538 const NotificationSource& source,
464 const NotificationDetails& details) { 539 const NotificationDetails& details) {
(...skipping 11 matching lines...) Expand all
476 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator(); 551 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
477 !it.IsAtEnd(); it.Advance()) { 552 !it.IsAtEnd(); it.Advance()) {
478 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages)); 553 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
479 } 554 }
480 } 555 }
481 556
482 void PluginService::RegisterPepperPlugins() { 557 void PluginService::RegisterPepperPlugins() {
483 // TODO(abarth): It seems like the PepperPluginRegistry should do this work. 558 // TODO(abarth): It seems like the PepperPluginRegistry should do this work.
484 PepperPluginRegistry::ComputeList(&ppapi_plugins_); 559 PepperPluginRegistry::ComputeList(&ppapi_plugins_);
485 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) { 560 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
486 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin( 561 GetPluginList()->RegisterInternalPlugin(
487 ppapi_plugins_[i].ToWebPluginInfo()); 562 ppapi_plugins_[i].ToWebPluginInfo());
488 } 563 }
489 } 564 }
490 565
491 // There should generally be very few plugins so a brute-force search is fine. 566 // There should generally be very few plugins so a brute-force search is fine.
492 PepperPluginInfo* PluginService::GetRegisteredPpapiPluginInfo( 567 PepperPluginInfo* PluginService::GetRegisteredPpapiPluginInfo(
493 const FilePath& plugin_path) { 568 const FilePath& plugin_path) {
494 PepperPluginInfo* info = NULL; 569 PepperPluginInfo* info = NULL;
495 for (size_t i = 0; i < ppapi_plugins_.size(); i++) { 570 for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
496 if (ppapi_plugins_[i].path == plugin_path) { 571 if (ppapi_plugins_[i].path == plugin_path) {
497 info = &ppapi_plugins_[i]; 572 info = &ppapi_plugins_[i];
498 break; 573 break;
499 } 574 }
500 } 575 }
501 if (info) 576 if (info)
502 return info; 577 return info;
503 // We did not find the plugin in our list. But wait! the plugin can also 578 // We did not find the plugin in our list. But wait! the plugin can also
504 // be a latecomer, as it happens with pepper flash. This information 579 // be a latecomer, as it happens with pepper flash. This information
505 // can be obtained from the PluginList singleton and we can use it to 580 // can be obtained from the PluginList singleton and we can use it to
506 // construct it and add it to the list. This same deal needs to be done 581 // construct it and add it to the list. This same deal needs to be done
507 // in the renderer side in PepperPluginRegistry. 582 // in the renderer side in PepperPluginRegistry.
508 webkit::WebPluginInfo webplugin_info; 583 webkit::WebPluginInfo webplugin_info;
509 if (!webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath( 584 if (!GetPluginList()->GetPluginInfoByPath(plugin_path, &webplugin_info))
510 plugin_path, &webplugin_info))
511 return NULL; 585 return NULL;
512 PepperPluginInfo new_pepper_info; 586 PepperPluginInfo new_pepper_info;
513 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info)) 587 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
514 return NULL; 588 return NULL;
515 ppapi_plugins_.push_back(new_pepper_info); 589 ppapi_plugins_.push_back(new_pepper_info);
516 return &ppapi_plugins_[ppapi_plugins_.size() - 1]; 590 return &ppapi_plugins_[ppapi_plugins_.size() - 1];
517 } 591 }
518 592
519 #if defined(OS_POSIX) && !defined(OS_MACOSX) 593 #if defined(OS_POSIX) && !defined(OS_MACOSX)
520 // static 594 // static
521 void PluginService::RegisterFilePathWatcher( 595 void PluginService::RegisterFilePathWatcher(
522 FilePathWatcher *watcher, 596 FilePathWatcher *watcher,
523 const FilePath& path, 597 const FilePath& path,
524 FilePathWatcher::Delegate* delegate) { 598 FilePathWatcher::Delegate* delegate) {
525 bool result = watcher->Watch(path, delegate); 599 bool result = watcher->Watch(path, delegate);
526 DCHECK(result); 600 DCHECK(result);
527 } 601 }
528 #endif 602 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698