blob: 09ae4dcb8c6d8c27eec5a156a5d87c85167e795f [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
avib7348942015-12-25 20:57:107#include <stddef.h>
8
[email protected]d33e7cc2011-09-23 01:43:569#include "base/bind.h"
[email protected]d48f1e0c2009-02-12 20:57:5410#include "base/command_line.h"
[email protected]7b3ee8b2011-04-01 18:48:1911#include "base/compiler_specific.h"
[email protected]57999812013-02-24 05:40:5212#include "base/files/file_path.h"
skyostil95082a62015-06-05 19:53:0713#include "base/location.h"
[email protected]fd8d8d6c2013-02-28 02:48:3314#include "base/metrics/histogram.h"
skyostil95082a62015-06-05 19:53:0715#include "base/single_thread_task_runner.h"
[email protected]348fbaac2013-06-11 06:31:5116#include "base/strings/string_util.h"
[email protected]74ebfb12013-06-07 20:48:0017#include "base/strings/utf_string_conversions.h"
[email protected]7f070d42011-03-09 20:25:3218#include "base/synchronization/waitable_event.h"
[email protected]34b99632011-01-01 01:01:0619#include "base/threading/thread.h"
avib7348942015-12-25 20:57:1020#include "build/build_config.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"
wfh1a90e032015-04-14 17:10:1724#include "content/common/content_switches_internal.h"
[email protected]dac6a5a2013-07-25 05:06:4825#include "content/common/pepper_plugin_list.h"
[email protected]29e2fb42013-07-19 01:13:4726#include "content/common/plugin_list.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]31f376c2012-03-13 16:43:0930#include "content/public/browser/plugin_service_filter.h"
[email protected]ce967862012-02-09 22:47:0531#include "content/public/browser/resource_context.h"
[email protected]73270292013-08-09 03:48:0732#include "content/public/common/content_constants.h"
[email protected]c08950d22011-10-13 22:20:2933#include "content/public/common/content_switches.h"
[email protected]bd5d6cf2011-12-01 00:39:1234#include "content/public/common/process_type.h"
[email protected]d7bd3e52013-07-21 04:29:2035#include "content/public/common/webplugininfo.h"
[email protected]191eb3f72010-12-21 06:27:5036
[email protected]3b91edbe2012-09-27 22:49:2337#if defined(OS_WIN)
[email protected]29e2fb42013-07-19 01:13:4738#include "content/common/plugin_constants_win.h"
[email protected]bde885b2013-09-12 20:55:5339#include "ui/gfx/win/hwnd_util.h"
[email protected]3b91edbe2012-09-27 22:49:2340#endif
41
42#if defined(OS_POSIX)
43#include "content/browser/plugin_loader_posix.h"
44#endif
45
[email protected]52348b22012-11-07 10:19:3446#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]6665571f2013-01-15 07:59:5247using ::base::FilePathWatcher;
[email protected]493c8002011-04-14 16:56:0148#endif
49
[email protected]130757672012-10-24 00:26:1950namespace content {
[email protected]d33e7cc2011-09-23 01:43:5651namespace {
52
[email protected]fd8d8d6c2013-02-28 02:48:3353// This enum is used to collect Flash usage data.
54enum FlashUsage {
55 // Number of browser processes that have started at least one NPAPI Flash
56 // process during their lifetime.
57 START_NPAPI_FLASH_AT_LEAST_ONCE,
58 // Number of browser processes that have started at least one PPAPI Flash
59 // process during their lifetime.
60 START_PPAPI_FLASH_AT_LEAST_ONCE,
61 // Total number of browser processes.
62 TOTAL_BROWSER_PROCESSES,
63 FLASH_USAGE_ENUM_COUNT
64};
65
wfh0539f2f52015-01-21 14:36:4666enum NPAPIPluginStatus {
67 // Platform does not support NPAPI.
68 NPAPI_STATUS_UNSUPPORTED,
69 // Platform supports NPAPI and NPAPI is disabled.
70 NPAPI_STATUS_DISABLED,
71 // Platform supports NPAPI and NPAPI is enabled.
72 NPAPI_STATUS_ENABLED,
73 NPAPI_STATUS_ENUM_COUNT
74};
75
[email protected]1b517202012-12-19 17:16:1076bool LoadPluginListInProcess() {
77#if defined(OS_WIN)
78 return true;
79#else
80 // If on POSIX, we don't want to load the list of NPAPI plugins in-process as
81 // that causes instability.
[email protected]6d057a0c2013-07-09 21:12:0782
83 // Can't load the plugins on the utility thread when in single process mode
[email protected]10212452013-07-16 20:10:5584 // since that requires GTK which can only be used on the main thread.
[email protected]6d057a0c2013-07-09 21:12:0785 if (RenderProcessHost::run_renderer_in_process())
86 return true;
87
[email protected]9a60ccb2013-07-19 22:23:3688 return !PluginService::GetInstance()->NPAPIPluginsSupported();
[email protected]1b517202012-12-19 17:16:1089#endif
90}
91
[email protected]49125952011-09-27 18:05:1592// Callback set on the PluginList to assert that plugin loading happens on the
93// correct thread.
[email protected]1b517202012-12-19 17:16:1094void WillLoadPluginsCallback(
[email protected]a33fa9d2012-05-16 14:47:4995 base::SequencedWorkerPool::SequenceToken token) {
[email protected]1b517202012-12-19 17:16:1096 if (LoadPluginListInProcess()) {
97 CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
98 token));
99 } else {
100 CHECK(false) << "Plugin loading should happen out-of-process.";
101 }
[email protected]a79912252012-05-16 11:52:19102}
[email protected]d33e7cc2011-09-23 01:43:56103
[email protected]a96ec6a2009-11-04 17:27:08104#if defined(OS_MACOSX)
[email protected]07b71c82013-01-08 19:07:31105void NotifyPluginsOfActivation() {
mostynb4c27d042015-03-18 21:47:47106 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]a96ec6a2009-11-04 17:27:08107
[email protected]4967f792012-01-20 22:14:40108 for (PluginProcessHostIterator iter; !iter.Done(); ++iter)
109 iter->OnAppActivation();
[email protected]a96ec6a2009-11-04 17:27:08110}
[email protected]3b48dbc2012-01-06 16:34:17111#endif
[email protected]45a22e62011-10-12 09:48:02112
thakis84dff942015-07-28 20:47:38113#if defined(OS_POSIX)
114#if !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]2dec8ec2013-02-07 19:20:34115void NotifyPluginDirChanged(const base::FilePath& path, bool error) {
[email protected]07b71c82013-01-08 19:07:31116 if (error) {
[email protected]634d23d2011-01-19 10:38:19117 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
118 // stopping the watcher would be enough. Or possibly restart it.
119 NOTREACHED();
[email protected]07b71c82013-01-08 19:07:31120 return;
[email protected]634d23d2011-01-19 10:38:19121 }
[email protected]07b71c82013-01-08 19:07:31122 VLOG(1) << "Watched path changed: " << path.value();
123 // Make the plugin list update itself
[email protected]29e2fb42013-07-19 01:13:47124 PluginList::Singleton()->RefreshPlugins();
[email protected]07b71c82013-01-08 19:07:31125 BrowserThread::PostTask(
126 BrowserThread::UI, FROM_HERE,
127 base::Bind(&PluginService::PurgePluginListCache,
128 static_cast<BrowserContext*>(NULL), false));
129}
thakis84dff942015-07-28 20:47:38130#endif // !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19131
skyostil95082a62015-06-05 19:53:07132void ForwardCallback(base::SingleThreadTaskRunner* target_task_runner,
[email protected]aa7f8802014-01-27 16:56:32133 const PluginService::GetPluginsCallback& callback,
134 const std::vector<WebPluginInfo>& plugins) {
skyostil95082a62015-06-05 19:53:07135 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins));
[email protected]aa7f8802014-01-27 16:56:32136}
thakis84dff942015-07-28 20:47:38137#endif // defined(OS_POSIX)
[email protected]aa7f8802014-01-27 16:56:32138
[email protected]07b71c82013-01-08 19:07:31139} // namespace
140
[email protected]3a5180ae2011-12-21 02:39:38141// static
142PluginService* PluginService::GetInstance() {
[email protected]e67385f2011-12-21 06:00:56143 return PluginServiceImpl::GetInstance();
[email protected]3a5180ae2011-12-21 02:39:38144}
145
146void PluginService::PurgePluginListCache(BrowserContext* browser_context,
147 bool reload_pages) {
148 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
149 !it.IsAtEnd(); it.Advance()) {
150 RenderProcessHost* host = it.GetCurrentValue();
151 if (!browser_context || host->GetBrowserContext() == browser_context)
152 host->Send(new ViewMsg_PurgePluginListCache(reload_pages));
153 }
154}
155
initial.commit09911bf2008-07-26 23:55:29156// static
[email protected]e67385f2011-12-21 06:00:56157PluginServiceImpl* PluginServiceImpl::GetInstance() {
olli.raula36aa8be2015-09-10 11:14:22158 return base::Singleton<PluginServiceImpl>::get();
initial.commit09911bf2008-07-26 23:55:29159}
160
[email protected]e67385f2011-12-21 06:00:56161PluginServiceImpl::PluginServiceImpl()
wfh0539f2f52015-01-21 14:36:46162 : npapi_plugins_enabled_(false), filter_(NULL) {
[email protected]fd8d8d6c2013-02-28 02:48:33163 // Collect the total number of browser processes (which create
164 // PluginServiceImpl objects, to be precise). The number is used to normalize
165 // the number of processes which start at least one NPAPI/PPAPI Flash process.
166 static bool counted = false;
167 if (!counted) {
168 counted = true;
169 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage", TOTAL_BROWSER_PROCESSES,
170 FLASH_USAGE_ENUM_COUNT);
171 }
[email protected]ee066172011-11-10 23:20:05172}
173
[email protected]e67385f2011-12-21 06:00:56174PluginServiceImpl::~PluginServiceImpl() {
[email protected]ee066172011-11-10 23:20:05175 // Make sure no plugin channel requests have been leaked.
176 DCHECK(pending_plugin_clients_.empty());
177}
178
[email protected]e67385f2011-12-21 06:00:56179void PluginServiceImpl::Init() {
[email protected]a33fa9d2012-05-16 14:47:49180 plugin_list_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken();
[email protected]29e2fb42013-07-19 01:13:47181 PluginList::Singleton()->set_will_load_plugins_callback(
[email protected]1b517202012-12-19 17:16:10182 base::Bind(&WillLoadPluginsCallback, plugin_list_token_));
[email protected]49125952011-09-27 18:05:15183
[email protected]4e0616e2010-05-28 14:55:53184 RegisterPepperPlugins();
185
[email protected]9a1c4262010-06-29 21:50:27186 // Load any specified on the command line as well.
[email protected]479278702014-08-11 20:32:09187 const base::CommandLine* command_line =
188 base::CommandLine::ForCurrentProcess();
[email protected]2dec8ec2013-02-07 19:20:34189 base::FilePath path =
190 command_line->GetSwitchValuePath(switches::kLoadPlugin);
[email protected]7bf795d92010-05-22 00:14:28191 if (!path.empty())
[email protected]f520b5b2011-11-08 02:42:14192 AddExtraPluginPath(path);
[email protected]9a1c4262010-06-29 21:50:27193 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
194 if (!path.empty())
[email protected]29e2fb42013-07-19 01:13:47195 PluginList::Singleton()->AddExtraPluginDir(path);
[email protected]e87ce862013-06-12 17:30:48196
197 if (command_line->HasSwitch(switches::kDisablePluginsDiscovery))
[email protected]29e2fb42013-07-19 01:13:47198 PluginList::Singleton()->DisablePluginsDiscovery();
[email protected]dfba8762011-09-02 12:49:54199}
200
[email protected]e67385f2011-12-21 06:00:56201void PluginServiceImpl::StartWatchingPlugins() {
[email protected]634d23d2011-01-19 10:38:19202 // Start watching for changes in the plugin list. This means watching
203 // for changes in the Windows registry keys and on both Windows and POSIX
204 // watch for changes in the paths that are expected to contain plugins.
[email protected]b547fd42009-04-23 23:16:27205#if defined(OS_WIN)
[email protected]86ec4f6e2011-04-20 16:21:19206 if (hkcu_key_.Create(HKEY_CURRENT_USER,
[email protected]29e2fb42013-07-19 01:13:47207 kRegistryMozillaPlugins,
[email protected]86ec4f6e2011-04-20 16:21:19208 KEY_NOTIFY) == ERROR_SUCCESS) {
rvargas6f315b82014-10-17 01:28:58209 base::win::RegKey::ChangeCallback callback =
210 base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
211 base::Unretained(&hkcu_key_));
212 hkcu_key_.StartWatching(callback);
[email protected]b547fd42009-04-23 23:16:27213 }
[email protected]86ec4f6e2011-04-20 16:21:19214 if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
[email protected]29e2fb42013-07-19 01:13:47215 kRegistryMozillaPlugins,
[email protected]86ec4f6e2011-04-20 16:21:19216 KEY_NOTIFY) == ERROR_SUCCESS) {
rvargas6f315b82014-10-17 01:28:58217 base::win::RegKey::ChangeCallback callback =
218 base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
rvargasb8056152014-11-08 01:44:28219 base::Unretained(&hklm_key_));
rvargas6f315b82014-10-17 01:28:58220 hklm_key_.StartWatching(callback);
[email protected]b547fd42009-04-23 23:16:27221 }
[email protected]a33fa9d2012-05-16 14:47:49222#endif
[email protected]52348b22012-11-07 10:19:34223#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19224// On ChromeOS the user can't install plugins anyway and on Windows all
225// important plugins register themselves in the registry so no need to do that.
[email protected]07b71c82013-01-08 19:07:31226
[email protected]634d23d2011-01-19 10:38:19227 // Get the list of all paths for registering the FilePathWatchers
228 // that will track and if needed reload the list of plugins on runtime.
[email protected]2dec8ec2013-02-07 19:20:34229 std::vector<base::FilePath> plugin_dirs;
[email protected]29e2fb42013-07-19 01:13:47230 PluginList::Singleton()->GetPluginDirectories(&plugin_dirs);
[email protected]894bb502009-05-21 22:39:57231
[email protected]634d23d2011-01-19 10:38:19232 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
[email protected]634d23d2011-01-19 10:38:19233 // FilePathWatcher can not handle non-absolute paths under windows.
234 // We don't watch for file changes in windows now but if this should ever
235 // be extended to Windows these lines might save some time of debugging.
236#if defined(OS_WIN)
237 if (!plugin_dirs[i].IsAbsolute())
238 continue;
239#endif
[email protected]493c8002011-04-14 16:56:01240 FilePathWatcher* watcher = new FilePathWatcher();
[email protected]634d23d2011-01-19 10:38:19241 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
242 BrowserThread::PostTask(
243 BrowserThread::FILE, FROM_HERE,
[email protected]e67385f2011-12-21 06:00:56244 base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
[email protected]07b71c82013-01-08 19:07:31245 plugin_dirs[i]));
[email protected]634d23d2011-01-19 10:38:19246 file_watchers_.push_back(watcher);
247 }
248#endif
initial.commit09911bf2008-07-26 23:55:29249}
250
[email protected]e67385f2011-12-21 06:00:56251PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
[email protected]2dec8ec2013-02-07 19:20:34252 const base::FilePath& plugin_path) {
[email protected]4967f792012-01-20 22:14:40253 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
254 if (iter->info().path == plugin_path)
255 return *iter;
[email protected]a436d922009-02-13 23:16:42256 }
257
initial.commit09911bf2008-07-26 23:55:29258 return NULL;
259}
260
[email protected]e67385f2011-12-21 06:00:56261PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
[email protected]2dec8ec2013-02-07 19:20:34262 const base::FilePath& plugin_path,
263 const base::FilePath& profile_data_directory) {
[email protected]4967f792012-01-20 22:14:40264 for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]dd9a0952012-05-31 20:11:31265 if (iter->plugin_path() == plugin_path &&
266 iter->profile_data_directory() == profile_data_directory) {
[email protected]4967f792012-01-20 22:14:40267 return *iter;
[email protected]dd9a0952012-05-31 20:11:31268 }
[email protected]a08ebea2011-02-13 17:50:20269 }
[email protected]a08ebea2011-02-13 17:50:20270 return NULL;
271}
272
[email protected]e67385f2011-12-21 06:00:56273PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
[email protected]2dec8ec2013-02-07 19:20:34274 const base::FilePath& broker_path) {
[email protected]4967f792012-01-20 22:14:40275 for (PpapiBrokerProcessHostIterator iter; !iter.Done(); ++iter) {
276 if (iter->plugin_path() == broker_path)
277 return *iter;
[email protected]eb415bf0e2011-04-14 02:45:42278 }
279
280 return NULL;
281}
282
[email protected]e67385f2011-12-21 06:00:56283PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54284 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34285 const base::FilePath& plugin_path) {
mostynb4c27d042015-03-18 21:47:47286 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]a08ebea2011-02-13 17:50:20287
[email protected]6be31d202013-02-01 18:20:54288 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
289 return NULL;
290
[email protected]a08ebea2011-02-13 17:50:20291 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
initial.commit09911bf2008-07-26 23:55:29292 if (plugin_host)
293 return plugin_host;
294
[email protected]d7bd3e52013-07-21 04:29:20295 WebPluginInfo info;
[email protected]88ca4912011-10-12 14:00:43296 if (!GetPluginInfoByPath(plugin_path, &info)) {
[email protected]a27a9382009-02-11 23:55:10297 return NULL;
298 }
299
[email protected]fd8d8d6c2013-02-28 02:48:33300 // Record when NPAPI Flash process is started for the first time.
301 static bool counted = false;
[email protected]32956122013-12-25 07:29:24302 if (!counted && base::UTF16ToUTF8(info.name) == kFlashPluginName) {
[email protected]fd8d8d6c2013-02-28 02:48:33303 counted = true;
304 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
305 START_NPAPI_FLASH_AT_LEAST_ONCE,
306 FLASH_USAGE_ENUM_COUNT);
307 }
[email protected]132bca82013-12-10 09:14:47308#if defined(OS_CHROMEOS)
309 // TODO(ihf): Move to an earlier place once crbug.com/314301 is fixed. For now
310 // we still want Plugin.FlashUsage recorded if we end up here.
311 LOG(WARNING) << "Refusing to start npapi plugin on ChromeOS.";
312 return NULL;
313#endif
initial.commit09911bf2008-07-26 23:55:29314 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]8b8a554d2010-11-18 13:26:40315 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
[email protected]99907362012-01-11 05:41:40316 if (!new_host->Init(info)) {
[email protected]a08ebea2011-02-13 17:50:20317 NOTREACHED(); // Init is not expected to fail.
initial.commit09911bf2008-07-26 23:55:29318 return NULL;
319 }
[email protected]8b8a554d2010-11-18 13:26:40320 return new_host.release();
initial.commit09911bf2008-07-26 23:55:29321}
322
[email protected]e67385f2011-12-21 06:00:56323PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54324 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34325 const base::FilePath& plugin_path,
[email protected]8522332e2013-08-28 19:42:59326 const base::FilePath& profile_data_directory) {
mostynb4c27d042015-03-18 21:47:47327 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]a08ebea2011-02-13 17:50:20328
[email protected]132bca82013-12-10 09:14:47329 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) {
330 VLOG(1) << "Unable to load ppapi plugin: " << plugin_path.MaybeAsASCII();
[email protected]6be31d202013-02-01 18:20:54331 return NULL;
[email protected]132bca82013-12-10 09:14:47332 }
[email protected]6be31d202013-02-01 18:20:54333
[email protected]dd9a0952012-05-31 20:11:31334 PpapiPluginProcessHost* plugin_host =
335 FindPpapiPluginProcess(plugin_path, profile_data_directory);
[email protected]a08ebea2011-02-13 17:50:20336 if (plugin_host)
337 return plugin_host;
338
[email protected]eb415bf0e2011-04-14 02:45:42339 // Validate that the plugin is actually registered.
[email protected]130757672012-10-24 00:26:19340 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]132bca82013-12-10 09:14:47341 if (!info) {
342 VLOG(1) << "Unable to find ppapi plugin registration for: "
343 << plugin_path.MaybeAsASCII();
[email protected]a08ebea2011-02-13 17:50:20344 return NULL;
[email protected]132bca82013-12-10 09:14:47345 }
[email protected]a08ebea2011-02-13 17:50:20346
[email protected]fd8d8d6c2013-02-28 02:48:33347 // Record when PPAPI Flash process is started for the first time.
348 static bool counted = false;
349 if (!counted && info->name == kFlashPluginName) {
350 counted = true;
351 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
352 START_PPAPI_FLASH_AT_LEAST_ONCE,
353 FLASH_USAGE_ENUM_COUNT);
354 }
355
[email protected]a08ebea2011-02-13 17:50:20356 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]132bca82013-12-10 09:14:47357 plugin_host = PpapiPluginProcessHost::CreatePluginHost(
[email protected]8522332e2013-08-28 19:42:59358 *info, profile_data_directory);
[email protected]132bca82013-12-10 09:14:47359 if (!plugin_host) {
360 VLOG(1) << "Unable to create ppapi plugin process for: "
361 << plugin_path.MaybeAsASCII();
362 }
363
364 return plugin_host;
[email protected]a08ebea2011-02-13 17:50:20365}
366
[email protected]e67385f2011-12-21 06:00:56367PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
[email protected]6be31d202013-02-01 18:20:54368 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34369 const base::FilePath& plugin_path) {
mostynb4c27d042015-03-18 21:47:47370 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]eb415bf0e2011-04-14 02:45:42371
[email protected]6be31d202013-02-01 18:20:54372 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
373 return NULL;
374
[email protected]a50432d2011-09-30 16:32:14375 PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42376 if (plugin_host)
377 return plugin_host;
378
379 // Validate that the plugin is actually registered.
[email protected]130757672012-10-24 00:26:19380 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42381 if (!info)
382 return NULL;
383
384 // TODO(ddorwin): Uncomment once out of process is supported.
385 // DCHECK(info->is_out_of_process);
386
387 // This broker isn't loaded by any broker process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14388 return PpapiPluginProcessHost::CreateBrokerHost(*info);
[email protected]eb415bf0e2011-04-14 02:45:42389}
390
[email protected]e67385f2011-12-21 06:00:56391void PluginServiceImpl::OpenChannelToNpapiPlugin(
[email protected]c8f73ab2011-01-22 00:05:17392 int render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16393 int render_frame_id,
[email protected]610c0892009-09-08 19:46:18394 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54395 const GURL& page_url,
[email protected]610c0892009-09-08 19:46:18396 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39397 PluginProcessHost::Client* client) {
mostynb4c27d042015-03-18 21:47:47398 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4befe7592011-09-14 22:49:09399 DCHECK(!ContainsKey(pending_plugin_clients_, client));
400 pending_plugin_clients_.insert(client);
[email protected]88ca4912011-10-12 14:00:43401
402 // Make sure plugins are loaded if necessary.
[email protected]209f2ae2012-03-13 01:28:08403 PluginServiceFilterParams params = {
[email protected]88ca4912011-10-12 14:00:43404 render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16405 render_frame_id,
[email protected]88ca4912011-10-12 14:00:43406 page_url,
[email protected]df02aca2012-02-09 21:03:20407 client->GetResourceContext()
[email protected]88ca4912011-10-12 14:00:43408 };
[email protected]e67385f2011-12-21 06:00:56409 GetPlugins(base::Bind(
410 &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
411 base::Unretained(this), params, url, mime_type, client));
[email protected]6fdd4182010-10-14 23:59:26412}
413
[email protected]e67385f2011-12-21 06:00:56414void PluginServiceImpl::OpenChannelToPpapiPlugin(
[email protected]6be31d202013-02-01 18:20:54415 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34416 const base::FilePath& plugin_path,
417 const base::FilePath& profile_data_directory,
[email protected]a50432d2011-09-30 16:32:14418 PpapiPluginProcessHost::PluginClient* client) {
[email protected]d259a8e2011-05-18 22:31:09419 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
[email protected]8522332e2013-08-28 19:42:59420 render_process_id, plugin_path, profile_data_directory);
[email protected]1bf0fb22012-04-12 21:44:16421 if (plugin_host) {
[email protected]a08ebea2011-02-13 17:50:20422 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16423 } else {
424 // Send error.
[email protected]108fd342013-01-04 20:46:54425 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
[email protected]1bf0fb22012-04-12 21:44:16426 }
[email protected]a08ebea2011-02-13 17:50:20427}
428
[email protected]e67385f2011-12-21 06:00:56429void PluginServiceImpl::OpenChannelToPpapiBroker(
[email protected]6be31d202013-02-01 18:20:54430 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34431 const base::FilePath& path,
[email protected]a50432d2011-09-30 16:32:14432 PpapiPluginProcessHost::BrokerClient* client) {
[email protected]6be31d202013-02-01 18:20:54433 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(
434 render_process_id, path);
[email protected]1bf0fb22012-04-12 21:44:16435 if (plugin_host) {
[email protected]a50432d2011-09-30 16:32:14436 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16437 } else {
438 // Send error.
[email protected]108fd342013-01-04 20:46:54439 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
[email protected]1bf0fb22012-04-12 21:44:16440 }
[email protected]eb415bf0e2011-04-14 02:45:42441}
442
[email protected]e67385f2011-12-21 06:00:56443void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
[email protected]4befe7592011-09-14 22:49:09444 PluginProcessHost::Client* client) {
mostynb4c27d042015-03-18 21:47:47445 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4befe7592011-09-14 22:49:09446 DCHECK(ContainsKey(pending_plugin_clients_, client));
447 pending_plugin_clients_.erase(client);
448}
449
[email protected]e67385f2011-12-21 06:00:56450void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
[email protected]209f2ae2012-03-13 01:28:08451 const PluginServiceFilterParams& params,
[email protected]88ca4912011-10-12 14:00:43452 const GURL& url,
453 const std::string& mime_type,
454 PluginProcessHost::Client* client,
[email protected]d7bd3e52013-07-21 04:29:20455 const std::vector<WebPluginInfo>&) {
[email protected]60eca4eb2013-12-06 00:02:16456 GetAllowedPluginForOpenChannelToPlugin(
457 params.render_process_id, params.render_frame_id, url, params.page_url,
458 mime_type, client, params.resource_context);
[email protected]88ca4912011-10-12 14:00:43459}
460
[email protected]e67385f2011-12-21 06:00:56461void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
[email protected]c8f73ab2011-01-22 00:05:17462 int render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16463 int render_frame_id,
[email protected]6fdd4182010-10-14 23:59:26464 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54465 const GURL& page_url,
[email protected]6fdd4182010-10-14 23:59:26466 const std::string& mime_type,
[email protected]87c4be42011-09-16 01:10:59467 PluginProcessHost::Client* client,
[email protected]130757672012-10-24 00:26:19468 ResourceContext* resource_context) {
[email protected]d7bd3e52013-07-21 04:29:20469 WebPluginInfo info;
[email protected]dfba8762011-09-02 12:49:54470 bool allow_wildcard = true;
[email protected]11e1c182011-05-17 20:26:27471 bool found = GetPluginInfo(
[email protected]60eca4eb2013-12-06 00:02:16472 render_process_id, render_frame_id, resource_context,
[email protected]dfba8762011-09-02 12:49:54473 url, page_url, mime_type, allow_wildcard,
474 NULL, &info, NULL);
[email protected]2dec8ec2013-02-07 19:20:34475 base::FilePath plugin_path;
[email protected]68598072011-07-29 08:21:28476 if (found)
[email protected]dfba8762011-09-02 12:49:54477 plugin_path = info.path;
[email protected]6fdd4182010-10-14 23:59:26478
479 // Now we jump back to the IO thread to finish opening the channel.
[email protected]e67385f2011-12-21 06:00:56480 BrowserThread::PostTask(
481 BrowserThread::IO, FROM_HERE,
482 base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
[email protected]6be31d202013-02-01 18:20:54483 base::Unretained(this),
484 render_process_id,
485 plugin_path,
486 client));
wfh30443502015-05-01 21:58:30487 if (filter_) {
488 DCHECK_EQ(WebPluginInfo::PLUGIN_TYPE_NPAPI, info.type);
wfhec1f7352015-05-07 23:44:54489 filter_->NPAPIPluginLoaded(render_process_id, render_frame_id, mime_type,
490 info);
wfh30443502015-05-01 21:58:30491 }
[email protected]6fdd4182010-10-14 23:59:26492}
493
[email protected]e67385f2011-12-21 06:00:56494void PluginServiceImpl::FinishOpenChannelToPlugin(
[email protected]6be31d202013-02-01 18:20:54495 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34496 const base::FilePath& plugin_path,
[email protected]46b69e42010-11-02 12:26:39497 PluginProcessHost::Client* client) {
mostynb4c27d042015-03-18 21:47:47498 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]20a793e2010-10-12 06:50:08499
[email protected]4befe7592011-09-14 22:49:09500 // Make sure it hasn't been canceled yet.
501 if (!ContainsKey(pending_plugin_clients_, client))
502 return;
503 pending_plugin_clients_.erase(client);
504
[email protected]6be31d202013-02-01 18:20:54505 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(
506 render_process_id, plugin_path);
[email protected]4befe7592011-09-14 22:49:09507 if (plugin_host) {
508 client->OnFoundPluginProcessHost(plugin_host);
[email protected]46b69e42010-11-02 12:26:39509 plugin_host->OpenChannelToPlugin(client);
[email protected]4befe7592011-09-14 22:49:09510 } else {
[email protected]46b69e42010-11-02 12:26:39511 client->OnError();
[email protected]4befe7592011-09-14 22:49:09512 }
initial.commit09911bf2008-07-26 23:55:29513}
514
[email protected]e67385f2011-12-21 06:00:56515bool PluginServiceImpl::GetPluginInfoArray(
[email protected]51b63f62011-10-05 18:55:42516 const GURL& url,
517 const std::string& mime_type,
518 bool allow_wildcard,
[email protected]d7bd3e52013-07-21 04:29:20519 std::vector<WebPluginInfo>* plugins,
[email protected]51b63f62011-10-05 18:55:42520 std::vector<std::string>* actual_mime_types) {
521 bool use_stale = false;
[email protected]29e2fb42013-07-19 01:13:47522 PluginList::Singleton()->GetPluginInfoArray(
[email protected]9a60ccb2013-07-19 22:23:36523 url, mime_type, allow_wildcard, &use_stale, NPAPIPluginsSupported(),
524 plugins, actual_mime_types);
[email protected]51b63f62011-10-05 18:55:42525 return use_stale;
526}
527
[email protected]e67385f2011-12-21 06:00:56528bool PluginServiceImpl::GetPluginInfo(int render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16529 int render_frame_id,
[email protected]130757672012-10-24 00:26:19530 ResourceContext* context,
[email protected]e67385f2011-12-21 06:00:56531 const GURL& url,
532 const GURL& page_url,
533 const std::string& mime_type,
534 bool allow_wildcard,
535 bool* is_stale,
[email protected]d7bd3e52013-07-21 04:29:20536 WebPluginInfo* info,
[email protected]e67385f2011-12-21 06:00:56537 std::string* actual_mime_type) {
[email protected]d7bd3e52013-07-21 04:29:20538 std::vector<WebPluginInfo> plugins;
[email protected]68598072011-07-29 08:21:28539 std::vector<std::string> mime_types;
[email protected]88ca4912011-10-12 14:00:43540 bool stale = GetPluginInfoArray(
541 url, mime_type, allow_wildcard, &plugins, &mime_types);
542 if (is_stale)
543 *is_stale = stale;
[email protected]dfba8762011-09-02 12:49:54544
[email protected]68598072011-07-29 08:21:28545 for (size_t i = 0; i < plugins.size(); ++i) {
[email protected]05f511282013-02-05 15:02:50546 if (!filter_ || filter_->IsPluginAvailable(render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16547 render_frame_id,
[email protected]05f511282013-02-05 15:02:50548 context,
549 url,
550 page_url,
551 &plugins[i])) {
[email protected]68598072011-07-29 08:21:28552 *info = plugins[i];
553 if (actual_mime_type)
554 *actual_mime_type = mime_types[i];
555 return true;
556 }
557 }
558 return false;
[email protected]6fdd4182010-10-14 23:59:26559}
560
[email protected]2dec8ec2013-02-07 19:20:34561bool PluginServiceImpl::GetPluginInfoByPath(const base::FilePath& plugin_path,
[email protected]d7bd3e52013-07-21 04:29:20562 WebPluginInfo* info) {
563 std::vector<WebPluginInfo> plugins;
[email protected]29e2fb42013-07-19 01:13:47564 PluginList::Singleton()->GetPluginsNoRefresh(&plugins);
[email protected]88ca4912011-10-12 14:00:43565
[email protected]d7bd3e52013-07-21 04:29:20566 for (std::vector<WebPluginInfo>::iterator it = plugins.begin();
[email protected]88ca4912011-10-12 14:00:43567 it != plugins.end();
568 ++it) {
569 if (it->path == plugin_path) {
570 *info = *it;
571 return true;
572 }
573 }
574
575 return false;
576}
577
[email protected]fcf75d42013-12-03 20:11:26578base::string16 PluginServiceImpl::GetPluginDisplayNameByPath(
[email protected]2dec8ec2013-02-07 19:20:34579 const base::FilePath& path) {
[email protected]fcf75d42013-12-03 20:11:26580 base::string16 plugin_name = path.LossyDisplayName();
[email protected]d7bd3e52013-07-21 04:29:20581 WebPluginInfo info;
[email protected]8be45842012-04-13 19:49:29582 if (PluginService::GetInstance()->GetPluginInfoByPath(path, &info) &&
583 !info.name.empty()) {
584 plugin_name = info.name;
585#if defined(OS_MACOSX)
586 // Many plugins on the Mac have .plugin in the actual name, which looks
587 // terrible, so look for that and strip it off if present.
588 const std::string kPluginExtension = ".plugin";
brettwa7ff1b292015-07-16 17:49:29589 if (base::EndsWith(plugin_name, base::ASCIIToUTF16(kPluginExtension),
590 base::CompareCase::SENSITIVE))
[email protected]8be45842012-04-13 19:49:29591 plugin_name.erase(plugin_name.length() - kPluginExtension.length());
592#endif // OS_MACOSX
593 }
594 return plugin_name;
595}
596
[email protected]e67385f2011-12-21 06:00:56597void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
skyostil95082a62015-06-05 19:53:07598 scoped_refptr<base::SingleThreadTaskRunner> target_task_runner(
599 base::ThreadTaskRunnerHandle::Get());
[email protected]49125952011-09-27 18:05:15600
[email protected]1b517202012-12-19 17:16:10601 if (LoadPluginListInProcess()) {
skyostil95082a62015-06-05 19:53:07602 BrowserThread::GetBlockingPool()
603 ->PostSequencedWorkerTaskWithShutdownBehavior(
604 plugin_list_token_, FROM_HERE,
[email protected]1b517202012-12-19 17:16:10605 base::Bind(&PluginServiceImpl::GetPluginsInternal,
skyostil95082a62015-06-05 19:53:07606 base::Unretained(this), target_task_runner, callback),
607 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
[email protected]1b517202012-12-19 17:16:10608 return;
609 }
610#if defined(OS_POSIX)
skyostil95082a62015-06-05 19:53:07611 BrowserThread::PostTask(
612 BrowserThread::IO, FROM_HERE,
[email protected]aa7f8802014-01-27 16:56:32613 base::Bind(&PluginServiceImpl::GetPluginsOnIOThread,
skyostil95082a62015-06-05 19:53:07614 base::Unretained(this), target_task_runner, callback));
[email protected]a33fa9d2012-05-16 14:47:49615#else
[email protected]1b517202012-12-19 17:16:10616 NOTREACHED();
[email protected]49125952011-09-27 18:05:15617#endif
[email protected]d33e7cc2011-09-23 01:43:56618}
619
[email protected]e67385f2011-12-21 06:00:56620void PluginServiceImpl::GetPluginsInternal(
skyostil95082a62015-06-05 19:53:07621 base::SingleThreadTaskRunner* target_task_runner,
622 const PluginService::GetPluginsCallback& callback) {
[email protected]a33fa9d2012-05-16 14:47:49623 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
624 plugin_list_token_));
[email protected]d33e7cc2011-09-23 01:43:56625
[email protected]d7bd3e52013-07-21 04:29:20626 std::vector<WebPluginInfo> plugins;
[email protected]9a60ccb2013-07-19 22:23:36627 PluginList::Singleton()->GetPlugins(&plugins, NPAPIPluginsSupported());
[email protected]d33e7cc2011-09-23 01:43:56628
skyostil95082a62015-06-05 19:53:07629 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins));
[email protected]dfba8762011-09-02 12:49:54630}
631
[email protected]aa7f8802014-01-27 16:56:32632#if defined(OS_POSIX)
633void PluginServiceImpl::GetPluginsOnIOThread(
skyostil95082a62015-06-05 19:53:07634 base::SingleThreadTaskRunner* target_task_runner,
[email protected]aa7f8802014-01-27 16:56:32635 const GetPluginsCallback& callback) {
mostynb4c27d042015-03-18 21:47:47636 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]aa7f8802014-01-27 16:56:32637
638 // If we switch back to loading plugins in process, then we need to make
639 // sure g_thread_init() gets called since plugins may call glib at load.
640
dcheng54c3719d2014-08-26 21:52:56641 if (!plugin_loader_.get())
[email protected]aa7f8802014-01-27 16:56:32642 plugin_loader_ = new PluginLoaderPosix;
643
skyostil95082a62015-06-05 19:53:07644 plugin_loader_->GetPlugins(base::Bind(
645 &ForwardCallback, make_scoped_refptr(target_task_runner), callback));
[email protected]aa7f8802014-01-27 16:56:32646}
647#endif
648
[email protected]b547fd42009-04-23 23:16:27649#if defined(OS_WIN)
rvargas6f315b82014-10-17 01:28:58650void PluginServiceImpl::OnKeyChanged(base::win::RegKey* key) {
651 key->StartWatching(base::Bind(&PluginServiceImpl::OnKeyChanged,
652 base::Unretained(this),
rvargasb8056152014-11-08 01:44:28653 base::Unretained(key)));
[email protected]b547fd42009-04-23 23:16:27654
[email protected]29e2fb42013-07-19 01:13:47655 PluginList::Singleton()->RefreshPlugins();
[email protected]45a22e62011-10-12 09:48:02656 PurgePluginListCache(NULL, false);
dcheng4fe6ccad2014-10-16 03:09:26657}
rvargas6f315b82014-10-17 01:28:58658#endif // defined(OS_WIN)
[email protected]894bb502009-05-21 22:39:57659
[email protected]e67385f2011-12-21 06:00:56660void PluginServiceImpl::RegisterPepperPlugins() {
[email protected]dac6a5a2013-07-25 05:06:48661 ComputePepperPluginList(&ppapi_plugins_);
[email protected]a08ebea2011-02-13 17:50:20662 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]c6f3dea2012-01-14 02:23:11663 RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo(), true);
[email protected]4e0616e2010-05-28 14:55:53664 }
665}
[email protected]634d23d2011-01-19 10:38:19666
[email protected]eb415bf0e2011-04-14 02:45:42667// There should generally be very few plugins so a brute-force search is fine.
[email protected]130757672012-10-24 00:26:19668PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
[email protected]2dec8ec2013-02-07 19:20:34669 const base::FilePath& plugin_path) {
[email protected]130757672012-10-24 00:26:19670 PepperPluginInfo* info = NULL;
[email protected]3627aa3f2013-09-17 22:32:51671 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]6b14feb2011-08-16 11:22:56672 if (ppapi_plugins_[i].path == plugin_path) {
673 info = &ppapi_plugins_[i];
674 break;
675 }
[email protected]eb415bf0e2011-04-14 02:45:42676 }
[email protected]076117592011-08-17 03:16:41677 if (info)
678 return info;
679 // We did not find the plugin in our list. But wait! the plugin can also
680 // be a latecomer, as it happens with pepper flash. This information
681 // can be obtained from the PluginList singleton and we can use it to
682 // construct it and add it to the list. This same deal needs to be done
683 // in the renderer side in PepperPluginRegistry.
[email protected]d7bd3e52013-07-21 04:29:20684 WebPluginInfo webplugin_info;
[email protected]88ca4912011-10-12 14:00:43685 if (!GetPluginInfoByPath(plugin_path, &webplugin_info))
[email protected]076117592011-08-17 03:16:41686 return NULL;
[email protected]130757672012-10-24 00:26:19687 PepperPluginInfo new_pepper_info;
[email protected]076117592011-08-17 03:16:41688 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
689 return NULL;
690 ppapi_plugins_.push_back(new_pepper_info);
691 return &ppapi_plugins_[ppapi_plugins_.size() - 1];
[email protected]eb415bf0e2011-04-14 02:45:42692}
693
[email protected]52348b22012-11-07 10:19:34694#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19695// static
[email protected]07b71c82013-01-08 19:07:31696void PluginServiceImpl::RegisterFilePathWatcher(FilePathWatcher* watcher,
[email protected]2dec8ec2013-02-07 19:20:34697 const base::FilePath& path) {
[email protected]07b71c82013-01-08 19:07:31698 bool result = watcher->Watch(path, false,
699 base::Bind(&NotifyPluginDirChanged));
[email protected]634d23d2011-01-19 10:38:19700 DCHECK(result);
701}
702#endif
[email protected]f520b5b2011-11-08 02:42:14703
[email protected]130757672012-10-24 00:26:19704void PluginServiceImpl::SetFilter(PluginServiceFilter* filter) {
[email protected]3a5180ae2011-12-21 02:39:38705 filter_ = filter;
706}
707
[email protected]130757672012-10-24 00:26:19708PluginServiceFilter* PluginServiceImpl::GetFilter() {
[email protected]3a5180ae2011-12-21 02:39:38709 return filter_;
710}
711
[email protected]2dec8ec2013-02-07 19:20:34712void PluginServiceImpl::ForcePluginShutdown(const base::FilePath& plugin_path) {
[email protected]b6a2f8de2012-01-31 17:28:49713 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
714 BrowserThread::PostTask(
715 BrowserThread::IO, FROM_HERE,
716 base::Bind(&PluginServiceImpl::ForcePluginShutdown,
717 base::Unretained(this), plugin_path));
718 return;
719 }
720
721 PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path);
722 if (plugin)
723 plugin->ForceShutdown();
724}
725
[email protected]47214d882012-02-29 06:28:48726static const unsigned int kMaxCrashesPerInterval = 3;
727static const unsigned int kCrashesInterval = 120;
728
[email protected]2dec8ec2013-02-07 19:20:34729void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) {
mostynb4c27d042015-03-18 21:47:47730 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]2dec8ec2013-02-07 19:20:34731 std::map<base::FilePath, std::vector<base::Time> >::iterator i =
[email protected]47214d882012-02-29 06:28:48732 crash_times_.find(path);
733 if (i == crash_times_.end()) {
734 crash_times_[path] = std::vector<base::Time>();
735 i = crash_times_.find(path);
736 }
737 if (i->second.size() == kMaxCrashesPerInterval) {
738 i->second.erase(i->second.begin());
739 }
740 base::Time time = base::Time::Now();
741 i->second.push_back(time);
742}
743
[email protected]2dec8ec2013-02-07 19:20:34744bool PluginServiceImpl::IsPluginUnstable(const base::FilePath& path) {
mostynb4c27d042015-03-18 21:47:47745 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]2dec8ec2013-02-07 19:20:34746 std::map<base::FilePath, std::vector<base::Time> >::const_iterator i =
[email protected]47214d882012-02-29 06:28:48747 crash_times_.find(path);
748 if (i == crash_times_.end()) {
749 return false;
750 }
751 if (i->second.size() != kMaxCrashesPerInterval) {
752 return false;
753 }
754 base::TimeDelta delta = base::Time::Now() - i->second[0];
[email protected]d8c70062013-04-24 00:22:34755 return delta.InSeconds() <= kCrashesInterval;
[email protected]47214d882012-02-29 06:28:48756}
757
[email protected]e67385f2011-12-21 06:00:56758void PluginServiceImpl::RefreshPlugins() {
[email protected]29e2fb42013-07-19 01:13:47759 PluginList::Singleton()->RefreshPlugins();
[email protected]f520b5b2011-11-08 02:42:14760}
761
[email protected]2dec8ec2013-02-07 19:20:34762void PluginServiceImpl::AddExtraPluginPath(const base::FilePath& path) {
[email protected]a01c8c8f2014-05-09 17:24:53763 if (!NPAPIPluginsSupported()) {
[email protected]9a60ccb2013-07-19 22:23:36764 // TODO(jam): remove and just have CHECK once we're sure this doesn't get
765 // triggered.
[email protected]efde84b02013-11-23 04:18:20766 DVLOG(0) << "NPAPI plugins not supported";
[email protected]9a60ccb2013-07-19 22:23:36767 return;
768 }
[email protected]29e2fb42013-07-19 01:13:47769 PluginList::Singleton()->AddExtraPluginPath(path);
[email protected]c6f3dea2012-01-14 02:23:11770}
771
[email protected]2dec8ec2013-02-07 19:20:34772void PluginServiceImpl::RemoveExtraPluginPath(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47773 PluginList::Singleton()->RemoveExtraPluginPath(path);
[email protected]8f3372122013-07-18 04:34:14774}
775
776void PluginServiceImpl::AddExtraPluginDir(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47777 PluginList::Singleton()->AddExtraPluginDir(path);
[email protected]8f3372122013-07-18 04:34:14778}
779
780void PluginServiceImpl::RegisterInternalPlugin(
[email protected]d7bd3e52013-07-21 04:29:20781 const WebPluginInfo& info,
[email protected]8f3372122013-07-18 04:34:14782 bool add_at_beginning) {
wfha79d1022015-02-20 16:13:13783 // Internal plugins should never be NPAPI.
784 CHECK_NE(info.type, WebPluginInfo::PLUGIN_TYPE_NPAPI);
785 if (info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
[email protected]efde84b02013-11-23 04:18:20786 DVLOG(0) << "Don't register NPAPI plugins when they're not supported";
[email protected]9a60ccb2013-07-19 22:23:36787 return;
788 }
[email protected]29e2fb42013-07-19 01:13:47789 PluginList::Singleton()->RegisterInternalPlugin(info, add_at_beginning);
[email protected]f520b5b2011-11-08 02:42:14790}
791
[email protected]2dec8ec2013-02-07 19:20:34792void PluginServiceImpl::UnregisterInternalPlugin(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47793 PluginList::Singleton()->UnregisterInternalPlugin(path);
[email protected]f520b5b2011-11-08 02:42:14794}
795
[email protected]8f3372122013-07-18 04:34:14796void PluginServiceImpl::GetInternalPlugins(
[email protected]d7bd3e52013-07-21 04:29:20797 std::vector<WebPluginInfo>* plugins) {
[email protected]29e2fb42013-07-19 01:13:47798 PluginList::Singleton()->GetInternalPlugins(plugins);
[email protected]8f3372122013-07-18 04:34:14799}
800
[email protected]9a60ccb2013-07-19 22:23:36801bool PluginServiceImpl::NPAPIPluginsSupported() {
wfha79d1022015-02-20 16:13:13802#if defined(OS_WIN) || defined(OS_MACOSX)
wfh6be06282015-07-20 18:04:02803 npapi_plugins_enabled_ = GetContentClient()->browser()->IsNPAPIEnabled();
wfhad38f5a32015-06-03 17:11:07804#if defined(OS_WIN)
wfh6be06282015-07-20 18:04:02805 // NPAPI plugins don't play well with Win32k renderer lockdown.
806 if (npapi_plugins_enabled_)
807 DisableWin32kRendererLockdown();
wfhad38f5a32015-06-03 17:11:07808#endif
wfh6be06282015-07-20 18:04:02809 NPAPIPluginStatus status =
810 npapi_plugins_enabled_ ? NPAPI_STATUS_ENABLED : NPAPI_STATUS_DISABLED;
wfha79d1022015-02-20 16:13:13811#else
wfh6be06282015-07-20 18:04:02812 NPAPIPluginStatus status = NPAPI_STATUS_UNSUPPORTED;
wfha79d1022015-02-20 16:13:13813#endif
wfh6be06282015-07-20 18:04:02814 UMA_HISTOGRAM_ENUMERATION("Plugin.NPAPIStatus", status,
815 NPAPI_STATUS_ENUM_COUNT);
wfha79d1022015-02-20 16:13:13816
wfh0539f2f52015-01-21 14:36:46817 return npapi_plugins_enabled_;
[email protected]9a60ccb2013-07-19 22:23:36818}
819
[email protected]8f3372122013-07-18 04:34:14820void PluginServiceImpl::DisablePluginsDiscoveryForTesting() {
[email protected]29e2fb42013-07-19 01:13:47821 PluginList::Singleton()->DisablePluginsDiscovery();
[email protected]ee066172011-11-10 23:20:05822}
823
[email protected]5904cb42012-09-24 15:05:20824#if defined(OS_MACOSX)
825void PluginServiceImpl::AppActivated() {
826 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]07b71c82013-01-08 19:07:31827 base::Bind(&NotifyPluginsOfActivation));
[email protected]5904cb42012-09-24 15:05:20828}
[email protected]9a60ccb2013-07-19 22:23:36829#elif defined(OS_WIN)
830
831bool GetPluginPropertyFromWindow(
832 HWND window, const wchar_t* plugin_atom_property,
833 base::string16* plugin_property) {
scottmg4800fc22015-04-29 00:31:20834 ATOM plugin_atom = static_cast<ATOM>(
835 reinterpret_cast<uintptr_t>(GetPropW(window, plugin_atom_property)));
[email protected]9a60ccb2013-07-19 22:23:36836 if (plugin_atom != 0) {
837 WCHAR plugin_property_local[MAX_PATH] = {0};
838 GlobalGetAtomNameW(plugin_atom,
839 plugin_property_local,
840 ARRAYSIZE(plugin_property_local));
841 *plugin_property = plugin_property_local;
842 return true;
843 }
844 return false;
845}
846
847bool PluginServiceImpl::GetPluginInfoFromWindow(
848 HWND window,
849 base::string16* plugin_name,
850 base::string16* plugin_version) {
851 if (!IsPluginWindow(window))
852 return false;
853
jam3458fc002014-09-10 03:21:41854
855 DWORD process_id = 0;
856 GetWindowThreadProcessId(window, &process_id);
857 WebPluginInfo info;
858 if (!PluginProcessHost::GetWebPluginInfoFromPluginPid(process_id, &info))
859 return false;
860
861 *plugin_name = info.name;
862 *plugin_version = info.version;
[email protected]9a60ccb2013-07-19 22:23:36863 return true;
864}
865
866bool PluginServiceImpl::IsPluginWindow(HWND window) {
[email protected]bde885b2013-09-12 20:55:53867 return gfx::GetClassName(window) == base::string16(kNativeWindowClassName);
[email protected]9a60ccb2013-07-19 22:23:36868}
[email protected]5904cb42012-09-24 15:05:20869#endif
870
[email protected]aec5ed52014-06-20 07:51:42871bool PluginServiceImpl::PpapiDevChannelSupported(
872 BrowserContext* browser_context,
873 const GURL& document_url) {
wfh6be06282015-07-20 18:04:02874 return GetContentClient()->browser()->IsPluginAllowedToUseDevChannelAPIs(
875 browser_context, document_url);
[email protected]8ddc6b7c2013-12-12 20:42:06876}
877
[email protected]130757672012-10-24 00:26:19878} // namespace content