Added automatic update for plugins based on watching file changes.

BUG=48383
TEST=Add or remove some files to a default plugin location and check in about:plugins whether the change got detected. Also part of integration tests.

Review URL: http://codereview.chromium.org/6163003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71783 0039d316-1c4b-4281-b951-d872f2087c98
parent d1466334
...@@ -56,6 +56,29 @@ static void NotifyPluginsOfActivation() { ...@@ -56,6 +56,29 @@ static void NotifyPluginsOfActivation() {
} }
#endif #endif
static void PurgePluginListCache(bool reload_pages) {
for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
!it.IsAtEnd(); it.Advance()) {
it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
}
}
#if defined(OS_LINUX)
// Delegate class for monitoring directories.
class PluginDirWatcherDelegate : public FilePathWatcher::Delegate {
virtual void OnFilePathChanged(const FilePath& path) {
VLOG(1) << "Watched path changed: " << path.value();
// Make the plugin list update itself
webkit::npapi::PluginList::Singleton()->RefreshPlugins();
}
virtual void OnError() {
// TODO(pastarmovj): Add some sensible error handling. Maybe silently
// stopping the watcher would be enough. Or possibly restart it.
NOTREACHED();
}
};
#endif
// static // static
bool PluginService::enable_chrome_plugins_ = true; bool PluginService::enable_chrome_plugins_ = true;
...@@ -120,6 +143,9 @@ PluginService::PluginService() ...@@ -120,6 +143,9 @@ PluginService::PluginService()
chrome::RegisterInternalGPUPlugin(); chrome::RegisterInternalGPUPlugin();
// Start watching for changes in the plugin list. This means watching
// for changes in the Windows registry keys and on both Windows and POSIX
// watch for changes in the paths that are expected to contain plugins.
#if defined(OS_WIN) #if defined(OS_WIN)
hkcu_key_.Create( hkcu_key_.Create(
HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY); HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
...@@ -143,7 +169,36 @@ PluginService::PluginService() ...@@ -143,7 +169,36 @@ PluginService::PluginService()
user_data_dir.Append("Plugins")); user_data_dir.Append("Plugins"));
} }
#endif #endif
// The FilePathWatcher produces too many false positives on MacOS (access time
// updates?) which will lead to enforcing updates of the plugins way too often.
// On ChromeOS the user can't install plugins anyway and on Windows all
// important plugins register themselves in the registry so no need to do that.
#if defined(OS_LINUX)
file_watcher_delegate_ = new PluginDirWatcherDelegate();
// Get the list of all paths for registering the FilePathWatchers
// that will track and if needed reload the list of plugins on runtime.
std::vector<FilePath> plugin_dirs;
webkit::npapi::PluginList::Singleton()->GetPluginDirectories(
&plugin_dirs);
for (size_t i = 0; i < plugin_dirs.size(); ++i) {
FilePathWatcher* watcher = new FilePathWatcher();
// FilePathWatcher can not handle non-absolute paths under windows.
// We don't watch for file changes in windows now but if this should ever
// be extended to Windows these lines might save some time of debugging.
#if defined(OS_WIN)
if (!plugin_dirs[i].IsAbsolute())
continue;
#endif
VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
NewRunnableFunction(
&PluginService::RegisterFilePathWatcher,
watcher, plugin_dirs[i], file_watcher_delegate_));
file_watchers_.push_back(watcher);
}
#endif
registrar_.Add(this, NotificationType::EXTENSION_LOADED, registrar_.Add(this, NotificationType::EXTENSION_LOADED,
NotificationService::AllSources()); NotificationService::AllSources());
registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
...@@ -302,13 +357,6 @@ bool PluginService::GetFirstAllowedPluginInfo( ...@@ -302,13 +357,6 @@ bool PluginService::GetFirstAllowedPluginInfo(
#endif #endif
} }
static void PurgePluginListCache(bool reload_pages) {
for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
!it.IsAtEnd(); it.Advance()) {
it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
}
}
void PluginService::OnWaitableEventSignaled( void PluginService::OnWaitableEventSignaled(
base::WaitableEvent* waitable_event) { base::WaitableEvent* waitable_event) {
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -320,6 +368,9 @@ void PluginService::OnWaitableEventSignaled( ...@@ -320,6 +368,9 @@ void PluginService::OnWaitableEventSignaled(
webkit::npapi::PluginList::Singleton()->RefreshPlugins(); webkit::npapi::PluginList::Singleton()->RefreshPlugins();
PurgePluginListCache(true); PurgePluginListCache(true);
#else
// This event should only get signaled on a Windows machine.
NOTREACHED();
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
} }
...@@ -384,7 +435,7 @@ void PluginService::Observe(NotificationType type, ...@@ -384,7 +435,7 @@ void PluginService::Observe(NotificationType type,
break; break;
} }
default: default:
DCHECK(false); NOTREACHED();
} }
} }
...@@ -426,3 +477,14 @@ void PluginService::RegisterPepperPlugins() { ...@@ -426,3 +477,14 @@ void PluginService::RegisterPepperPlugins() {
webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info); webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info);
} }
} }
#if defined(OS_LINUX)
// static
void PluginService::RegisterFilePathWatcher(
FilePathWatcher *watcher,
const FilePath& path,
FilePathWatcher::Delegate* delegate) {
bool result = watcher->Watch(path, delegate);
DCHECK(result);
}
#endif
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/file_path.h" #include "base/file_path.h"
#include "base/hash_tables.h" #include "base/hash_tables.h"
#include "base/scoped_vector.h"
#include "base/singleton.h" #include "base/singleton.h"
#include "base/synchronization/waitable_event_watcher.h" #include "base/synchronization/waitable_event_watcher.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -28,6 +29,10 @@ ...@@ -28,6 +29,10 @@
#include "base/win/registry.h" #include "base/win/registry.h"
#endif #endif
#if defined(OS_LINUX)
#include "chrome/browser/file_path_watcher/file_path_watcher.h"
#endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
namespace chromeos { namespace chromeos {
class PluginSelectionPolicy; class PluginSelectionPolicy;
...@@ -40,6 +45,7 @@ class Message; ...@@ -40,6 +45,7 @@ class Message;
class MessageLoop; class MessageLoop;
class Profile; class Profile;
class PluginDirWatcherDelegate;
class ResourceDispatcherHost; class ResourceDispatcherHost;
namespace net { namespace net {
...@@ -144,6 +150,14 @@ class PluginService ...@@ -144,6 +150,14 @@ class PluginService
const FilePath& plugin_path, const FilePath& plugin_path,
PluginProcessHost::Client* client); PluginProcessHost::Client* client);
#if defined(OS_LINUX)
// Registers a new FilePathWatcher for a given path.
static void RegisterFilePathWatcher(
FilePathWatcher* watcher,
const FilePath& path,
FilePathWatcher::Delegate* delegate);
#endif
// mapping between plugin path and PluginProcessHost // mapping between plugin path and PluginProcessHost
typedef base::hash_map<FilePath, PluginProcessHost*> PluginMap; typedef base::hash_map<FilePath, PluginProcessHost*> PluginMap;
PluginMap plugin_hosts_; PluginMap plugin_hosts_;
...@@ -181,6 +195,11 @@ class PluginService ...@@ -181,6 +195,11 @@ class PluginService
base::WaitableEventWatcher hklm_watcher_; base::WaitableEventWatcher hklm_watcher_;
#endif #endif
#if defined(OS_LINUX)
ScopedVector<FilePathWatcher> file_watchers_;
scoped_refptr<PluginDirWatcherDelegate> file_watcher_delegate_;
#endif
// Set to true if chrome plugins are enabled. Defaults to true. // Set to true if chrome plugins are enabled. Defaults to true.
static bool enable_chrome_plugins_; static bool enable_chrome_plugins_;
......
...@@ -97,6 +97,9 @@ class PluginList { ...@@ -97,6 +97,9 @@ class PluginList {
// Same as above, but specifies a directory in which to search for plugins. // Same as above, but specifies a directory in which to search for plugins.
void AddExtraPluginDir(const FilePath& plugin_dir); void AddExtraPluginDir(const FilePath& plugin_dir);
// Get the ordered list of directories from which to load plugins
void GetPluginDirectories(std::vector<FilePath>* plugin_dirs);
// Register an internal plugin with the specified plugin information and // Register an internal plugin with the specified plugin information and
// function pointers. An internal plugin must be registered before it can // function pointers. An internal plugin must be registered before it can
// be loaded using PluginList::LoadPlugin(). // be loaded using PluginList::LoadPlugin().
...@@ -283,9 +286,6 @@ class PluginList { ...@@ -283,9 +286,6 @@ class PluginList {
// Do any initialization. // Do any initialization.
void PlatformInit(); void PlatformInit();
// Get the ordered list of directories from which to load plugins
void GetPluginDirectories(std::vector<FilePath>* plugin_dirs);
// //
// Command-line switches // Command-line switches
// //
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment