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 "chrome/browser/plugin_service.h" | 5 #include "chrome/browser/plugin_service.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
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" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
50 | 50 |
51 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); | 51 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); |
52 !iter.Done(); ++iter) { | 52 !iter.Done(); ++iter) { |
53 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); | 53 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); |
54 plugin->OnAppActivation(); | 54 plugin->OnAppActivation(); |
55 } | 55 } |
56 } | 56 } |
57 #endif | 57 #endif |
58 | 58 |
| 59 static void PurgePluginListCache(bool reload_pages) { |
| 60 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator(); |
| 61 !it.IsAtEnd(); it.Advance()) { |
| 62 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages)); |
| 63 } |
| 64 } |
| 65 |
| 66 #if defined(OS_LINUX) |
| 67 // Delegate class for monitoring directories. |
| 68 class PluginDirWatcherDelegate : public FilePathWatcher::Delegate { |
| 69 virtual void OnFilePathChanged(const FilePath& path) { |
| 70 VLOG(1) << "Watched path changed: " << path.value(); |
| 71 // Make the plugin list update itself |
| 72 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); |
| 73 } |
| 74 virtual void OnError() { |
| 75 // TODO(pastarmovj): Add some sensible error handling. Maybe silently |
| 76 // stopping the watcher would be enough. Or possibly restart it. |
| 77 NOTREACHED(); |
| 78 } |
| 79 }; |
| 80 #endif |
| 81 |
59 // static | 82 // static |
60 bool PluginService::enable_chrome_plugins_ = true; | 83 bool PluginService::enable_chrome_plugins_ = true; |
61 | 84 |
62 // static | 85 // static |
63 void PluginService::InitGlobalInstance(Profile* profile) { | 86 void PluginService::InitGlobalInstance(Profile* profile) { |
64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 87 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
65 | 88 |
66 // We first group the plugins and then figure out which groups to disable. | 89 // We first group the plugins and then figure out which groups to disable. |
67 PluginUpdater::GetInstance()->DisablePluginGroupsFromPrefs(profile); | 90 PluginUpdater::GetInstance()->DisablePluginGroupsFromPrefs(profile); |
68 | 91 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 } | 136 } |
114 #endif | 137 #endif |
115 | 138 |
116 #if defined(OS_CHROMEOS) | 139 #if defined(OS_CHROMEOS) |
117 plugin_selection_policy_ = new chromeos::PluginSelectionPolicy; | 140 plugin_selection_policy_ = new chromeos::PluginSelectionPolicy; |
118 plugin_selection_policy_->StartInit(); | 141 plugin_selection_policy_->StartInit(); |
119 #endif | 142 #endif |
120 | 143 |
121 chrome::RegisterInternalGPUPlugin(); | 144 chrome::RegisterInternalGPUPlugin(); |
122 | 145 |
| 146 // Start watching for changes in the plugin list. This means watching |
| 147 // for changes in the Windows registry keys and on both Windows and POSIX |
| 148 // watch for changes in the paths that are expected to contain plugins. |
123 #if defined(OS_WIN) | 149 #if defined(OS_WIN) |
124 hkcu_key_.Create( | 150 hkcu_key_.Create( |
125 HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); | 151 HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); |
126 hklm_key_.Create( | 152 hklm_key_.Create( |
127 HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); | 153 HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); |
128 if (hkcu_key_.StartWatching()) { | 154 if (hkcu_key_.StartWatching()) { |
129 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event())); | 155 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event())); |
130 hkcu_watcher_.StartWatching(hkcu_event_.get(), this); | 156 hkcu_watcher_.StartWatching(hkcu_event_.get(), this); |
131 } | 157 } |
132 | 158 |
133 if (hklm_key_.StartWatching()) { | 159 if (hklm_key_.StartWatching()) { |
134 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event())); | 160 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event())); |
135 hklm_watcher_.StartWatching(hklm_event_.get(), this); | 161 hklm_watcher_.StartWatching(hklm_event_.get(), this); |
136 } | 162 } |
137 #elif defined(OS_POSIX) && !defined(OS_MACOSX) | 163 #elif defined(OS_POSIX) && !defined(OS_MACOSX) |
138 // Also find plugins in a user-specific plugins dir, | 164 // Also find plugins in a user-specific plugins dir, |
139 // e.g. ~/.config/chromium/Plugins. | 165 // e.g. ~/.config/chromium/Plugins. |
140 FilePath user_data_dir; | 166 FilePath user_data_dir; |
141 if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { | 167 if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { |
142 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir( | 168 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir( |
143 user_data_dir.Append("Plugins")); | 169 user_data_dir.Append("Plugins")); |
144 } | 170 } |
145 #endif | 171 #endif |
| 172 // The FilePathWatcher produces too many false positives on MacOS (access time |
| 173 // updates?) which will lead to enforcing updates of the plugins way too often. |
| 174 // On ChromeOS the user can't install plugins anyway and on Windows all |
| 175 // important plugins register themselves in the registry so no need to do that. |
| 176 #if defined(OS_LINUX) |
| 177 file_watcher_delegate_ = new PluginDirWatcherDelegate(); |
| 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; |
| 181 webkit::npapi::PluginList::Singleton()->GetPluginDirectories( |
| 182 &plugin_dirs); |
146 | 183 |
| 184 for (size_t i = 0; i < plugin_dirs.size(); ++i) { |
| 185 FilePathWatcher* watcher = new FilePathWatcher(); |
| 186 // FilePathWatcher can not handle non-absolute paths under windows. |
| 187 // We don't watch for file changes in windows now but if this should ever |
| 188 // be extended to Windows these lines might save some time of debugging. |
| 189 #if defined(OS_WIN) |
| 190 if (!plugin_dirs[i].IsAbsolute()) |
| 191 continue; |
| 192 #endif |
| 193 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value(); |
| 194 BrowserThread::PostTask( |
| 195 BrowserThread::FILE, FROM_HERE, |
| 196 NewRunnableFunction( |
| 197 &PluginService::RegisterFilePathWatcher, |
| 198 watcher, plugin_dirs[i], file_watcher_delegate_)); |
| 199 file_watchers_.push_back(watcher); |
| 200 } |
| 201 #endif |
147 registrar_.Add(this, NotificationType::EXTENSION_LOADED, | 202 registrar_.Add(this, NotificationType::EXTENSION_LOADED, |
148 NotificationService::AllSources()); | 203 NotificationService::AllSources()); |
149 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, | 204 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, |
150 NotificationService::AllSources()); | 205 NotificationService::AllSources()); |
151 #if defined(OS_MACOSX) | 206 #if defined(OS_MACOSX) |
152 // We need to know when the browser comes forward so we can bring modal plugin | 207 // We need to know when the browser comes forward so we can bring modal plugin |
153 // windows forward too. | 208 // windows forward too. |
154 registrar_.Add(this, NotificationType::APP_ACTIVATED, | 209 registrar_.Add(this, NotificationType::APP_ACTIVATED, |
155 NotificationService::AllSources()); | 210 NotificationService::AllSources()); |
156 #endif | 211 #endif |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 *actual_mime_type = actual_mime_types[allowed_index]; | 350 *actual_mime_type = actual_mime_types[allowed_index]; |
296 return true; | 351 return true; |
297 } | 352 } |
298 return false; | 353 return false; |
299 #else | 354 #else |
300 return webkit::npapi::PluginList::Singleton()->GetPluginInfo( | 355 return webkit::npapi::PluginList::Singleton()->GetPluginInfo( |
301 url, mime_type, allow_wildcard, info, actual_mime_type); | 356 url, mime_type, allow_wildcard, info, actual_mime_type); |
302 #endif | 357 #endif |
303 } | 358 } |
304 | 359 |
305 static void PurgePluginListCache(bool reload_pages) { | |
306 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator(); | |
307 !it.IsAtEnd(); it.Advance()) { | |
308 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages)); | |
309 } | |
310 } | |
311 | |
312 void PluginService::OnWaitableEventSignaled( | 360 void PluginService::OnWaitableEventSignaled( |
313 base::WaitableEvent* waitable_event) { | 361 base::WaitableEvent* waitable_event) { |
314 #if defined(OS_WIN) | 362 #if defined(OS_WIN) |
315 if (waitable_event == hkcu_event_.get()) { | 363 if (waitable_event == hkcu_event_.get()) { |
316 hkcu_key_.StartWatching(); | 364 hkcu_key_.StartWatching(); |
317 } else { | 365 } else { |
318 hklm_key_.StartWatching(); | 366 hklm_key_.StartWatching(); |
319 } | 367 } |
320 | 368 |
321 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); | 369 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); |
322 PurgePluginListCache(true); | 370 PurgePluginListCache(true); |
| 371 #else |
| 372 // This event should only get signaled on a Windows machine. |
| 373 NOTREACHED(); |
323 #endif // defined(OS_WIN) | 374 #endif // defined(OS_WIN) |
324 } | 375 } |
325 | 376 |
326 static void ForceShutdownPlugin(const FilePath& plugin_path) { | 377 static void ForceShutdownPlugin(const FilePath& plugin_path) { |
327 PluginProcessHost* plugin = | 378 PluginProcessHost* plugin = |
328 PluginService::GetInstance()->FindPluginProcess(plugin_path); | 379 PluginService::GetInstance()->FindPluginProcess(plugin_path); |
329 if (plugin) | 380 if (plugin) |
330 plugin->ForceShutdown(); | 381 plugin->ForceShutdown(); |
331 } | 382 } |
332 | 383 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 NewRunnableFunction(&NotifyPluginsOfActivation)); | 428 NewRunnableFunction(&NotifyPluginsOfActivation)); |
378 break; | 429 break; |
379 } | 430 } |
380 #endif | 431 #endif |
381 | 432 |
382 case NotificationType::PLUGIN_ENABLE_STATUS_CHANGED: { | 433 case NotificationType::PLUGIN_ENABLE_STATUS_CHANGED: { |
383 PurgePluginListCache(false); | 434 PurgePluginListCache(false); |
384 break; | 435 break; |
385 } | 436 } |
386 default: | 437 default: |
387 DCHECK(false); | 438 NOTREACHED(); |
388 } | 439 } |
389 } | 440 } |
390 | 441 |
391 bool PluginService::PrivatePluginAllowedForURL(const FilePath& plugin_path, | 442 bool PluginService::PrivatePluginAllowedForURL(const FilePath& plugin_path, |
392 const GURL& url) { | 443 const GURL& url) { |
393 if (url.is_empty()) | 444 if (url.is_empty()) |
394 return true; // Caller wants all plugins. | 445 return true; // Caller wants all plugins. |
395 | 446 |
396 PrivatePluginMap::iterator it = private_plugins_.find(plugin_path); | 447 PrivatePluginMap::iterator it = private_plugins_.find(plugin_path); |
397 if (it == private_plugins_.end()) | 448 if (it == private_plugins_.end()) |
(...skipping 21 matching lines...) Expand all Loading... |
419 info.mime_types = ASCIIToWide(JoinString(plugins[i].mime_types, '|')); | 470 info.mime_types = ASCIIToWide(JoinString(plugins[i].mime_types, '|')); |
420 | 471 |
421 // These NPAPI entry points will never be called. TODO(darin): Come up | 472 // These NPAPI entry points will never be called. TODO(darin): Come up |
422 // with a cleaner way to register pepper plugins with the NPAPI PluginList, | 473 // with a cleaner way to register pepper plugins with the NPAPI PluginList, |
423 // or perhaps refactor the PluginList to be less specific to NPAPI. | 474 // or perhaps refactor the PluginList to be less specific to NPAPI. |
424 memset(&info.entry_points, 0, sizeof(info.entry_points)); | 475 memset(&info.entry_points, 0, sizeof(info.entry_points)); |
425 | 476 |
426 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info); | 477 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info); |
427 } | 478 } |
428 } | 479 } |
| 480 |
| 481 #if defined(OS_LINUX) |
| 482 // static |
| 483 void PluginService::RegisterFilePathWatcher( |
| 484 FilePathWatcher *watcher, |
| 485 const FilePath& path, |
| 486 FilePathWatcher::Delegate* delegate) { |
| 487 bool result = watcher->Watch(path, delegate); |
| 488 DCHECK(result); |
| 489 } |
| 490 #endif |
OLD | NEW |