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

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

Issue 6163003: Added automatic update for plugins based on watching file changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed a line >80chars long. Created 9 years, 11 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "build/build_config.h" 5 #include "build/build_config.h"
6 6
7 #include "chrome/browser/plugin_service.h" 7 #include "chrome/browser/plugin_service.h"
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/stl_util-inl.h"
11 #include "base/string_util.h" 12 #include "base/string_util.h"
12 #include "base/threading/thread.h" 13 #include "base/threading/thread.h"
13 #include "base/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
14 #include "base/values.h" 15 #include "base/values.h"
15 #include "base/synchronization/waitable_event.h" 16 #include "base/synchronization/waitable_event.h"
16 #include "chrome/browser/browser_process.h" 17 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/browser_thread.h" 18 #include "chrome/browser/browser_thread.h"
18 #include "chrome/browser/chrome_plugin_host.h" 19 #include "chrome/browser/chrome_plugin_host.h"
19 #include "chrome/browser/extensions/extension_service.h" 20 #include "chrome/browser/extensions/extension_service.h"
20 #include "chrome/browser/plugin_updater.h" 21 #include "chrome/browser/plugin_updater.h"
(...skipping 30 matching lines...) Expand all
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
52 53
53 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); 54 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS);
54 !iter.Done(); ++iter) { 55 !iter.Done(); ++iter) {
55 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); 56 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
56 plugin->OnAppActivation(); 57 plugin->OnAppActivation();
57 } 58 }
58 } 59 }
59 #endif 60 #endif
60 61
62 static void PurgePluginListCache(bool reload_pages) {
63 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
64 !it.IsAtEnd(); it.Advance()) {
65 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
66 }
67 }
68
69 // Delegate class for monitoring directories.
70 class PluginDirWatcherDelegate : public FilePathWatcher::Delegate {
71 virtual void OnFilePathChanged(const FilePath& path) {
72 VLOG(1) << "Watched path changed : " << path.value();
73
74 // Make the plugin list update itself
75 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
76 BrowserThread::PostTask(
77 BrowserThread::UI, FROM_HERE,
Bernhard Bauer 2011/01/10 13:27:20 Is there are reason you're calling this method on
jam 2011/01/10 17:18:10 yep RenderProcessHost lives on the UI thread
pastarmovj 2011/01/11 17:17:26 It was a comment from John back than "since this i
pastarmovj 2011/01/11 17:17:26 Sorry I didn't post my answer earlier, when I had
78 NewRunnableFunction(&PurgePluginListCache, true));
79 }
80 virtual void OnError() {
81 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
82 // stopping the watcher would be enough. Or possibly restart it.
83 NOTREACHED();
84 }
85 };
86
61 // static 87 // static
62 bool PluginService::enable_chrome_plugins_ = true; 88 bool PluginService::enable_chrome_plugins_ = true;
63 89
64 // static 90 // static
65 void PluginService::InitGlobalInstance(Profile* profile) { 91 void PluginService::InitGlobalInstance(Profile* profile) {
66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
67 93
68 // We first group the plugins and then figure out which groups to disable. 94 // We first group the plugins and then figure out which groups to disable.
69 PluginUpdater::GetInstance()->DisablePluginGroupsFromPrefs(profile); 95 PluginUpdater::GetInstance()->DisablePluginGroupsFromPrefs(profile);
70 96
71 // Have Chrome plugins write their data to the profile directory. 97 // Have Chrome plugins write their data to the profile directory.
72 GetInstance()->SetChromePluginDataDir(profile->GetPath()); 98 GetInstance()->SetChromePluginDataDir(profile->GetPath());
73 } 99 }
74 100
75 // static 101 // static
76 PluginService* PluginService::GetInstance() { 102 PluginService* PluginService::GetInstance() {
77 return Singleton<PluginService>::get(); 103 return Singleton<PluginService>::get();
78 } 104 }
79 105
80 // static 106 // static
81 void PluginService::EnableChromePlugins(bool enable) { 107 void PluginService::EnableChromePlugins(bool enable) {
82 enable_chrome_plugins_ = enable; 108 enable_chrome_plugins_ = enable;
83 } 109 }
84 110
85 PluginService::PluginService() 111 PluginService::PluginService()
86 : main_message_loop_(MessageLoop::current()), 112 : main_message_loop_(MessageLoop::current()),
87 resource_dispatcher_host_(NULL), 113 resource_dispatcher_host_(NULL),
88 ui_locale_(g_browser_process->GetApplicationLocale()) { 114 ui_locale_(g_browser_process->GetApplicationLocale()),
115 file_watcher_delegate_(new PluginDirWatcherDelegate()) {
89 RegisterPepperPlugins(); 116 RegisterPepperPlugins();
90 117
91 // Have the NPAPI plugin list search for Chrome plugins as well. 118 // Have the NPAPI plugin list search for Chrome plugins as well.
92 ChromePluginLib::RegisterPluginsWithNPAPI(); 119 ChromePluginLib::RegisterPluginsWithNPAPI();
93 120
94 // Load any specified on the command line as well. 121 // Load any specified on the command line as well.
95 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 122 const CommandLine* command_line = CommandLine::ForCurrentProcess();
96 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin); 123 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin);
97 if (!path.empty()) 124 if (!path.empty())
98 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path); 125 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path);
(...skipping 16 matching lines...) Expand all
115 } 142 }
116 #endif 143 #endif
117 144
118 #if defined(OS_CHROMEOS) 145 #if defined(OS_CHROMEOS)
119 plugin_selection_policy_ = new chromeos::PluginSelectionPolicy; 146 plugin_selection_policy_ = new chromeos::PluginSelectionPolicy;
120 plugin_selection_policy_->StartInit(); 147 plugin_selection_policy_->StartInit();
121 #endif 148 #endif
122 149
123 chrome::RegisterInternalGPUPlugin(); 150 chrome::RegisterInternalGPUPlugin();
124 151
152 // Start watching for changes in the plugin list. This means watching
153 // for changes in the Windows registry keys and on both Windows and POSIX
154 // watch for changes in the paths that are expected to contain plugins.
125 #if defined(OS_WIN) 155 #if defined(OS_WIN)
126 hkcu_key_.Create( 156 hkcu_key_.Create(
127 HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); 157 HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
128 hklm_key_.Create( 158 hklm_key_.Create(
129 HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); 159 HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
130 if (hkcu_key_.StartWatching()) { 160 if (hkcu_key_.StartWatching()) {
131 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event())); 161 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
132 hkcu_watcher_.StartWatching(hkcu_event_.get(), this); 162 hkcu_watcher_.StartWatching(hkcu_event_.get(), this);
133 } 163 }
134 164
135 if (hklm_key_.StartWatching()) { 165 if (hklm_key_.StartWatching()) {
136 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event())); 166 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
137 hklm_watcher_.StartWatching(hklm_event_.get(), this); 167 hklm_watcher_.StartWatching(hklm_event_.get(), this);
138 } 168 }
139 #elif defined(OS_POSIX) && !defined(OS_MACOSX) 169 #elif defined(OS_POSIX) && !defined(OS_MACOSX)
140 // Also find plugins in a user-specific plugins dir, 170 // Also find plugins in a user-specific plugins dir,
141 // e.g. ~/.config/chromium/Plugins. 171 // e.g. ~/.config/chromium/Plugins.
142 FilePath user_data_dir; 172 FilePath user_data_dir;
143 if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { 173 if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
144 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir( 174 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(
145 user_data_dir.Append("Plugins")); 175 user_data_dir.Append("Plugins"));
146 } 176 }
147 #endif 177 #endif
178 // Get the list of all paths for registering the FilePathWatchers
179 // that will track and if needed reload the list of plugins on runtime.
180 std::vector<FilePath> plugin_dirs_list;
jam 2011/01/10 17:18:10 nit: plugin_dirs_ is enough, especially since list
pastarmovj 2011/01/11 17:17:26 That's true, thanks for the note :) Done.
181 webkit::npapi::PluginList::Singleton()->GetPluginDirectories(
182 &plugin_dirs_list);
183
184 for (size_t i = 0; i < plugin_dirs_list.size(); ++i) {
185 FilePathWatcher* watcher = new FilePathWatcher();
186 VLOG(1) << "Watching for changes in : " << plugin_dirs_list[i].value();
Bernhard Bauer 2011/01/10 13:27:20 Nit: no space before the colon.
pastarmovj 2011/01/11 17:17:26 Done.
187 BrowserThread::PostTask(
188 BrowserThread::FILE, FROM_HERE,
189 NewRunnableFunction(
190 &PluginService::RegisterFilePathWatcher,
191 watcher, plugin_dirs_list[i], file_watcher_delegate_));
192 file_watchers_.push_back(watcher);
193 }
148 194
149 registrar_.Add(this, NotificationType::EXTENSION_LOADED, 195 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
150 NotificationService::AllSources()); 196 NotificationService::AllSources());
151 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, 197 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
152 NotificationService::AllSources()); 198 NotificationService::AllSources());
153 #if defined(OS_MACOSX) 199 #if defined(OS_MACOSX)
154 // We need to know when the browser comes forward so we can bring modal plugin 200 // We need to know when the browser comes forward so we can bring modal plugin
155 // windows forward too. 201 // windows forward too.
156 registrar_.Add(this, NotificationType::APP_ACTIVATED, 202 registrar_.Add(this, NotificationType::APP_ACTIVATED,
157 NotificationService::AllSources()); 203 NotificationService::AllSources());
158 #endif 204 #endif
159 registrar_.Add(this, NotificationType::PLUGIN_ENABLE_STATUS_CHANGED, 205 registrar_.Add(this, NotificationType::PLUGIN_ENABLE_STATUS_CHANGED,
160 NotificationService::AllSources()); 206 NotificationService::AllSources());
161 } 207 }
162 208
163 PluginService::~PluginService() { 209 PluginService::~PluginService() {
164 #if defined(OS_WIN) 210 #if defined(OS_WIN)
165 // Release the events since they're owned by RegKey, not WaitableEvent. 211 // Release the events since they're owned by RegKey, not WaitableEvent.
166 hkcu_watcher_.StopWatching(); 212 hkcu_watcher_.StopWatching();
167 hklm_watcher_.StopWatching(); 213 hklm_watcher_.StopWatching();
168 hkcu_event_->Release(); 214 hkcu_event_->Release();
169 hklm_event_->Release(); 215 hklm_event_->Release();
170 #endif 216 #endif
217 // Delete the file watchers to release the refcounted delegates.
218 STLDeleteElements(&file_watchers_);
171 } 219 }
172 220
173 void PluginService::LoadChromePlugins( 221 void PluginService::LoadChromePlugins(
174 ResourceDispatcherHost* resource_dispatcher_host) { 222 ResourceDispatcherHost* resource_dispatcher_host) {
175 if (!enable_chrome_plugins_) 223 if (!enable_chrome_plugins_)
176 return; 224 return;
177 225
178 resource_dispatcher_host_ = resource_dispatcher_host; 226 resource_dispatcher_host_ = resource_dispatcher_host;
179 ChromePluginLib::LoadChromePlugins(GetCPBrowserFuncsForBrowser()); 227 ChromePluginLib::LoadChromePlugins(GetCPBrowserFuncsForBrowser());
180 } 228 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 *actual_mime_type = actual_mime_types[allowed_index]; 345 *actual_mime_type = actual_mime_types[allowed_index];
298 return true; 346 return true;
299 } 347 }
300 return false; 348 return false;
301 #else 349 #else
302 return webkit::npapi::PluginList::Singleton()->GetPluginInfo( 350 return webkit::npapi::PluginList::Singleton()->GetPluginInfo(
303 url, mime_type, allow_wildcard, info, actual_mime_type); 351 url, mime_type, allow_wildcard, info, actual_mime_type);
304 #endif 352 #endif
305 } 353 }
306 354
307 static void PurgePluginListCache(bool reload_pages) {
308 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
309 !it.IsAtEnd(); it.Advance()) {
310 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
311 }
312 }
313
314 void PluginService::OnWaitableEventSignaled( 355 void PluginService::OnWaitableEventSignaled(
315 base::WaitableEvent* waitable_event) { 356 base::WaitableEvent* waitable_event) {
316 #if defined(OS_WIN) 357 #if defined(OS_WIN)
317 if (waitable_event == hkcu_event_.get()) { 358 if (waitable_event == hkcu_event_.get()) {
318 hkcu_key_.StartWatching(); 359 hkcu_key_.StartWatching();
319 } else { 360 } else {
320 hklm_key_.StartWatching(); 361 hklm_key_.StartWatching();
321 } 362 }
322 363
323 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); 364 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
324 PurgePluginListCache(true); 365 PurgePluginListCache(true);
366 #else
367 // This event should only get signaled on a Windows machine.
368 NOTREACHED();
325 #endif // defined(OS_WIN) 369 #endif // defined(OS_WIN)
326 } 370 }
327 371
328 static void ForceShutdownPlugin(const FilePath& plugin_path) { 372 static void ForceShutdownPlugin(const FilePath& plugin_path) {
329 PluginProcessHost* plugin = 373 PluginProcessHost* plugin =
330 PluginService::GetInstance()->FindPluginProcess(plugin_path); 374 PluginService::GetInstance()->FindPluginProcess(plugin_path);
331 if (plugin) 375 if (plugin)
332 plugin->ForceShutdown(); 376 plugin->ForceShutdown();
333 } 377 }
334 378
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 NewRunnableFunction(&NotifyPluginsOfActivation)); 423 NewRunnableFunction(&NotifyPluginsOfActivation));
380 break; 424 break;
381 } 425 }
382 #endif 426 #endif
383 427
384 case NotificationType::PLUGIN_ENABLE_STATUS_CHANGED: { 428 case NotificationType::PLUGIN_ENABLE_STATUS_CHANGED: {
385 PurgePluginListCache(false); 429 PurgePluginListCache(false);
386 break; 430 break;
387 } 431 }
388 default: 432 default:
389 DCHECK(false); 433 NOTREACHED();
390 } 434 }
391 } 435 }
392 436
393 bool PluginService::PrivatePluginAllowedForURL(const FilePath& plugin_path, 437 bool PluginService::PrivatePluginAllowedForURL(const FilePath& plugin_path,
394 const GURL& url) { 438 const GURL& url) {
395 if (url.is_empty()) 439 if (url.is_empty())
396 return true; // Caller wants all plugins. 440 return true; // Caller wants all plugins.
397 441
398 PrivatePluginMap::iterator it = private_plugins_.find(plugin_path); 442 PrivatePluginMap::iterator it = private_plugins_.find(plugin_path);
399 if (it == private_plugins_.end()) 443 if (it == private_plugins_.end())
(...skipping 21 matching lines...) Expand all
421 info.mime_types = ASCIIToWide(JoinString(plugins[i].mime_types, '|')); 465 info.mime_types = ASCIIToWide(JoinString(plugins[i].mime_types, '|'));
422 466
423 // These NPAPI entry points will never be called. TODO(darin): Come up 467 // These NPAPI entry points will never be called. TODO(darin): Come up
424 // with a cleaner way to register pepper plugins with the NPAPI PluginList, 468 // with a cleaner way to register pepper plugins with the NPAPI PluginList,
425 // or perhaps refactor the PluginList to be less specific to NPAPI. 469 // or perhaps refactor the PluginList to be less specific to NPAPI.
426 memset(&info.entry_points, 0, sizeof(info.entry_points)); 470 memset(&info.entry_points, 0, sizeof(info.entry_points));
427 471
428 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info); 472 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info);
429 } 473 }
430 } 474 }
475
476 // static
477 void PluginService::RegisterFilePathWatcher(
478 FilePathWatcher *watcher,
479 const FilePath& path,
480 FilePathWatcher::Delegate* delegate) {
481 DCHECK(watcher->Watch(path, delegate));
Bernhard Bauer 2011/01/10 13:27:20 Isn't this whole line a no-op in a release build?
pastarmovj 2011/01/11 17:17:26 True. Sorry about that.
482 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698