blob: 253c5c50209c5add2f5fdb1966aa709b7961cd51 [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]57999812013-02-24 05:40:5210#include "base/files/file_path.h"
skyostil95082a62015-06-05 19:53:0711#include "base/location.h"
[email protected]fd8d8d6c2013-02-28 02:48:3312#include "base/metrics/histogram.h"
skyostil95082a62015-06-05 19:53:0713#include "base/single_thread_task_runner.h"
[email protected]348fbaac2013-06-11 06:31:5114#include "base/strings/string_util.h"
[email protected]74ebfb12013-06-07 20:48:0015#include "base/strings/utf_string_conversions.h"
[email protected]7f070d42011-03-09 20:25:3216#include "base/synchronization/waitable_event.h"
[email protected]34b99632011-01-01 01:01:0617#include "base/threading/thread.h"
[email protected]a01efd22011-03-01 00:38:3218#include "content/browser/ppapi_plugin_process_host.h"
[email protected]f3b1a082011-11-18 00:34:3019#include "content/browser/renderer_host/render_process_host_impl.h"
[email protected]b3c41c0b2012-03-06 15:48:3220#include "content/browser/renderer_host/render_view_host_impl.h"
wfh1a90e032015-04-14 17:10:1721#include "content/common/content_switches_internal.h"
[email protected]dac6a5a2013-07-25 05:06:4822#include "content/common/pepper_plugin_list.h"
[email protected]29e2fb42013-07-19 01:13:4723#include "content/common/plugin_list.h"
[email protected]38b592902011-04-16 02:08:4224#include "content/common/view_messages.h"
[email protected]c38831a12011-10-28 12:44:4925#include "content/public/browser/browser_thread.h"
[email protected]87f3c082011-10-19 18:07:4426#include "content/public/browser/content_browser_client.h"
[email protected]31f376c2012-03-13 16:43:0927#include "content/public/browser/plugin_service_filter.h"
[email protected]ce967862012-02-09 22:47:0528#include "content/public/browser/resource_context.h"
[email protected]73270292013-08-09 03:48:0729#include "content/public/common/content_constants.h"
[email protected]c08950d22011-10-13 22:20:2930#include "content/public/common/content_switches.h"
[email protected]bd5d6cf2011-12-01 00:39:1231#include "content/public/common/process_type.h"
[email protected]d7bd3e52013-07-21 04:29:2032#include "content/public/common/webplugininfo.h"
[email protected]191eb3f72010-12-21 06:27:5033
[email protected]3b91edbe2012-09-27 22:49:2334#if defined(OS_WIN)
[email protected]29e2fb42013-07-19 01:13:4735#include "content/common/plugin_constants_win.h"
[email protected]bde885b2013-09-12 20:55:5336#include "ui/gfx/win/hwnd_util.h"
[email protected]3b91edbe2012-09-27 22:49:2337#endif
38
39#if defined(OS_POSIX)
40#include "content/browser/plugin_loader_posix.h"
41#endif
42
[email protected]52348b22012-11-07 10:19:3443#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]6665571f2013-01-15 07:59:5244using ::base::FilePathWatcher;
[email protected]493c8002011-04-14 16:56:0145#endif
46
[email protected]130757672012-10-24 00:26:1947namespace content {
[email protected]d33e7cc2011-09-23 01:43:5648namespace {
49
[email protected]fd8d8d6c2013-02-28 02:48:3350// This enum is used to collect Flash usage data.
51enum FlashUsage {
52 // Number of browser processes that have started at least one NPAPI Flash
53 // process during their lifetime.
54 START_NPAPI_FLASH_AT_LEAST_ONCE,
55 // Number of browser processes that have started at least one PPAPI Flash
56 // process during their lifetime.
57 START_PPAPI_FLASH_AT_LEAST_ONCE,
58 // Total number of browser processes.
59 TOTAL_BROWSER_PROCESSES,
60 FLASH_USAGE_ENUM_COUNT
61};
62
wfh0539f2f52015-01-21 14:36:4663enum NPAPIPluginStatus {
64 // Platform does not support NPAPI.
65 NPAPI_STATUS_UNSUPPORTED,
66 // Platform supports NPAPI and NPAPI is disabled.
67 NPAPI_STATUS_DISABLED,
68 // Platform supports NPAPI and NPAPI is enabled.
69 NPAPI_STATUS_ENABLED,
70 NPAPI_STATUS_ENUM_COUNT
71};
72
[email protected]1b517202012-12-19 17:16:1073bool LoadPluginListInProcess() {
74#if defined(OS_WIN)
75 return true;
76#else
77 // If on POSIX, we don't want to load the list of NPAPI plugins in-process as
78 // that causes instability.
[email protected]6d057a0c2013-07-09 21:12:0779
80 // Can't load the plugins on the utility thread when in single process mode
[email protected]10212452013-07-16 20:10:5581 // since that requires GTK which can only be used on the main thread.
[email protected]6d057a0c2013-07-09 21:12:0782 if (RenderProcessHost::run_renderer_in_process())
83 return true;
84
[email protected]9a60ccb2013-07-19 22:23:3685 return !PluginService::GetInstance()->NPAPIPluginsSupported();
[email protected]1b517202012-12-19 17:16:1086#endif
87}
88
[email protected]49125952011-09-27 18:05:1589// Callback set on the PluginList to assert that plugin loading happens on the
90// correct thread.
[email protected]1b517202012-12-19 17:16:1091void WillLoadPluginsCallback(
[email protected]a33fa9d2012-05-16 14:47:4992 base::SequencedWorkerPool::SequenceToken token) {
[email protected]1b517202012-12-19 17:16:1093 if (LoadPluginListInProcess()) {
94 CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
95 token));
96 } else {
97 CHECK(false) << "Plugin loading should happen out-of-process.";
98 }
[email protected]a79912252012-05-16 11:52:1999}
[email protected]d33e7cc2011-09-23 01:43:56100
[email protected]a96ec6a2009-11-04 17:27:08101#if defined(OS_MACOSX)
[email protected]07b71c82013-01-08 19:07:31102void NotifyPluginsOfActivation() {
mostynb4c27d042015-03-18 21:47:47103 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]a96ec6a2009-11-04 17:27:08104
[email protected]4967f792012-01-20 22:14:40105 for (PluginProcessHostIterator iter; !iter.Done(); ++iter)
106 iter->OnAppActivation();
[email protected]a96ec6a2009-11-04 17:27:08107}
[email protected]3b48dbc2012-01-06 16:34:17108#endif
[email protected]45a22e62011-10-12 09:48:02109
thakis84dff942015-07-28 20:47:38110#if defined(OS_POSIX)
111#if !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]2dec8ec2013-02-07 19:20:34112void NotifyPluginDirChanged(const base::FilePath& path, bool error) {
[email protected]07b71c82013-01-08 19:07:31113 if (error) {
[email protected]634d23d2011-01-19 10:38:19114 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
115 // stopping the watcher would be enough. Or possibly restart it.
116 NOTREACHED();
[email protected]07b71c82013-01-08 19:07:31117 return;
[email protected]634d23d2011-01-19 10:38:19118 }
[email protected]07b71c82013-01-08 19:07:31119 VLOG(1) << "Watched path changed: " << path.value();
120 // Make the plugin list update itself
[email protected]29e2fb42013-07-19 01:13:47121 PluginList::Singleton()->RefreshPlugins();
[email protected]07b71c82013-01-08 19:07:31122 BrowserThread::PostTask(
123 BrowserThread::UI, FROM_HERE,
124 base::Bind(&PluginService::PurgePluginListCache,
125 static_cast<BrowserContext*>(NULL), false));
126}
thakis84dff942015-07-28 20:47:38127#endif // !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19128
skyostil95082a62015-06-05 19:53:07129void ForwardCallback(base::SingleThreadTaskRunner* target_task_runner,
[email protected]aa7f8802014-01-27 16:56:32130 const PluginService::GetPluginsCallback& callback,
131 const std::vector<WebPluginInfo>& plugins) {
skyostil95082a62015-06-05 19:53:07132 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins));
[email protected]aa7f8802014-01-27 16:56:32133}
thakis84dff942015-07-28 20:47:38134#endif // defined(OS_POSIX)
[email protected]aa7f8802014-01-27 16:56:32135
[email protected]07b71c82013-01-08 19:07:31136} // namespace
137
[email protected]3a5180ae2011-12-21 02:39:38138// static
139PluginService* PluginService::GetInstance() {
[email protected]e67385f2011-12-21 06:00:56140 return PluginServiceImpl::GetInstance();
[email protected]3a5180ae2011-12-21 02:39:38141}
142
143void PluginService::PurgePluginListCache(BrowserContext* browser_context,
144 bool reload_pages) {
145 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
146 !it.IsAtEnd(); it.Advance()) {
147 RenderProcessHost* host = it.GetCurrentValue();
148 if (!browser_context || host->GetBrowserContext() == browser_context)
149 host->Send(new ViewMsg_PurgePluginListCache(reload_pages));
150 }
151}
152
initial.commit09911bf2008-07-26 23:55:29153// static
[email protected]e67385f2011-12-21 06:00:56154PluginServiceImpl* PluginServiceImpl::GetInstance() {
155 return Singleton<PluginServiceImpl>::get();
initial.commit09911bf2008-07-26 23:55:29156}
157
[email protected]e67385f2011-12-21 06:00:56158PluginServiceImpl::PluginServiceImpl()
wfh0539f2f52015-01-21 14:36:46159 : npapi_plugins_enabled_(false), filter_(NULL) {
[email protected]fd8d8d6c2013-02-28 02:48:33160 // Collect the total number of browser processes (which create
161 // PluginServiceImpl objects, to be precise). The number is used to normalize
162 // the number of processes which start at least one NPAPI/PPAPI Flash process.
163 static bool counted = false;
164 if (!counted) {
165 counted = true;
166 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage", TOTAL_BROWSER_PROCESSES,
167 FLASH_USAGE_ENUM_COUNT);
168 }
[email protected]ee066172011-11-10 23:20:05169}
170
[email protected]e67385f2011-12-21 06:00:56171PluginServiceImpl::~PluginServiceImpl() {
[email protected]ee066172011-11-10 23:20:05172 // Make sure no plugin channel requests have been leaked.
173 DCHECK(pending_plugin_clients_.empty());
174}
175
[email protected]e67385f2011-12-21 06:00:56176void PluginServiceImpl::Init() {
[email protected]a33fa9d2012-05-16 14:47:49177 plugin_list_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken();
[email protected]29e2fb42013-07-19 01:13:47178 PluginList::Singleton()->set_will_load_plugins_callback(
[email protected]1b517202012-12-19 17:16:10179 base::Bind(&WillLoadPluginsCallback, plugin_list_token_));
[email protected]49125952011-09-27 18:05:15180
[email protected]4e0616e2010-05-28 14:55:53181 RegisterPepperPlugins();
182
[email protected]9a1c4262010-06-29 21:50:27183 // Load any specified on the command line as well.
[email protected]479278702014-08-11 20:32:09184 const base::CommandLine* command_line =
185 base::CommandLine::ForCurrentProcess();
[email protected]2dec8ec2013-02-07 19:20:34186 base::FilePath path =
187 command_line->GetSwitchValuePath(switches::kLoadPlugin);
[email protected]7bf795d92010-05-22 00:14:28188 if (!path.empty())
[email protected]f520b5b2011-11-08 02:42:14189 AddExtraPluginPath(path);
[email protected]9a1c4262010-06-29 21:50:27190 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
191 if (!path.empty())
[email protected]29e2fb42013-07-19 01:13:47192 PluginList::Singleton()->AddExtraPluginDir(path);
[email protected]e87ce862013-06-12 17:30:48193
194 if (command_line->HasSwitch(switches::kDisablePluginsDiscovery))
[email protected]29e2fb42013-07-19 01:13:47195 PluginList::Singleton()->DisablePluginsDiscovery();
[email protected]dfba8762011-09-02 12:49:54196}
197
[email protected]e67385f2011-12-21 06:00:56198void PluginServiceImpl::StartWatchingPlugins() {
[email protected]634d23d2011-01-19 10:38:19199 // Start watching for changes in the plugin list. This means watching
200 // for changes in the Windows registry keys and on both Windows and POSIX
201 // watch for changes in the paths that are expected to contain plugins.
[email protected]b547fd42009-04-23 23:16:27202#if defined(OS_WIN)
[email protected]86ec4f6e2011-04-20 16:21:19203 if (hkcu_key_.Create(HKEY_CURRENT_USER,
[email protected]29e2fb42013-07-19 01:13:47204 kRegistryMozillaPlugins,
[email protected]86ec4f6e2011-04-20 16:21:19205 KEY_NOTIFY) == ERROR_SUCCESS) {
rvargas6f315b82014-10-17 01:28:58206 base::win::RegKey::ChangeCallback callback =
207 base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
208 base::Unretained(&hkcu_key_));
209 hkcu_key_.StartWatching(callback);
[email protected]b547fd42009-04-23 23:16:27210 }
[email protected]86ec4f6e2011-04-20 16:21:19211 if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
[email protected]29e2fb42013-07-19 01:13:47212 kRegistryMozillaPlugins,
[email protected]86ec4f6e2011-04-20 16:21:19213 KEY_NOTIFY) == ERROR_SUCCESS) {
rvargas6f315b82014-10-17 01:28:58214 base::win::RegKey::ChangeCallback callback =
215 base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
rvargasb8056152014-11-08 01:44:28216 base::Unretained(&hklm_key_));
rvargas6f315b82014-10-17 01:28:58217 hklm_key_.StartWatching(callback);
[email protected]b547fd42009-04-23 23:16:27218 }
[email protected]a33fa9d2012-05-16 14:47:49219#endif
[email protected]52348b22012-11-07 10:19:34220#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19221// On ChromeOS the user can't install plugins anyway and on Windows all
222// important plugins register themselves in the registry so no need to do that.
[email protected]07b71c82013-01-08 19:07:31223
[email protected]634d23d2011-01-19 10:38:19224 // Get the list of all paths for registering the FilePathWatchers
225 // that will track and if needed reload the list of plugins on runtime.
[email protected]2dec8ec2013-02-07 19:20:34226 std::vector<base::FilePath> plugin_dirs;
[email protected]29e2fb42013-07-19 01:13:47227 PluginList::Singleton()->GetPluginDirectories(&plugin_dirs);
[email protected]894bb502009-05-21 22:39:57228
[email protected]634d23d2011-01-19 10:38:19229 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
[email protected]634d23d2011-01-19 10:38:19230 // FilePathWatcher can not handle non-absolute paths under windows.
231 // We don't watch for file changes in windows now but if this should ever
232 // be extended to Windows these lines might save some time of debugging.
233#if defined(OS_WIN)
234 if (!plugin_dirs[i].IsAbsolute())
235 continue;
236#endif
[email protected]493c8002011-04-14 16:56:01237 FilePathWatcher* watcher = new FilePathWatcher();
[email protected]634d23d2011-01-19 10:38:19238 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
239 BrowserThread::PostTask(
240 BrowserThread::FILE, FROM_HERE,
[email protected]e67385f2011-12-21 06:00:56241 base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
[email protected]07b71c82013-01-08 19:07:31242 plugin_dirs[i]));
[email protected]634d23d2011-01-19 10:38:19243 file_watchers_.push_back(watcher);
244 }
245#endif
initial.commit09911bf2008-07-26 23:55:29246}
247
[email protected]e67385f2011-12-21 06:00:56248PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
[email protected]2dec8ec2013-02-07 19:20:34249 const base::FilePath& plugin_path) {
[email protected]4967f792012-01-20 22:14:40250 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
251 if (iter->info().path == plugin_path)
252 return *iter;
[email protected]a436d922009-02-13 23:16:42253 }
254
initial.commit09911bf2008-07-26 23:55:29255 return NULL;
256}
257
[email protected]e67385f2011-12-21 06:00:56258PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
[email protected]2dec8ec2013-02-07 19:20:34259 const base::FilePath& plugin_path,
260 const base::FilePath& profile_data_directory) {
[email protected]4967f792012-01-20 22:14:40261 for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]dd9a0952012-05-31 20:11:31262 if (iter->plugin_path() == plugin_path &&
263 iter->profile_data_directory() == profile_data_directory) {
[email protected]4967f792012-01-20 22:14:40264 return *iter;
[email protected]dd9a0952012-05-31 20:11:31265 }
[email protected]a08ebea2011-02-13 17:50:20266 }
[email protected]a08ebea2011-02-13 17:50:20267 return NULL;
268}
269
[email protected]e67385f2011-12-21 06:00:56270PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
[email protected]2dec8ec2013-02-07 19:20:34271 const base::FilePath& broker_path) {
[email protected]4967f792012-01-20 22:14:40272 for (PpapiBrokerProcessHostIterator iter; !iter.Done(); ++iter) {
273 if (iter->plugin_path() == broker_path)
274 return *iter;
[email protected]eb415bf0e2011-04-14 02:45:42275 }
276
277 return NULL;
278}
279
[email protected]e67385f2011-12-21 06:00:56280PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54281 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34282 const base::FilePath& plugin_path) {
mostynb4c27d042015-03-18 21:47:47283 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]a08ebea2011-02-13 17:50:20284
[email protected]6be31d202013-02-01 18:20:54285 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
286 return NULL;
287
[email protected]a08ebea2011-02-13 17:50:20288 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
initial.commit09911bf2008-07-26 23:55:29289 if (plugin_host)
290 return plugin_host;
291
[email protected]d7bd3e52013-07-21 04:29:20292 WebPluginInfo info;
[email protected]88ca4912011-10-12 14:00:43293 if (!GetPluginInfoByPath(plugin_path, &info)) {
[email protected]a27a9382009-02-11 23:55:10294 return NULL;
295 }
296
[email protected]fd8d8d6c2013-02-28 02:48:33297 // Record when NPAPI Flash process is started for the first time.
298 static bool counted = false;
[email protected]32956122013-12-25 07:29:24299 if (!counted && base::UTF16ToUTF8(info.name) == kFlashPluginName) {
[email protected]fd8d8d6c2013-02-28 02:48:33300 counted = true;
301 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
302 START_NPAPI_FLASH_AT_LEAST_ONCE,
303 FLASH_USAGE_ENUM_COUNT);
304 }
[email protected]132bca82013-12-10 09:14:47305#if defined(OS_CHROMEOS)
306 // TODO(ihf): Move to an earlier place once crbug.com/314301 is fixed. For now
307 // we still want Plugin.FlashUsage recorded if we end up here.
308 LOG(WARNING) << "Refusing to start npapi plugin on ChromeOS.";
309 return NULL;
310#endif
initial.commit09911bf2008-07-26 23:55:29311 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]8b8a554d2010-11-18 13:26:40312 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
[email protected]99907362012-01-11 05:41:40313 if (!new_host->Init(info)) {
[email protected]a08ebea2011-02-13 17:50:20314 NOTREACHED(); // Init is not expected to fail.
initial.commit09911bf2008-07-26 23:55:29315 return NULL;
316 }
[email protected]8b8a554d2010-11-18 13:26:40317 return new_host.release();
initial.commit09911bf2008-07-26 23:55:29318}
319
[email protected]e67385f2011-12-21 06:00:56320PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54321 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34322 const base::FilePath& plugin_path,
[email protected]8522332e2013-08-28 19:42:59323 const base::FilePath& profile_data_directory) {
mostynb4c27d042015-03-18 21:47:47324 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]a08ebea2011-02-13 17:50:20325
[email protected]132bca82013-12-10 09:14:47326 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) {
327 VLOG(1) << "Unable to load ppapi plugin: " << plugin_path.MaybeAsASCII();
[email protected]6be31d202013-02-01 18:20:54328 return NULL;
[email protected]132bca82013-12-10 09:14:47329 }
[email protected]6be31d202013-02-01 18:20:54330
[email protected]dd9a0952012-05-31 20:11:31331 PpapiPluginProcessHost* plugin_host =
332 FindPpapiPluginProcess(plugin_path, profile_data_directory);
[email protected]a08ebea2011-02-13 17:50:20333 if (plugin_host)
334 return plugin_host;
335
[email protected]eb415bf0e2011-04-14 02:45:42336 // Validate that the plugin is actually registered.
[email protected]130757672012-10-24 00:26:19337 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]132bca82013-12-10 09:14:47338 if (!info) {
339 VLOG(1) << "Unable to find ppapi plugin registration for: "
340 << plugin_path.MaybeAsASCII();
[email protected]a08ebea2011-02-13 17:50:20341 return NULL;
[email protected]132bca82013-12-10 09:14:47342 }
[email protected]a08ebea2011-02-13 17:50:20343
[email protected]fd8d8d6c2013-02-28 02:48:33344 // Record when PPAPI Flash process is started for the first time.
345 static bool counted = false;
346 if (!counted && info->name == kFlashPluginName) {
347 counted = true;
348 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
349 START_PPAPI_FLASH_AT_LEAST_ONCE,
350 FLASH_USAGE_ENUM_COUNT);
351 }
352
[email protected]a08ebea2011-02-13 17:50:20353 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]132bca82013-12-10 09:14:47354 plugin_host = PpapiPluginProcessHost::CreatePluginHost(
[email protected]8522332e2013-08-28 19:42:59355 *info, profile_data_directory);
[email protected]132bca82013-12-10 09:14:47356 if (!plugin_host) {
357 VLOG(1) << "Unable to create ppapi plugin process for: "
358 << plugin_path.MaybeAsASCII();
359 }
360
361 return plugin_host;
[email protected]a08ebea2011-02-13 17:50:20362}
363
[email protected]e67385f2011-12-21 06:00:56364PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
[email protected]6be31d202013-02-01 18:20:54365 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34366 const base::FilePath& plugin_path) {
mostynb4c27d042015-03-18 21:47:47367 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]eb415bf0e2011-04-14 02:45:42368
[email protected]6be31d202013-02-01 18:20:54369 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
370 return NULL;
371
[email protected]a50432d2011-09-30 16:32:14372 PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42373 if (plugin_host)
374 return plugin_host;
375
376 // Validate that the plugin is actually registered.
[email protected]130757672012-10-24 00:26:19377 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42378 if (!info)
379 return NULL;
380
381 // TODO(ddorwin): Uncomment once out of process is supported.
382 // DCHECK(info->is_out_of_process);
383
384 // This broker isn't loaded by any broker process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14385 return PpapiPluginProcessHost::CreateBrokerHost(*info);
[email protected]eb415bf0e2011-04-14 02:45:42386}
387
[email protected]e67385f2011-12-21 06:00:56388void PluginServiceImpl::OpenChannelToNpapiPlugin(
[email protected]c8f73ab2011-01-22 00:05:17389 int render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16390 int render_frame_id,
[email protected]610c0892009-09-08 19:46:18391 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54392 const GURL& page_url,
[email protected]610c0892009-09-08 19:46:18393 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39394 PluginProcessHost::Client* client) {
mostynb4c27d042015-03-18 21:47:47395 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4befe7592011-09-14 22:49:09396 DCHECK(!ContainsKey(pending_plugin_clients_, client));
397 pending_plugin_clients_.insert(client);
[email protected]88ca4912011-10-12 14:00:43398
399 // Make sure plugins are loaded if necessary.
[email protected]209f2ae2012-03-13 01:28:08400 PluginServiceFilterParams params = {
[email protected]88ca4912011-10-12 14:00:43401 render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16402 render_frame_id,
[email protected]88ca4912011-10-12 14:00:43403 page_url,
[email protected]df02aca2012-02-09 21:03:20404 client->GetResourceContext()
[email protected]88ca4912011-10-12 14:00:43405 };
[email protected]e67385f2011-12-21 06:00:56406 GetPlugins(base::Bind(
407 &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
408 base::Unretained(this), params, url, mime_type, client));
[email protected]6fdd4182010-10-14 23:59:26409}
410
[email protected]e67385f2011-12-21 06:00:56411void PluginServiceImpl::OpenChannelToPpapiPlugin(
[email protected]6be31d202013-02-01 18:20:54412 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34413 const base::FilePath& plugin_path,
414 const base::FilePath& profile_data_directory,
[email protected]a50432d2011-09-30 16:32:14415 PpapiPluginProcessHost::PluginClient* client) {
[email protected]d259a8e2011-05-18 22:31:09416 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
[email protected]8522332e2013-08-28 19:42:59417 render_process_id, plugin_path, profile_data_directory);
[email protected]1bf0fb22012-04-12 21:44:16418 if (plugin_host) {
[email protected]a08ebea2011-02-13 17:50:20419 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16420 } else {
421 // Send error.
[email protected]108fd342013-01-04 20:46:54422 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
[email protected]1bf0fb22012-04-12 21:44:16423 }
[email protected]a08ebea2011-02-13 17:50:20424}
425
[email protected]e67385f2011-12-21 06:00:56426void PluginServiceImpl::OpenChannelToPpapiBroker(
[email protected]6be31d202013-02-01 18:20:54427 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34428 const base::FilePath& path,
[email protected]a50432d2011-09-30 16:32:14429 PpapiPluginProcessHost::BrokerClient* client) {
[email protected]6be31d202013-02-01 18:20:54430 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(
431 render_process_id, path);
[email protected]1bf0fb22012-04-12 21:44:16432 if (plugin_host) {
[email protected]a50432d2011-09-30 16:32:14433 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16434 } else {
435 // Send error.
[email protected]108fd342013-01-04 20:46:54436 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
[email protected]1bf0fb22012-04-12 21:44:16437 }
[email protected]eb415bf0e2011-04-14 02:45:42438}
439
[email protected]e67385f2011-12-21 06:00:56440void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
[email protected]4befe7592011-09-14 22:49:09441 PluginProcessHost::Client* client) {
mostynb4c27d042015-03-18 21:47:47442 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4befe7592011-09-14 22:49:09443 DCHECK(ContainsKey(pending_plugin_clients_, client));
444 pending_plugin_clients_.erase(client);
445}
446
[email protected]e67385f2011-12-21 06:00:56447void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
[email protected]209f2ae2012-03-13 01:28:08448 const PluginServiceFilterParams& params,
[email protected]88ca4912011-10-12 14:00:43449 const GURL& url,
450 const std::string& mime_type,
451 PluginProcessHost::Client* client,
[email protected]d7bd3e52013-07-21 04:29:20452 const std::vector<WebPluginInfo>&) {
[email protected]60eca4eb2013-12-06 00:02:16453 GetAllowedPluginForOpenChannelToPlugin(
454 params.render_process_id, params.render_frame_id, url, params.page_url,
455 mime_type, client, params.resource_context);
[email protected]88ca4912011-10-12 14:00:43456}
457
[email protected]e67385f2011-12-21 06:00:56458void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
[email protected]c8f73ab2011-01-22 00:05:17459 int render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16460 int render_frame_id,
[email protected]6fdd4182010-10-14 23:59:26461 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54462 const GURL& page_url,
[email protected]6fdd4182010-10-14 23:59:26463 const std::string& mime_type,
[email protected]87c4be42011-09-16 01:10:59464 PluginProcessHost::Client* client,
[email protected]130757672012-10-24 00:26:19465 ResourceContext* resource_context) {
[email protected]d7bd3e52013-07-21 04:29:20466 WebPluginInfo info;
[email protected]dfba8762011-09-02 12:49:54467 bool allow_wildcard = true;
[email protected]11e1c182011-05-17 20:26:27468 bool found = GetPluginInfo(
[email protected]60eca4eb2013-12-06 00:02:16469 render_process_id, render_frame_id, resource_context,
[email protected]dfba8762011-09-02 12:49:54470 url, page_url, mime_type, allow_wildcard,
471 NULL, &info, NULL);
[email protected]2dec8ec2013-02-07 19:20:34472 base::FilePath plugin_path;
[email protected]68598072011-07-29 08:21:28473 if (found)
[email protected]dfba8762011-09-02 12:49:54474 plugin_path = info.path;
[email protected]6fdd4182010-10-14 23:59:26475
476 // Now we jump back to the IO thread to finish opening the channel.
[email protected]e67385f2011-12-21 06:00:56477 BrowserThread::PostTask(
478 BrowserThread::IO, FROM_HERE,
479 base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
[email protected]6be31d202013-02-01 18:20:54480 base::Unretained(this),
481 render_process_id,
482 plugin_path,
483 client));
wfh30443502015-05-01 21:58:30484 if (filter_) {
485 DCHECK_EQ(WebPluginInfo::PLUGIN_TYPE_NPAPI, info.type);
wfhec1f7352015-05-07 23:44:54486 filter_->NPAPIPluginLoaded(render_process_id, render_frame_id, mime_type,
487 info);
wfh30443502015-05-01 21:58:30488 }
[email protected]6fdd4182010-10-14 23:59:26489}
490
[email protected]e67385f2011-12-21 06:00:56491void PluginServiceImpl::FinishOpenChannelToPlugin(
[email protected]6be31d202013-02-01 18:20:54492 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34493 const base::FilePath& plugin_path,
[email protected]46b69e42010-11-02 12:26:39494 PluginProcessHost::Client* client) {
mostynb4c27d042015-03-18 21:47:47495 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]20a793e2010-10-12 06:50:08496
[email protected]4befe7592011-09-14 22:49:09497 // Make sure it hasn't been canceled yet.
498 if (!ContainsKey(pending_plugin_clients_, client))
499 return;
500 pending_plugin_clients_.erase(client);
501
[email protected]6be31d202013-02-01 18:20:54502 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(
503 render_process_id, plugin_path);
[email protected]4befe7592011-09-14 22:49:09504 if (plugin_host) {
505 client->OnFoundPluginProcessHost(plugin_host);
[email protected]46b69e42010-11-02 12:26:39506 plugin_host->OpenChannelToPlugin(client);
[email protected]4befe7592011-09-14 22:49:09507 } else {
[email protected]46b69e42010-11-02 12:26:39508 client->OnError();
[email protected]4befe7592011-09-14 22:49:09509 }
initial.commit09911bf2008-07-26 23:55:29510}
511
[email protected]e67385f2011-12-21 06:00:56512bool PluginServiceImpl::GetPluginInfoArray(
[email protected]51b63f62011-10-05 18:55:42513 const GURL& url,
514 const std::string& mime_type,
515 bool allow_wildcard,
[email protected]d7bd3e52013-07-21 04:29:20516 std::vector<WebPluginInfo>* plugins,
[email protected]51b63f62011-10-05 18:55:42517 std::vector<std::string>* actual_mime_types) {
518 bool use_stale = false;
[email protected]29e2fb42013-07-19 01:13:47519 PluginList::Singleton()->GetPluginInfoArray(
[email protected]9a60ccb2013-07-19 22:23:36520 url, mime_type, allow_wildcard, &use_stale, NPAPIPluginsSupported(),
521 plugins, actual_mime_types);
[email protected]51b63f62011-10-05 18:55:42522 return use_stale;
523}
524
[email protected]e67385f2011-12-21 06:00:56525bool PluginServiceImpl::GetPluginInfo(int render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16526 int render_frame_id,
[email protected]130757672012-10-24 00:26:19527 ResourceContext* context,
[email protected]e67385f2011-12-21 06:00:56528 const GURL& url,
529 const GURL& page_url,
530 const std::string& mime_type,
531 bool allow_wildcard,
532 bool* is_stale,
[email protected]d7bd3e52013-07-21 04:29:20533 WebPluginInfo* info,
[email protected]e67385f2011-12-21 06:00:56534 std::string* actual_mime_type) {
[email protected]d7bd3e52013-07-21 04:29:20535 std::vector<WebPluginInfo> plugins;
[email protected]68598072011-07-29 08:21:28536 std::vector<std::string> mime_types;
[email protected]88ca4912011-10-12 14:00:43537 bool stale = GetPluginInfoArray(
538 url, mime_type, allow_wildcard, &plugins, &mime_types);
539 if (is_stale)
540 *is_stale = stale;
[email protected]dfba8762011-09-02 12:49:54541
[email protected]68598072011-07-29 08:21:28542 for (size_t i = 0; i < plugins.size(); ++i) {
[email protected]05f511282013-02-05 15:02:50543 if (!filter_ || filter_->IsPluginAvailable(render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16544 render_frame_id,
[email protected]05f511282013-02-05 15:02:50545 context,
546 url,
547 page_url,
548 &plugins[i])) {
[email protected]68598072011-07-29 08:21:28549 *info = plugins[i];
550 if (actual_mime_type)
551 *actual_mime_type = mime_types[i];
552 return true;
553 }
554 }
555 return false;
[email protected]6fdd4182010-10-14 23:59:26556}
557
[email protected]2dec8ec2013-02-07 19:20:34558bool PluginServiceImpl::GetPluginInfoByPath(const base::FilePath& plugin_path,
[email protected]d7bd3e52013-07-21 04:29:20559 WebPluginInfo* info) {
560 std::vector<WebPluginInfo> plugins;
[email protected]29e2fb42013-07-19 01:13:47561 PluginList::Singleton()->GetPluginsNoRefresh(&plugins);
[email protected]88ca4912011-10-12 14:00:43562
[email protected]d7bd3e52013-07-21 04:29:20563 for (std::vector<WebPluginInfo>::iterator it = plugins.begin();
[email protected]88ca4912011-10-12 14:00:43564 it != plugins.end();
565 ++it) {
566 if (it->path == plugin_path) {
567 *info = *it;
568 return true;
569 }
570 }
571
572 return false;
573}
574
[email protected]fcf75d42013-12-03 20:11:26575base::string16 PluginServiceImpl::GetPluginDisplayNameByPath(
[email protected]2dec8ec2013-02-07 19:20:34576 const base::FilePath& path) {
[email protected]fcf75d42013-12-03 20:11:26577 base::string16 plugin_name = path.LossyDisplayName();
[email protected]d7bd3e52013-07-21 04:29:20578 WebPluginInfo info;
[email protected]8be45842012-04-13 19:49:29579 if (PluginService::GetInstance()->GetPluginInfoByPath(path, &info) &&
580 !info.name.empty()) {
581 plugin_name = info.name;
582#if defined(OS_MACOSX)
583 // Many plugins on the Mac have .plugin in the actual name, which looks
584 // terrible, so look for that and strip it off if present.
585 const std::string kPluginExtension = ".plugin";
brettwa7ff1b292015-07-16 17:49:29586 if (base::EndsWith(plugin_name, base::ASCIIToUTF16(kPluginExtension),
587 base::CompareCase::SENSITIVE))
[email protected]8be45842012-04-13 19:49:29588 plugin_name.erase(plugin_name.length() - kPluginExtension.length());
589#endif // OS_MACOSX
590 }
591 return plugin_name;
592}
593
[email protected]e67385f2011-12-21 06:00:56594void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
skyostil95082a62015-06-05 19:53:07595 scoped_refptr<base::SingleThreadTaskRunner> target_task_runner(
596 base::ThreadTaskRunnerHandle::Get());
[email protected]49125952011-09-27 18:05:15597
[email protected]1b517202012-12-19 17:16:10598 if (LoadPluginListInProcess()) {
skyostil95082a62015-06-05 19:53:07599 BrowserThread::GetBlockingPool()
600 ->PostSequencedWorkerTaskWithShutdownBehavior(
601 plugin_list_token_, FROM_HERE,
[email protected]1b517202012-12-19 17:16:10602 base::Bind(&PluginServiceImpl::GetPluginsInternal,
skyostil95082a62015-06-05 19:53:07603 base::Unretained(this), target_task_runner, callback),
604 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
[email protected]1b517202012-12-19 17:16:10605 return;
606 }
607#if defined(OS_POSIX)
skyostil95082a62015-06-05 19:53:07608 BrowserThread::PostTask(
609 BrowserThread::IO, FROM_HERE,
[email protected]aa7f8802014-01-27 16:56:32610 base::Bind(&PluginServiceImpl::GetPluginsOnIOThread,
skyostil95082a62015-06-05 19:53:07611 base::Unretained(this), target_task_runner, callback));
[email protected]a33fa9d2012-05-16 14:47:49612#else
[email protected]1b517202012-12-19 17:16:10613 NOTREACHED();
[email protected]49125952011-09-27 18:05:15614#endif
[email protected]d33e7cc2011-09-23 01:43:56615}
616
[email protected]e67385f2011-12-21 06:00:56617void PluginServiceImpl::GetPluginsInternal(
skyostil95082a62015-06-05 19:53:07618 base::SingleThreadTaskRunner* target_task_runner,
619 const PluginService::GetPluginsCallback& callback) {
[email protected]a33fa9d2012-05-16 14:47:49620 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
621 plugin_list_token_));
[email protected]d33e7cc2011-09-23 01:43:56622
[email protected]d7bd3e52013-07-21 04:29:20623 std::vector<WebPluginInfo> plugins;
[email protected]9a60ccb2013-07-19 22:23:36624 PluginList::Singleton()->GetPlugins(&plugins, NPAPIPluginsSupported());
[email protected]d33e7cc2011-09-23 01:43:56625
skyostil95082a62015-06-05 19:53:07626 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins));
[email protected]dfba8762011-09-02 12:49:54627}
628
[email protected]aa7f8802014-01-27 16:56:32629#if defined(OS_POSIX)
630void PluginServiceImpl::GetPluginsOnIOThread(
skyostil95082a62015-06-05 19:53:07631 base::SingleThreadTaskRunner* target_task_runner,
[email protected]aa7f8802014-01-27 16:56:32632 const GetPluginsCallback& callback) {
mostynb4c27d042015-03-18 21:47:47633 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]aa7f8802014-01-27 16:56:32634
635 // If we switch back to loading plugins in process, then we need to make
636 // sure g_thread_init() gets called since plugins may call glib at load.
637
dcheng54c3719d2014-08-26 21:52:56638 if (!plugin_loader_.get())
[email protected]aa7f8802014-01-27 16:56:32639 plugin_loader_ = new PluginLoaderPosix;
640
skyostil95082a62015-06-05 19:53:07641 plugin_loader_->GetPlugins(base::Bind(
642 &ForwardCallback, make_scoped_refptr(target_task_runner), callback));
[email protected]aa7f8802014-01-27 16:56:32643}
644#endif
645
[email protected]b547fd42009-04-23 23:16:27646#if defined(OS_WIN)
rvargas6f315b82014-10-17 01:28:58647void PluginServiceImpl::OnKeyChanged(base::win::RegKey* key) {
648 key->StartWatching(base::Bind(&PluginServiceImpl::OnKeyChanged,
649 base::Unretained(this),
rvargasb8056152014-11-08 01:44:28650 base::Unretained(key)));
[email protected]b547fd42009-04-23 23:16:27651
[email protected]29e2fb42013-07-19 01:13:47652 PluginList::Singleton()->RefreshPlugins();
[email protected]45a22e62011-10-12 09:48:02653 PurgePluginListCache(NULL, false);
dcheng4fe6ccad2014-10-16 03:09:26654}
rvargas6f315b82014-10-17 01:28:58655#endif // defined(OS_WIN)
[email protected]894bb502009-05-21 22:39:57656
[email protected]e67385f2011-12-21 06:00:56657void PluginServiceImpl::RegisterPepperPlugins() {
[email protected]dac6a5a2013-07-25 05:06:48658 ComputePepperPluginList(&ppapi_plugins_);
[email protected]a08ebea2011-02-13 17:50:20659 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]c6f3dea2012-01-14 02:23:11660 RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo(), true);
[email protected]4e0616e2010-05-28 14:55:53661 }
662}
[email protected]634d23d2011-01-19 10:38:19663
[email protected]eb415bf0e2011-04-14 02:45:42664// There should generally be very few plugins so a brute-force search is fine.
[email protected]130757672012-10-24 00:26:19665PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
[email protected]2dec8ec2013-02-07 19:20:34666 const base::FilePath& plugin_path) {
[email protected]130757672012-10-24 00:26:19667 PepperPluginInfo* info = NULL;
[email protected]3627aa3f2013-09-17 22:32:51668 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]6b14feb2011-08-16 11:22:56669 if (ppapi_plugins_[i].path == plugin_path) {
670 info = &ppapi_plugins_[i];
671 break;
672 }
[email protected]eb415bf0e2011-04-14 02:45:42673 }
[email protected]076117592011-08-17 03:16:41674 if (info)
675 return info;
676 // We did not find the plugin in our list. But wait! the plugin can also
677 // be a latecomer, as it happens with pepper flash. This information
678 // can be obtained from the PluginList singleton and we can use it to
679 // construct it and add it to the list. This same deal needs to be done
680 // in the renderer side in PepperPluginRegistry.
[email protected]d7bd3e52013-07-21 04:29:20681 WebPluginInfo webplugin_info;
[email protected]88ca4912011-10-12 14:00:43682 if (!GetPluginInfoByPath(plugin_path, &webplugin_info))
[email protected]076117592011-08-17 03:16:41683 return NULL;
[email protected]130757672012-10-24 00:26:19684 PepperPluginInfo new_pepper_info;
[email protected]076117592011-08-17 03:16:41685 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
686 return NULL;
687 ppapi_plugins_.push_back(new_pepper_info);
688 return &ppapi_plugins_[ppapi_plugins_.size() - 1];
[email protected]eb415bf0e2011-04-14 02:45:42689}
690
[email protected]52348b22012-11-07 10:19:34691#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19692// static
[email protected]07b71c82013-01-08 19:07:31693void PluginServiceImpl::RegisterFilePathWatcher(FilePathWatcher* watcher,
[email protected]2dec8ec2013-02-07 19:20:34694 const base::FilePath& path) {
[email protected]07b71c82013-01-08 19:07:31695 bool result = watcher->Watch(path, false,
696 base::Bind(&NotifyPluginDirChanged));
[email protected]634d23d2011-01-19 10:38:19697 DCHECK(result);
698}
699#endif
[email protected]f520b5b2011-11-08 02:42:14700
[email protected]130757672012-10-24 00:26:19701void PluginServiceImpl::SetFilter(PluginServiceFilter* filter) {
[email protected]3a5180ae2011-12-21 02:39:38702 filter_ = filter;
703}
704
[email protected]130757672012-10-24 00:26:19705PluginServiceFilter* PluginServiceImpl::GetFilter() {
[email protected]3a5180ae2011-12-21 02:39:38706 return filter_;
707}
708
[email protected]2dec8ec2013-02-07 19:20:34709void PluginServiceImpl::ForcePluginShutdown(const base::FilePath& plugin_path) {
[email protected]b6a2f8de2012-01-31 17:28:49710 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
711 BrowserThread::PostTask(
712 BrowserThread::IO, FROM_HERE,
713 base::Bind(&PluginServiceImpl::ForcePluginShutdown,
714 base::Unretained(this), plugin_path));
715 return;
716 }
717
718 PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path);
719 if (plugin)
720 plugin->ForceShutdown();
721}
722
[email protected]47214d882012-02-29 06:28:48723static const unsigned int kMaxCrashesPerInterval = 3;
724static const unsigned int kCrashesInterval = 120;
725
[email protected]2dec8ec2013-02-07 19:20:34726void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) {
mostynb4c27d042015-03-18 21:47:47727 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]2dec8ec2013-02-07 19:20:34728 std::map<base::FilePath, std::vector<base::Time> >::iterator i =
[email protected]47214d882012-02-29 06:28:48729 crash_times_.find(path);
730 if (i == crash_times_.end()) {
731 crash_times_[path] = std::vector<base::Time>();
732 i = crash_times_.find(path);
733 }
734 if (i->second.size() == kMaxCrashesPerInterval) {
735 i->second.erase(i->second.begin());
736 }
737 base::Time time = base::Time::Now();
738 i->second.push_back(time);
739}
740
[email protected]2dec8ec2013-02-07 19:20:34741bool PluginServiceImpl::IsPluginUnstable(const base::FilePath& path) {
mostynb4c27d042015-03-18 21:47:47742 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]2dec8ec2013-02-07 19:20:34743 std::map<base::FilePath, std::vector<base::Time> >::const_iterator i =
[email protected]47214d882012-02-29 06:28:48744 crash_times_.find(path);
745 if (i == crash_times_.end()) {
746 return false;
747 }
748 if (i->second.size() != kMaxCrashesPerInterval) {
749 return false;
750 }
751 base::TimeDelta delta = base::Time::Now() - i->second[0];
[email protected]d8c70062013-04-24 00:22:34752 return delta.InSeconds() <= kCrashesInterval;
[email protected]47214d882012-02-29 06:28:48753}
754
[email protected]e67385f2011-12-21 06:00:56755void PluginServiceImpl::RefreshPlugins() {
[email protected]29e2fb42013-07-19 01:13:47756 PluginList::Singleton()->RefreshPlugins();
[email protected]f520b5b2011-11-08 02:42:14757}
758
[email protected]2dec8ec2013-02-07 19:20:34759void PluginServiceImpl::AddExtraPluginPath(const base::FilePath& path) {
[email protected]a01c8c8f2014-05-09 17:24:53760 if (!NPAPIPluginsSupported()) {
[email protected]9a60ccb2013-07-19 22:23:36761 // TODO(jam): remove and just have CHECK once we're sure this doesn't get
762 // triggered.
[email protected]efde84b02013-11-23 04:18:20763 DVLOG(0) << "NPAPI plugins not supported";
[email protected]9a60ccb2013-07-19 22:23:36764 return;
765 }
[email protected]29e2fb42013-07-19 01:13:47766 PluginList::Singleton()->AddExtraPluginPath(path);
[email protected]c6f3dea2012-01-14 02:23:11767}
768
[email protected]2dec8ec2013-02-07 19:20:34769void PluginServiceImpl::RemoveExtraPluginPath(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47770 PluginList::Singleton()->RemoveExtraPluginPath(path);
[email protected]8f3372122013-07-18 04:34:14771}
772
773void PluginServiceImpl::AddExtraPluginDir(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47774 PluginList::Singleton()->AddExtraPluginDir(path);
[email protected]8f3372122013-07-18 04:34:14775}
776
777void PluginServiceImpl::RegisterInternalPlugin(
[email protected]d7bd3e52013-07-21 04:29:20778 const WebPluginInfo& info,
[email protected]8f3372122013-07-18 04:34:14779 bool add_at_beginning) {
wfha79d1022015-02-20 16:13:13780 // Internal plugins should never be NPAPI.
781 CHECK_NE(info.type, WebPluginInfo::PLUGIN_TYPE_NPAPI);
782 if (info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
[email protected]efde84b02013-11-23 04:18:20783 DVLOG(0) << "Don't register NPAPI plugins when they're not supported";
[email protected]9a60ccb2013-07-19 22:23:36784 return;
785 }
[email protected]29e2fb42013-07-19 01:13:47786 PluginList::Singleton()->RegisterInternalPlugin(info, add_at_beginning);
[email protected]f520b5b2011-11-08 02:42:14787}
788
[email protected]2dec8ec2013-02-07 19:20:34789void PluginServiceImpl::UnregisterInternalPlugin(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47790 PluginList::Singleton()->UnregisterInternalPlugin(path);
[email protected]f520b5b2011-11-08 02:42:14791}
792
[email protected]8f3372122013-07-18 04:34:14793void PluginServiceImpl::GetInternalPlugins(
[email protected]d7bd3e52013-07-21 04:29:20794 std::vector<WebPluginInfo>* plugins) {
[email protected]29e2fb42013-07-19 01:13:47795 PluginList::Singleton()->GetInternalPlugins(plugins);
[email protected]8f3372122013-07-18 04:34:14796}
797
[email protected]9a60ccb2013-07-19 22:23:36798bool PluginServiceImpl::NPAPIPluginsSupported() {
wfha79d1022015-02-20 16:13:13799#if defined(OS_WIN) || defined(OS_MACOSX)
wfh6be06282015-07-20 18:04:02800 npapi_plugins_enabled_ = GetContentClient()->browser()->IsNPAPIEnabled();
wfhad38f5a32015-06-03 17:11:07801#if defined(OS_WIN)
wfh6be06282015-07-20 18:04:02802 // NPAPI plugins don't play well with Win32k renderer lockdown.
803 if (npapi_plugins_enabled_)
804 DisableWin32kRendererLockdown();
wfhad38f5a32015-06-03 17:11:07805#endif
wfh6be06282015-07-20 18:04:02806 NPAPIPluginStatus status =
807 npapi_plugins_enabled_ ? NPAPI_STATUS_ENABLED : NPAPI_STATUS_DISABLED;
wfha79d1022015-02-20 16:13:13808#else
wfh6be06282015-07-20 18:04:02809 NPAPIPluginStatus status = NPAPI_STATUS_UNSUPPORTED;
wfha79d1022015-02-20 16:13:13810#endif
wfh6be06282015-07-20 18:04:02811 UMA_HISTOGRAM_ENUMERATION("Plugin.NPAPIStatus", status,
812 NPAPI_STATUS_ENUM_COUNT);
wfha79d1022015-02-20 16:13:13813
wfh0539f2f52015-01-21 14:36:46814 return npapi_plugins_enabled_;
[email protected]9a60ccb2013-07-19 22:23:36815}
816
[email protected]8f3372122013-07-18 04:34:14817void PluginServiceImpl::DisablePluginsDiscoveryForTesting() {
[email protected]29e2fb42013-07-19 01:13:47818 PluginList::Singleton()->DisablePluginsDiscovery();
[email protected]ee066172011-11-10 23:20:05819}
820
[email protected]5904cb42012-09-24 15:05:20821#if defined(OS_MACOSX)
822void PluginServiceImpl::AppActivated() {
823 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]07b71c82013-01-08 19:07:31824 base::Bind(&NotifyPluginsOfActivation));
[email protected]5904cb42012-09-24 15:05:20825}
[email protected]9a60ccb2013-07-19 22:23:36826#elif defined(OS_WIN)
827
828bool GetPluginPropertyFromWindow(
829 HWND window, const wchar_t* plugin_atom_property,
830 base::string16* plugin_property) {
scottmg4800fc22015-04-29 00:31:20831 ATOM plugin_atom = static_cast<ATOM>(
832 reinterpret_cast<uintptr_t>(GetPropW(window, plugin_atom_property)));
[email protected]9a60ccb2013-07-19 22:23:36833 if (plugin_atom != 0) {
834 WCHAR plugin_property_local[MAX_PATH] = {0};
835 GlobalGetAtomNameW(plugin_atom,
836 plugin_property_local,
837 ARRAYSIZE(plugin_property_local));
838 *plugin_property = plugin_property_local;
839 return true;
840 }
841 return false;
842}
843
844bool PluginServiceImpl::GetPluginInfoFromWindow(
845 HWND window,
846 base::string16* plugin_name,
847 base::string16* plugin_version) {
848 if (!IsPluginWindow(window))
849 return false;
850
jam3458fc002014-09-10 03:21:41851
852 DWORD process_id = 0;
853 GetWindowThreadProcessId(window, &process_id);
854 WebPluginInfo info;
855 if (!PluginProcessHost::GetWebPluginInfoFromPluginPid(process_id, &info))
856 return false;
857
858 *plugin_name = info.name;
859 *plugin_version = info.version;
[email protected]9a60ccb2013-07-19 22:23:36860 return true;
861}
862
863bool PluginServiceImpl::IsPluginWindow(HWND window) {
[email protected]bde885b2013-09-12 20:55:53864 return gfx::GetClassName(window) == base::string16(kNativeWindowClassName);
[email protected]9a60ccb2013-07-19 22:23:36865}
[email protected]5904cb42012-09-24 15:05:20866#endif
867
[email protected]aec5ed52014-06-20 07:51:42868bool PluginServiceImpl::PpapiDevChannelSupported(
869 BrowserContext* browser_context,
870 const GURL& document_url) {
wfh6be06282015-07-20 18:04:02871 return GetContentClient()->browser()->IsPluginAllowedToUseDevChannelAPIs(
872 browser_context, document_url);
[email protected]8ddc6b7c2013-12-12 20:42:06873}
874
[email protected]130757672012-10-24 00:26:19875} // namespace content