OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } | |
OLD | NEW |