blob: 76a44b440e7e932f4c5f40bc56b3a9a03c3dd4f3 [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"
[email protected]d778e0422013-03-06 18:10:2214#include "base/strings/string_split.h"
[email protected]f63582d2013-06-11 22:52:5415#include "base/strings/string_util.h"
[email protected]13ac53532013-03-30 00:27:0016#include "base/strings/sys_string_conversions.h"
[email protected]906265872013-06-07 22:40:4517#include "base/strings/utf_string_conversions.h"
avia9aa7a82015-12-25 03:06:3118#include "build/build_config.h"
[email protected]1bbbc492013-08-09 00:36:1519#include "content/public/common/content_switches.h"
[email protected]b7344502009-01-12 19:43:4420#include "net/base/mime_util.h"
[email protected]ad677772013-06-29 14:18:3821#include "url/gurl.h"
initial.commitf5b16fe2008-07-27 00:20:5122
[email protected]29e2fb42013-07-19 01:13:4723namespace content {
24
25namespace {
[email protected]0b300172012-09-27 16:11:5226
scottmg5e65e3a2017-03-08 08:48:4627base::LazyInstance<PluginList>::DestructorAtExit g_singleton =
28 LAZY_INSTANCE_INITIALIZER;
[email protected]123a04962011-11-03 15:43:0129
[email protected]3b91edbe2012-09-27 22:49:2330} // namespace
[email protected]123a04962011-11-03 15:43:0131
[email protected]19537112009-01-21 19:38:1432// static
initial.commitf5b16fe2008-07-27 00:20:5133PluginList* PluginList::Singleton() {
[email protected]35fa6a22009-08-15 00:04:0134 return g_singleton.Pointer();
initial.commitf5b16fe2008-07-27 00:20:5135}
36
[email protected]4e59e812010-04-06 20:51:1637void PluginList::RefreshPlugins() {
[email protected]20305ec2011-01-21 04:55:5238 base::AutoLock lock(lock_);
[email protected]a33fa9d2012-05-16 14:47:4939 loading_state_ = LOADING_STATE_NEEDS_REFRESH;
[email protected]367230c52009-02-21 01:44:3040}
initial.commitf5b16fe2008-07-27 00:20:5141
[email protected]d7bd3e52013-07-21 04:29:2042void PluginList::RegisterInternalPlugin(const WebPluginInfo& info,
[email protected]c6f3dea2012-01-14 02:23:1143 bool add_at_beginning) {
[email protected]20305ec2011-01-21 04:55:5244 base::AutoLock lock(lock_);
[email protected]8ca37f42011-11-02 16:03:4145
[email protected]fee3a982013-07-18 18:12:4846 internal_plugins_.push_back(info);
[email protected]8ca37f42011-11-02 16:03:4147 if (add_at_beginning) {
48 // Newer registrations go earlier in the list so they can override the MIME
49 // types of older registrations.
[email protected]c6f3dea2012-01-14 02:23:1150 extra_plugin_paths_.insert(extra_plugin_paths_.begin(), info.path);
[email protected]8ca37f42011-11-02 16:03:4151 } else {
[email protected]c6f3dea2012-01-14 02:23:1152 extra_plugin_paths_.push_back(info.path);
[email protected]8ca37f42011-11-02 16:03:4153 }
[email protected]f99c73ad2011-01-11 00:43:4454}
55
[email protected]a3ef4832013-02-02 05:12:3356void PluginList::UnregisterInternalPlugin(const base::FilePath& path) {
[email protected]20305ec2011-01-21 04:55:5257 base::AutoLock lock(lock_);
[email protected]797d9a62013-09-13 23:36:0758 bool found = false;
[email protected]00c39612010-03-06 02:53:2859 for (size_t i = 0; i < internal_plugins_.size(); i++) {
[email protected]fee3a982013-07-18 18:12:4860 if (internal_plugins_[i].path == path) {
[email protected]00c39612010-03-06 02:53:2861 internal_plugins_.erase(internal_plugins_.begin() + i);
[email protected]797d9a62013-09-13 23:36:0762 found = true;
63 break;
[email protected]00c39612010-03-06 02:53:2864 }
65 }
[email protected]797d9a62013-09-13 23:36:0766 DCHECK(found);
67 RemoveExtraPluginPathLocked(path);
[email protected]00c39612010-03-06 02:53:2868}
69
[email protected]d4af1e72011-10-21 17:45:4370void PluginList::GetInternalPlugins(
[email protected]d7bd3e52013-07-21 04:29:2071 std::vector<WebPluginInfo>* internal_plugins) {
[email protected]d4af1e72011-10-21 17:45:4372 base::AutoLock lock(lock_);
73
[email protected]d7bd3e52013-07-21 04:29:2074 for (std::vector<WebPluginInfo>::iterator it = internal_plugins_.begin();
[email protected]d4af1e72011-10-21 17:45:4375 it != internal_plugins_.end();
76 ++it) {
[email protected]fee3a982013-07-18 18:12:4877 internal_plugins->push_back(*it);
[email protected]d4af1e72011-10-21 17:45:4378 }
79}
80
[email protected]a3ef4832013-02-02 05:12:3381bool PluginList::ReadPluginInfo(const base::FilePath& filename,
[email protected]d7bd3e52013-07-21 04:29:2082 WebPluginInfo* info) {
pimane8c57ea2016-04-06 01:19:3683 base::AutoLock lock(lock_);
84 for (const auto& plugin : internal_plugins_) {
85 if (filename == plugin.path) {
86 *info = plugin;
87 return true;
[email protected]8ff26092009-01-29 01:53:2488 }
89 }
pimane8c57ea2016-04-06 01:19:3690 return false;
[email protected]8ff26092009-01-29 01:53:2491}
92
[email protected]4e59e812010-04-06 20:51:1693PluginList::PluginList()
pimane8c57ea2016-04-06 01:19:3694 : loading_state_(LOADING_STATE_NEEDS_REFRESH) {
[email protected]b83ff222011-01-24 17:37:1295}
initial.commitf5b16fe2008-07-27 00:20:5196
[email protected]aa7f8802014-01-27 16:56:3297bool PluginList::PrepareForPluginLoading() {
98 base::AutoLock lock(lock_);
99 if (loading_state_ == LOADING_STATE_UP_TO_DATE)
100 return false;
[email protected]a33fa9d2012-05-16 14:47:49101
[email protected]aa7f8802014-01-27 16:56:32102 loading_state_ = LOADING_STATE_REFRESHING;
103 return true;
104}
105
pimane8c57ea2016-04-06 01:19:36106void PluginList::LoadPlugins() {
[email protected]aa7f8802014-01-27 16:56:32107 if (!PrepareForPluginLoading())
108 return;
[email protected]a466a0c2010-10-02 00:42:39109
[email protected]d7bd3e52013-07-21 04:29:20110 std::vector<WebPluginInfo> new_plugins;
[email protected]9a60ccb2013-07-19 22:23:36111 base::Closure will_load_callback;
112 {
113 base::AutoLock lock(lock_);
114 will_load_callback = will_load_plugins_callback_;
115 }
116 if (!will_load_callback.is_null())
117 will_load_callback.Run();
118
119 std::vector<base::FilePath> plugin_paths;
pimane8c57ea2016-04-06 01:19:36120 GetPluginPathsToLoad(&plugin_paths);
[email protected]9a60ccb2013-07-19 22:23:36121
122 for (std::vector<base::FilePath>::const_iterator it = plugin_paths.begin();
123 it != plugin_paths.end();
124 ++it) {
125 WebPluginInfo plugin_info;
126 LoadPluginIntoPluginList(*it, &new_plugins, &plugin_info);
127 }
[email protected]1134a002010-10-08 08:03:14128
[email protected]aa7f8802014-01-27 16:56:32129 SetPlugins(new_plugins);
initial.commitf5b16fe2008-07-27 00:20:51130}
131
[email protected]68b63bc2012-08-20 22:14:03132bool PluginList::LoadPluginIntoPluginList(
[email protected]a3ef4832013-02-02 05:12:33133 const base::FilePath& path,
[email protected]d7bd3e52013-07-21 04:29:20134 std::vector<WebPluginInfo>* plugins,
[email protected]68b63bc2012-08-20 22:14:03135 WebPluginInfo* plugin_info) {
[email protected]fee3a982013-07-18 18:12:48136 if (!ReadPluginInfo(path, plugin_info))
[email protected]68b63bc2012-08-20 22:14:03137 return false;
138
pimane8c57ea2016-04-06 01:19:36139 // TODO(piman): Do we still need this after NPAPI removal?
140 for (size_t i = 0; i < plugin_info->mime_types.size(); ++i) {
141 // TODO: don't load global handlers for now.
142 // WebKit hands to the Plugin before it tries
143 // to handle mimeTypes on its own.
144 const std::string &mime_type = plugin_info->mime_types[i].mime_type;
145 if (mime_type == "*")
146 return false;
[email protected]68b63bc2012-08-20 22:14:03147 }
148 plugins->push_back(*plugin_info);
149 return true;
150}
151
pimane8c57ea2016-04-06 01:19:36152void PluginList::GetPluginPathsToLoad(
153 std::vector<base::FilePath>* plugin_paths) {
[email protected]d4af1e72011-10-21 17:45:43154 // Don't want to hold the lock while loading new plugins, so we don't block
155 // other methods if they're called on other threads.
[email protected]a3ef4832013-02-02 05:12:33156 std::vector<base::FilePath> extra_plugin_paths;
[email protected]d4af1e72011-10-21 17:45:43157 {
158 base::AutoLock lock(lock_);
159 extra_plugin_paths = extra_plugin_paths_;
[email protected]49125952011-09-27 18:05:15160 }
[email protected]d4af1e72011-10-21 17:45:43161
[email protected]d4af1e72011-10-21 17:45:43162 for (size_t i = 0; i < extra_plugin_paths.size(); ++i) {
[email protected]a3ef4832013-02-02 05:12:33163 const base::FilePath& path = extra_plugin_paths[i];
[email protected]d4af1e72011-10-21 17:45:43164 if (std::find(plugin_paths->begin(), plugin_paths->end(), path) !=
165 plugin_paths->end()) {
166 continue;
167 }
168 plugin_paths->push_back(path);
169 }
[email protected]49125952011-09-27 18:05:15170}
171
[email protected]d7bd3e52013-07-21 04:29:20172void PluginList::SetPlugins(const std::vector<WebPluginInfo>& plugins) {
[email protected]49125952011-09-27 18:05:15173 base::AutoLock lock(lock_);
174
tommyclie86b2982015-03-16 20:16:45175 // If we haven't been invalidated in the mean time, mark the plugin list as
thakis3e861de2016-06-14 14:24:01176 // up to date.
[email protected]aa7f8802014-01-27 16:56:32177 if (loading_state_ != LOADING_STATE_NEEDS_REFRESH)
178 loading_state_ = LOADING_STATE_UP_TO_DATE;
[email protected]49125952011-09-27 18:05:15179
[email protected]aa7f8802014-01-27 16:56:32180 plugins_list_ = plugins;
[email protected]49125952011-09-27 18:05:15181}
182
183void PluginList::set_will_load_plugins_callback(const base::Closure& callback) {
184 base::AutoLock lock(lock_);
185 will_load_plugins_callback_ = callback;
186}
187
pimane8c57ea2016-04-06 01:19:36188void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) {
189 LoadPlugins();
[email protected]20305ec2011-01-21 04:55:52190 base::AutoLock lock(lock_);
[email protected]68b63bc2012-08-20 22:14:03191 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
initial.commitf5b16fe2008-07-27 00:20:51192}
193
[email protected]d7bd3e52013-07-21 04:29:20194bool PluginList::GetPluginsNoRefresh(std::vector<WebPluginInfo>* plugins) {
[email protected]49125952011-09-27 18:05:15195 base::AutoLock lock(lock_);
[email protected]68b63bc2012-08-20 22:14:03196 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
197
[email protected]480c7cc2012-06-29 17:38:44198 return loading_state_ == LOADING_STATE_UP_TO_DATE;
[email protected]49125952011-09-27 18:05:15199}
200
[email protected]9bcdced72010-12-07 20:51:36201void PluginList::GetPluginInfoArray(
202 const GURL& url,
203 const std::string& mime_type,
204 bool allow_wildcard,
[email protected]68598072011-07-29 08:21:28205 bool* use_stale,
[email protected]d7bd3e52013-07-21 04:29:20206 std::vector<WebPluginInfo>* info,
[email protected]9bcdced72010-12-07 20:51:36207 std::vector<std::string>* actual_mime_types) {
brettw8e2106d2015-08-11 19:30:22208 DCHECK(mime_type == base::ToLowerASCII(mime_type));
[email protected]20a793e2010-10-12 06:50:08209 DCHECK(info);
210
[email protected]68598072011-07-29 08:21:28211 if (!use_stale)
pimane8c57ea2016-04-06 01:19:36212 LoadPlugins();
[email protected]20305ec2011-01-21 04:55:52213 base::AutoLock lock(lock_);
[email protected]68598072011-07-29 08:21:28214 if (use_stale)
[email protected]a33fa9d2012-05-16 14:47:49215 *use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE);
[email protected]f4d43cb2013-10-28 20:53:07216 info->clear();
[email protected]20a793e2010-10-12 06:50:08217 if (actual_mime_types)
218 actual_mime_types->clear();
219
[email protected]a3ef4832013-02-02 05:12:33220 std::set<base::FilePath> visited_plugins;
[email protected]20a793e2010-10-12 06:50:08221
[email protected]dfba8762011-09-02 12:49:54222 // Add in plugins by mime type.
[email protected]68b63bc2012-08-20 22:14:03223 for (size_t i = 0; i < plugins_list_.size(); ++i) {
224 if (SupportsType(plugins_list_[i], mime_type, allow_wildcard)) {
[email protected]a3ef4832013-02-02 05:12:33225 base::FilePath path = plugins_list_[i].path;
[email protected]68b63bc2012-08-20 22:14:03226 if (visited_plugins.insert(path).second) {
[email protected]f4d43cb2013-10-28 20:53:07227 info->push_back(plugins_list_[i]);
[email protected]68b63bc2012-08-20 22:14:03228 if (actual_mime_types)
229 actual_mime_types->push_back(mime_type);
[email protected]20a793e2010-10-12 06:50:08230 }
231 }
232 }
233
[email protected]dfba8762011-09-02 12:49:54234 // Add in plugins by url.
tommyclie86b2982015-03-16 20:16:45235 // We do not permit URL-sniff based plugin MIME type overrides aside from
[email protected]cafe0d02013-07-23 15:16:20236 // the case where the "type" was initially missing.
237 // We collected stats to determine this approach isn't a major compat issue,
238 // and we defend against content confusion attacks in various cases, such
tommyclie86b2982015-03-16 20:16:45239 // as when the user doesn't have the Flash plugin enabled.
[email protected]20a793e2010-10-12 06:50:08240 std::string path = url.path();
241 std::string::size_type last_dot = path.rfind('.');
[email protected]cafe0d02013-07-23 15:16:20242 if (last_dot != std::string::npos && mime_type.empty()) {
[email protected]cb1f4ac2014-08-07 16:55:42243 std::string extension =
brettw8e2106d2015-08-11 19:30:22244 base::ToLowerASCII(base::StringPiece(path).substr(last_dot + 1));
[email protected]20a793e2010-10-12 06:50:08245 std::string actual_mime_type;
[email protected]68b63bc2012-08-20 22:14:03246 for (size_t i = 0; i < plugins_list_.size(); ++i) {
247 if (SupportsExtension(plugins_list_[i], extension, &actual_mime_type)) {
[email protected]a3ef4832013-02-02 05:12:33248 base::FilePath path = plugins_list_[i].path;
[email protected]cafe0d02013-07-23 15:16:20249 if (visited_plugins.insert(path).second) {
[email protected]f4d43cb2013-10-28 20:53:07250 info->push_back(plugins_list_[i]);
[email protected]68b63bc2012-08-20 22:14:03251 if (actual_mime_types)
252 actual_mime_types->push_back(actual_mime_type);
[email protected]20a793e2010-10-12 06:50:08253 }
254 }
255 }
256 }
[email protected]20a793e2010-10-12 06:50:08257}
258
[email protected]d7bd3e52013-07-21 04:29:20259bool PluginList::SupportsType(const WebPluginInfo& plugin,
[email protected]b83ff222011-01-24 17:37:12260 const std::string& mime_type,
261 bool allow_wildcard) {
262 // Webkit will ask for a plugin to handle empty mime types.
263 if (mime_type.empty())
264 return false;
265
266 for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
[email protected]d7bd3e52013-07-21 04:29:20267 const WebPluginMimeType& mime_info = plugin.mime_types[i];
[email protected]b83ff222011-01-24 17:37:12268 if (net::MatchesMimeType(mime_info.mime_type, mime_type)) {
269 if (!allow_wildcard && mime_info.mime_type == "*")
270 continue;
271 return true;
272 }
273 }
274 return false;
275}
276
[email protected]d7bd3e52013-07-21 04:29:20277bool PluginList::SupportsExtension(const WebPluginInfo& plugin,
[email protected]b83ff222011-01-24 17:37:12278 const std::string& extension,
279 std::string* actual_mime_type) {
280 for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
[email protected]d7bd3e52013-07-21 04:29:20281 const WebPluginMimeType& mime_type = plugin.mime_types[i];
[email protected]b83ff222011-01-24 17:37:12282 for (size_t j = 0; j < mime_type.file_extensions.size(); ++j) {
283 if (mime_type.file_extensions[j] == extension) {
284 if (actual_mime_type)
285 *actual_mime_type = mime_type.mime_type;
286 return true;
[email protected]a466a0c2010-10-02 00:42:39287 }
288 }
289 }
[email protected]b83ff222011-01-24 17:37:12290 return false;
[email protected]a466a0c2010-10-02 00:42:39291}
292
[email protected]797d9a62013-09-13 23:36:07293void PluginList::RemoveExtraPluginPathLocked(
294 const base::FilePath& plugin_path) {
295 lock_.AssertAcquired();
296 std::vector<base::FilePath>::iterator it =
297 std::find(extra_plugin_paths_.begin(), extra_plugin_paths_.end(),
298 plugin_path);
299 if (it != extra_plugin_paths_.end())
300 extra_plugin_paths_.erase(it);
301}
302
[email protected]a466a0c2010-10-02 00:42:39303PluginList::~PluginList() {
304}
305
initial.commitf5b16fe2008-07-27 00:20:51306
[email protected]29e2fb42013-07-19 01:13:47307} // namespace content