blob: 8cd4cbc2d567a52232c23c882d9d38c1e0ba8507 [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]34b99632011-01-01 01:01:0616#include "base/threading/thread.h"
[email protected]be1ce6a72010-08-03 14:35:2217#include "base/utf_string_conversions.h"
[email protected]cec1b8d2010-03-24 00:21:3418#include "base/values.h"
[email protected]6be08ae2011-10-18 02:23:2319#include "content/browser/plugin_loader_posix.h"
[email protected]dfba8762011-09-02 12:49:5420#include "content/browser/plugin_service_filter.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]a0421732011-02-23 03:55:4023#include "content/browser/renderer_host/render_view_host.h"
[email protected]d259a8e2011-05-18 22:31:0924#include "content/browser/resource_context.h"
[email protected]49125952011-09-27 18:05:1525#include "content/browser/utility_process_host.h"
[email protected]cebc3dc2011-04-18 17:15:0026#include "content/common/pepper_plugin_registry.h"
[email protected]105303e2011-03-14 22:16:1027#include "content/common/plugin_messages.h"
[email protected]49125952011-09-27 18:05:1528#include "content/common/utility_messages.h"
[email protected]38b592902011-04-16 02:08:4229#include "content/common/view_messages.h"
[email protected]c38831a12011-10-28 12:44:4930#include "content/public/browser/browser_thread.h"
[email protected]87f3c082011-10-19 18:07:4431#include "content/public/browser/content_browser_client.h"
[email protected]c38831a12011-10-28 12:44:4932#include "content/public/browser/notification_service.h"
[email protected]0d6e9bd2011-10-18 04:29:1633#include "content/public/browser/notification_types.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
51// Helper function that merely runs the callback with the result. Called on the
52// thread on which the original GetPlugins() call was made.
53static void RunGetPluginsCallback(
54 const PluginService::GetPluginsCallback& callback,
55 const std::vector<webkit::WebPluginInfo>& result) {
56 callback.Run(result);
57}
58
59// A callback for GetPlugins() that then gets the freshly loaded plugin groups
60// and runs the callback for GetPluginGroups().
61static void GetPluginsForGroupsCallback(
62 const PluginService::GetPluginGroupsCallback& callback,
63 const std::vector<webkit::WebPluginInfo>& plugins) {
64 std::vector<webkit::npapi::PluginGroup> groups;
65 webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, &groups);
66 callback.Run(groups);
67}
68
[email protected]49125952011-09-27 18:05:1569// Callback set on the PluginList to assert that plugin loading happens on the
70// correct thread.
71void WillLoadPluginsCallback() {
[email protected]6a0dc7a2011-11-02 14:37:0772#if defined(OS_WIN)
[email protected]88ca4912011-10-12 14:00:4373 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]49125952011-09-27 18:05:1574#else
[email protected]88ca4912011-10-12 14:00:4375 CHECK(false) << "Plugin loading should happen out-of-process.";
[email protected]49125952011-09-27 18:05:1576#endif
77}
78
[email protected]d33e7cc2011-09-23 01:43:5679} // namespace
80
[email protected]a96ec6a2009-11-04 17:27:0881#if defined(OS_MACOSX)
82static void NotifyPluginsOfActivation() {
[email protected]f8b3ef82010-10-11 02:45:5283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]a96ec6a2009-11-04 17:27:0884
[email protected]bd5d6cf2011-12-01 00:39:1285 for (BrowserChildProcessHost::Iterator iter(
86 content::PROCESS_TYPE_PLUGIN);
[email protected]a96ec6a2009-11-04 17:27:0887 !iter.Done(); ++iter) {
88 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
89 plugin->OnAppActivation();
90 }
91}
[email protected]3b48dbc2012-01-06 16:34:1792#endif
93#if defined(OS_POSIX) && !defined(OS_OPENBSD)
[email protected]634d23d2011-01-19 10:38:1994// Delegate class for monitoring directories.
95class PluginDirWatcherDelegate : public FilePathWatcher::Delegate {
[email protected]7b3ee8b2011-04-01 18:48:1996 virtual void OnFilePathChanged(const FilePath& path) OVERRIDE {
[email protected]634d23d2011-01-19 10:38:1997 VLOG(1) << "Watched path changed: " << path.value();
98 // Make the plugin list update itself
99 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
[email protected]ee6fcb22011-10-22 01:27:06100 BrowserThread::PostTask(
101 BrowserThread::UI, FROM_HERE,
[email protected]3a5180ae2011-12-21 02:39:38102 base::Bind(&content::PluginService::PurgePluginListCache,
[email protected]ee6fcb22011-10-22 01:27:06103 static_cast<content::BrowserContext*>(NULL), false));
[email protected]634d23d2011-01-19 10:38:19104 }
[email protected]45a22e62011-10-12 09:48:02105
[email protected]7b3ee8b2011-04-01 18:48:19106 virtual void OnFilePathError(const FilePath& path) OVERRIDE {
[email protected]634d23d2011-01-19 10:38:19107 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
108 // stopping the watcher would be enough. Or possibly restart it.
109 NOTREACHED();
110 }
111};
112#endif
113
[email protected]3a5180ae2011-12-21 02:39:38114namespace content {
115// static
116PluginService* PluginService::GetInstance() {
[email protected]e67385f2011-12-21 06:00:56117 return PluginServiceImpl::GetInstance();
[email protected]3a5180ae2011-12-21 02:39:38118}
119
120void PluginService::PurgePluginListCache(BrowserContext* browser_context,
121 bool reload_pages) {
122 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
123 !it.IsAtEnd(); it.Advance()) {
124 RenderProcessHost* host = it.GetCurrentValue();
125 if (!browser_context || host->GetBrowserContext() == browser_context)
126 host->Send(new ViewMsg_PurgePluginListCache(reload_pages));
127 }
128}
129
130} // namespace content
131
initial.commit09911bf2008-07-26 23:55:29132// static
[email protected]e67385f2011-12-21 06:00:56133PluginServiceImpl* PluginServiceImpl::GetInstance() {
134 return Singleton<PluginServiceImpl>::get();
initial.commit09911bf2008-07-26 23:55:29135}
136
[email protected]e67385f2011-12-21 06:00:56137PluginServiceImpl::PluginServiceImpl()
[email protected]ee066172011-11-10 23:20:05138 : plugin_list_(NULL),
139 ui_locale_(
[email protected]dfba8762011-09-02 12:49:54140 content::GetContentClient()->browser()->GetApplicationLocale()),
141 filter_(NULL) {
[email protected]ee066172011-11-10 23:20:05142}
143
[email protected]e67385f2011-12-21 06:00:56144PluginServiceImpl::~PluginServiceImpl() {
[email protected]ee066172011-11-10 23:20:05145#if defined(OS_WIN)
146 // Release the events since they're owned by RegKey, not WaitableEvent.
147 hkcu_watcher_.StopWatching();
148 hklm_watcher_.StopWatching();
149 if (hkcu_event_.get())
150 hkcu_event_->Release();
151 if (hklm_event_.get())
152 hklm_event_->Release();
153#endif
154 // Make sure no plugin channel requests have been leaked.
155 DCHECK(pending_plugin_clients_.empty());
156}
157
[email protected]e67385f2011-12-21 06:00:56158void PluginServiceImpl::Init() {
[email protected]ee066172011-11-10 23:20:05159 if (!plugin_list_)
160 plugin_list_ = webkit::npapi::PluginList::Singleton();
161
[email protected]3a5180ae2011-12-21 02:39:38162 plugin_list_->set_will_load_plugins_callback(
[email protected]49125952011-09-27 18:05:15163 base::Bind(&WillLoadPluginsCallback));
164
[email protected]4e0616e2010-05-28 14:55:53165 RegisterPepperPlugins();
166
[email protected]3a5180ae2011-12-21 02:39:38167 content::GetContentClient()->AddNPAPIPlugins(plugin_list_);
[email protected]f520b5b2011-11-08 02:42:14168
[email protected]9a1c4262010-06-29 21:50:27169 // Load any specified on the command line as well.
[email protected]d48f1e0c2009-02-12 20:57:54170 const CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]c4e52f0d2009-11-06 19:55:16171 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin);
[email protected]7bf795d92010-05-22 00:14:28172 if (!path.empty())
[email protected]f520b5b2011-11-08 02:42:14173 AddExtraPluginPath(path);
[email protected]9a1c4262010-06-29 21:50:27174 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
175 if (!path.empty())
[email protected]3a5180ae2011-12-21 02:39:38176 plugin_list_->AddExtraPluginDir(path);
[email protected]7bf795d92010-05-22 00:14:28177
[email protected]dfba8762011-09-02 12:49:54178#if defined(OS_MACOSX)
179 // We need to know when the browser comes forward so we can bring modal plugin
180 // windows forward too.
181 registrar_.Add(this, content::NOTIFICATION_APP_ACTIVATED,
[email protected]ad50def52011-10-19 23:17:07182 content::NotificationService::AllSources());
[email protected]dfba8762011-09-02 12:49:54183#endif
184}
185
[email protected]e67385f2011-12-21 06:00:56186void PluginServiceImpl::StartWatchingPlugins() {
[email protected]634d23d2011-01-19 10:38:19187 // Start watching for changes in the plugin list. This means watching
188 // for changes in the Windows registry keys and on both Windows and POSIX
189 // watch for changes in the paths that are expected to contain plugins.
[email protected]b547fd42009-04-23 23:16:27190#if defined(OS_WIN)
[email protected]86ec4f6e2011-04-20 16:21:19191 if (hkcu_key_.Create(HKEY_CURRENT_USER,
192 webkit::npapi::kRegistryMozillaPlugins,
193 KEY_NOTIFY) == ERROR_SUCCESS) {
194 if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
195 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
196 hkcu_watcher_.StartWatching(hkcu_event_.get(), this);
197 }
[email protected]b547fd42009-04-23 23:16:27198 }
[email protected]86ec4f6e2011-04-20 16:21:19199 if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
200 webkit::npapi::kRegistryMozillaPlugins,
201 KEY_NOTIFY) == ERROR_SUCCESS) {
202 if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
203 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
204 hklm_watcher_.StartWatching(hklm_event_.get(), this);
205 }
[email protected]b547fd42009-04-23 23:16:27206 }
[email protected]3b48dbc2012-01-06 16:34:17207#elif defined(OS_POSIX) && !defined(OS_OPENBSD)
[email protected]634d23d2011-01-19 10:38:19208// On ChromeOS the user can't install plugins anyway and on Windows all
209// important plugins register themselves in the registry so no need to do that.
[email protected]634d23d2011-01-19 10:38:19210 file_watcher_delegate_ = new PluginDirWatcherDelegate();
211 // Get the list of all paths for registering the FilePathWatchers
212 // that will track and if needed reload the list of plugins on runtime.
213 std::vector<FilePath> plugin_dirs;
[email protected]3a5180ae2011-12-21 02:39:38214 plugin_list_->GetPluginDirectories(&plugin_dirs);
[email protected]894bb502009-05-21 22:39:57215
[email protected]634d23d2011-01-19 10:38:19216 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
[email protected]634d23d2011-01-19 10:38:19217 // FilePathWatcher can not handle non-absolute paths under windows.
218 // We don't watch for file changes in windows now but if this should ever
219 // be extended to Windows these lines might save some time of debugging.
220#if defined(OS_WIN)
221 if (!plugin_dirs[i].IsAbsolute())
222 continue;
223#endif
[email protected]493c8002011-04-14 16:56:01224 FilePathWatcher* watcher = new FilePathWatcher();
[email protected]634d23d2011-01-19 10:38:19225 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
226 BrowserThread::PostTask(
227 BrowserThread::FILE, FROM_HERE,
[email protected]e67385f2011-12-21 06:00:56228 base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
[email protected]81050512011-12-19 19:32:51229 plugin_dirs[i], file_watcher_delegate_));
[email protected]634d23d2011-01-19 10:38:19230 file_watchers_.push_back(watcher);
231 }
232#endif
initial.commit09911bf2008-07-26 23:55:29233}
234
[email protected]e67385f2011-12-21 06:00:56235const std::string& PluginServiceImpl::GetUILocale() {
initial.commit09911bf2008-07-26 23:55:29236 return ui_locale_;
237}
238
[email protected]e67385f2011-12-21 06:00:56239PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
[email protected]28ab7f92009-01-06 21:39:04240 const FilePath& plugin_path) {
[email protected]f8b3ef82010-10-11 02:45:52241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
initial.commit09911bf2008-07-26 23:55:29242
[email protected]bd5d6cf2011-12-01 00:39:12243 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_PLUGIN);
[email protected]a436d922009-02-13 23:16:42244 !iter.Done(); ++iter) {
245 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
246 if (plugin->info().path == plugin_path)
247 return plugin;
248 }
249
initial.commit09911bf2008-07-26 23:55:29250 return NULL;
251}
252
[email protected]e67385f2011-12-21 06:00:56253PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
[email protected]610c0892009-09-08 19:46:18254 const FilePath& plugin_path) {
[email protected]f8b3ef82010-10-11 02:45:52255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
initial.commit09911bf2008-07-26 23:55:29256
[email protected]a08ebea2011-02-13 17:50:20257 for (BrowserChildProcessHost::Iterator iter(
[email protected]bd5d6cf2011-12-01 00:39:12258 content::PROCESS_TYPE_PPAPI_PLUGIN);
[email protected]a08ebea2011-02-13 17:50:20259 !iter.Done(); ++iter) {
260 PpapiPluginProcessHost* plugin =
261 static_cast<PpapiPluginProcessHost*>(*iter);
262 if (plugin->plugin_path() == plugin_path)
263 return plugin;
264 }
265
266 return NULL;
267}
268
[email protected]e67385f2011-12-21 06:00:56269PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
[email protected]eb415bf0e2011-04-14 02:45:42270 const FilePath& broker_path) {
271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
272
273 for (BrowserChildProcessHost::Iterator iter(
[email protected]bd5d6cf2011-12-01 00:39:12274 content::PROCESS_TYPE_PPAPI_BROKER);
[email protected]eb415bf0e2011-04-14 02:45:42275 !iter.Done(); ++iter) {
[email protected]a50432d2011-09-30 16:32:14276 PpapiPluginProcessHost* broker =
277 static_cast<PpapiPluginProcessHost*>(*iter);
278 if (broker->plugin_path() == broker_path)
[email protected]eb415bf0e2011-04-14 02:45:42279 return broker;
280 }
281
282 return NULL;
283}
284
[email protected]e67385f2011-12-21 06:00:56285PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
[email protected]a08ebea2011-02-13 17:50:20286 const FilePath& plugin_path) {
287 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
288
289 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
initial.commit09911bf2008-07-26 23:55:29290 if (plugin_host)
291 return plugin_host;
292
[email protected]91d9f3d2011-08-14 05:24:44293 webkit::WebPluginInfo info;
[email protected]88ca4912011-10-12 14:00:43294 if (!GetPluginInfoByPath(plugin_path, &info)) {
[email protected]a27a9382009-02-11 23:55:10295 return NULL;
296 }
297
initial.commit09911bf2008-07-26 23:55:29298 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]8b8a554d2010-11-18 13:26:40299 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
300 if (!new_host->Init(info, ui_locale_)) {
[email protected]a08ebea2011-02-13 17:50:20301 NOTREACHED(); // Init is not expected to fail.
initial.commit09911bf2008-07-26 23:55:29302 return NULL;
303 }
[email protected]8b8a554d2010-11-18 13:26:40304 return new_host.release();
initial.commit09911bf2008-07-26 23:55:29305}
306
[email protected]e67385f2011-12-21 06:00:56307PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
[email protected]d259a8e2011-05-18 22:31:09308 const FilePath& plugin_path,
[email protected]a50432d2011-09-30 16:32:14309 PpapiPluginProcessHost::PluginClient* client) {
[email protected]a08ebea2011-02-13 17:50:20310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
311
312 PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path);
313 if (plugin_host)
314 return plugin_host;
315
[email protected]eb415bf0e2011-04-14 02:45:42316 // Validate that the plugin is actually registered.
[email protected]738a7212011-10-21 17:33:52317 content::PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]a08ebea2011-02-13 17:50:20318 if (!info)
319 return NULL;
320
321 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14322 return PpapiPluginProcessHost::CreatePluginHost(
323 *info,
324 client->GetResourceContext()->host_resolver());
[email protected]a08ebea2011-02-13 17:50:20325}
326
[email protected]e67385f2011-12-21 06:00:56327PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
[email protected]eb415bf0e2011-04-14 02:45:42328 const FilePath& plugin_path) {
329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
330
[email protected]a50432d2011-09-30 16:32:14331 PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42332 if (plugin_host)
333 return plugin_host;
334
335 // Validate that the plugin is actually registered.
[email protected]738a7212011-10-21 17:33:52336 content::PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42337 if (!info)
338 return NULL;
339
340 // TODO(ddorwin): Uncomment once out of process is supported.
341 // DCHECK(info->is_out_of_process);
342
343 // This broker isn't loaded by any broker process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14344 return PpapiPluginProcessHost::CreateBrokerHost(*info);
[email protected]eb415bf0e2011-04-14 02:45:42345}
346
[email protected]e67385f2011-12-21 06:00:56347void PluginServiceImpl::OpenChannelToNpapiPlugin(
[email protected]c8f73ab2011-01-22 00:05:17348 int render_process_id,
349 int render_view_id,
[email protected]610c0892009-09-08 19:46:18350 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54351 const GURL& page_url,
[email protected]610c0892009-09-08 19:46:18352 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39353 PluginProcessHost::Client* client) {
[email protected]76b70f92011-11-21 19:31:14354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]4befe7592011-09-14 22:49:09355 DCHECK(!ContainsKey(pending_plugin_clients_, client));
356 pending_plugin_clients_.insert(client);
[email protected]88ca4912011-10-12 14:00:43357
358 // Make sure plugins are loaded if necessary.
359 content::PluginServiceFilterParams params = {
360 render_process_id,
361 render_view_id,
362 page_url,
363 &client->GetResourceContext()
364 };
[email protected]e67385f2011-12-21 06:00:56365 GetPlugins(base::Bind(
366 &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
367 base::Unretained(this), params, url, mime_type, client));
[email protected]6fdd4182010-10-14 23:59:26368}
369
[email protected]e67385f2011-12-21 06:00:56370void PluginServiceImpl::OpenChannelToPpapiPlugin(
[email protected]a08ebea2011-02-13 17:50:20371 const FilePath& path,
[email protected]a50432d2011-09-30 16:32:14372 PpapiPluginProcessHost::PluginClient* client) {
[email protected]d259a8e2011-05-18 22:31:09373 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
374 path, client);
[email protected]a08ebea2011-02-13 17:50:20375 if (plugin_host)
376 plugin_host->OpenChannelToPlugin(client);
377 else // Send error.
378 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
379}
380
[email protected]e67385f2011-12-21 06:00:56381void PluginServiceImpl::OpenChannelToPpapiBroker(
[email protected]eb415bf0e2011-04-14 02:45:42382 const FilePath& path,
[email protected]a50432d2011-09-30 16:32:14383 PpapiPluginProcessHost::BrokerClient* client) {
384 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(path);
[email protected]eb415bf0e2011-04-14 02:45:42385 if (plugin_host)
[email protected]a50432d2011-09-30 16:32:14386 plugin_host->OpenChannelToPlugin(client);
[email protected]eb415bf0e2011-04-14 02:45:42387 else // Send error.
388 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
389}
390
[email protected]e67385f2011-12-21 06:00:56391void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
[email protected]4befe7592011-09-14 22:49:09392 PluginProcessHost::Client* client) {
393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
394 DCHECK(ContainsKey(pending_plugin_clients_, client));
395 pending_plugin_clients_.erase(client);
396}
397
[email protected]e67385f2011-12-21 06:00:56398void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
[email protected]88ca4912011-10-12 14:00:43399 const content::PluginServiceFilterParams& params,
400 const GURL& url,
401 const std::string& mime_type,
402 PluginProcessHost::Client* client,
403 const std::vector<webkit::WebPluginInfo>&) {
404 GetAllowedPluginForOpenChannelToPlugin(params.render_process_id,
405 params.render_view_id, url, params.page_url, mime_type, client,
406 params.resource_context);
407}
408
[email protected]e67385f2011-12-21 06:00:56409void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
[email protected]c8f73ab2011-01-22 00:05:17410 int render_process_id,
411 int render_view_id,
[email protected]6fdd4182010-10-14 23:59:26412 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54413 const GURL& page_url,
[email protected]6fdd4182010-10-14 23:59:26414 const std::string& mime_type,
[email protected]87c4be42011-09-16 01:10:59415 PluginProcessHost::Client* client,
416 const content::ResourceContext* resource_context) {
[email protected]91d9f3d2011-08-14 05:24:44417 webkit::WebPluginInfo info;
[email protected]dfba8762011-09-02 12:49:54418 bool allow_wildcard = true;
[email protected]11e1c182011-05-17 20:26:27419 bool found = GetPluginInfo(
[email protected]87c4be42011-09-16 01:10:59420 render_process_id, render_view_id, *resource_context,
[email protected]dfba8762011-09-02 12:49:54421 url, page_url, mime_type, allow_wildcard,
422 NULL, &info, NULL);
[email protected]6fdd4182010-10-14 23:59:26423 FilePath plugin_path;
[email protected]68598072011-07-29 08:21:28424 if (found)
[email protected]dfba8762011-09-02 12:49:54425 plugin_path = info.path;
[email protected]6fdd4182010-10-14 23:59:26426
427 // Now we jump back to the IO thread to finish opening the channel.
[email protected]e67385f2011-12-21 06:00:56428 BrowserThread::PostTask(
429 BrowserThread::IO, FROM_HERE,
430 base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
[email protected]88ca4912011-10-12 14:00:43431 base::Unretained(this), plugin_path, client));
[email protected]6fdd4182010-10-14 23:59:26432}
433
[email protected]e67385f2011-12-21 06:00:56434void PluginServiceImpl::FinishOpenChannelToPlugin(
[email protected]6fdd4182010-10-14 23:59:26435 const FilePath& plugin_path,
[email protected]46b69e42010-11-02 12:26:39436 PluginProcessHost::Client* client) {
[email protected]f8b3ef82010-10-11 02:45:52437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]20a793e2010-10-12 06:50:08438
[email protected]4befe7592011-09-14 22:49:09439 // Make sure it hasn't been canceled yet.
440 if (!ContainsKey(pending_plugin_clients_, client))
441 return;
442 pending_plugin_clients_.erase(client);
443
[email protected]a08ebea2011-02-13 17:50:20444 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path);
[email protected]4befe7592011-09-14 22:49:09445 if (plugin_host) {
446 client->OnFoundPluginProcessHost(plugin_host);
[email protected]46b69e42010-11-02 12:26:39447 plugin_host->OpenChannelToPlugin(client);
[email protected]4befe7592011-09-14 22:49:09448 } else {
[email protected]46b69e42010-11-02 12:26:39449 client->OnError();
[email protected]4befe7592011-09-14 22:49:09450 }
initial.commit09911bf2008-07-26 23:55:29451}
452
[email protected]e67385f2011-12-21 06:00:56453bool PluginServiceImpl::GetPluginInfoArray(
[email protected]51b63f62011-10-05 18:55:42454 const GURL& url,
455 const std::string& mime_type,
456 bool allow_wildcard,
457 std::vector<webkit::WebPluginInfo>* plugins,
458 std::vector<std::string>* actual_mime_types) {
459 bool use_stale = false;
[email protected]3a5180ae2011-12-21 02:39:38460 plugin_list_->GetPluginInfoArray(url, mime_type, allow_wildcard,
461 &use_stale, plugins, actual_mime_types);
[email protected]51b63f62011-10-05 18:55:42462 return use_stale;
463}
464
[email protected]e67385f2011-12-21 06:00:56465bool PluginServiceImpl::GetPluginInfo(int render_process_id,
466 int render_view_id,
467 const content::ResourceContext& context,
468 const GURL& url,
469 const GURL& page_url,
470 const std::string& mime_type,
471 bool allow_wildcard,
472 bool* is_stale,
473 webkit::WebPluginInfo* info,
474 std::string* actual_mime_type) {
[email protected]91d9f3d2011-08-14 05:24:44475 std::vector<webkit::WebPluginInfo> plugins;
[email protected]68598072011-07-29 08:21:28476 std::vector<std::string> mime_types;
[email protected]88ca4912011-10-12 14:00:43477 bool stale = GetPluginInfoArray(
478 url, mime_type, allow_wildcard, &plugins, &mime_types);
479 if (is_stale)
480 *is_stale = stale;
[email protected]dfba8762011-09-02 12:49:54481 if (plugins.size() > 1 &&
482 plugins.back().path ==
483 FilePath(webkit::npapi::kDefaultPluginLibraryName)) {
484 // If there is at least one plug-in handling the required MIME type (apart
485 // from the default plug-in), we don't need the default plug-in.
486 plugins.pop_back();
487 }
488
[email protected]68598072011-07-29 08:21:28489 for (size_t i = 0; i < plugins.size(); ++i) {
[email protected]dfba8762011-09-02 12:49:54490 if (!filter_ || filter_->ShouldUsePlugin(render_process_id,
491 render_view_id,
492 &context,
493 url,
494 page_url,
495 &plugins[i])) {
[email protected]68598072011-07-29 08:21:28496 *info = plugins[i];
497 if (actual_mime_type)
498 *actual_mime_type = mime_types[i];
499 return true;
500 }
501 }
502 return false;
[email protected]6fdd4182010-10-14 23:59:26503}
504
[email protected]e67385f2011-12-21 06:00:56505bool PluginServiceImpl::GetPluginInfoByPath(const FilePath& plugin_path,
506 webkit::WebPluginInfo* info) {
[email protected]88ca4912011-10-12 14:00:43507 std::vector<webkit::WebPluginInfo> plugins;
[email protected]3a5180ae2011-12-21 02:39:38508 plugin_list_->GetPluginsIfNoRefreshNeeded(&plugins);
[email protected]88ca4912011-10-12 14:00:43509
510 for (std::vector<webkit::WebPluginInfo>::iterator it = plugins.begin();
511 it != plugins.end();
512 ++it) {
513 if (it->path == plugin_path) {
514 *info = *it;
515 return true;
516 }
517 }
518
519 return false;
520}
521
[email protected]e67385f2011-12-21 06:00:56522void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
[email protected]49125952011-09-27 18:05:15523 scoped_refptr<base::MessageLoopProxy> target_loop(
524 MessageLoop::current()->message_loop_proxy());
525
[email protected]6a0dc7a2011-11-02 14:37:07526#if defined(OS_WIN)
[email protected]e67385f2011-12-21 06:00:56527 BrowserThread::PostTask(
528 BrowserThread::FILE, FROM_HERE,
529 base::Bind(&PluginServiceImpl::GetPluginsInternal, base::Unretained(this),
[email protected]49125952011-09-27 18:05:15530 target_loop, callback));
531#else
532 std::vector<webkit::WebPluginInfo> cached_plugins;
[email protected]3a5180ae2011-12-21 02:39:38533 if (plugin_list_->GetPluginsIfNoRefreshNeeded(&cached_plugins)) {
[email protected]49125952011-09-27 18:05:15534 // Can't assume the caller is reentrant.
535 target_loop->PostTask(FROM_HERE,
536 base::Bind(&RunGetPluginsCallback, callback, cached_plugins));
537 } else {
[email protected]4bb85b92011-11-05 02:53:29538 // If we switch back to loading plugins in process, then we need to make
539 // sure g_thread_init() gets called since plugins may call glib at load.
[email protected]d4af1e72011-10-21 17:45:43540 if (!plugin_loader_.get())
541 plugin_loader_ = new PluginLoaderPosix;
[email protected]49125952011-09-27 18:05:15542 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]d4af1e72011-10-21 17:45:43543 base::Bind(&PluginLoaderPosix::LoadPlugins, plugin_loader_,
544 target_loop, callback));
[email protected]49125952011-09-27 18:05:15545 }
546#endif
[email protected]d33e7cc2011-09-23 01:43:56547}
548
[email protected]e67385f2011-12-21 06:00:56549void PluginServiceImpl::GetPluginGroups(
550 const GetPluginGroupsCallback& callback) {
[email protected]d33e7cc2011-09-23 01:43:56551 GetPlugins(base::Bind(&GetPluginsForGroupsCallback, callback));
552}
553
[email protected]e67385f2011-12-21 06:00:56554void PluginServiceImpl::GetPluginsInternal(
[email protected]d33e7cc2011-09-23 01:43:56555 base::MessageLoopProxy* target_loop,
556 const PluginService::GetPluginsCallback& callback) {
557 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
558
559 std::vector<webkit::WebPluginInfo> plugins;
[email protected]3a5180ae2011-12-21 02:39:38560 plugin_list_->GetPlugins(&plugins);
[email protected]d33e7cc2011-09-23 01:43:56561
562 target_loop->PostTask(FROM_HERE,
563 base::Bind(&RunGetPluginsCallback, callback, plugins));
[email protected]dfba8762011-09-02 12:49:54564}
565
[email protected]e67385f2011-12-21 06:00:56566void PluginServiceImpl::OnWaitableEventSignaled(
[email protected]580522632009-08-17 21:55:55567 base::WaitableEvent* waitable_event) {
[email protected]b547fd42009-04-23 23:16:27568#if defined(OS_WIN)
569 if (waitable_event == hkcu_event_.get()) {
570 hkcu_key_.StartWatching();
571 } else {
572 hklm_key_.StartWatching();
573 }
574
[email protected]3a5180ae2011-12-21 02:39:38575 plugin_list_->RefreshPlugins();
[email protected]45a22e62011-10-12 09:48:02576 PurgePluginListCache(NULL, false);
[email protected]634d23d2011-01-19 10:38:19577#else
578 // This event should only get signaled on a Windows machine.
579 NOTREACHED();
[email protected]9de09f82009-08-17 20:13:53580#endif // defined(OS_WIN)
[email protected]b547fd42009-04-23 23:16:27581}
[email protected]894bb502009-05-21 22:39:57582
[email protected]e67385f2011-12-21 06:00:56583void PluginServiceImpl::Observe(int type,
584 const content::NotificationSource& source,
585 const content::NotificationDetails& details) {
[email protected]a96ec6a2009-11-04 17:27:08586#if defined(OS_MACOSX)
[email protected]dfba8762011-09-02 12:49:54587 if (type == content::NOTIFICATION_APP_ACTIVATED) {
588 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]81050512011-12-19 19:32:51589 base::Bind(&NotifyPluginsOfActivation));
[email protected]dfba8762011-09-02 12:49:54590 return;
[email protected]894bb502009-05-21 22:39:57591 }
[email protected]dfba8762011-09-02 12:49:54592#endif
593 NOTREACHED();
[email protected]c8f73ab2011-01-22 00:05:17594}
595
[email protected]e67385f2011-12-21 06:00:56596void PluginServiceImpl::RegisterPepperPlugins() {
[email protected]84396dbc2011-04-14 06:33:42597 // TODO(abarth): It seems like the PepperPluginRegistry should do this work.
[email protected]a08ebea2011-02-13 17:50:20598 PepperPluginRegistry::ComputeList(&ppapi_plugins_);
599 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]f520b5b2011-11-08 02:42:14600 RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo());
[email protected]4e0616e2010-05-28 14:55:53601 }
602}
[email protected]634d23d2011-01-19 10:38:19603
[email protected]eb415bf0e2011-04-14 02:45:42604// There should generally be very few plugins so a brute-force search is fine.
[email protected]e67385f2011-12-21 06:00:56605content::PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
[email protected]eb415bf0e2011-04-14 02:45:42606 const FilePath& plugin_path) {
[email protected]738a7212011-10-21 17:33:52607 content::PepperPluginInfo* info = NULL;
[email protected]eb415bf0e2011-04-14 02:45:42608 for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
[email protected]6b14feb2011-08-16 11:22:56609 if (ppapi_plugins_[i].path == plugin_path) {
610 info = &ppapi_plugins_[i];
611 break;
612 }
[email protected]eb415bf0e2011-04-14 02:45:42613 }
[email protected]076117592011-08-17 03:16:41614 if (info)
615 return info;
616 // We did not find the plugin in our list. But wait! the plugin can also
617 // be a latecomer, as it happens with pepper flash. This information
618 // can be obtained from the PluginList singleton and we can use it to
619 // construct it and add it to the list. This same deal needs to be done
620 // in the renderer side in PepperPluginRegistry.
621 webkit::WebPluginInfo webplugin_info;
[email protected]88ca4912011-10-12 14:00:43622 if (!GetPluginInfoByPath(plugin_path, &webplugin_info))
[email protected]076117592011-08-17 03:16:41623 return NULL;
[email protected]738a7212011-10-21 17:33:52624 content::PepperPluginInfo new_pepper_info;
[email protected]076117592011-08-17 03:16:41625 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
626 return NULL;
627 ppapi_plugins_.push_back(new_pepper_info);
628 return &ppapi_plugins_[ppapi_plugins_.size() - 1];
[email protected]eb415bf0e2011-04-14 02:45:42629}
630
[email protected]3b48dbc2012-01-06 16:34:17631#if defined(OS_POSIX) && !defined(OS_OPENBSD)
[email protected]634d23d2011-01-19 10:38:19632// static
[email protected]e67385f2011-12-21 06:00:56633void PluginServiceImpl::RegisterFilePathWatcher(
[email protected]634d23d2011-01-19 10:38:19634 FilePathWatcher *watcher,
635 const FilePath& path,
636 FilePathWatcher::Delegate* delegate) {
[email protected]7b3ee8b2011-04-01 18:48:19637 bool result = watcher->Watch(path, delegate);
[email protected]634d23d2011-01-19 10:38:19638 DCHECK(result);
639}
640#endif
[email protected]f520b5b2011-11-08 02:42:14641
[email protected]e67385f2011-12-21 06:00:56642void PluginServiceImpl::SetFilter(content::PluginServiceFilter* filter) {
[email protected]3a5180ae2011-12-21 02:39:38643 filter_ = filter;
644}
645
[email protected]e67385f2011-12-21 06:00:56646content::PluginServiceFilter* PluginServiceImpl::GetFilter() {
[email protected]3a5180ae2011-12-21 02:39:38647 return filter_;
648}
649
[email protected]e67385f2011-12-21 06:00:56650void PluginServiceImpl::RefreshPlugins() {
[email protected]3a5180ae2011-12-21 02:39:38651 plugin_list_->RefreshPlugins();
[email protected]f520b5b2011-11-08 02:42:14652}
653
[email protected]e67385f2011-12-21 06:00:56654void PluginServiceImpl::AddExtraPluginPath(const FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38655 plugin_list_->AddExtraPluginPath(path);
[email protected]f520b5b2011-11-08 02:42:14656}
657
[email protected]e67385f2011-12-21 06:00:56658void PluginServiceImpl::RemoveExtraPluginPath(const FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38659 plugin_list_->RemoveExtraPluginPath(path);
[email protected]f520b5b2011-11-08 02:42:14660}
661
[email protected]e67385f2011-12-21 06:00:56662void PluginServiceImpl::UnregisterInternalPlugin(const FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38663 plugin_list_->UnregisterInternalPlugin(path);
[email protected]f520b5b2011-11-08 02:42:14664}
665
[email protected]e67385f2011-12-21 06:00:56666void PluginServiceImpl::SetPluginListForTesting(
[email protected]ee066172011-11-10 23:20:05667 webkit::npapi::PluginList* plugin_list) {
668 plugin_list_ = plugin_list;
669}
670
[email protected]e67385f2011-12-21 06:00:56671void PluginServiceImpl::RegisterInternalPlugin(
672 const webkit::WebPluginInfo& info) {
[email protected]3a5180ae2011-12-21 02:39:38673 plugin_list_->RegisterInternalPlugin(info);
[email protected]f520b5b2011-11-08 02:42:14674}
675
[email protected]e67385f2011-12-21 06:00:56676string16 PluginServiceImpl::GetPluginGroupName(const std::string& plugin_name) {
[email protected]3a5180ae2011-12-21 02:39:38677 return plugin_list_->GetPluginGroupName(plugin_name);
678}
679
[email protected]e67385f2011-12-21 06:00:56680webkit::npapi::PluginList* PluginServiceImpl::GetPluginList() {
[email protected]3a5180ae2011-12-21 02:39:38681 return plugin_list_;
[email protected]f520b5b2011-11-08 02:42:14682}