summaryrefslogtreecommitdiffstats
path: root/content/browser/plugin_service_impl.cc
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-21 06:00:56 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-21 06:00:56 +0000
commite67385f3093d79371b080f3042b754cf4fd0e63e (patch)
treed0309f72fb6da658e325e7e84080a4cbd8eb397c /content/browser/plugin_service_impl.cc
parentd487beefe0374fb88cebc02b95063fa7ae6f5beb (diff)
downloadchromium_src-e67385f3093d79371b080f3042b754cf4fd0e63e.zip
chromium_src-e67385f3093d79371b080f3042b754cf4fd0e63e.tar.gz
chromium_src-e67385f3093d79371b080f3042b754cf4fd0e63e.tar.bz2
Rename PluginService to PluginServiceImpl.
BUG=98716 Review URL: http://codereview.chromium.org/9019004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@115279 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/plugin_service_impl.cc')
-rw-r--r--content/browser/plugin_service_impl.cc683
1 files changed, 683 insertions, 0 deletions
diff --git a/content/browser/plugin_service_impl.cc b/content/browser/plugin_service_impl.cc
new file mode 100644
index 0000000..fd1f0bd
--- /dev/null
+++ b/content/browser/plugin_service_impl.cc
@@ -0,0 +1,683 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/plugin_service_impl.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/file_path.h"
+#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/path_service.h"
+#include "base/string_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "content/browser/plugin_loader_posix.h"
+#include "content/browser/plugin_service_filter.h"
+#include "content/browser/ppapi_plugin_process_host.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/resource_context.h"
+#include "content/browser/utility_process_host.h"
+#include "content/common/pepper_plugin_registry.h"
+#include "content/common/plugin_messages.h"
+#include "content/common/utility_messages.h"
+#include "content/common/view_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/process_type.h"
+#include "webkit/plugins/npapi/plugin_constants_win.h"
+#include "webkit/plugins/npapi/plugin_group.h"
+#include "webkit/plugins/npapi/plugin_list.h"
+#include "webkit/plugins/webplugininfo.h"
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
+using ::base::files::FilePathWatcher;
+#endif
+
+using content::BrowserThread;
+using content::PluginService;
+using content::PluginServiceFilter;
+
+namespace {
+
+// Helper function that merely runs the callback with the result. Called on the
+// thread on which the original GetPlugins() call was made.
+static void RunGetPluginsCallback(
+ const PluginService::GetPluginsCallback& callback,
+ const std::vector<webkit::WebPluginInfo>& result) {
+ callback.Run(result);
+}
+
+// A callback for GetPlugins() that then gets the freshly loaded plugin groups
+// and runs the callback for GetPluginGroups().
+static void GetPluginsForGroupsCallback(
+ const PluginService::GetPluginGroupsCallback& callback,
+ const std::vector<webkit::WebPluginInfo>& plugins) {
+ std::vector<webkit::npapi::PluginGroup> groups;
+ webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, &groups);
+ callback.Run(groups);
+}
+
+// Callback set on the PluginList to assert that plugin loading happens on the
+// correct thread.
+void WillLoadPluginsCallback() {
+#if defined(OS_WIN)
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+#else
+ CHECK(false) << "Plugin loading should happen out-of-process.";
+#endif
+}
+
+} // namespace
+
+#if defined(OS_MACOSX)
+static void NotifyPluginsOfActivation() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ for (BrowserChildProcessHost::Iterator iter(
+ content::PROCESS_TYPE_PLUGIN);
+ !iter.Done(); ++iter) {
+ PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
+ plugin->OnAppActivation();
+ }
+}
+#elif defined(OS_POSIX) && !defined(OS_OPENBSD)
+// Delegate class for monitoring directories.
+class PluginDirWatcherDelegate : public FilePathWatcher::Delegate {
+ virtual void OnFilePathChanged(const FilePath& path) OVERRIDE {
+ VLOG(1) << "Watched path changed: " << path.value();
+ // Make the plugin list update itself
+ webkit::npapi::PluginList::Singleton()->RefreshPlugins();
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&content::PluginService::PurgePluginListCache,
+ static_cast<content::BrowserContext*>(NULL), false));
+ }
+
+ virtual void OnFilePathError(const FilePath& path) OVERRIDE {
+ // TODO(pastarmovj): Add some sensible error handling. Maybe silently
+ // stopping the watcher would be enough. Or possibly restart it.
+ NOTREACHED();
+ }
+};
+#endif
+
+namespace content {
+// static
+PluginService* PluginService::GetInstance() {
+ return PluginServiceImpl::GetInstance();
+}
+
+void PluginService::PurgePluginListCache(BrowserContext* browser_context,
+ bool reload_pages) {
+ for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
+ !it.IsAtEnd(); it.Advance()) {
+ RenderProcessHost* host = it.GetCurrentValue();
+ if (!browser_context || host->GetBrowserContext() == browser_context)
+ host->Send(new ViewMsg_PurgePluginListCache(reload_pages));
+ }
+}
+
+} // namespace content
+
+// static
+PluginServiceImpl* PluginServiceImpl::GetInstance() {
+ return Singleton<PluginServiceImpl>::get();
+}
+
+PluginServiceImpl::PluginServiceImpl()
+ : plugin_list_(NULL),
+ ui_locale_(
+ content::GetContentClient()->browser()->GetApplicationLocale()),
+ filter_(NULL) {
+}
+
+PluginServiceImpl::~PluginServiceImpl() {
+#if defined(OS_WIN)
+ // Release the events since they're owned by RegKey, not WaitableEvent.
+ hkcu_watcher_.StopWatching();
+ hklm_watcher_.StopWatching();
+ if (hkcu_event_.get())
+ hkcu_event_->Release();
+ if (hklm_event_.get())
+ hklm_event_->Release();
+#endif
+ // Make sure no plugin channel requests have been leaked.
+ DCHECK(pending_plugin_clients_.empty());
+}
+
+void PluginServiceImpl::Init() {
+ if (!plugin_list_)
+ plugin_list_ = webkit::npapi::PluginList::Singleton();
+
+ plugin_list_->set_will_load_plugins_callback(
+ base::Bind(&WillLoadPluginsCallback));
+
+ RegisterPepperPlugins();
+
+ content::GetContentClient()->AddNPAPIPlugins(plugin_list_);
+
+ // Load any specified on the command line as well.
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin);
+ if (!path.empty())
+ AddExtraPluginPath(path);
+ path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
+ if (!path.empty())
+ plugin_list_->AddExtraPluginDir(path);
+
+#if defined(OS_MACOSX)
+ // We need to know when the browser comes forward so we can bring modal plugin
+ // windows forward too.
+ registrar_.Add(this, content::NOTIFICATION_APP_ACTIVATED,
+ content::NotificationService::AllSources());
+#endif
+}
+
+void PluginServiceImpl::StartWatchingPlugins() {
+ // 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 (hkcu_key_.Create(HKEY_CURRENT_USER,
+ webkit::npapi::kRegistryMozillaPlugins,
+ KEY_NOTIFY) == ERROR_SUCCESS) {
+ if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
+ hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
+ hkcu_watcher_.StartWatching(hkcu_event_.get(), this);
+ }
+ }
+ if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
+ webkit::npapi::kRegistryMozillaPlugins,
+ KEY_NOTIFY) == ERROR_SUCCESS) {
+ if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
+ hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
+ hklm_watcher_.StartWatching(hklm_event_.get(), this);
+ }
+ }
+#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
+// 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.
+ 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;
+ plugin_list_->GetPluginDirectories(&plugin_dirs);
+
+ for (size_t i = 0; i < plugin_dirs.size(); ++i) {
+ // 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
+ FilePathWatcher* watcher = new FilePathWatcher();
+ VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
+ plugin_dirs[i], file_watcher_delegate_));
+ file_watchers_.push_back(watcher);
+ }
+#endif
+}
+
+const std::string& PluginServiceImpl::GetUILocale() {
+ return ui_locale_;
+}
+
+PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
+ const FilePath& plugin_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_PLUGIN);
+ !iter.Done(); ++iter) {
+ PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
+ if (plugin->info().path == plugin_path)
+ return plugin;
+ }
+
+ return NULL;
+}
+
+PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
+ const FilePath& plugin_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ for (BrowserChildProcessHost::Iterator iter(
+ content::PROCESS_TYPE_PPAPI_PLUGIN);
+ !iter.Done(); ++iter) {
+ PpapiPluginProcessHost* plugin =
+ static_cast<PpapiPluginProcessHost*>(*iter);
+ if (plugin->plugin_path() == plugin_path)
+ return plugin;
+ }
+
+ return NULL;
+}
+
+PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
+ const FilePath& broker_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ for (BrowserChildProcessHost::Iterator iter(
+ content::PROCESS_TYPE_PPAPI_BROKER);
+ !iter.Done(); ++iter) {
+ PpapiPluginProcessHost* broker =
+ static_cast<PpapiPluginProcessHost*>(*iter);
+ if (broker->plugin_path() == broker_path)
+ return broker;
+ }
+
+ return NULL;
+}
+
+PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
+ const FilePath& plugin_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
+ if (plugin_host)
+ return plugin_host;
+
+ webkit::WebPluginInfo info;
+ if (!GetPluginInfoByPath(plugin_path, &info)) {
+ return NULL;
+ }
+
+ // This plugin isn't loaded by any plugin process, so create a new process.
+ scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
+ if (!new_host->Init(info, ui_locale_)) {
+ NOTREACHED(); // Init is not expected to fail.
+ return NULL;
+ }
+ return new_host.release();
+}
+
+PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
+ const FilePath& plugin_path,
+ PpapiPluginProcessHost::PluginClient* client) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path);
+ if (plugin_host)
+ return plugin_host;
+
+ // Validate that the plugin is actually registered.
+ content::PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
+ if (!info)
+ return NULL;
+
+ // This plugin isn't loaded by any plugin process, so create a new process.
+ return PpapiPluginProcessHost::CreatePluginHost(
+ *info,
+ client->GetResourceContext()->host_resolver());
+}
+
+PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
+ const FilePath& plugin_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
+ if (plugin_host)
+ return plugin_host;
+
+ // Validate that the plugin is actually registered.
+ content::PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
+ if (!info)
+ return NULL;
+
+ // TODO(ddorwin): Uncomment once out of process is supported.
+ // DCHECK(info->is_out_of_process);
+
+ // This broker isn't loaded by any broker process, so create a new process.
+ return PpapiPluginProcessHost::CreateBrokerHost(*info);
+}
+
+void PluginServiceImpl::OpenChannelToNpapiPlugin(
+ int render_process_id,
+ int render_view_id,
+ const GURL& url,
+ const GURL& page_url,
+ const std::string& mime_type,
+ PluginProcessHost::Client* client) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(!ContainsKey(pending_plugin_clients_, client));
+ pending_plugin_clients_.insert(client);
+
+ // Make sure plugins are loaded if necessary.
+ content::PluginServiceFilterParams params = {
+ render_process_id,
+ render_view_id,
+ page_url,
+ &client->GetResourceContext()
+ };
+ GetPlugins(base::Bind(
+ &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
+ base::Unretained(this), params, url, mime_type, client));
+}
+
+void PluginServiceImpl::OpenChannelToPpapiPlugin(
+ const FilePath& path,
+ PpapiPluginProcessHost::PluginClient* client) {
+ PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
+ path, client);
+ if (plugin_host)
+ plugin_host->OpenChannelToPlugin(client);
+ else // Send error.
+ client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
+}
+
+void PluginServiceImpl::OpenChannelToPpapiBroker(
+ const FilePath& path,
+ PpapiPluginProcessHost::BrokerClient* client) {
+ PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(path);
+ if (plugin_host)
+ plugin_host->OpenChannelToPlugin(client);
+ else // Send error.
+ client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
+}
+
+void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
+ PluginProcessHost::Client* client) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(ContainsKey(pending_plugin_clients_, client));
+ pending_plugin_clients_.erase(client);
+}
+
+void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
+ const content::PluginServiceFilterParams& params,
+ const GURL& url,
+ const std::string& mime_type,
+ PluginProcessHost::Client* client,
+ const std::vector<webkit::WebPluginInfo>&) {
+ GetAllowedPluginForOpenChannelToPlugin(params.render_process_id,
+ params.render_view_id, url, params.page_url, mime_type, client,
+ params.resource_context);
+}
+
+void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
+ int render_process_id,
+ int render_view_id,
+ const GURL& url,
+ const GURL& page_url,
+ const std::string& mime_type,
+ PluginProcessHost::Client* client,
+ const content::ResourceContext* resource_context) {
+ webkit::WebPluginInfo info;
+ bool allow_wildcard = true;
+ bool found = GetPluginInfo(
+ render_process_id, render_view_id, *resource_context,
+ url, page_url, mime_type, allow_wildcard,
+ NULL, &info, NULL);
+ FilePath plugin_path;
+ if (found)
+ plugin_path = info.path;
+
+ // Now we jump back to the IO thread to finish opening the channel.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
+ base::Unretained(this), plugin_path, client));
+}
+
+void PluginServiceImpl::FinishOpenChannelToPlugin(
+ const FilePath& plugin_path,
+ PluginProcessHost::Client* client) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Make sure it hasn't been canceled yet.
+ if (!ContainsKey(pending_plugin_clients_, client))
+ return;
+ pending_plugin_clients_.erase(client);
+
+ PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path);
+ if (plugin_host) {
+ client->OnFoundPluginProcessHost(plugin_host);
+ plugin_host->OpenChannelToPlugin(client);
+ } else {
+ client->OnError();
+ }
+}
+
+bool PluginServiceImpl::GetPluginInfoArray(
+ const GURL& url,
+ const std::string& mime_type,
+ bool allow_wildcard,
+ std::vector<webkit::WebPluginInfo>* plugins,
+ std::vector<std::string>* actual_mime_types) {
+ bool use_stale = false;
+ plugin_list_->GetPluginInfoArray(url, mime_type, allow_wildcard,
+ &use_stale, plugins, actual_mime_types);
+ return use_stale;
+}
+
+bool PluginServiceImpl::GetPluginInfo(int render_process_id,
+ int render_view_id,
+ const content::ResourceContext& context,
+ const GURL& url,
+ const GURL& page_url,
+ const std::string& mime_type,
+ bool allow_wildcard,
+ bool* is_stale,
+ webkit::WebPluginInfo* info,
+ std::string* actual_mime_type) {
+ std::vector<webkit::WebPluginInfo> plugins;
+ std::vector<std::string> mime_types;
+ bool stale = GetPluginInfoArray(
+ url, mime_type, allow_wildcard, &plugins, &mime_types);
+ if (is_stale)
+ *is_stale = stale;
+ if (plugins.size() > 1 &&
+ plugins.back().path ==
+ FilePath(webkit::npapi::kDefaultPluginLibraryName)) {
+ // If there is at least one plug-in handling the required MIME type (apart
+ // from the default plug-in), we don't need the default plug-in.
+ plugins.pop_back();
+ }
+
+ for (size_t i = 0; i < plugins.size(); ++i) {
+ if (!filter_ || filter_->ShouldUsePlugin(render_process_id,
+ render_view_id,
+ &context,
+ url,
+ page_url,
+ &plugins[i])) {
+ *info = plugins[i];
+ if (actual_mime_type)
+ *actual_mime_type = mime_types[i];
+ return true;
+ }
+ }
+ return false;
+}
+
+bool PluginServiceImpl::GetPluginInfoByPath(const FilePath& plugin_path,
+ webkit::WebPluginInfo* info) {
+ std::vector<webkit::WebPluginInfo> plugins;
+ plugin_list_->GetPluginsIfNoRefreshNeeded(&plugins);
+
+ for (std::vector<webkit::WebPluginInfo>::iterator it = plugins.begin();
+ it != plugins.end();
+ ++it) {
+ if (it->path == plugin_path) {
+ *info = *it;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
+ scoped_refptr<base::MessageLoopProxy> target_loop(
+ MessageLoop::current()->message_loop_proxy());
+
+#if defined(OS_WIN)
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&PluginServiceImpl::GetPluginsInternal, base::Unretained(this),
+ target_loop, callback));
+#else
+ std::vector<webkit::WebPluginInfo> cached_plugins;
+ if (plugin_list_->GetPluginsIfNoRefreshNeeded(&cached_plugins)) {
+ // Can't assume the caller is reentrant.
+ target_loop->PostTask(FROM_HERE,
+ base::Bind(&RunGetPluginsCallback, callback, cached_plugins));
+ } else {
+ // If we switch back to loading plugins in process, then we need to make
+ // sure g_thread_init() gets called since plugins may call glib at load.
+ if (!plugin_loader_.get())
+ plugin_loader_ = new PluginLoaderPosix;
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&PluginLoaderPosix::LoadPlugins, plugin_loader_,
+ target_loop, callback));
+ }
+#endif
+}
+
+void PluginServiceImpl::GetPluginGroups(
+ const GetPluginGroupsCallback& callback) {
+ GetPlugins(base::Bind(&GetPluginsForGroupsCallback, callback));
+}
+
+void PluginServiceImpl::GetPluginsInternal(
+ base::MessageLoopProxy* target_loop,
+ const PluginService::GetPluginsCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ std::vector<webkit::WebPluginInfo> plugins;
+ plugin_list_->GetPlugins(&plugins);
+
+ target_loop->PostTask(FROM_HERE,
+ base::Bind(&RunGetPluginsCallback, callback, plugins));
+}
+
+void PluginServiceImpl::OnWaitableEventSignaled(
+ base::WaitableEvent* waitable_event) {
+#if defined(OS_WIN)
+ if (waitable_event == hkcu_event_.get()) {
+ hkcu_key_.StartWatching();
+ } else {
+ hklm_key_.StartWatching();
+ }
+
+ plugin_list_->RefreshPlugins();
+ PurgePluginListCache(NULL, false);
+#else
+ // This event should only get signaled on a Windows machine.
+ NOTREACHED();
+#endif // defined(OS_WIN)
+}
+
+void PluginServiceImpl::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+#if defined(OS_MACOSX)
+ if (type == content::NOTIFICATION_APP_ACTIVATED) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&NotifyPluginsOfActivation));
+ return;
+ }
+#endif
+ NOTREACHED();
+}
+
+void PluginServiceImpl::RegisterPepperPlugins() {
+ // TODO(abarth): It seems like the PepperPluginRegistry should do this work.
+ PepperPluginRegistry::ComputeList(&ppapi_plugins_);
+ for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
+ RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo());
+ }
+}
+
+// There should generally be very few plugins so a brute-force search is fine.
+content::PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
+ const FilePath& plugin_path) {
+ content::PepperPluginInfo* info = NULL;
+ for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
+ if (ppapi_plugins_[i].path == plugin_path) {
+ info = &ppapi_plugins_[i];
+ break;
+ }
+ }
+ if (info)
+ return info;
+ // We did not find the plugin in our list. But wait! the plugin can also
+ // be a latecomer, as it happens with pepper flash. This information
+ // can be obtained from the PluginList singleton and we can use it to
+ // construct it and add it to the list. This same deal needs to be done
+ // in the renderer side in PepperPluginRegistry.
+ webkit::WebPluginInfo webplugin_info;
+ if (!GetPluginInfoByPath(plugin_path, &webplugin_info))
+ return NULL;
+ content::PepperPluginInfo new_pepper_info;
+ if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
+ return NULL;
+ ppapi_plugins_.push_back(new_pepper_info);
+ return &ppapi_plugins_[ppapi_plugins_.size() - 1];
+}
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
+// static
+void PluginServiceImpl::RegisterFilePathWatcher(
+ FilePathWatcher *watcher,
+ const FilePath& path,
+ FilePathWatcher::Delegate* delegate) {
+ bool result = watcher->Watch(path, delegate);
+ DCHECK(result);
+}
+#endif
+
+void PluginServiceImpl::SetFilter(content::PluginServiceFilter* filter) {
+ filter_ = filter;
+}
+
+content::PluginServiceFilter* PluginServiceImpl::GetFilter() {
+ return filter_;
+}
+
+void PluginServiceImpl::RefreshPlugins() {
+ plugin_list_->RefreshPlugins();
+}
+
+void PluginServiceImpl::AddExtraPluginPath(const FilePath& path) {
+ plugin_list_->AddExtraPluginPath(path);
+}
+
+void PluginServiceImpl::RemoveExtraPluginPath(const FilePath& path) {
+ plugin_list_->RemoveExtraPluginPath(path);
+}
+
+void PluginServiceImpl::UnregisterInternalPlugin(const FilePath& path) {
+ plugin_list_->UnregisterInternalPlugin(path);
+}
+
+void PluginServiceImpl::SetPluginListForTesting(
+ webkit::npapi::PluginList* plugin_list) {
+ plugin_list_ = plugin_list;
+}
+
+void PluginServiceImpl::RegisterInternalPlugin(
+ const webkit::WebPluginInfo& info) {
+ plugin_list_->RegisterInternalPlugin(info);
+}
+
+string16 PluginServiceImpl::GetPluginGroupName(const std::string& plugin_name) {
+ return plugin_list_->GetPluginGroupName(plugin_name);
+}
+
+webkit::npapi::PluginList* PluginServiceImpl::GetPluginList() {
+ return plugin_list_;
+}