blob: a0d8813411926caaa3d5d47ae43d3a52af1c709b [file] [log] [blame]
[email protected]c6f3dea2012-01-14 02:23:111// 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.commitf5b16fe2008-07-27 00:20:514
Lei Zhangd8c53182019-02-06 22:24:395#include "content/browser/plugin_list.h"
initial.commitf5b16fe2008-07-27 00:20:516
avia9aa7a82015-12-25 03:06:317#include <stddef.h>
8
[email protected]cec1b8d2010-03-24 00:21:349#include <algorithm>
10
[email protected]3c0c0bf52010-06-25 06:05:0911#include "base/command_line.h"
[email protected]19537112009-01-21 19:38:1412#include "base/lazy_instance.h"
initial.commitf5b16fe2008-07-27 00:20:5113#include "base/logging.h"
Zhuoyu Qian39a909a2018-10-16 03:48:5214#include "base/stl_util.h"
[email protected]d778e0422013-03-06 18:10:2215#include "base/strings/string_split.h"
[email protected]f63582d2013-06-11 22:52:5416#include "base/strings/string_util.h"
[email protected]13ac53532013-03-30 00:27:0017#include "base/strings/sys_string_conversions.h"
[email protected]906265872013-06-07 22:40:4518#include "base/strings/utf_string_conversions.h"
avia9aa7a82015-12-25 03:06:3119#include "build/build_config.h"
[email protected]1bbbc492013-08-09 00:36:1520#include "content/public/common/content_switches.h"
[email protected]b7344502009-01-12 19:43:4421#include "net/base/mime_util.h"
[email protected]ad677772013-06-29 14:18:3822#include "url/gurl.h"
initial.commitf5b16fe2008-07-27 00:20:5123
[email protected]29e2fb42013-07-19 01:13:4724namespace content {
25
26namespace {
[email protected]0b300172012-09-27 16:11:5227
scottmg5e65e3a2017-03-08 08:48:4628base::LazyInstance<PluginList>::DestructorAtExit g_singleton =
29 LAZY_INSTANCE_INITIALIZER;
[email protected]123a04962011-11-03 15:43:0130
Lei Zhanga2eb18782018-08-15 18:09:2131// Returns true if the plugin supports |mime_type|. |mime_type| should be all
32// lower case.
33bool SupportsType(const WebPluginInfo& plugin,
34 const std::string& mime_type,
35 bool allow_wildcard) {
36 // Webkit will ask for a plugin to handle empty mime types.
37 if (mime_type.empty())
38 return false;
39
40 for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
41 const WebPluginMimeType& mime_info = plugin.mime_types[i];
42 if (net::MatchesMimeType(mime_info.mime_type, mime_type)) {
43 if (!allow_wildcard && mime_info.mime_type == "*")
44 continue;
45 return true;
46 }
47 }
48 return false;
49}
50
51// Returns true if the given plugin supports a given file extension.
52// |extension| should be all lower case. |actual_mime_type| will be set to the
53// MIME type if found. The MIME type which corresponds to the extension is
54// optionally returned back.
55bool SupportsExtension(const WebPluginInfo& plugin,
56 const std::string& extension,
57 std::string* actual_mime_type) {
58 for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
59 const WebPluginMimeType& mime_type = plugin.mime_types[i];
60 for (size_t j = 0; j < mime_type.file_extensions.size(); ++j) {
61 if (mime_type.file_extensions[j] == extension) {
62 *actual_mime_type = mime_type.mime_type;
63 return true;
64 }
65 }
66 }
67 return false;
68}
69
[email protected]3b91edbe2012-09-27 22:49:2370} // namespace
[email protected]123a04962011-11-03 15:43:0171
[email protected]19537112009-01-21 19:38:1472// static
initial.commitf5b16fe2008-07-27 00:20:5173PluginList* PluginList::Singleton() {
[email protected]35fa6a22009-08-15 00:04:0174 return g_singleton.Pointer();
initial.commitf5b16fe2008-07-27 00:20:5175}
76
[email protected]4e59e812010-04-06 20:51:1677void PluginList::RefreshPlugins() {
[email protected]20305ec2011-01-21 04:55:5278 base::AutoLock lock(lock_);
[email protected]a33fa9d2012-05-16 14:47:4979 loading_state_ = LOADING_STATE_NEEDS_REFRESH;
[email protected]367230c52009-02-21 01:44:3080}
initial.commitf5b16fe2008-07-27 00:20:5181
[email protected]d7bd3e52013-07-21 04:29:2082void PluginList::RegisterInternalPlugin(const WebPluginInfo& info,
[email protected]c6f3dea2012-01-14 02:23:1183 bool add_at_beginning) {
[email protected]20305ec2011-01-21 04:55:5284 base::AutoLock lock(lock_);
[email protected]8ca37f42011-11-02 16:03:4185
[email protected]fee3a98b2013-07-18 18:12:4886 internal_plugins_.push_back(info);
[email protected]8ca37f42011-11-02 16:03:4187 if (add_at_beginning) {
88 // Newer registrations go earlier in the list so they can override the MIME
89 // types of older registrations.
[email protected]c6f3dea2012-01-14 02:23:1190 extra_plugin_paths_.insert(extra_plugin_paths_.begin(), info.path);
[email protected]8ca37f42011-11-02 16:03:4191 } else {
[email protected]c6f3dea2012-01-14 02:23:1192 extra_plugin_paths_.push_back(info.path);
[email protected]8ca37f42011-11-02 16:03:4193 }
[email protected]f99c73ad2011-01-11 00:43:4494}
95
[email protected]a3ef4832013-02-02 05:12:3396void PluginList::UnregisterInternalPlugin(const base::FilePath& path) {
[email protected]20305ec2011-01-21 04:55:5297 base::AutoLock lock(lock_);
[email protected]797d9a62013-09-13 23:36:0798 bool found = false;
[email protected]00c39612010-03-06 02:53:2899 for (size_t i = 0; i < internal_plugins_.size(); i++) {
[email protected]fee3a98b2013-07-18 18:12:48100 if (internal_plugins_[i].path == path) {
[email protected]00c39612010-03-06 02:53:28101 internal_plugins_.erase(internal_plugins_.begin() + i);
[email protected]797d9a62013-09-13 23:36:07102 found = true;
103 break;
[email protected]00c39612010-03-06 02:53:28104 }
105 }
[email protected]797d9a62013-09-13 23:36:07106 DCHECK(found);
107 RemoveExtraPluginPathLocked(path);
[email protected]00c39612010-03-06 02:53:28108}
109
[email protected]d4af1e72011-10-21 17:45:43110void PluginList::GetInternalPlugins(
[email protected]d7bd3e52013-07-21 04:29:20111 std::vector<WebPluginInfo>* internal_plugins) {
[email protected]d4af1e72011-10-21 17:45:43112 base::AutoLock lock(lock_);
113
[email protected]d7bd3e52013-07-21 04:29:20114 for (std::vector<WebPluginInfo>::iterator it = internal_plugins_.begin();
Lei Zhangd8c53182019-02-06 22:24:39115 it != internal_plugins_.end(); ++it) {
[email protected]fee3a98b2013-07-18 18:12:48116 internal_plugins->push_back(*it);
[email protected]d4af1e72011-10-21 17:45:43117 }
118}
119
[email protected]a3ef4832013-02-02 05:12:33120bool PluginList::ReadPluginInfo(const base::FilePath& filename,
[email protected]d7bd3e52013-07-21 04:29:20121 WebPluginInfo* info) {
pimane8c57ea2016-04-06 01:19:36122 base::AutoLock lock(lock_);
123 for (const auto& plugin : internal_plugins_) {
124 if (filename == plugin.path) {
125 *info = plugin;
126 return true;
[email protected]8ff26092009-01-29 01:53:24127 }
128 }
pimane8c57ea2016-04-06 01:19:36129 return false;
[email protected]8ff26092009-01-29 01:53:24130}
131
Lei Zhangd8c53182019-02-06 22:24:39132PluginList::PluginList() : loading_state_(LOADING_STATE_NEEDS_REFRESH) {}
initial.commitf5b16fe2008-07-27 00:20:51133
[email protected]aa7f8802014-01-27 16:56:32134bool PluginList::PrepareForPluginLoading() {
135 base::AutoLock lock(lock_);
136 if (loading_state_ == LOADING_STATE_UP_TO_DATE)
137 return false;
[email protected]a33fa9d2012-05-16 14:47:49138
[email protected]aa7f8802014-01-27 16:56:32139 loading_state_ = LOADING_STATE_REFRESHING;
140 return true;
141}
142
pimane8c57ea2016-04-06 01:19:36143void PluginList::LoadPlugins() {
[email protected]aa7f8802014-01-27 16:56:32144 if (!PrepareForPluginLoading())
145 return;
[email protected]a466a0c2010-10-02 00:42:39146
[email protected]d7bd3e52013-07-21 04:29:20147 std::vector<WebPluginInfo> new_plugins;
Lei Zhangc213e122019-02-07 00:17:02148 base::OnceClosure will_load_callback;
[email protected]9a60ccb2013-07-19 22:23:36149 {
150 base::AutoLock lock(lock_);
151 will_load_callback = will_load_plugins_callback_;
152 }
Lei Zhangc213e122019-02-07 00:17:02153 if (will_load_callback)
Tommy Nyquist4b749d02018-03-20 21:46:29154 std::move(will_load_callback).Run();
[email protected]9a60ccb2013-07-19 22:23:36155
156 std::vector<base::FilePath> plugin_paths;
pimane8c57ea2016-04-06 01:19:36157 GetPluginPathsToLoad(&plugin_paths);
[email protected]9a60ccb2013-07-19 22:23:36158
159 for (std::vector<base::FilePath>::const_iterator it = plugin_paths.begin();
Lei Zhangd8c53182019-02-06 22:24:39160 it != plugin_paths.end(); ++it) {
[email protected]9a60ccb2013-07-19 22:23:36161 WebPluginInfo plugin_info;
162 LoadPluginIntoPluginList(*it, &new_plugins, &plugin_info);
163 }
[email protected]1134a002010-10-08 08:03:14164
[email protected]aa7f8802014-01-27 16:56:32165 SetPlugins(new_plugins);
initial.commitf5b16fe2008-07-27 00:20:51166}
167
Lei Zhangd8c53182019-02-06 22:24:39168bool PluginList::LoadPluginIntoPluginList(const base::FilePath& path,
169 std::vector<WebPluginInfo>* plugins,
170 WebPluginInfo* plugin_info) {
[email protected]fee3a98b2013-07-18 18:12:48171 if (!ReadPluginInfo(path, plugin_info))
[email protected]68b63bc2012-08-20 22:14:03172 return false;
173
pimane8c57ea2016-04-06 01:19:36174 // TODO(piman): Do we still need this after NPAPI removal?
175 for (size_t i = 0; i < plugin_info->mime_types.size(); ++i) {
176 // TODO: don't load global handlers for now.
177 // WebKit hands to the Plugin before it tries
178 // to handle mimeTypes on its own.
Lei Zhangd8c53182019-02-06 22:24:39179 const std::string& mime_type = plugin_info->mime_types[i].mime_type;
pimane8c57ea2016-04-06 01:19:36180 if (mime_type == "*")
181 return false;
[email protected]68b63bc2012-08-20 22:14:03182 }
183 plugins->push_back(*plugin_info);
184 return true;
185}
186
pimane8c57ea2016-04-06 01:19:36187void PluginList::GetPluginPathsToLoad(
188 std::vector<base::FilePath>* plugin_paths) {
[email protected]d4af1e72011-10-21 17:45:43189 // Don't want to hold the lock while loading new plugins, so we don't block
190 // other methods if they're called on other threads.
[email protected]a3ef4832013-02-02 05:12:33191 std::vector<base::FilePath> extra_plugin_paths;
[email protected]d4af1e72011-10-21 17:45:43192 {
193 base::AutoLock lock(lock_);
194 extra_plugin_paths = extra_plugin_paths_;
[email protected]49125952011-09-27 18:05:15195 }
[email protected]d4af1e72011-10-21 17:45:43196
[email protected]d4af1e72011-10-21 17:45:43197 for (size_t i = 0; i < extra_plugin_paths.size(); ++i) {
[email protected]a3ef4832013-02-02 05:12:33198 const base::FilePath& path = extra_plugin_paths[i];
Zhuoyu Qian39a909a2018-10-16 03:48:52199 if (base::ContainsValue(*plugin_paths, path))
[email protected]d4af1e72011-10-21 17:45:43200 continue;
[email protected]d4af1e72011-10-21 17:45:43201 plugin_paths->push_back(path);
202 }
[email protected]49125952011-09-27 18:05:15203}
204
[email protected]d7bd3e52013-07-21 04:29:20205void PluginList::SetPlugins(const std::vector<WebPluginInfo>& plugins) {
[email protected]49125952011-09-27 18:05:15206 base::AutoLock lock(lock_);
207
tommyclie86b2982015-03-16 20:16:45208 // If we haven't been invalidated in the mean time, mark the plugin list as
thakis3e861de2016-06-14 14:24:01209 // up to date.
[email protected]aa7f8802014-01-27 16:56:32210 if (loading_state_ != LOADING_STATE_NEEDS_REFRESH)
211 loading_state_ = LOADING_STATE_UP_TO_DATE;
[email protected]49125952011-09-27 18:05:15212
[email protected]aa7f8802014-01-27 16:56:32213 plugins_list_ = plugins;
[email protected]49125952011-09-27 18:05:15214}
215
Lei Zhangc213e122019-02-07 00:17:02216void PluginList::set_will_load_plugins_callback(
217 const base::RepeatingClosure& callback) {
[email protected]49125952011-09-27 18:05:15218 base::AutoLock lock(lock_);
219 will_load_plugins_callback_ = callback;
220}
221
pimane8c57ea2016-04-06 01:19:36222void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) {
223 LoadPlugins();
[email protected]20305ec2011-01-21 04:55:52224 base::AutoLock lock(lock_);
[email protected]68b63bc2012-08-20 22:14:03225 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
initial.commitf5b16fe2008-07-27 00:20:51226}
227
[email protected]d7bd3e52013-07-21 04:29:20228bool PluginList::GetPluginsNoRefresh(std::vector<WebPluginInfo>* plugins) {
[email protected]49125952011-09-27 18:05:15229 base::AutoLock lock(lock_);
[email protected]68b63bc2012-08-20 22:14:03230 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
231
[email protected]480c7cc2012-06-29 17:38:44232 return loading_state_ == LOADING_STATE_UP_TO_DATE;
[email protected]49125952011-09-27 18:05:15233}
234
[email protected]9bcdced72010-12-07 20:51:36235void PluginList::GetPluginInfoArray(
236 const GURL& url,
237 const std::string& mime_type,
238 bool allow_wildcard,
[email protected]68598072011-07-29 08:21:28239 bool* use_stale,
[email protected]d7bd3e52013-07-21 04:29:20240 std::vector<WebPluginInfo>* info,
[email protected]9bcdced72010-12-07 20:51:36241 std::vector<std::string>* actual_mime_types) {
brettw8e2106d2015-08-11 19:30:22242 DCHECK(mime_type == base::ToLowerASCII(mime_type));
[email protected]20a793e2010-10-12 06:50:08243 DCHECK(info);
244
[email protected]68598072011-07-29 08:21:28245 if (!use_stale)
pimane8c57ea2016-04-06 01:19:36246 LoadPlugins();
[email protected]20305ec2011-01-21 04:55:52247 base::AutoLock lock(lock_);
[email protected]68598072011-07-29 08:21:28248 if (use_stale)
[email protected]a33fa9d2012-05-16 14:47:49249 *use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE);
[email protected]f4d43cb2013-10-28 20:53:07250 info->clear();
[email protected]20a793e2010-10-12 06:50:08251 if (actual_mime_types)
252 actual_mime_types->clear();
253
[email protected]a3ef4832013-02-02 05:12:33254 std::set<base::FilePath> visited_plugins;
[email protected]20a793e2010-10-12 06:50:08255
[email protected]dfba8762011-09-02 12:49:54256 // Add in plugins by mime type.
[email protected]68b63bc2012-08-20 22:14:03257 for (size_t i = 0; i < plugins_list_.size(); ++i) {
258 if (SupportsType(plugins_list_[i], mime_type, allow_wildcard)) {
[email protected]a3ef4832013-02-02 05:12:33259 base::FilePath path = plugins_list_[i].path;
[email protected]68b63bc2012-08-20 22:14:03260 if (visited_plugins.insert(path).second) {
[email protected]f4d43cb2013-10-28 20:53:07261 info->push_back(plugins_list_[i]);
[email protected]68b63bc2012-08-20 22:14:03262 if (actual_mime_types)
263 actual_mime_types->push_back(mime_type);
[email protected]20a793e2010-10-12 06:50:08264 }
265 }
266 }
267
[email protected]dfba8762011-09-02 12:49:54268 // Add in plugins by url.
tommyclie86b2982015-03-16 20:16:45269 // We do not permit URL-sniff based plugin MIME type overrides aside from
[email protected]cafe0d02013-07-23 15:16:20270 // the case where the "type" was initially missing.
271 // We collected stats to determine this approach isn't a major compat issue,
272 // and we defend against content confusion attacks in various cases, such
tommyclie86b2982015-03-16 20:16:45273 // as when the user doesn't have the Flash plugin enabled.
[email protected]20a793e2010-10-12 06:50:08274 std::string path = url.path();
275 std::string::size_type last_dot = path.rfind('.');
[email protected]cafe0d02013-07-23 15:16:20276 if (last_dot != std::string::npos && mime_type.empty()) {
[email protected]cb1f4ac2014-08-07 16:55:42277 std::string extension =
brettw8e2106d2015-08-11 19:30:22278 base::ToLowerASCII(base::StringPiece(path).substr(last_dot + 1));
[email protected]20a793e2010-10-12 06:50:08279 std::string actual_mime_type;
[email protected]68b63bc2012-08-20 22:14:03280 for (size_t i = 0; i < plugins_list_.size(); ++i) {
281 if (SupportsExtension(plugins_list_[i], extension, &actual_mime_type)) {
Dave Tapuska4876a48f2018-02-16 19:02:39282 base::FilePath plugin_path = plugins_list_[i].path;
283 if (visited_plugins.insert(plugin_path).second) {
[email protected]f4d43cb2013-10-28 20:53:07284 info->push_back(plugins_list_[i]);
[email protected]68b63bc2012-08-20 22:14:03285 if (actual_mime_types)
286 actual_mime_types->push_back(actual_mime_type);
[email protected]20a793e2010-10-12 06:50:08287 }
288 }
289 }
290 }
[email protected]20a793e2010-10-12 06:50:08291}
292
[email protected]797d9a62013-09-13 23:36:07293void PluginList::RemoveExtraPluginPathLocked(
294 const base::FilePath& plugin_path) {
295 lock_.AssertAcquired();
Lei Zhangd8c53182019-02-06 22:24:39296 std::vector<base::FilePath>::iterator it = std::find(
297 extra_plugin_paths_.begin(), extra_plugin_paths_.end(), plugin_path);
[email protected]797d9a62013-09-13 23:36:07298 if (it != extra_plugin_paths_.end())
299 extra_plugin_paths_.erase(it);
300}
301
Lei Zhangd8c53182019-02-06 22:24:39302PluginList::~PluginList() {}
initial.commitf5b16fe2008-07-27 00:20:51303
[email protected]29e2fb42013-07-19 01:13:47304} // namespace content