blob: 99924b14420e42b8b8c7aad34138d6e90260cd12 [file] [log] [blame]
[email protected]3b48dbc2012-01-06 16:34:171// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]e67385f2011-12-21 06:00:565#include "content/browser/plugin_service_impl.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]d33e7cc2011-09-23 01:43:567#include "base/bind.h"
[email protected]d48f1e0c2009-02-12 20:57:548#include "base/command_line.h"
[email protected]7b3ee8b2011-04-01 18:48:199#include "base/compiler_specific.h"
[email protected]dfba8762011-09-02 12:49:5410#include "base/file_path.h"
[email protected]d33e7cc2011-09-23 01:43:5611#include "base/message_loop.h"
12#include "base/message_loop_proxy.h"
[email protected]9c49ff02010-01-27 01:20:5513#include "base/path_service.h"
[email protected]d70539de2009-06-24 22:17:0614#include "base/string_util.h"
[email protected]7f070d42011-03-09 20:25:3215#include "base/synchronization/waitable_event.h"
[email protected]00b25432012-04-07 04:21:3716#include "base/threading/sequenced_worker_pool.h"
[email protected]34b99632011-01-01 01:01:0617#include "base/threading/thread.h"
[email protected]be1ce6a72010-08-03 14:35:2218#include "base/utf_string_conversions.h"
[email protected]cec1b8d2010-03-24 00:21:3419#include "base/values.h"
[email protected]6be08ae2011-10-18 02:23:2320#include "content/browser/plugin_loader_posix.h"
[email protected]a01efd22011-03-01 00:38:3221#include "content/browser/ppapi_plugin_process_host.h"
[email protected]f3b1a082011-11-18 00:34:3022#include "content/browser/renderer_host/render_process_host_impl.h"
[email protected]b3c41c0b2012-03-06 15:48:3223#include "content/browser/renderer_host/render_view_host_impl.h"
[email protected]cebc3dc2011-04-18 17:15:0024#include "content/common/pepper_plugin_registry.h"
[email protected]105303e2011-03-14 22:16:1025#include "content/common/plugin_messages.h"
[email protected]49125952011-09-27 18:05:1526#include "content/common/utility_messages.h"
[email protected]38b592902011-04-16 02:08:4227#include "content/common/view_messages.h"
[email protected]c38831a12011-10-28 12:44:4928#include "content/public/browser/browser_thread.h"
[email protected]87f3c082011-10-19 18:07:4429#include "content/public/browser/content_browser_client.h"
[email protected]c38831a12011-10-28 12:44:4930#include "content/public/browser/notification_service.h"
[email protected]0d6e9bd2011-10-18 04:29:1631#include "content/public/browser/notification_types.h"
[email protected]31f376c2012-03-13 16:43:0932#include "content/public/browser/plugin_service_filter.h"
[email protected]ce967862012-02-09 22:47:0533#include "content/public/browser/resource_context.h"
[email protected]c08950d22011-10-13 22:20:2934#include "content/public/common/content_switches.h"
[email protected]bd5d6cf2011-12-01 00:39:1235#include "content/public/common/process_type.h"
[email protected]191eb3f72010-12-21 06:27:5036#include "webkit/plugins/npapi/plugin_constants_win.h"
[email protected]d33e7cc2011-09-23 01:43:5637#include "webkit/plugins/npapi/plugin_group.h"
[email protected]191eb3f72010-12-21 06:27:5038#include "webkit/plugins/npapi/plugin_list.h"
[email protected]91d9f3d2011-08-14 05:24:4439#include "webkit/plugins/webplugininfo.h"
[email protected]191eb3f72010-12-21 06:27:5040
[email protected]3b48dbc2012-01-06 16:34:1741#if defined(OS_POSIX) && !defined(OS_OPENBSD)
[email protected]493c8002011-04-14 16:56:0142using ::base::files::FilePathWatcher;
43#endif
44
[email protected]631bb742011-11-02 11:29:3945using content::BrowserThread;
[email protected]e67385f2011-12-21 06:00:5646using content::PluginService;
[email protected]dfba8762011-09-02 12:49:5447using content::PluginServiceFilter;
48
[email protected]d33e7cc2011-09-23 01:43:5649namespace {
50
[email protected]d33e7cc2011-09-23 01:43:5651// A callback for GetPlugins() that then gets the freshly loaded plugin groups
52// and runs the callback for GetPluginGroups().
53static void GetPluginsForGroupsCallback(
54 const PluginService::GetPluginGroupsCallback& callback,
55 const std::vector<webkit::WebPluginInfo>& plugins) {
56 std::vector<webkit::npapi::PluginGroup> groups;
57 webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, &groups);
58 callback.Run(groups);
59}
60
[email protected]49125952011-09-27 18:05:1561// Callback set on the PluginList to assert that plugin loading happens on the
62// correct thread.
63void WillLoadPluginsCallback() {
[email protected]6a0dc7a2011-11-02 14:37:0764#if defined(OS_WIN)
[email protected]00b25432012-04-07 04:21:3765 CHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
[email protected]49125952011-09-27 18:05:1566#else
[email protected]88ca4912011-10-12 14:00:4367 CHECK(false) << "Plugin loading should happen out-of-process.";
[email protected]49125952011-09-27 18:05:1568#endif
69}
70
[email protected]d33e7cc2011-09-23 01:43:5671} // namespace
72
[email protected]a96ec6a2009-11-04 17:27:0873#if defined(OS_MACOSX)
74static void NotifyPluginsOfActivation() {
[email protected]f8b3ef82010-10-11 02:45:5275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]a96ec6a2009-11-04 17:27:0876
[email protected]4967f792012-01-20 22:14:4077 for (PluginProcessHostIterator iter; !iter.Done(); ++iter)
78 iter->OnAppActivation();
[email protected]a96ec6a2009-11-04 17:27:0879}
[email protected]3b48dbc2012-01-06 16:34:1780#endif
81#if defined(OS_POSIX) && !defined(OS_OPENBSD)
[email protected]634d23d2011-01-19 10:38:1982// Delegate class for monitoring directories.
83class PluginDirWatcherDelegate : public FilePathWatcher::Delegate {
[email protected]7b3ee8b2011-04-01 18:48:1984 virtual void OnFilePathChanged(const FilePath& path) OVERRIDE {
[email protected]634d23d2011-01-19 10:38:1985 VLOG(1) << "Watched path changed: " << path.value();
86 // Make the plugin list update itself
87 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
[email protected]ee6fcb22011-10-22 01:27:0688 BrowserThread::PostTask(
89 BrowserThread::UI, FROM_HERE,
[email protected]3a5180ae2011-12-21 02:39:3890 base::Bind(&content::PluginService::PurgePluginListCache,
[email protected]ee6fcb22011-10-22 01:27:0691 static_cast<content::BrowserContext*>(NULL), false));
[email protected]634d23d2011-01-19 10:38:1992 }
[email protected]45a22e62011-10-12 09:48:0293
[email protected]7b3ee8b2011-04-01 18:48:1994 virtual void OnFilePathError(const FilePath& path) OVERRIDE {
[email protected]634d23d2011-01-19 10:38:1995 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
96 // stopping the watcher would be enough. Or possibly restart it.
97 NOTREACHED();
98 }
99};
100#endif
101
[email protected]3a5180ae2011-12-21 02:39:38102namespace content {
103// static
104PluginService* PluginService::GetInstance() {
[email protected]e67385f2011-12-21 06:00:56105 return PluginServiceImpl::GetInstance();
[email protected]3a5180ae2011-12-21 02:39:38106}
107
108void PluginService::PurgePluginListCache(BrowserContext* browser_context,
109 bool reload_pages) {
110 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
111 !it.IsAtEnd(); it.Advance()) {
112 RenderProcessHost* host = it.GetCurrentValue();
113 if (!browser_context || host->GetBrowserContext() == browser_context)
114 host->Send(new ViewMsg_PurgePluginListCache(reload_pages));
115 }
116}
117
118} // namespace content
119
initial.commit09911bf2008-07-26 23:55:29120// static
[email protected]e67385f2011-12-21 06:00:56121PluginServiceImpl* PluginServiceImpl::GetInstance() {
122 return Singleton<PluginServiceImpl>::get();
initial.commit09911bf2008-07-26 23:55:29123}
124
[email protected]e67385f2011-12-21 06:00:56125PluginServiceImpl::PluginServiceImpl()
[email protected]99907362012-01-11 05:41:40126 : plugin_list_(NULL), filter_(NULL) {
[email protected]ee066172011-11-10 23:20:05127}
128
[email protected]e67385f2011-12-21 06:00:56129PluginServiceImpl::~PluginServiceImpl() {
[email protected]ee066172011-11-10 23:20:05130#if defined(OS_WIN)
131 // Release the events since they're owned by RegKey, not WaitableEvent.
132 hkcu_watcher_.StopWatching();
133 hklm_watcher_.StopWatching();
134 if (hkcu_event_.get())
135 hkcu_event_->Release();
136 if (hklm_event_.get())
137 hklm_event_->Release();
138#endif
139 // Make sure no plugin channel requests have been leaked.
140 DCHECK(pending_plugin_clients_.empty());
141}
142
[email protected]e67385f2011-12-21 06:00:56143void PluginServiceImpl::Init() {
[email protected]ee066172011-11-10 23:20:05144 if (!plugin_list_)
145 plugin_list_ = webkit::npapi::PluginList::Singleton();
146
[email protected]3a5180ae2011-12-21 02:39:38147 plugin_list_->set_will_load_plugins_callback(
[email protected]49125952011-09-27 18:05:15148 base::Bind(&WillLoadPluginsCallback));
149
[email protected]4e0616e2010-05-28 14:55:53150 RegisterPepperPlugins();
151
[email protected]3a5180ae2011-12-21 02:39:38152 content::GetContentClient()->AddNPAPIPlugins(plugin_list_);
[email protected]f520b5b2011-11-08 02:42:14153
[email protected]9a1c4262010-06-29 21:50:27154 // Load any specified on the command line as well.
[email protected]d48f1e0c2009-02-12 20:57:54155 const CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]c4e52f0d2009-11-06 19:55:16156 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin);
[email protected]7bf795d92010-05-22 00:14:28157 if (!path.empty())
[email protected]f520b5b2011-11-08 02:42:14158 AddExtraPluginPath(path);
[email protected]9a1c4262010-06-29 21:50:27159 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
160 if (!path.empty())
[email protected]3a5180ae2011-12-21 02:39:38161 plugin_list_->AddExtraPluginDir(path);
[email protected]7bf795d92010-05-22 00:14:28162
[email protected]dfba8762011-09-02 12:49:54163#if defined(OS_MACOSX)
164 // We need to know when the browser comes forward so we can bring modal plugin
165 // windows forward too.
166 registrar_.Add(this, content::NOTIFICATION_APP_ACTIVATED,
[email protected]ad50def52011-10-19 23:17:07167 content::NotificationService::AllSources());
[email protected]dfba8762011-09-02 12:49:54168#endif
169}
170
[email protected]e67385f2011-12-21 06:00:56171void PluginServiceImpl::StartWatchingPlugins() {
[email protected]634d23d2011-01-19 10:38:19172 // Start watching for changes in the plugin list. This means watching
173 // for changes in the Windows registry keys and on both Windows and POSIX
174 // watch for changes in the paths that are expected to contain plugins.
[email protected]b547fd42009-04-23 23:16:27175#if defined(OS_WIN)
[email protected]86ec4f6e2011-04-20 16:21:19176 if (hkcu_key_.Create(HKEY_CURRENT_USER,
177 webkit::npapi::kRegistryMozillaPlugins,
178 KEY_NOTIFY) == ERROR_SUCCESS) {
179 if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
180 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
181 hkcu_watcher_.StartWatching(hkcu_event_.get(), this);
182 }
[email protected]b547fd42009-04-23 23:16:27183 }
[email protected]86ec4f6e2011-04-20 16:21:19184 if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
185 webkit::npapi::kRegistryMozillaPlugins,
186 KEY_NOTIFY) == ERROR_SUCCESS) {
187 if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
188 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
189 hklm_watcher_.StartWatching(hklm_event_.get(), this);
190 }
[email protected]b547fd42009-04-23 23:16:27191 }
[email protected]3b48dbc2012-01-06 16:34:17192#elif defined(OS_POSIX) && !defined(OS_OPENBSD)
[email protected]634d23d2011-01-19 10:38:19193// On ChromeOS the user can't install plugins anyway and on Windows all
194// important plugins register themselves in the registry so no need to do that.
[email protected]634d23d2011-01-19 10:38:19195 file_watcher_delegate_ = new PluginDirWatcherDelegate();
196 // Get the list of all paths for registering the FilePathWatchers
197 // that will track and if needed reload the list of plugins on runtime.
198 std::vector<FilePath> plugin_dirs;
[email protected]3a5180ae2011-12-21 02:39:38199 plugin_list_->GetPluginDirectories(&plugin_dirs);
[email protected]894bb502009-05-21 22:39:57200
[email protected]634d23d2011-01-19 10:38:19201 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
[email protected]634d23d2011-01-19 10:38:19202 // FilePathWatcher can not handle non-absolute paths under windows.
203 // We don't watch for file changes in windows now but if this should ever
204 // be extended to Windows these lines might save some time of debugging.
205#if defined(OS_WIN)
206 if (!plugin_dirs[i].IsAbsolute())
207 continue;
208#endif
[email protected]493c8002011-04-14 16:56:01209 FilePathWatcher* watcher = new FilePathWatcher();
[email protected]634d23d2011-01-19 10:38:19210 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
211 BrowserThread::PostTask(
212 BrowserThread::FILE, FROM_HERE,
[email protected]e67385f2011-12-21 06:00:56213 base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
[email protected]81050512011-12-19 19:32:51214 plugin_dirs[i], file_watcher_delegate_));
[email protected]634d23d2011-01-19 10:38:19215 file_watchers_.push_back(watcher);
216 }
217#endif
initial.commit09911bf2008-07-26 23:55:29218}
219
[email protected]e67385f2011-12-21 06:00:56220PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
[email protected]28ab7f92009-01-06 21:39:04221 const FilePath& plugin_path) {
[email protected]4967f792012-01-20 22:14:40222 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
223 if (iter->info().path == plugin_path)
224 return *iter;
[email protected]a436d922009-02-13 23:16:42225 }
226
initial.commit09911bf2008-07-26 23:55:29227 return NULL;
228}
229
[email protected]e67385f2011-12-21 06:00:56230PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
[email protected]610c0892009-09-08 19:46:18231 const FilePath& plugin_path) {
[email protected]4967f792012-01-20 22:14:40232 for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) {
233 if (iter->plugin_path() == plugin_path)
234 return *iter;
[email protected]a08ebea2011-02-13 17:50:20235 }
236
237 return NULL;
238}
239
[email protected]e67385f2011-12-21 06:00:56240PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
[email protected]eb415bf0e2011-04-14 02:45:42241 const FilePath& broker_path) {
[email protected]4967f792012-01-20 22:14:40242 for (PpapiBrokerProcessHostIterator iter; !iter.Done(); ++iter) {
243 if (iter->plugin_path() == broker_path)
244 return *iter;
[email protected]eb415bf0e2011-04-14 02:45:42245 }
246
247 return NULL;
248}
249
[email protected]e67385f2011-12-21 06:00:56250PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
[email protected]a08ebea2011-02-13 17:50:20251 const FilePath& plugin_path) {
252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
253
254 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
initial.commit09911bf2008-07-26 23:55:29255 if (plugin_host)
256 return plugin_host;
257
[email protected]91d9f3d2011-08-14 05:24:44258 webkit::WebPluginInfo info;
[email protected]88ca4912011-10-12 14:00:43259 if (!GetPluginInfoByPath(plugin_path, &info)) {
[email protected]a27a9382009-02-11 23:55:10260 return NULL;
261 }
262
initial.commit09911bf2008-07-26 23:55:29263 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]8b8a554d2010-11-18 13:26:40264 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
[email protected]99907362012-01-11 05:41:40265 if (!new_host->Init(info)) {
[email protected]a08ebea2011-02-13 17:50:20266 NOTREACHED(); // Init is not expected to fail.
initial.commit09911bf2008-07-26 23:55:29267 return NULL;
268 }
[email protected]8b8a554d2010-11-18 13:26:40269 return new_host.release();
initial.commit09911bf2008-07-26 23:55:29270}
271
[email protected]e67385f2011-12-21 06:00:56272PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
[email protected]d259a8e2011-05-18 22:31:09273 const FilePath& plugin_path,
[email protected]a50432d2011-09-30 16:32:14274 PpapiPluginProcessHost::PluginClient* client) {
[email protected]a08ebea2011-02-13 17:50:20275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
276
277 PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path);
278 if (plugin_host)
279 return plugin_host;
280
[email protected]eb415bf0e2011-04-14 02:45:42281 // Validate that the plugin is actually registered.
[email protected]738a7212011-10-21 17:33:52282 content::PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]a08ebea2011-02-13 17:50:20283 if (!info)
284 return NULL;
285
286 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14287 return PpapiPluginProcessHost::CreatePluginHost(
288 *info,
[email protected]df02aca2012-02-09 21:03:20289 client->GetResourceContext()->GetHostResolver());
[email protected]a08ebea2011-02-13 17:50:20290}
291
[email protected]e67385f2011-12-21 06:00:56292PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
[email protected]eb415bf0e2011-04-14 02:45:42293 const FilePath& plugin_path) {
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
295
[email protected]a50432d2011-09-30 16:32:14296 PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42297 if (plugin_host)
298 return plugin_host;
299
300 // Validate that the plugin is actually registered.
[email protected]738a7212011-10-21 17:33:52301 content::PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42302 if (!info)
303 return NULL;
304
305 // TODO(ddorwin): Uncomment once out of process is supported.
306 // DCHECK(info->is_out_of_process);
307
308 // This broker isn't loaded by any broker process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14309 return PpapiPluginProcessHost::CreateBrokerHost(*info);
[email protected]eb415bf0e2011-04-14 02:45:42310}
311
[email protected]e67385f2011-12-21 06:00:56312void PluginServiceImpl::OpenChannelToNpapiPlugin(
[email protected]c8f73ab2011-01-22 00:05:17313 int render_process_id,
314 int render_view_id,
[email protected]610c0892009-09-08 19:46:18315 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54316 const GURL& page_url,
[email protected]610c0892009-09-08 19:46:18317 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39318 PluginProcessHost::Client* client) {
[email protected]76b70f92011-11-21 19:31:14319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]4befe7592011-09-14 22:49:09320 DCHECK(!ContainsKey(pending_plugin_clients_, client));
321 pending_plugin_clients_.insert(client);
[email protected]88ca4912011-10-12 14:00:43322
323 // Make sure plugins are loaded if necessary.
[email protected]209f2ae2012-03-13 01:28:08324 PluginServiceFilterParams params = {
[email protected]88ca4912011-10-12 14:00:43325 render_process_id,
326 render_view_id,
327 page_url,
[email protected]df02aca2012-02-09 21:03:20328 client->GetResourceContext()
[email protected]88ca4912011-10-12 14:00:43329 };
[email protected]e67385f2011-12-21 06:00:56330 GetPlugins(base::Bind(
331 &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
332 base::Unretained(this), params, url, mime_type, client));
[email protected]6fdd4182010-10-14 23:59:26333}
334
[email protected]e67385f2011-12-21 06:00:56335void PluginServiceImpl::OpenChannelToPpapiPlugin(
[email protected]a08ebea2011-02-13 17:50:20336 const FilePath& path,
[email protected]a50432d2011-09-30 16:32:14337 PpapiPluginProcessHost::PluginClient* client) {
[email protected]d259a8e2011-05-18 22:31:09338 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
339 path, client);
[email protected]1bf0fb22012-04-12 21:44:16340 if (plugin_host) {
[email protected]a08ebea2011-02-13 17:50:20341 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16342 } else {
343 // Send error.
344 client->OnPpapiChannelOpened(base::kNullProcessHandle,
345 IPC::ChannelHandle());
346 }
[email protected]a08ebea2011-02-13 17:50:20347}
348
[email protected]e67385f2011-12-21 06:00:56349void PluginServiceImpl::OpenChannelToPpapiBroker(
[email protected]eb415bf0e2011-04-14 02:45:42350 const FilePath& path,
[email protected]a50432d2011-09-30 16:32:14351 PpapiPluginProcessHost::BrokerClient* client) {
352 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(path);
[email protected]1bf0fb22012-04-12 21:44:16353 if (plugin_host) {
[email protected]a50432d2011-09-30 16:32:14354 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16355 } else {
356 // Send error.
357 client->OnPpapiChannelOpened(base::kNullProcessHandle,
358 IPC::ChannelHandle());
359 }
[email protected]eb415bf0e2011-04-14 02:45:42360}
361
[email protected]e67385f2011-12-21 06:00:56362void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
[email protected]4befe7592011-09-14 22:49:09363 PluginProcessHost::Client* client) {
364 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
365 DCHECK(ContainsKey(pending_plugin_clients_, client));
366 pending_plugin_clients_.erase(client);
367}
368
[email protected]e67385f2011-12-21 06:00:56369void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
[email protected]209f2ae2012-03-13 01:28:08370 const PluginServiceFilterParams& params,
[email protected]88ca4912011-10-12 14:00:43371 const GURL& url,
372 const std::string& mime_type,
373 PluginProcessHost::Client* client,
374 const std::vector<webkit::WebPluginInfo>&) {
375 GetAllowedPluginForOpenChannelToPlugin(params.render_process_id,
376 params.render_view_id, url, params.page_url, mime_type, client,
377 params.resource_context);
378}
379
[email protected]e67385f2011-12-21 06:00:56380void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
[email protected]c8f73ab2011-01-22 00:05:17381 int render_process_id,
382 int render_view_id,
[email protected]6fdd4182010-10-14 23:59:26383 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54384 const GURL& page_url,
[email protected]6fdd4182010-10-14 23:59:26385 const std::string& mime_type,
[email protected]87c4be42011-09-16 01:10:59386 PluginProcessHost::Client* client,
[email protected]df02aca2012-02-09 21:03:20387 content::ResourceContext* resource_context) {
[email protected]91d9f3d2011-08-14 05:24:44388 webkit::WebPluginInfo info;
[email protected]dfba8762011-09-02 12:49:54389 bool allow_wildcard = true;
[email protected]11e1c182011-05-17 20:26:27390 bool found = GetPluginInfo(
[email protected]df02aca2012-02-09 21:03:20391 render_process_id, render_view_id, resource_context,
[email protected]dfba8762011-09-02 12:49:54392 url, page_url, mime_type, allow_wildcard,
393 NULL, &info, NULL);
[email protected]6fdd4182010-10-14 23:59:26394 FilePath plugin_path;
[email protected]68598072011-07-29 08:21:28395 if (found)
[email protected]dfba8762011-09-02 12:49:54396 plugin_path = info.path;
[email protected]6fdd4182010-10-14 23:59:26397
398 // Now we jump back to the IO thread to finish opening the channel.
[email protected]e67385f2011-12-21 06:00:56399 BrowserThread::PostTask(
400 BrowserThread::IO, FROM_HERE,
401 base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
[email protected]88ca4912011-10-12 14:00:43402 base::Unretained(this), plugin_path, client));
[email protected]6fdd4182010-10-14 23:59:26403}
404
[email protected]e67385f2011-12-21 06:00:56405void PluginServiceImpl::FinishOpenChannelToPlugin(
[email protected]6fdd4182010-10-14 23:59:26406 const FilePath& plugin_path,
[email protected]46b69e42010-11-02 12:26:39407 PluginProcessHost::Client* client) {
[email protected]f8b3ef82010-10-11 02:45:52408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]20a793e2010-10-12 06:50:08409
[email protected]4befe7592011-09-14 22:49:09410 // Make sure it hasn't been canceled yet.
411 if (!ContainsKey(pending_plugin_clients_, client))
412 return;
413 pending_plugin_clients_.erase(client);
414
[email protected]a08ebea2011-02-13 17:50:20415 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path);
[email protected]4befe7592011-09-14 22:49:09416 if (plugin_host) {
417 client->OnFoundPluginProcessHost(plugin_host);
[email protected]46b69e42010-11-02 12:26:39418 plugin_host->OpenChannelToPlugin(client);
[email protected]4befe7592011-09-14 22:49:09419 } else {
[email protected]46b69e42010-11-02 12:26:39420 client->OnError();
[email protected]4befe7592011-09-14 22:49:09421 }
initial.commit09911bf2008-07-26 23:55:29422}
423
[email protected]e67385f2011-12-21 06:00:56424bool PluginServiceImpl::GetPluginInfoArray(
[email protected]51b63f62011-10-05 18:55:42425 const GURL& url,
426 const std::string& mime_type,
427 bool allow_wildcard,
428 std::vector<webkit::WebPluginInfo>* plugins,
429 std::vector<std::string>* actual_mime_types) {
430 bool use_stale = false;
[email protected]3a5180ae2011-12-21 02:39:38431 plugin_list_->GetPluginInfoArray(url, mime_type, allow_wildcard,
432 &use_stale, plugins, actual_mime_types);
[email protected]51b63f62011-10-05 18:55:42433 return use_stale;
434}
435
[email protected]e67385f2011-12-21 06:00:56436bool PluginServiceImpl::GetPluginInfo(int render_process_id,
437 int render_view_id,
[email protected]df02aca2012-02-09 21:03:20438 content::ResourceContext* context,
[email protected]e67385f2011-12-21 06:00:56439 const GURL& url,
440 const GURL& page_url,
441 const std::string& mime_type,
442 bool allow_wildcard,
443 bool* is_stale,
444 webkit::WebPluginInfo* info,
445 std::string* actual_mime_type) {
[email protected]91d9f3d2011-08-14 05:24:44446 std::vector<webkit::WebPluginInfo> plugins;
[email protected]68598072011-07-29 08:21:28447 std::vector<std::string> mime_types;
[email protected]88ca4912011-10-12 14:00:43448 bool stale = GetPluginInfoArray(
449 url, mime_type, allow_wildcard, &plugins, &mime_types);
450 if (is_stale)
451 *is_stale = stale;
[email protected]dfba8762011-09-02 12:49:54452
[email protected]68598072011-07-29 08:21:28453 for (size_t i = 0; i < plugins.size(); ++i) {
[email protected]dfba8762011-09-02 12:49:54454 if (!filter_ || filter_->ShouldUsePlugin(render_process_id,
455 render_view_id,
[email protected]df02aca2012-02-09 21:03:20456 context,
[email protected]dfba8762011-09-02 12:49:54457 url,
458 page_url,
459 &plugins[i])) {
[email protected]68598072011-07-29 08:21:28460 *info = plugins[i];
461 if (actual_mime_type)
462 *actual_mime_type = mime_types[i];
463 return true;
464 }
465 }
466 return false;
[email protected]6fdd4182010-10-14 23:59:26467}
468
[email protected]e67385f2011-12-21 06:00:56469bool PluginServiceImpl::GetPluginInfoByPath(const FilePath& plugin_path,
470 webkit::WebPluginInfo* info) {
[email protected]88ca4912011-10-12 14:00:43471 std::vector<webkit::WebPluginInfo> plugins;
[email protected]3a5180ae2011-12-21 02:39:38472 plugin_list_->GetPluginsIfNoRefreshNeeded(&plugins);
[email protected]88ca4912011-10-12 14:00:43473
474 for (std::vector<webkit::WebPluginInfo>::iterator it = plugins.begin();
475 it != plugins.end();
476 ++it) {
477 if (it->path == plugin_path) {
478 *info = *it;
479 return true;
480 }
481 }
482
483 return false;
484}
485
[email protected]e67385f2011-12-21 06:00:56486void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
[email protected]49125952011-09-27 18:05:15487 scoped_refptr<base::MessageLoopProxy> target_loop(
488 MessageLoop::current()->message_loop_proxy());
489
[email protected]6a0dc7a2011-11-02 14:37:07490#if defined(OS_WIN)
[email protected]00b25432012-04-07 04:21:37491 BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
492 FROM_HERE,
[email protected]e67385f2011-12-21 06:00:56493 base::Bind(&PluginServiceImpl::GetPluginsInternal, base::Unretained(this),
[email protected]00b25432012-04-07 04:21:37494 target_loop, callback),
495 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
[email protected]49125952011-09-27 18:05:15496#else
497 std::vector<webkit::WebPluginInfo> cached_plugins;
[email protected]3a5180ae2011-12-21 02:39:38498 if (plugin_list_->GetPluginsIfNoRefreshNeeded(&cached_plugins)) {
[email protected]49125952011-09-27 18:05:15499 // Can't assume the caller is reentrant.
500 target_loop->PostTask(FROM_HERE,
[email protected]00b25432012-04-07 04:21:37501 base::Bind(callback, cached_plugins));
[email protected]49125952011-09-27 18:05:15502 } else {
[email protected]4bb85b92011-11-05 02:53:29503 // If we switch back to loading plugins in process, then we need to make
504 // sure g_thread_init() gets called since plugins may call glib at load.
[email protected]d4af1e72011-10-21 17:45:43505 if (!plugin_loader_.get())
506 plugin_loader_ = new PluginLoaderPosix;
[email protected]49125952011-09-27 18:05:15507 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]d4af1e72011-10-21 17:45:43508 base::Bind(&PluginLoaderPosix::LoadPlugins, plugin_loader_,
509 target_loop, callback));
[email protected]49125952011-09-27 18:05:15510 }
511#endif
[email protected]d33e7cc2011-09-23 01:43:56512}
513
[email protected]e67385f2011-12-21 06:00:56514void PluginServiceImpl::GetPluginGroups(
515 const GetPluginGroupsCallback& callback) {
[email protected]d33e7cc2011-09-23 01:43:56516 GetPlugins(base::Bind(&GetPluginsForGroupsCallback, callback));
517}
518
[email protected]e67385f2011-12-21 06:00:56519void PluginServiceImpl::GetPluginsInternal(
[email protected]d33e7cc2011-09-23 01:43:56520 base::MessageLoopProxy* target_loop,
521 const PluginService::GetPluginsCallback& callback) {
[email protected]00b25432012-04-07 04:21:37522 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
[email protected]d33e7cc2011-09-23 01:43:56523
524 std::vector<webkit::WebPluginInfo> plugins;
[email protected]3a5180ae2011-12-21 02:39:38525 plugin_list_->GetPlugins(&plugins);
[email protected]d33e7cc2011-09-23 01:43:56526
527 target_loop->PostTask(FROM_HERE,
[email protected]00b25432012-04-07 04:21:37528 base::Bind(callback, plugins));
[email protected]dfba8762011-09-02 12:49:54529}
530
[email protected]e67385f2011-12-21 06:00:56531void PluginServiceImpl::OnWaitableEventSignaled(
[email protected]580522632009-08-17 21:55:55532 base::WaitableEvent* waitable_event) {
[email protected]b547fd42009-04-23 23:16:27533#if defined(OS_WIN)
534 if (waitable_event == hkcu_event_.get()) {
535 hkcu_key_.StartWatching();
536 } else {
537 hklm_key_.StartWatching();
538 }
539
[email protected]3a5180ae2011-12-21 02:39:38540 plugin_list_->RefreshPlugins();
[email protected]45a22e62011-10-12 09:48:02541 PurgePluginListCache(NULL, false);
[email protected]634d23d2011-01-19 10:38:19542#else
543 // This event should only get signaled on a Windows machine.
544 NOTREACHED();
[email protected]9de09f82009-08-17 20:13:53545#endif // defined(OS_WIN)
[email protected]b547fd42009-04-23 23:16:27546}
[email protected]894bb502009-05-21 22:39:57547
[email protected]e67385f2011-12-21 06:00:56548void PluginServiceImpl::Observe(int type,
549 const content::NotificationSource& source,
550 const content::NotificationDetails& details) {
[email protected]a96ec6a2009-11-04 17:27:08551#if defined(OS_MACOSX)
[email protected]dfba8762011-09-02 12:49:54552 if (type == content::NOTIFICATION_APP_ACTIVATED) {
553 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]81050512011-12-19 19:32:51554 base::Bind(&NotifyPluginsOfActivation));
[email protected]dfba8762011-09-02 12:49:54555 return;
[email protected]894bb502009-05-21 22:39:57556 }
[email protected]dfba8762011-09-02 12:49:54557#endif
558 NOTREACHED();
[email protected]c8f73ab2011-01-22 00:05:17559}
560
[email protected]e67385f2011-12-21 06:00:56561void PluginServiceImpl::RegisterPepperPlugins() {
[email protected]84396dbc2011-04-14 06:33:42562 // TODO(abarth): It seems like the PepperPluginRegistry should do this work.
[email protected]a08ebea2011-02-13 17:50:20563 PepperPluginRegistry::ComputeList(&ppapi_plugins_);
564 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]c6f3dea2012-01-14 02:23:11565 RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo(), true);
[email protected]4e0616e2010-05-28 14:55:53566 }
567}
[email protected]634d23d2011-01-19 10:38:19568
[email protected]eb415bf0e2011-04-14 02:45:42569// There should generally be very few plugins so a brute-force search is fine.
[email protected]e67385f2011-12-21 06:00:56570content::PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
[email protected]eb415bf0e2011-04-14 02:45:42571 const FilePath& plugin_path) {
[email protected]738a7212011-10-21 17:33:52572 content::PepperPluginInfo* info = NULL;
[email protected]eb415bf0e2011-04-14 02:45:42573 for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
[email protected]6b14feb2011-08-16 11:22:56574 if (ppapi_plugins_[i].path == plugin_path) {
575 info = &ppapi_plugins_[i];
576 break;
577 }
[email protected]eb415bf0e2011-04-14 02:45:42578 }
[email protected]076117592011-08-17 03:16:41579 if (info)
580 return info;
581 // We did not find the plugin in our list. But wait! the plugin can also
582 // be a latecomer, as it happens with pepper flash. This information
583 // can be obtained from the PluginList singleton and we can use it to
584 // construct it and add it to the list. This same deal needs to be done
585 // in the renderer side in PepperPluginRegistry.
586 webkit::WebPluginInfo webplugin_info;
[email protected]88ca4912011-10-12 14:00:43587 if (!GetPluginInfoByPath(plugin_path, &webplugin_info))
[email protected]076117592011-08-17 03:16:41588 return NULL;
[email protected]738a7212011-10-21 17:33:52589 content::PepperPluginInfo new_pepper_info;
[email protected]076117592011-08-17 03:16:41590 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
591 return NULL;
592 ppapi_plugins_.push_back(new_pepper_info);
593 return &ppapi_plugins_[ppapi_plugins_.size() - 1];
[email protected]eb415bf0e2011-04-14 02:45:42594}
595
[email protected]3b48dbc2012-01-06 16:34:17596#if defined(OS_POSIX) && !defined(OS_OPENBSD)
[email protected]634d23d2011-01-19 10:38:19597// static
[email protected]e67385f2011-12-21 06:00:56598void PluginServiceImpl::RegisterFilePathWatcher(
[email protected]634d23d2011-01-19 10:38:19599 FilePathWatcher *watcher,
600 const FilePath& path,
601 FilePathWatcher::Delegate* delegate) {
[email protected]7b3ee8b2011-04-01 18:48:19602 bool result = watcher->Watch(path, delegate);
[email protected]634d23d2011-01-19 10:38:19603 DCHECK(result);
604}
605#endif
[email protected]f520b5b2011-11-08 02:42:14606
[email protected]e67385f2011-12-21 06:00:56607void PluginServiceImpl::SetFilter(content::PluginServiceFilter* filter) {
[email protected]3a5180ae2011-12-21 02:39:38608 filter_ = filter;
609}
610
[email protected]e67385f2011-12-21 06:00:56611content::PluginServiceFilter* PluginServiceImpl::GetFilter() {
[email protected]3a5180ae2011-12-21 02:39:38612 return filter_;
613}
614
[email protected]b6a2f8de2012-01-31 17:28:49615void PluginServiceImpl::ForcePluginShutdown(const FilePath& plugin_path) {
616 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
617 BrowserThread::PostTask(
618 BrowserThread::IO, FROM_HERE,
619 base::Bind(&PluginServiceImpl::ForcePluginShutdown,
620 base::Unretained(this), plugin_path));
621 return;
622 }
623
624 PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path);
625 if (plugin)
626 plugin->ForceShutdown();
627}
628
[email protected]47214d882012-02-29 06:28:48629static const unsigned int kMaxCrashesPerInterval = 3;
630static const unsigned int kCrashesInterval = 120;
631
632void PluginServiceImpl::RegisterPluginCrash(const FilePath& path) {
633 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
634 std::map<FilePath, std::vector<base::Time> >::iterator i =
635 crash_times_.find(path);
636 if (i == crash_times_.end()) {
637 crash_times_[path] = std::vector<base::Time>();
638 i = crash_times_.find(path);
639 }
640 if (i->second.size() == kMaxCrashesPerInterval) {
641 i->second.erase(i->second.begin());
642 }
643 base::Time time = base::Time::Now();
644 i->second.push_back(time);
645}
646
647bool PluginServiceImpl::IsPluginUnstable(const FilePath& path) {
648 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
649 std::map<FilePath, std::vector<base::Time> >::const_iterator i =
650 crash_times_.find(path);
651 if (i == crash_times_.end()) {
652 return false;
653 }
654 if (i->second.size() != kMaxCrashesPerInterval) {
655 return false;
656 }
657 base::TimeDelta delta = base::Time::Now() - i->second[0];
658 if (delta.InSeconds() <= kCrashesInterval) {
659 return true;
660 }
661 return false;
662}
663
[email protected]e67385f2011-12-21 06:00:56664void PluginServiceImpl::RefreshPlugins() {
[email protected]3a5180ae2011-12-21 02:39:38665 plugin_list_->RefreshPlugins();
[email protected]f520b5b2011-11-08 02:42:14666}
667
[email protected]e67385f2011-12-21 06:00:56668void PluginServiceImpl::AddExtraPluginPath(const FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38669 plugin_list_->AddExtraPluginPath(path);
[email protected]f520b5b2011-11-08 02:42:14670}
671
[email protected]c6f3dea2012-01-14 02:23:11672void PluginServiceImpl::AddExtraPluginDir(const FilePath& path) {
673 plugin_list_->AddExtraPluginDir(path);
674}
675
[email protected]e67385f2011-12-21 06:00:56676void PluginServiceImpl::RemoveExtraPluginPath(const FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38677 plugin_list_->RemoveExtraPluginPath(path);
[email protected]f520b5b2011-11-08 02:42:14678}
679
[email protected]e67385f2011-12-21 06:00:56680void PluginServiceImpl::UnregisterInternalPlugin(const FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38681 plugin_list_->UnregisterInternalPlugin(path);
[email protected]f520b5b2011-11-08 02:42:14682}
683
[email protected]e67385f2011-12-21 06:00:56684void PluginServiceImpl::SetPluginListForTesting(
[email protected]ee066172011-11-10 23:20:05685 webkit::npapi::PluginList* plugin_list) {
686 plugin_list_ = plugin_list;
687}
688
[email protected]e67385f2011-12-21 06:00:56689void PluginServiceImpl::RegisterInternalPlugin(
[email protected]c6f3dea2012-01-14 02:23:11690 const webkit::WebPluginInfo& info,
691 bool add_at_beginning) {
692 plugin_list_->RegisterInternalPlugin(info, add_at_beginning);
[email protected]f520b5b2011-11-08 02:42:14693}
694
[email protected]e67385f2011-12-21 06:00:56695string16 PluginServiceImpl::GetPluginGroupName(const std::string& plugin_name) {
[email protected]3a5180ae2011-12-21 02:39:38696 return plugin_list_->GetPluginGroupName(plugin_name);
697}
698
[email protected]e67385f2011-12-21 06:00:56699webkit::npapi::PluginList* PluginServiceImpl::GetPluginList() {
[email protected]3a5180ae2011-12-21 02:39:38700 return plugin_list_;
[email protected]f520b5b2011-11-08 02:42:14701}