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

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: Removed PurgePluginListCache from the file watchere as it lead to crashes when plugins were in use. 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
« no previous file with comments | « chrome/browser/plugin_service.h ('k') | webkit/plugins/npapi/plugin_list.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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();
pastarmovj 2011/01/12 16:51:09 Problem here was that PurgePluginCache can be exec
76 }
77 virtual void OnError() {
78 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
79 // stopping the watcher would be enough. Or possibly restart it.
80 NOTREACHED();
81 }
82 };
83
61 // static 84 // static
62 bool PluginService::enable_chrome_plugins_ = true; 85 bool PluginService::enable_chrome_plugins_ = true;
63 86
64 // static 87 // static
65 void PluginService::InitGlobalInstance(Profile* profile) { 88 void PluginService::InitGlobalInstance(Profile* profile) {
66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
67 90
68 // We first group the plugins and then figure out which groups to disable. 91 // We first group the plugins and then figure out which groups to disable.
69 PluginUpdater::GetInstance()->DisablePluginGroupsFromPrefs(profile); 92 PluginUpdater::GetInstance()->DisablePluginGroupsFromPrefs(profile);
70 93
71 // Have Chrome plugins write their data to the profile directory. 94 // Have Chrome plugins write their data to the profile directory.
72 GetInstance()->SetChromePluginDataDir(profile->GetPath()); 95 GetInstance()->SetChromePluginDataDir(profile->GetPath());
73 } 96 }
74 97
75 // static 98 // static
76 PluginService* PluginService::GetInstance() { 99 PluginService* PluginService::GetInstance() {
77 return Singleton<PluginService>::get(); 100 return Singleton<PluginService>::get();
78 } 101 }
79 102
80 // static 103 // static
81 void PluginService::EnableChromePlugins(bool enable) { 104 void PluginService::EnableChromePlugins(bool enable) {
82 enable_chrome_plugins_ = enable; 105 enable_chrome_plugins_ = enable;
83 } 106 }
84 107
85 PluginService::PluginService() 108 PluginService::PluginService()
86 : main_message_loop_(MessageLoop::current()), 109 : main_message_loop_(MessageLoop::current()),
87 resource_dispatcher_host_(NULL), 110 resource_dispatcher_host_(NULL),
88 ui_locale_(g_browser_process->GetApplicationLocale()) { 111 ui_locale_(g_browser_process->GetApplicationLocale()),
112 file_watcher_delegate_(new PluginDirWatcherDelegate()) {
89 RegisterPepperPlugins(); 113 RegisterPepperPlugins();
90 114
91 // Have the NPAPI plugin list search for Chrome plugins as well. 115 // Have the NPAPI plugin list search for Chrome plugins as well.
92 ChromePluginLib::RegisterPluginsWithNPAPI(); 116 ChromePluginLib::RegisterPluginsWithNPAPI();
93 117
94 // Load any specified on the command line as well. 118 // Load any specified on the command line as well.
95 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 119 const CommandLine* command_line = CommandLine::ForCurrentProcess();
96 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin); 120 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin);
97 if (!path.empty()) 121 if (!path.empty())
98 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path); 122 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path);
(...skipping 16 matching lines...) Expand all
115 } 139 }
116 #endif 140 #endif
117 141
118 #if defined(OS_CHROMEOS) 142 #if defined(OS_CHROMEOS)
119 plugin_selection_policy_ = new chromeos::PluginSelectionPolicy; 143 plugin_selection_policy_ = new chromeos::PluginSelectionPolicy;
120 plugin_selection_policy_->StartInit(); 144 plugin_selection_policy_->StartInit();
121 #endif 145 #endif
122 146
123 chrome::RegisterInternalGPUPlugin(); 147 chrome::RegisterInternalGPUPlugin();
124 148
149 // Start watching for changes in the plugin list. This means watching
150 // for changes in the Windows registry keys and on both Windows and POSIX
151 // watch for changes in the paths that are expected to contain plugins.
125 #if defined(OS_WIN) 152 #if defined(OS_WIN)
126 hkcu_key_.Create( 153 hkcu_key_.Create(
127 HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); 154 HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
128 hklm_key_.Create( 155 hklm_key_.Create(
129 HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); 156 HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
130 if (hkcu_key_.StartWatching()) { 157 if (hkcu_key_.StartWatching()) {
131 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event())); 158 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
132 hkcu_watcher_.StartWatching(hkcu_event_.get(), this); 159 hkcu_watcher_.StartWatching(hkcu_event_.get(), this);
133 } 160 }
134 161
135 if (hklm_key_.StartWatching()) { 162 if (hklm_key_.StartWatching()) {
136 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event())); 163 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
137 hklm_watcher_.StartWatching(hklm_event_.get(), this); 164 hklm_watcher_.StartWatching(hklm_event_.get(), this);
138 } 165 }
139 #elif defined(OS_POSIX) && !defined(OS_MACOSX) 166 #elif defined(OS_POSIX) && !defined(OS_MACOSX)
140 // Also find plugins in a user-specific plugins dir, 167 // Also find plugins in a user-specific plugins dir,
141 // e.g. ~/.config/chromium/Plugins. 168 // e.g. ~/.config/chromium/Plugins.
142 FilePath user_data_dir; 169 FilePath user_data_dir;
143 if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { 170 if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
144 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir( 171 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(
145 user_data_dir.Append("Plugins")); 172 user_data_dir.Append("Plugins"));
146 } 173 }
147 #endif 174 #endif
175 // Get the list of all paths for registering the FilePathWatchers
176 // that will track and if needed reload the list of plugins on runtime.
177 std::vector<FilePath> plugin_dirs;
178 webkit::npapi::PluginList::Singleton()->GetPluginDirectories(
179 &plugin_dirs);
180
181 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
182 FilePathWatcher* watcher = new FilePathWatcher();
183 // FilePathWatcher can not handle non-absolute paths under windows.
184 #if defined(OS_WIN)
185 if(!plugin_dirs[i].IsAbsolute())
186 continue;
187 #endif
188 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
189 BrowserThread::PostTask(
190 BrowserThread::FILE, FROM_HERE,
191 NewRunnableFunction(
192 &PluginService::RegisterFilePathWatcher,
193 watcher, plugin_dirs[i], file_watcher_delegate_));
194 file_watchers_.push_back(watcher);
195 }
148 196
149 registrar_.Add(this, NotificationType::EXTENSION_LOADED, 197 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
150 NotificationService::AllSources()); 198 NotificationService::AllSources());
151 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, 199 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
152 NotificationService::AllSources()); 200 NotificationService::AllSources());
153 #if defined(OS_MACOSX) 201 #if defined(OS_MACOSX)
154 // We need to know when the browser comes forward so we can bring modal plugin 202 // We need to know when the browser comes forward so we can bring modal plugin
155 // windows forward too. 203 // windows forward too.
156 registrar_.Add(this, NotificationType::APP_ACTIVATED, 204 registrar_.Add(this, NotificationType::APP_ACTIVATED,
157 NotificationService::AllSources()); 205 NotificationService::AllSources());
(...skipping 139 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);
pastarmovj 2011/01/12 16:51:09 I can imagine this will lead to the same problem (
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
335 void PluginService::Observe(NotificationType type, 379 void PluginService::Observe(NotificationType type,
336 const NotificationSource& source, 380 const NotificationSource& source,
337 const NotificationDetails& details) { 381 const NotificationDetails& details) {
338 switch (type.value) { 382 switch (type.value) {
339 case NotificationType::EXTENSION_LOADED: { 383 case NotificationType::EXTENSION_LOADED: {
340 const Extension* extension = Details<const Extension>(details).ptr(); 384 const Extension* extension = Details<const Extension>(details).ptr();
341 bool plugins_changed = false; 385 bool plugins_changed = false;
342 for (size_t i = 0; i < extension->plugins().size(); ++i) { 386 for (size_t i = 0; i < extension->plugins().size(); ++i) {
343 const Extension::PluginInfo& plugin = extension->plugins()[i]; 387 const Extension::PluginInfo& plugin = extension->plugins()[i];
344 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); 388 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
345 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(plugin.path); 389 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(plugin.path);
346 plugins_changed = true; 390 plugins_changed = true;
347 if (!plugin.is_public) 391 if (!plugin.is_public)
348 private_plugins_[plugin.path] = extension->url(); 392 private_plugins_[plugin.path] = extension->url();
349 } 393 }
350 if (plugins_changed) 394 if (plugins_changed)
351 PurgePluginListCache(false); 395 PurgePluginListCache(false);
pastarmovj 2011/01/12 16:51:09 Dito.
352 break; 396 break;
353 } 397 }
354 398
355 case NotificationType::EXTENSION_UNLOADED: { 399 case NotificationType::EXTENSION_UNLOADED: {
356 const Extension* extension = 400 const Extension* extension =
357 Details<UnloadedExtensionInfo>(details)->extension; 401 Details<UnloadedExtensionInfo>(details)->extension;
358 bool plugins_changed = false; 402 bool plugins_changed = false;
359 for (size_t i = 0; i < extension->plugins().size(); ++i) { 403 for (size_t i = 0; i < extension->plugins().size(); ++i) {
360 const Extension::PluginInfo& plugin = extension->plugins()[i]; 404 const Extension::PluginInfo& plugin = extension->plugins()[i];
361 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 405 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
362 NewRunnableFunction(&ForceShutdownPlugin, 406 NewRunnableFunction(&ForceShutdownPlugin,
363 plugin.path)); 407 plugin.path));
364 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); 408 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
365 webkit::npapi::PluginList::Singleton()->RemoveExtraPluginPath( 409 webkit::npapi::PluginList::Singleton()->RemoveExtraPluginPath(
366 plugin.path); 410 plugin.path);
367 plugins_changed = true; 411 plugins_changed = true;
368 if (!plugin.is_public) 412 if (!plugin.is_public)
369 private_plugins_.erase(plugin.path); 413 private_plugins_.erase(plugin.path);
370 } 414 }
371 if (plugins_changed) 415 if (plugins_changed)
372 PurgePluginListCache(false); 416 PurgePluginListCache(false);
pastarmovj 2011/01/12 16:51:09 Dito.
373 break; 417 break;
374 } 418 }
375 419
376 #if defined(OS_MACOSX) 420 #if defined(OS_MACOSX)
377 case NotificationType::APP_ACTIVATED: { 421 case NotificationType::APP_ACTIVATED: {
378 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 422 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
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);
pastarmovj 2011/01/12 16:51:09 Dito. Here we need additional RefreshPlugins call
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 bool result = watcher->Watch(path, delegate);
482 DCHECK(result);
483 }
OLDNEW
« no previous file with comments | « chrome/browser/plugin_service.h ('k') | webkit/plugins/npapi/plugin_list.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698