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