blob: cbfa04205404528daddbcf56f2cafdfe58ddf006 [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
[email protected]29e2fb42013-07-19 01:13:475#include "content/common/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();
[email protected]d4af1e72011-10-21 17:45:43115 it != internal_plugins_.end();
116 ++it) {
[email protected]fee3a98b2013-07-18 18:12:48117 internal_plugins->push_back(*it);
[email protected]d4af1e72011-10-21 17:45:43118 }
119}
120
[email protected]a3ef4832013-02-02 05:12:33121bool PluginList::ReadPluginInfo(const base::FilePath& filename,
[email protected]d7bd3e52013-07-21 04:29:20122 WebPluginInfo* info) {
pimane8c57ea2016-04-06 01:19:36123 base::AutoLock lock(lock_);
124 for (const auto& plugin : internal_plugins_) {
125 if (filename == plugin.path) {
126 *info = plugin;
127 return true;
[email protected]8ff26092009-01-29 01:53:24128 }
129 }
pimane8c57ea2016-04-06 01:19:36130 return false;
[email protected]8ff26092009-01-29 01:53:24131}
132
[email protected]4e59e812010-04-06 20:51:16133PluginList::PluginList()
pimane8c57ea2016-04-06 01:19:36134 : loading_state_(LOADING_STATE_NEEDS_REFRESH) {
[email protected]b83ff222011-01-24 17:37:12135}
initial.commitf5b16fe2008-07-27 00:20:51136
[email protected]aa7f8802014-01-27 16:56:32137bool PluginList::PrepareForPluginLoading() {
138 base::AutoLock lock(lock_);
139 if (loading_state_ == LOADING_STATE_UP_TO_DATE)
140 return false;
[email protected]a33fa9d2012-05-16 14:47:49141
[email protected]aa7f8802014-01-27 16:56:32142 loading_state_ = LOADING_STATE_REFRESHING;
143 return true;
144}
145
pimane8c57ea2016-04-06 01:19:36146void PluginList::LoadPlugins() {
[email protected]aa7f8802014-01-27 16:56:32147 if (!PrepareForPluginLoading())
148 return;
[email protected]a466a0c2010-10-02 00:42:39149
[email protected]d7bd3e52013-07-21 04:29:20150 std::vector<WebPluginInfo> new_plugins;
[email protected]9a60ccb2013-07-19 22:23:36151 base::Closure will_load_callback;
152 {
153 base::AutoLock lock(lock_);
154 will_load_callback = will_load_plugins_callback_;
155 }
156 if (!will_load_callback.is_null())
Tommy Nyquist4b749d02018-03-20 21:46:29157 std::move(will_load_callback).Run();
[email protected]9a60ccb2013-07-19 22:23:36158
159 std::vector<base::FilePath> plugin_paths;
pimane8c57ea2016-04-06 01:19:36160 GetPluginPathsToLoad(&plugin_paths);
[email protected]9a60ccb2013-07-19 22:23:36161
162 for (std::vector<base::FilePath>::const_iterator it = plugin_paths.begin();
163 it != plugin_paths.end();
164 ++it) {
165 WebPluginInfo plugin_info;
166 LoadPluginIntoPluginList(*it, &new_plugins, &plugin_info);
167 }
[email protected]1134a002010-10-08 08:03:14168
[email protected]aa7f8802014-01-27 16:56:32169 SetPlugins(new_plugins);
initial.commitf5b16fe2008-07-27 00:20:51170}
171
[email protected]68b63bc2012-08-20 22:14:03172bool PluginList::LoadPluginIntoPluginList(
[email protected]a3ef4832013-02-02 05:12:33173 const base::FilePath& path,
[email protected]d7bd3e52013-07-21 04:29:20174 std::vector<WebPluginInfo>* plugins,
[email protected]68b63bc2012-08-20 22:14:03175 WebPluginInfo* plugin_info) {
[email protected]fee3a98b2013-07-18 18:12:48176 if (!ReadPluginInfo(path, plugin_info))
[email protected]68b63bc2012-08-20 22:14:03177 return false;
178
pimane8c57ea2016-04-06 01:19:36179 // TODO(piman): Do we still need this after NPAPI removal?
180 for (size_t i = 0; i < plugin_info->mime_types.size(); ++i) {
181 // TODO: don't load global handlers for now.
182 // WebKit hands to the Plugin before it tries
183 // to handle mimeTypes on its own.
184 const std::string &mime_type = plugin_info->mime_types[i].mime_type;
185 if (mime_type == "*")
186 return false;
[email protected]68b63bc2012-08-20 22:14:03187 }
188 plugins->push_back(*plugin_info);
189 return true;
190}
191
pimane8c57ea2016-04-06 01:19:36192void PluginList::GetPluginPathsToLoad(
193 std::vector<base::FilePath>* plugin_paths) {
[email protected]d4af1e72011-10-21 17:45:43194 // Don't want to hold the lock while loading new plugins, so we don't block
195 // other methods if they're called on other threads.
[email protected]a3ef4832013-02-02 05:12:33196 std::vector<base::FilePath> extra_plugin_paths;
[email protected]d4af1e72011-10-21 17:45:43197 {
198 base::AutoLock lock(lock_);
199 extra_plugin_paths = extra_plugin_paths_;
[email protected]49125952011-09-27 18:05:15200 }
[email protected]d4af1e72011-10-21 17:45:43201
[email protected]d4af1e72011-10-21 17:45:43202 for (size_t i = 0; i < extra_plugin_paths.size(); ++i) {
[email protected]a3ef4832013-02-02 05:12:33203 const base::FilePath& path = extra_plugin_paths[i];
Zhuoyu Qian39a909a2018-10-16 03:48:52204 if (base::ContainsValue(*plugin_paths, path))
[email protected]d4af1e72011-10-21 17:45:43205 continue;
[email protected]d4af1e72011-10-21 17:45:43206 plugin_paths->push_back(path);
207 }
[email protected]49125952011-09-27 18:05:15208}
209
[email protected]d7bd3e52013-07-21 04:29:20210void PluginList::SetPlugins(const std::vector<WebPluginInfo>& plugins) {
[email protected]49125952011-09-27 18:05:15211 base::AutoLock lock(lock_);
212
tommyclie86b2982015-03-16 20:16:45213 // If we haven't been invalidated in the mean time, mark the plugin list as
thakis3e861de2016-06-14 14:24:01214 // up to date.
[email protected]aa7f8802014-01-27 16:56:32215 if (loading_state_ != LOADING_STATE_NEEDS_REFRESH)
216 loading_state_ = LOADING_STATE_UP_TO_DATE;
[email protected]49125952011-09-27 18:05:15217
[email protected]aa7f8802014-01-27 16:56:32218 plugins_list_ = plugins;
[email protected]49125952011-09-27 18:05:15219}
220
221void PluginList::set_will_load_plugins_callback(const base::Closure& callback) {
222 base::AutoLock lock(lock_);
223 will_load_plugins_callback_ = callback;
224}
225
pimane8c57ea2016-04-06 01:19:36226void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) {
227 LoadPlugins();
[email protected]20305ec2011-01-21 04:55:52228 base::AutoLock lock(lock_);
[email protected]68b63bc2012-08-20 22:14:03229 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
initial.commitf5b16fe2008-07-27 00:20:51230}
231
[email protected]d7bd3e52013-07-21 04:29:20232bool PluginList::GetPluginsNoRefresh(std::vector<WebPluginInfo>* plugins) {
[email protected]49125952011-09-27 18:05:15233 base::AutoLock lock(lock_);
[email protected]68b63bc2012-08-20 22:14:03234 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
235
[email protected]480c7cc2012-06-29 17:38:44236 return loading_state_ == LOADING_STATE_UP_TO_DATE;
[email protected]49125952011-09-27 18:05:15237}
238
[email protected]9bcdced72010-12-07 20:51:36239void PluginList::GetPluginInfoArray(
240 const GURL& url,
241 const std::string& mime_type,
242 bool allow_wildcard,
[email protected]68598072011-07-29 08:21:28243 bool* use_stale,
[email protected]d7bd3e52013-07-21 04:29:20244 std::vector<WebPluginInfo>* info,
[email protected]9bcdced72010-12-07 20:51:36245 std::vector<std::string>* actual_mime_types) {
brettw8e2106d2015-08-11 19:30:22246 DCHECK(mime_type == base::ToLowerASCII(mime_type));
[email protected]20a793e2010-10-12 06:50:08247 DCHECK(info);
248
[email protected]68598072011-07-29 08:21:28249 if (!use_stale)
pimane8c57ea2016-04-06 01:19:36250 LoadPlugins();
[email protected]20305ec2011-01-21 04:55:52251 base::AutoLock lock(lock_);
[email protected]68598072011-07-29 08:21:28252 if (use_stale)
[email protected]a33fa9d2012-05-16 14:47:49253 *use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE);
[email protected]f4d43cb2013-10-28 20:53:07254 info->clear();
[email protected]20a793e2010-10-12 06:50:08255 if (actual_mime_types)
256 actual_mime_types->clear();
257
[email protected]a3ef4832013-02-02 05:12:33258 std::set<base::FilePath> visited_plugins;
[email protected]20a793e2010-10-12 06:50:08259
[email protected]dfba8762011-09-02 12:49:54260 // Add in plugins by mime type.
[email protected]68b63bc2012-08-20 22:14:03261 for (size_t i = 0; i < plugins_list_.size(); ++i) {
262 if (SupportsType(plugins_list_[i], mime_type, allow_wildcard)) {
[email protected]a3ef4832013-02-02 05:12:33263 base::FilePath path = plugins_list_[i].path;
[email protected]68b63bc2012-08-20 22:14:03264 if (visited_plugins.insert(path).second) {
[email protected]f4d43cb2013-10-28 20:53:07265 info->push_back(plugins_list_[i]);
[email protected]68b63bc2012-08-20 22:14:03266 if (actual_mime_types)
267 actual_mime_types->push_back(mime_type);
[email protected]20a793e2010-10-12 06:50:08268 }
269 }
270 }
271
[email protected]dfba8762011-09-02 12:49:54272 // Add in plugins by url.
tommyclie86b2982015-03-16 20:16:45273 // We do not permit URL-sniff based plugin MIME type overrides aside from
[email protected]cafe0d02013-07-23 15:16:20274 // the case where the "type" was initially missing.
275 // We collected stats to determine this approach isn't a major compat issue,
276 // and we defend against content confusion attacks in various cases, such
tommyclie86b2982015-03-16 20:16:45277 // as when the user doesn't have the Flash plugin enabled.
[email protected]20a793e2010-10-12 06:50:08278 std::string path = url.path();
279 std::string::size_type last_dot = path.rfind('.');
[email protected]cafe0d02013-07-23 15:16:20280 if (last_dot != std::string::npos && mime_type.empty()) {
[email protected]cb1f4ac2014-08-07 16:55:42281 std::string extension =
brettw8e2106d2015-08-11 19:30:22282 base::ToLowerASCII(base::StringPiece(path).substr(last_dot + 1));
[email protected]20a793e2010-10-12 06:50:08283 std::string actual_mime_type;
[email protected]68b63bc2012-08-20 22:14:03284 for (size_t i = 0; i < plugins_list_.size(); ++i) {
285 if (SupportsExtension(plugins_list_[i], extension, &actual_mime_type)) {
Dave Tapuska4876a48f2018-02-16 19:02:39286 base::FilePath plugin_path = plugins_list_[i].path;
287 if (visited_plugins.insert(plugin_path).second) {
[email protected]f4d43cb2013-10-28 20:53:07288 info->push_back(plugins_list_[i]);
[email protected]68b63bc2012-08-20 22:14:03289 if (actual_mime_types)
290 actual_mime_types->push_back(actual_mime_type);
[email protected]20a793e2010-10-12 06:50:08291 }
292 }
293 }
294 }
[email protected]20a793e2010-10-12 06:50:08295}
296
[email protected]797d9a62013-09-13 23:36:07297void PluginList::RemoveExtraPluginPathLocked(
298 const base::FilePath& plugin_path) {
299 lock_.AssertAcquired();
300 std::vector<base::FilePath>::iterator it =
301 std::find(extra_plugin_paths_.begin(), extra_plugin_paths_.end(),
302 plugin_path);
303 if (it != extra_plugin_paths_.end())
304 extra_plugin_paths_.erase(it);
305}
306
[email protected]a466a0c2010-10-02 00:42:39307PluginList::~PluginList() {
308}
309
initial.commitf5b16fe2008-07-27 00:20:51310
[email protected]29e2fb42013-07-19 01:13:47311} // namespace content