blob: 678171c753277165437a7db22213fc1c515cd3dc [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
[email protected]07b71c82013-01-08 19:07:31110#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]2dec8ec2013-02-07 19:20:34111void NotifyPluginDirChanged(const base::FilePath& path, bool error) {
[email protected]07b71c82013-01-08 19:07:31112 if (error) {
[email protected]634d23d2011-01-19 10:38:19113 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
114 // stopping the watcher would be enough. Or possibly restart it.
115 NOTREACHED();
[email protected]07b71c82013-01-08 19:07:31116 return;
[email protected]634d23d2011-01-19 10:38:19117 }
[email protected]07b71c82013-01-08 19:07:31118 VLOG(1) << "Watched path changed: " << path.value();
119 // Make the plugin list update itself
[email protected]29e2fb42013-07-19 01:13:47120 PluginList::Singleton()->RefreshPlugins();
[email protected]07b71c82013-01-08 19:07:31121 BrowserThread::PostTask(
122 BrowserThread::UI, FROM_HERE,
123 base::Bind(&PluginService::PurgePluginListCache,
124 static_cast<BrowserContext*>(NULL), false));
125}
[email protected]634d23d2011-01-19 10:38:19126#endif
127
skyostil95082a62015-06-05 19:53:07128void ForwardCallback(base::SingleThreadTaskRunner* target_task_runner,
[email protected]aa7f8802014-01-27 16:56:32129 const PluginService::GetPluginsCallback& callback,
130 const std::vector<WebPluginInfo>& plugins) {
skyostil95082a62015-06-05 19:53:07131 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins));
[email protected]aa7f8802014-01-27 16:56:32132}
133
[email protected]07b71c82013-01-08 19:07:31134} // namespace
135
[email protected]3a5180ae2011-12-21 02:39:38136// static
137PluginService* PluginService::GetInstance() {
[email protected]e67385f2011-12-21 06:00:56138 return PluginServiceImpl::GetInstance();
[email protected]3a5180ae2011-12-21 02:39:38139}
140
141void PluginService::PurgePluginListCache(BrowserContext* browser_context,
142 bool reload_pages) {
143 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
144 !it.IsAtEnd(); it.Advance()) {
145 RenderProcessHost* host = it.GetCurrentValue();
146 if (!browser_context || host->GetBrowserContext() == browser_context)
147 host->Send(new ViewMsg_PurgePluginListCache(reload_pages));
148 }
149}
150
initial.commit09911bf2008-07-26 23:55:29151// static
[email protected]e67385f2011-12-21 06:00:56152PluginServiceImpl* PluginServiceImpl::GetInstance() {
153 return Singleton<PluginServiceImpl>::get();
initial.commit09911bf2008-07-26 23:55:29154}
155
[email protected]e67385f2011-12-21 06:00:56156PluginServiceImpl::PluginServiceImpl()
wfh0539f2f52015-01-21 14:36:46157 : npapi_plugins_enabled_(false), filter_(NULL) {
[email protected]fd8d8d6c2013-02-28 02:48:33158 // Collect the total number of browser processes (which create
159 // PluginServiceImpl objects, to be precise). The number is used to normalize
160 // the number of processes which start at least one NPAPI/PPAPI Flash process.
161 static bool counted = false;
162 if (!counted) {
163 counted = true;
164 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage", TOTAL_BROWSER_PROCESSES,
165 FLASH_USAGE_ENUM_COUNT);
166 }
[email protected]ee066172011-11-10 23:20:05167}
168
[email protected]e67385f2011-12-21 06:00:56169PluginServiceImpl::~PluginServiceImpl() {
[email protected]ee066172011-11-10 23:20:05170 // Make sure no plugin channel requests have been leaked.
171 DCHECK(pending_plugin_clients_.empty());
172}
173
[email protected]e67385f2011-12-21 06:00:56174void PluginServiceImpl::Init() {
[email protected]a33fa9d2012-05-16 14:47:49175 plugin_list_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken();
[email protected]29e2fb42013-07-19 01:13:47176 PluginList::Singleton()->set_will_load_plugins_callback(
[email protected]1b517202012-12-19 17:16:10177 base::Bind(&WillLoadPluginsCallback, plugin_list_token_));
[email protected]49125952011-09-27 18:05:15178
[email protected]4e0616e2010-05-28 14:55:53179 RegisterPepperPlugins();
180
[email protected]9a1c4262010-06-29 21:50:27181 // Load any specified on the command line as well.
[email protected]479278702014-08-11 20:32:09182 const base::CommandLine* command_line =
183 base::CommandLine::ForCurrentProcess();
[email protected]2dec8ec2013-02-07 19:20:34184 base::FilePath path =
185 command_line->GetSwitchValuePath(switches::kLoadPlugin);
[email protected]7bf795d92010-05-22 00:14:28186 if (!path.empty())
[email protected]f520b5b2011-11-08 02:42:14187 AddExtraPluginPath(path);
[email protected]9a1c4262010-06-29 21:50:27188 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
189 if (!path.empty())
[email protected]29e2fb42013-07-19 01:13:47190 PluginList::Singleton()->AddExtraPluginDir(path);
[email protected]e87ce862013-06-12 17:30:48191
192 if (command_line->HasSwitch(switches::kDisablePluginsDiscovery))
[email protected]29e2fb42013-07-19 01:13:47193 PluginList::Singleton()->DisablePluginsDiscovery();
[email protected]dfba8762011-09-02 12:49:54194}
195
[email protected]e67385f2011-12-21 06:00:56196void PluginServiceImpl::StartWatchingPlugins() {
[email protected]634d23d2011-01-19 10:38:19197 // Start watching for changes in the plugin list. This means watching
198 // for changes in the Windows registry keys and on both Windows and POSIX
199 // watch for changes in the paths that are expected to contain plugins.
[email protected]b547fd42009-04-23 23:16:27200#if defined(OS_WIN)
[email protected]86ec4f6e2011-04-20 16:21:19201 if (hkcu_key_.Create(HKEY_CURRENT_USER,
[email protected]29e2fb42013-07-19 01:13:47202 kRegistryMozillaPlugins,
[email protected]86ec4f6e2011-04-20 16:21:19203 KEY_NOTIFY) == ERROR_SUCCESS) {
rvargas6f315b82014-10-17 01:28:58204 base::win::RegKey::ChangeCallback callback =
205 base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
206 base::Unretained(&hkcu_key_));
207 hkcu_key_.StartWatching(callback);
[email protected]b547fd42009-04-23 23:16:27208 }
[email protected]86ec4f6e2011-04-20 16:21:19209 if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
[email protected]29e2fb42013-07-19 01:13:47210 kRegistryMozillaPlugins,
[email protected]86ec4f6e2011-04-20 16:21:19211 KEY_NOTIFY) == ERROR_SUCCESS) {
rvargas6f315b82014-10-17 01:28:58212 base::win::RegKey::ChangeCallback callback =
213 base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
rvargasb8056152014-11-08 01:44:28214 base::Unretained(&hklm_key_));
rvargas6f315b82014-10-17 01:28:58215 hklm_key_.StartWatching(callback);
[email protected]b547fd42009-04-23 23:16:27216 }
[email protected]a33fa9d2012-05-16 14:47:49217#endif
[email protected]52348b22012-11-07 10:19:34218#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19219// On ChromeOS the user can't install plugins anyway and on Windows all
220// important plugins register themselves in the registry so no need to do that.
[email protected]07b71c82013-01-08 19:07:31221
[email protected]634d23d2011-01-19 10:38:19222 // Get the list of all paths for registering the FilePathWatchers
223 // that will track and if needed reload the list of plugins on runtime.
[email protected]2dec8ec2013-02-07 19:20:34224 std::vector<base::FilePath> plugin_dirs;
[email protected]29e2fb42013-07-19 01:13:47225 PluginList::Singleton()->GetPluginDirectories(&plugin_dirs);
[email protected]894bb502009-05-21 22:39:57226
[email protected]634d23d2011-01-19 10:38:19227 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
[email protected]634d23d2011-01-19 10:38:19228 // FilePathWatcher can not handle non-absolute paths under windows.
229 // We don't watch for file changes in windows now but if this should ever
230 // be extended to Windows these lines might save some time of debugging.
231#if defined(OS_WIN)
232 if (!plugin_dirs[i].IsAbsolute())
233 continue;
234#endif
[email protected]493c8002011-04-14 16:56:01235 FilePathWatcher* watcher = new FilePathWatcher();
[email protected]634d23d2011-01-19 10:38:19236 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
237 BrowserThread::PostTask(
238 BrowserThread::FILE, FROM_HERE,
[email protected]e67385f2011-12-21 06:00:56239 base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
[email protected]07b71c82013-01-08 19:07:31240 plugin_dirs[i]));
[email protected]634d23d2011-01-19 10:38:19241 file_watchers_.push_back(watcher);
242 }
243#endif
initial.commit09911bf2008-07-26 23:55:29244}
245
[email protected]e67385f2011-12-21 06:00:56246PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
[email protected]2dec8ec2013-02-07 19:20:34247 const base::FilePath& plugin_path) {
[email protected]4967f792012-01-20 22:14:40248 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
249 if (iter->info().path == plugin_path)
250 return *iter;
[email protected]a436d922009-02-13 23:16:42251 }
252
initial.commit09911bf2008-07-26 23:55:29253 return NULL;
254}
255
[email protected]e67385f2011-12-21 06:00:56256PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
[email protected]2dec8ec2013-02-07 19:20:34257 const base::FilePath& plugin_path,
258 const base::FilePath& profile_data_directory) {
[email protected]4967f792012-01-20 22:14:40259 for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]dd9a0952012-05-31 20:11:31260 if (iter->plugin_path() == plugin_path &&
261 iter->profile_data_directory() == profile_data_directory) {
[email protected]4967f792012-01-20 22:14:40262 return *iter;
[email protected]dd9a0952012-05-31 20:11:31263 }
[email protected]a08ebea2011-02-13 17:50:20264 }
[email protected]a08ebea2011-02-13 17:50:20265 return NULL;
266}
267
[email protected]e67385f2011-12-21 06:00:56268PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
[email protected]2dec8ec2013-02-07 19:20:34269 const base::FilePath& broker_path) {
[email protected]4967f792012-01-20 22:14:40270 for (PpapiBrokerProcessHostIterator iter; !iter.Done(); ++iter) {
271 if (iter->plugin_path() == broker_path)
272 return *iter;
[email protected]eb415bf0e2011-04-14 02:45:42273 }
274
275 return NULL;
276}
277
[email protected]e67385f2011-12-21 06:00:56278PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54279 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34280 const base::FilePath& plugin_path) {
mostynb4c27d042015-03-18 21:47:47281 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]a08ebea2011-02-13 17:50:20282
[email protected]6be31d202013-02-01 18:20:54283 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
284 return NULL;
285
[email protected]a08ebea2011-02-13 17:50:20286 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
initial.commit09911bf2008-07-26 23:55:29287 if (plugin_host)
288 return plugin_host;
289
[email protected]d7bd3e52013-07-21 04:29:20290 WebPluginInfo info;
[email protected]88ca4912011-10-12 14:00:43291 if (!GetPluginInfoByPath(plugin_path, &info)) {
[email protected]a27a9382009-02-11 23:55:10292 return NULL;
293 }
294
[email protected]fd8d8d6c2013-02-28 02:48:33295 // Record when NPAPI Flash process is started for the first time.
296 static bool counted = false;
[email protected]32956122013-12-25 07:29:24297 if (!counted && base::UTF16ToUTF8(info.name) == kFlashPluginName) {
[email protected]fd8d8d6c2013-02-28 02:48:33298 counted = true;
299 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
300 START_NPAPI_FLASH_AT_LEAST_ONCE,
301 FLASH_USAGE_ENUM_COUNT);
302 }
[email protected]132bca82013-12-10 09:14:47303#if defined(OS_CHROMEOS)
304 // TODO(ihf): Move to an earlier place once crbug.com/314301 is fixed. For now
305 // we still want Plugin.FlashUsage recorded if we end up here.
306 LOG(WARNING) << "Refusing to start npapi plugin on ChromeOS.";
307 return NULL;
308#endif
initial.commit09911bf2008-07-26 23:55:29309 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]8b8a554d2010-11-18 13:26:40310 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
[email protected]99907362012-01-11 05:41:40311 if (!new_host->Init(info)) {
[email protected]a08ebea2011-02-13 17:50:20312 NOTREACHED(); // Init is not expected to fail.
initial.commit09911bf2008-07-26 23:55:29313 return NULL;
314 }
[email protected]8b8a554d2010-11-18 13:26:40315 return new_host.release();
initial.commit09911bf2008-07-26 23:55:29316}
317
[email protected]e67385f2011-12-21 06:00:56318PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54319 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34320 const base::FilePath& plugin_path,
[email protected]8522332e2013-08-28 19:42:59321 const base::FilePath& profile_data_directory) {
mostynb4c27d042015-03-18 21:47:47322 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]a08ebea2011-02-13 17:50:20323
[email protected]132bca82013-12-10 09:14:47324 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) {
325 VLOG(1) << "Unable to load ppapi plugin: " << plugin_path.MaybeAsASCII();
[email protected]6be31d202013-02-01 18:20:54326 return NULL;
[email protected]132bca82013-12-10 09:14:47327 }
[email protected]6be31d202013-02-01 18:20:54328
[email protected]dd9a0952012-05-31 20:11:31329 PpapiPluginProcessHost* plugin_host =
330 FindPpapiPluginProcess(plugin_path, profile_data_directory);
[email protected]a08ebea2011-02-13 17:50:20331 if (plugin_host)
332 return plugin_host;
333
[email protected]eb415bf0e2011-04-14 02:45:42334 // Validate that the plugin is actually registered.
[email protected]130757672012-10-24 00:26:19335 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]132bca82013-12-10 09:14:47336 if (!info) {
337 VLOG(1) << "Unable to find ppapi plugin registration for: "
338 << plugin_path.MaybeAsASCII();
[email protected]a08ebea2011-02-13 17:50:20339 return NULL;
[email protected]132bca82013-12-10 09:14:47340 }
[email protected]a08ebea2011-02-13 17:50:20341
[email protected]fd8d8d6c2013-02-28 02:48:33342 // Record when PPAPI Flash process is started for the first time.
343 static bool counted = false;
344 if (!counted && info->name == kFlashPluginName) {
345 counted = true;
346 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
347 START_PPAPI_FLASH_AT_LEAST_ONCE,
348 FLASH_USAGE_ENUM_COUNT);
349 }
350
[email protected]a08ebea2011-02-13 17:50:20351 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]132bca82013-12-10 09:14:47352 plugin_host = PpapiPluginProcessHost::CreatePluginHost(
[email protected]8522332e2013-08-28 19:42:59353 *info, profile_data_directory);
[email protected]132bca82013-12-10 09:14:47354 if (!plugin_host) {
355 VLOG(1) << "Unable to create ppapi plugin process for: "
356 << plugin_path.MaybeAsASCII();
357 }
358
359 return plugin_host;
[email protected]a08ebea2011-02-13 17:50:20360}
361
[email protected]e67385f2011-12-21 06:00:56362PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
[email protected]6be31d202013-02-01 18:20:54363 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34364 const base::FilePath& plugin_path) {
mostynb4c27d042015-03-18 21:47:47365 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]eb415bf0e2011-04-14 02:45:42366
[email protected]6be31d202013-02-01 18:20:54367 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
368 return NULL;
369
[email protected]a50432d2011-09-30 16:32:14370 PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42371 if (plugin_host)
372 return plugin_host;
373
374 // Validate that the plugin is actually registered.
[email protected]130757672012-10-24 00:26:19375 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42376 if (!info)
377 return NULL;
378
379 // TODO(ddorwin): Uncomment once out of process is supported.
380 // DCHECK(info->is_out_of_process);
381
382 // This broker isn't loaded by any broker process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14383 return PpapiPluginProcessHost::CreateBrokerHost(*info);
[email protected]eb415bf0e2011-04-14 02:45:42384}
385
[email protected]e67385f2011-12-21 06:00:56386void PluginServiceImpl::OpenChannelToNpapiPlugin(
[email protected]c8f73ab2011-01-22 00:05:17387 int render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16388 int render_frame_id,
[email protected]610c0892009-09-08 19:46:18389 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54390 const GURL& page_url,
[email protected]610c0892009-09-08 19:46:18391 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39392 PluginProcessHost::Client* client) {
mostynb4c27d042015-03-18 21:47:47393 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4befe7592011-09-14 22:49:09394 DCHECK(!ContainsKey(pending_plugin_clients_, client));
395 pending_plugin_clients_.insert(client);
[email protected]88ca4912011-10-12 14:00:43396
397 // Make sure plugins are loaded if necessary.
[email protected]209f2ae2012-03-13 01:28:08398 PluginServiceFilterParams params = {
[email protected]88ca4912011-10-12 14:00:43399 render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16400 render_frame_id,
[email protected]88ca4912011-10-12 14:00:43401 page_url,
[email protected]df02aca2012-02-09 21:03:20402 client->GetResourceContext()
[email protected]88ca4912011-10-12 14:00:43403 };
[email protected]e67385f2011-12-21 06:00:56404 GetPlugins(base::Bind(
405 &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
406 base::Unretained(this), params, url, mime_type, client));
[email protected]6fdd4182010-10-14 23:59:26407}
408
[email protected]e67385f2011-12-21 06:00:56409void PluginServiceImpl::OpenChannelToPpapiPlugin(
[email protected]6be31d202013-02-01 18:20:54410 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34411 const base::FilePath& plugin_path,
412 const base::FilePath& profile_data_directory,
[email protected]a50432d2011-09-30 16:32:14413 PpapiPluginProcessHost::PluginClient* client) {
[email protected]d259a8e2011-05-18 22:31:09414 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
[email protected]8522332e2013-08-28 19:42:59415 render_process_id, plugin_path, profile_data_directory);
[email protected]1bf0fb22012-04-12 21:44:16416 if (plugin_host) {
[email protected]a08ebea2011-02-13 17:50:20417 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16418 } else {
419 // Send error.
[email protected]108fd342013-01-04 20:46:54420 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
[email protected]1bf0fb22012-04-12 21:44:16421 }
[email protected]a08ebea2011-02-13 17:50:20422}
423
[email protected]e67385f2011-12-21 06:00:56424void PluginServiceImpl::OpenChannelToPpapiBroker(
[email protected]6be31d202013-02-01 18:20:54425 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34426 const base::FilePath& path,
[email protected]a50432d2011-09-30 16:32:14427 PpapiPluginProcessHost::BrokerClient* client) {
[email protected]6be31d202013-02-01 18:20:54428 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(
429 render_process_id, path);
[email protected]1bf0fb22012-04-12 21:44:16430 if (plugin_host) {
[email protected]a50432d2011-09-30 16:32:14431 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16432 } else {
433 // Send error.
[email protected]108fd342013-01-04 20:46:54434 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
[email protected]1bf0fb22012-04-12 21:44:16435 }
[email protected]eb415bf0e2011-04-14 02:45:42436}
437
[email protected]e67385f2011-12-21 06:00:56438void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
[email protected]4befe7592011-09-14 22:49:09439 PluginProcessHost::Client* client) {
mostynb4c27d042015-03-18 21:47:47440 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]4befe7592011-09-14 22:49:09441 DCHECK(ContainsKey(pending_plugin_clients_, client));
442 pending_plugin_clients_.erase(client);
443}
444
[email protected]e67385f2011-12-21 06:00:56445void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
[email protected]209f2ae2012-03-13 01:28:08446 const PluginServiceFilterParams& params,
[email protected]88ca4912011-10-12 14:00:43447 const GURL& url,
448 const std::string& mime_type,
449 PluginProcessHost::Client* client,
[email protected]d7bd3e52013-07-21 04:29:20450 const std::vector<WebPluginInfo>&) {
[email protected]60eca4eb2013-12-06 00:02:16451 GetAllowedPluginForOpenChannelToPlugin(
452 params.render_process_id, params.render_frame_id, url, params.page_url,
453 mime_type, client, params.resource_context);
[email protected]88ca4912011-10-12 14:00:43454}
455
[email protected]e67385f2011-12-21 06:00:56456void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
[email protected]c8f73ab2011-01-22 00:05:17457 int render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16458 int render_frame_id,
[email protected]6fdd4182010-10-14 23:59:26459 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54460 const GURL& page_url,
[email protected]6fdd4182010-10-14 23:59:26461 const std::string& mime_type,
[email protected]87c4be42011-09-16 01:10:59462 PluginProcessHost::Client* client,
[email protected]130757672012-10-24 00:26:19463 ResourceContext* resource_context) {
[email protected]d7bd3e52013-07-21 04:29:20464 WebPluginInfo info;
[email protected]dfba8762011-09-02 12:49:54465 bool allow_wildcard = true;
[email protected]11e1c182011-05-17 20:26:27466 bool found = GetPluginInfo(
[email protected]60eca4eb2013-12-06 00:02:16467 render_process_id, render_frame_id, resource_context,
[email protected]dfba8762011-09-02 12:49:54468 url, page_url, mime_type, allow_wildcard,
469 NULL, &info, NULL);
[email protected]2dec8ec2013-02-07 19:20:34470 base::FilePath plugin_path;
[email protected]68598072011-07-29 08:21:28471 if (found)
[email protected]dfba8762011-09-02 12:49:54472 plugin_path = info.path;
[email protected]6fdd4182010-10-14 23:59:26473
474 // Now we jump back to the IO thread to finish opening the channel.
[email protected]e67385f2011-12-21 06:00:56475 BrowserThread::PostTask(
476 BrowserThread::IO, FROM_HERE,
477 base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
[email protected]6be31d202013-02-01 18:20:54478 base::Unretained(this),
479 render_process_id,
480 plugin_path,
481 client));
wfh30443502015-05-01 21:58:30482 if (filter_) {
483 DCHECK_EQ(WebPluginInfo::PLUGIN_TYPE_NPAPI, info.type);
wfhec1f7352015-05-07 23:44:54484 filter_->NPAPIPluginLoaded(render_process_id, render_frame_id, mime_type,
485 info);
wfh30443502015-05-01 21:58:30486 }
[email protected]6fdd4182010-10-14 23:59:26487}
488
[email protected]e67385f2011-12-21 06:00:56489void PluginServiceImpl::FinishOpenChannelToPlugin(
[email protected]6be31d202013-02-01 18:20:54490 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34491 const base::FilePath& plugin_path,
[email protected]46b69e42010-11-02 12:26:39492 PluginProcessHost::Client* client) {
mostynb4c27d042015-03-18 21:47:47493 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]20a793e2010-10-12 06:50:08494
[email protected]4befe7592011-09-14 22:49:09495 // Make sure it hasn't been canceled yet.
496 if (!ContainsKey(pending_plugin_clients_, client))
497 return;
498 pending_plugin_clients_.erase(client);
499
[email protected]6be31d202013-02-01 18:20:54500 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(
501 render_process_id, plugin_path);
[email protected]4befe7592011-09-14 22:49:09502 if (plugin_host) {
503 client->OnFoundPluginProcessHost(plugin_host);
[email protected]46b69e42010-11-02 12:26:39504 plugin_host->OpenChannelToPlugin(client);
[email protected]4befe7592011-09-14 22:49:09505 } else {
[email protected]46b69e42010-11-02 12:26:39506 client->OnError();
[email protected]4befe7592011-09-14 22:49:09507 }
initial.commit09911bf2008-07-26 23:55:29508}
509
[email protected]e67385f2011-12-21 06:00:56510bool PluginServiceImpl::GetPluginInfoArray(
[email protected]51b63f62011-10-05 18:55:42511 const GURL& url,
512 const std::string& mime_type,
513 bool allow_wildcard,
[email protected]d7bd3e52013-07-21 04:29:20514 std::vector<WebPluginInfo>* plugins,
[email protected]51b63f62011-10-05 18:55:42515 std::vector<std::string>* actual_mime_types) {
516 bool use_stale = false;
[email protected]29e2fb42013-07-19 01:13:47517 PluginList::Singleton()->GetPluginInfoArray(
[email protected]9a60ccb2013-07-19 22:23:36518 url, mime_type, allow_wildcard, &use_stale, NPAPIPluginsSupported(),
519 plugins, actual_mime_types);
[email protected]51b63f62011-10-05 18:55:42520 return use_stale;
521}
522
[email protected]e67385f2011-12-21 06:00:56523bool PluginServiceImpl::GetPluginInfo(int render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16524 int render_frame_id,
[email protected]130757672012-10-24 00:26:19525 ResourceContext* context,
[email protected]e67385f2011-12-21 06:00:56526 const GURL& url,
527 const GURL& page_url,
528 const std::string& mime_type,
529 bool allow_wildcard,
530 bool* is_stale,
[email protected]d7bd3e52013-07-21 04:29:20531 WebPluginInfo* info,
[email protected]e67385f2011-12-21 06:00:56532 std::string* actual_mime_type) {
[email protected]d7bd3e52013-07-21 04:29:20533 std::vector<WebPluginInfo> plugins;
[email protected]68598072011-07-29 08:21:28534 std::vector<std::string> mime_types;
[email protected]88ca4912011-10-12 14:00:43535 bool stale = GetPluginInfoArray(
536 url, mime_type, allow_wildcard, &plugins, &mime_types);
537 if (is_stale)
538 *is_stale = stale;
[email protected]dfba8762011-09-02 12:49:54539
[email protected]68598072011-07-29 08:21:28540 for (size_t i = 0; i < plugins.size(); ++i) {
[email protected]05f511282013-02-05 15:02:50541 if (!filter_ || filter_->IsPluginAvailable(render_process_id,
[email protected]60eca4eb2013-12-06 00:02:16542 render_frame_id,
[email protected]05f511282013-02-05 15:02:50543 context,
544 url,
545 page_url,
546 &plugins[i])) {
[email protected]68598072011-07-29 08:21:28547 *info = plugins[i];
548 if (actual_mime_type)
549 *actual_mime_type = mime_types[i];
550 return true;
551 }
552 }
553 return false;
[email protected]6fdd4182010-10-14 23:59:26554}
555
[email protected]2dec8ec2013-02-07 19:20:34556bool PluginServiceImpl::GetPluginInfoByPath(const base::FilePath& plugin_path,
[email protected]d7bd3e52013-07-21 04:29:20557 WebPluginInfo* info) {
558 std::vector<WebPluginInfo> plugins;
[email protected]29e2fb42013-07-19 01:13:47559 PluginList::Singleton()->GetPluginsNoRefresh(&plugins);
[email protected]88ca4912011-10-12 14:00:43560
[email protected]d7bd3e52013-07-21 04:29:20561 for (std::vector<WebPluginInfo>::iterator it = plugins.begin();
[email protected]88ca4912011-10-12 14:00:43562 it != plugins.end();
563 ++it) {
564 if (it->path == plugin_path) {
565 *info = *it;
566 return true;
567 }
568 }
569
570 return false;
571}
572
[email protected]fcf75d42013-12-03 20:11:26573base::string16 PluginServiceImpl::GetPluginDisplayNameByPath(
[email protected]2dec8ec2013-02-07 19:20:34574 const base::FilePath& path) {
[email protected]fcf75d42013-12-03 20:11:26575 base::string16 plugin_name = path.LossyDisplayName();
[email protected]d7bd3e52013-07-21 04:29:20576 WebPluginInfo info;
[email protected]8be45842012-04-13 19:49:29577 if (PluginService::GetInstance()->GetPluginInfoByPath(path, &info) &&
578 !info.name.empty()) {
579 plugin_name = info.name;
580#if defined(OS_MACOSX)
581 // Many plugins on the Mac have .plugin in the actual name, which looks
582 // terrible, so look for that and strip it off if present.
583 const std::string kPluginExtension = ".plugin";
[email protected]32956122013-12-25 07:29:24584 if (EndsWith(plugin_name, base::ASCIIToUTF16(kPluginExtension), true))
[email protected]8be45842012-04-13 19:49:29585 plugin_name.erase(plugin_name.length() - kPluginExtension.length());
586#endif // OS_MACOSX
587 }
588 return plugin_name;
589}
590
[email protected]e67385f2011-12-21 06:00:56591void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
skyostil95082a62015-06-05 19:53:07592 scoped_refptr<base::SingleThreadTaskRunner> target_task_runner(
593 base::ThreadTaskRunnerHandle::Get());
[email protected]49125952011-09-27 18:05:15594
[email protected]1b517202012-12-19 17:16:10595 if (LoadPluginListInProcess()) {
skyostil95082a62015-06-05 19:53:07596 BrowserThread::GetBlockingPool()
597 ->PostSequencedWorkerTaskWithShutdownBehavior(
598 plugin_list_token_, FROM_HERE,
[email protected]1b517202012-12-19 17:16:10599 base::Bind(&PluginServiceImpl::GetPluginsInternal,
skyostil95082a62015-06-05 19:53:07600 base::Unretained(this), target_task_runner, callback),
601 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
[email protected]1b517202012-12-19 17:16:10602 return;
603 }
604#if defined(OS_POSIX)
skyostil95082a62015-06-05 19:53:07605 BrowserThread::PostTask(
606 BrowserThread::IO, FROM_HERE,
[email protected]aa7f8802014-01-27 16:56:32607 base::Bind(&PluginServiceImpl::GetPluginsOnIOThread,
skyostil95082a62015-06-05 19:53:07608 base::Unretained(this), target_task_runner, callback));
[email protected]a33fa9d2012-05-16 14:47:49609#else
[email protected]1b517202012-12-19 17:16:10610 NOTREACHED();
[email protected]49125952011-09-27 18:05:15611#endif
[email protected]d33e7cc2011-09-23 01:43:56612}
613
[email protected]e67385f2011-12-21 06:00:56614void PluginServiceImpl::GetPluginsInternal(
skyostil95082a62015-06-05 19:53:07615 base::SingleThreadTaskRunner* target_task_runner,
616 const PluginService::GetPluginsCallback& callback) {
[email protected]a33fa9d2012-05-16 14:47:49617 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
618 plugin_list_token_));
[email protected]d33e7cc2011-09-23 01:43:56619
[email protected]d7bd3e52013-07-21 04:29:20620 std::vector<WebPluginInfo> plugins;
[email protected]9a60ccb2013-07-19 22:23:36621 PluginList::Singleton()->GetPlugins(&plugins, NPAPIPluginsSupported());
[email protected]d33e7cc2011-09-23 01:43:56622
skyostil95082a62015-06-05 19:53:07623 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins));
[email protected]dfba8762011-09-02 12:49:54624}
625
[email protected]aa7f8802014-01-27 16:56:32626#if defined(OS_POSIX)
627void PluginServiceImpl::GetPluginsOnIOThread(
skyostil95082a62015-06-05 19:53:07628 base::SingleThreadTaskRunner* target_task_runner,
[email protected]aa7f8802014-01-27 16:56:32629 const GetPluginsCallback& callback) {
mostynb4c27d042015-03-18 21:47:47630 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]aa7f8802014-01-27 16:56:32631
632 // If we switch back to loading plugins in process, then we need to make
633 // sure g_thread_init() gets called since plugins may call glib at load.
634
dcheng54c3719d2014-08-26 21:52:56635 if (!plugin_loader_.get())
[email protected]aa7f8802014-01-27 16:56:32636 plugin_loader_ = new PluginLoaderPosix;
637
skyostil95082a62015-06-05 19:53:07638 plugin_loader_->GetPlugins(base::Bind(
639 &ForwardCallback, make_scoped_refptr(target_task_runner), callback));
[email protected]aa7f8802014-01-27 16:56:32640}
641#endif
642
[email protected]b547fd42009-04-23 23:16:27643#if defined(OS_WIN)
rvargas6f315b82014-10-17 01:28:58644void PluginServiceImpl::OnKeyChanged(base::win::RegKey* key) {
645 key->StartWatching(base::Bind(&PluginServiceImpl::OnKeyChanged,
646 base::Unretained(this),
rvargasb8056152014-11-08 01:44:28647 base::Unretained(key)));
[email protected]b547fd42009-04-23 23:16:27648
[email protected]29e2fb42013-07-19 01:13:47649 PluginList::Singleton()->RefreshPlugins();
[email protected]45a22e62011-10-12 09:48:02650 PurgePluginListCache(NULL, false);
dcheng4fe6ccad2014-10-16 03:09:26651}
rvargas6f315b82014-10-17 01:28:58652#endif // defined(OS_WIN)
[email protected]894bb502009-05-21 22:39:57653
[email protected]e67385f2011-12-21 06:00:56654void PluginServiceImpl::RegisterPepperPlugins() {
[email protected]dac6a5a2013-07-25 05:06:48655 ComputePepperPluginList(&ppapi_plugins_);
[email protected]a08ebea2011-02-13 17:50:20656 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]c6f3dea2012-01-14 02:23:11657 RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo(), true);
[email protected]4e0616e2010-05-28 14:55:53658 }
659}
[email protected]634d23d2011-01-19 10:38:19660
[email protected]eb415bf0e2011-04-14 02:45:42661// There should generally be very few plugins so a brute-force search is fine.
[email protected]130757672012-10-24 00:26:19662PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
[email protected]2dec8ec2013-02-07 19:20:34663 const base::FilePath& plugin_path) {
[email protected]130757672012-10-24 00:26:19664 PepperPluginInfo* info = NULL;
[email protected]3627aa3f2013-09-17 22:32:51665 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]6b14feb2011-08-16 11:22:56666 if (ppapi_plugins_[i].path == plugin_path) {
667 info = &ppapi_plugins_[i];
668 break;
669 }
[email protected]eb415bf0e2011-04-14 02:45:42670 }
[email protected]076117592011-08-17 03:16:41671 if (info)
672 return info;
673 // We did not find the plugin in our list. But wait! the plugin can also
674 // be a latecomer, as it happens with pepper flash. This information
675 // can be obtained from the PluginList singleton and we can use it to
676 // construct it and add it to the list. This same deal needs to be done
677 // in the renderer side in PepperPluginRegistry.
[email protected]d7bd3e52013-07-21 04:29:20678 WebPluginInfo webplugin_info;
[email protected]88ca4912011-10-12 14:00:43679 if (!GetPluginInfoByPath(plugin_path, &webplugin_info))
[email protected]076117592011-08-17 03:16:41680 return NULL;
[email protected]130757672012-10-24 00:26:19681 PepperPluginInfo new_pepper_info;
[email protected]076117592011-08-17 03:16:41682 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
683 return NULL;
684 ppapi_plugins_.push_back(new_pepper_info);
685 return &ppapi_plugins_[ppapi_plugins_.size() - 1];
[email protected]eb415bf0e2011-04-14 02:45:42686}
687
[email protected]52348b22012-11-07 10:19:34688#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19689// static
[email protected]07b71c82013-01-08 19:07:31690void PluginServiceImpl::RegisterFilePathWatcher(FilePathWatcher* watcher,
[email protected]2dec8ec2013-02-07 19:20:34691 const base::FilePath& path) {
[email protected]07b71c82013-01-08 19:07:31692 bool result = watcher->Watch(path, false,
693 base::Bind(&NotifyPluginDirChanged));
[email protected]634d23d2011-01-19 10:38:19694 DCHECK(result);
695}
696#endif
[email protected]f520b5b2011-11-08 02:42:14697
[email protected]130757672012-10-24 00:26:19698void PluginServiceImpl::SetFilter(PluginServiceFilter* filter) {
[email protected]3a5180ae2011-12-21 02:39:38699 filter_ = filter;
700}
701
[email protected]130757672012-10-24 00:26:19702PluginServiceFilter* PluginServiceImpl::GetFilter() {
[email protected]3a5180ae2011-12-21 02:39:38703 return filter_;
704}
705
[email protected]2dec8ec2013-02-07 19:20:34706void PluginServiceImpl::ForcePluginShutdown(const base::FilePath& plugin_path) {
[email protected]b6a2f8de2012-01-31 17:28:49707 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
708 BrowserThread::PostTask(
709 BrowserThread::IO, FROM_HERE,
710 base::Bind(&PluginServiceImpl::ForcePluginShutdown,
711 base::Unretained(this), plugin_path));
712 return;
713 }
714
715 PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path);
716 if (plugin)
717 plugin->ForceShutdown();
718}
719
[email protected]47214d882012-02-29 06:28:48720static const unsigned int kMaxCrashesPerInterval = 3;
721static const unsigned int kCrashesInterval = 120;
722
[email protected]2dec8ec2013-02-07 19:20:34723void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) {
mostynb4c27d042015-03-18 21:47:47724 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]2dec8ec2013-02-07 19:20:34725 std::map<base::FilePath, std::vector<base::Time> >::iterator i =
[email protected]47214d882012-02-29 06:28:48726 crash_times_.find(path);
727 if (i == crash_times_.end()) {
728 crash_times_[path] = std::vector<base::Time>();
729 i = crash_times_.find(path);
730 }
731 if (i->second.size() == kMaxCrashesPerInterval) {
732 i->second.erase(i->second.begin());
733 }
734 base::Time time = base::Time::Now();
735 i->second.push_back(time);
736}
737
[email protected]2dec8ec2013-02-07 19:20:34738bool PluginServiceImpl::IsPluginUnstable(const base::FilePath& path) {
mostynb4c27d042015-03-18 21:47:47739 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]2dec8ec2013-02-07 19:20:34740 std::map<base::FilePath, std::vector<base::Time> >::const_iterator i =
[email protected]47214d882012-02-29 06:28:48741 crash_times_.find(path);
742 if (i == crash_times_.end()) {
743 return false;
744 }
745 if (i->second.size() != kMaxCrashesPerInterval) {
746 return false;
747 }
748 base::TimeDelta delta = base::Time::Now() - i->second[0];
[email protected]d8c70062013-04-24 00:22:34749 return delta.InSeconds() <= kCrashesInterval;
[email protected]47214d882012-02-29 06:28:48750}
751
[email protected]e67385f2011-12-21 06:00:56752void PluginServiceImpl::RefreshPlugins() {
[email protected]29e2fb42013-07-19 01:13:47753 PluginList::Singleton()->RefreshPlugins();
[email protected]f520b5b2011-11-08 02:42:14754}
755
[email protected]2dec8ec2013-02-07 19:20:34756void PluginServiceImpl::AddExtraPluginPath(const base::FilePath& path) {
[email protected]a01c8c8f2014-05-09 17:24:53757 if (!NPAPIPluginsSupported()) {
[email protected]9a60ccb2013-07-19 22:23:36758 // TODO(jam): remove and just have CHECK once we're sure this doesn't get
759 // triggered.
[email protected]efde84b02013-11-23 04:18:20760 DVLOG(0) << "NPAPI plugins not supported";
[email protected]9a60ccb2013-07-19 22:23:36761 return;
762 }
[email protected]29e2fb42013-07-19 01:13:47763 PluginList::Singleton()->AddExtraPluginPath(path);
[email protected]c6f3dea2012-01-14 02:23:11764}
765
[email protected]2dec8ec2013-02-07 19:20:34766void PluginServiceImpl::RemoveExtraPluginPath(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47767 PluginList::Singleton()->RemoveExtraPluginPath(path);
[email protected]8f3372122013-07-18 04:34:14768}
769
770void PluginServiceImpl::AddExtraPluginDir(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47771 PluginList::Singleton()->AddExtraPluginDir(path);
[email protected]8f3372122013-07-18 04:34:14772}
773
774void PluginServiceImpl::RegisterInternalPlugin(
[email protected]d7bd3e52013-07-21 04:29:20775 const WebPluginInfo& info,
[email protected]8f3372122013-07-18 04:34:14776 bool add_at_beginning) {
wfha79d1022015-02-20 16:13:13777 // Internal plugins should never be NPAPI.
778 CHECK_NE(info.type, WebPluginInfo::PLUGIN_TYPE_NPAPI);
779 if (info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
[email protected]efde84b02013-11-23 04:18:20780 DVLOG(0) << "Don't register NPAPI plugins when they're not supported";
[email protected]9a60ccb2013-07-19 22:23:36781 return;
782 }
[email protected]29e2fb42013-07-19 01:13:47783 PluginList::Singleton()->RegisterInternalPlugin(info, add_at_beginning);
[email protected]f520b5b2011-11-08 02:42:14784}
785
[email protected]2dec8ec2013-02-07 19:20:34786void PluginServiceImpl::UnregisterInternalPlugin(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47787 PluginList::Singleton()->UnregisterInternalPlugin(path);
[email protected]f520b5b2011-11-08 02:42:14788}
789
[email protected]8f3372122013-07-18 04:34:14790void PluginServiceImpl::GetInternalPlugins(
[email protected]d7bd3e52013-07-21 04:29:20791 std::vector<WebPluginInfo>* plugins) {
[email protected]29e2fb42013-07-19 01:13:47792 PluginList::Singleton()->GetInternalPlugins(plugins);
[email protected]8f3372122013-07-18 04:34:14793}
794
[email protected]9a60ccb2013-07-19 22:23:36795bool PluginServiceImpl::NPAPIPluginsSupported() {
wfha79d1022015-02-20 16:13:13796 static bool command_line_checked = false;
797
798 if (!command_line_checked) {
799#if defined(OS_WIN) || defined(OS_MACOSX)
800 const base::CommandLine* command_line =
801 base::CommandLine::ForCurrentProcess();
wfhcfdd80f32015-05-29 17:56:27802 npapi_plugins_enabled_ =
803 command_line->HasSwitch(switches::kEnableNpapiForTesting);
wfhad38f5a32015-06-03 17:11:07804#if defined(OS_WIN)
805 // NPAPI plugins don't play well with Win32k renderer lockdown.
806 if (npapi_plugins_enabled_)
807 DisableWin32kRendererLockdown();
808#endif
wfha79d1022015-02-20 16:13:13809 NPAPIPluginStatus status =
810 npapi_plugins_enabled_ ? NPAPI_STATUS_ENABLED : NPAPI_STATUS_DISABLED;
811#else
812 NPAPIPluginStatus status = NPAPI_STATUS_UNSUPPORTED;
813#endif
814 UMA_HISTOGRAM_ENUMERATION("Plugin.NPAPIStatus", status,
815 NPAPI_STATUS_ENUM_COUNT);
816 }
817
wfh0539f2f52015-01-21 14:36:46818 return npapi_plugins_enabled_;
[email protected]9a60ccb2013-07-19 22:23:36819}
820
[email protected]8f3372122013-07-18 04:34:14821void PluginServiceImpl::DisablePluginsDiscoveryForTesting() {
[email protected]29e2fb42013-07-19 01:13:47822 PluginList::Singleton()->DisablePluginsDiscovery();
[email protected]ee066172011-11-10 23:20:05823}
824
[email protected]5904cb42012-09-24 15:05:20825#if defined(OS_MACOSX)
826void PluginServiceImpl::AppActivated() {
827 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]07b71c82013-01-08 19:07:31828 base::Bind(&NotifyPluginsOfActivation));
[email protected]5904cb42012-09-24 15:05:20829}
[email protected]9a60ccb2013-07-19 22:23:36830#elif defined(OS_WIN)
831
832bool GetPluginPropertyFromWindow(
833 HWND window, const wchar_t* plugin_atom_property,
834 base::string16* plugin_property) {
scottmg4800fc22015-04-29 00:31:20835 ATOM plugin_atom = static_cast<ATOM>(
836 reinterpret_cast<uintptr_t>(GetPropW(window, plugin_atom_property)));
[email protected]9a60ccb2013-07-19 22:23:36837 if (plugin_atom != 0) {
838 WCHAR plugin_property_local[MAX_PATH] = {0};
839 GlobalGetAtomNameW(plugin_atom,
840 plugin_property_local,
841 ARRAYSIZE(plugin_property_local));
842 *plugin_property = plugin_property_local;
843 return true;
844 }
845 return false;
846}
847
848bool PluginServiceImpl::GetPluginInfoFromWindow(
849 HWND window,
850 base::string16* plugin_name,
851 base::string16* plugin_version) {
852 if (!IsPluginWindow(window))
853 return false;
854
jam3458fc002014-09-10 03:21:41855
856 DWORD process_id = 0;
857 GetWindowThreadProcessId(window, &process_id);
858 WebPluginInfo info;
859 if (!PluginProcessHost::GetWebPluginInfoFromPluginPid(process_id, &info))
860 return false;
861
862 *plugin_name = info.name;
863 *plugin_version = info.version;
[email protected]9a60ccb2013-07-19 22:23:36864 return true;
865}
866
867bool PluginServiceImpl::IsPluginWindow(HWND window) {
[email protected]bde885b2013-09-12 20:55:53868 return gfx::GetClassName(window) == base::string16(kNativeWindowClassName);
[email protected]9a60ccb2013-07-19 22:23:36869}
[email protected]5904cb42012-09-24 15:05:20870#endif
871
[email protected]aec5ed52014-06-20 07:51:42872bool PluginServiceImpl::PpapiDevChannelSupported(
873 BrowserContext* browser_context,
874 const GURL& document_url) {
[email protected]8ddc6b7c2013-12-12 20:42:06875 return content::GetContentClient()->browser()->
[email protected]aec5ed52014-06-20 07:51:42876 IsPluginAllowedToUseDevChannelAPIs(browser_context, document_url);
[email protected]8ddc6b7c2013-12-12 20:42:06877}
878
[email protected]130757672012-10-24 00:26:19879} // namespace content