OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/plugin_list.h" | 5 #include "content/common/plugin_list.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/version.h" |
16 #include "content/public/common/content_switches.h" | 17 #include "content/public/common/content_switches.h" |
17 #include "net/base/mime_util.h" | 18 #include "net/base/mime_util.h" |
18 #include "url/gurl.h" | 19 #include "url/gurl.h" |
19 | 20 |
20 #if defined(OS_WIN) | 21 #if defined(OS_WIN) |
21 #include "content/common/plugin_constants_win.h" | 22 #include "content/common/plugin_constants_win.h" |
22 #endif | 23 #endif |
23 | 24 |
24 namespace content { | 25 namespace content { |
25 | 26 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 mime_type.description.erase(ext); | 162 mime_type.description.erase(ext); |
162 } | 163 } |
163 } | 164 } |
164 | 165 |
165 parsed_mime_types->push_back(mime_type); | 166 parsed_mime_types->push_back(mime_type); |
166 } | 167 } |
167 | 168 |
168 return true; | 169 return true; |
169 } | 170 } |
170 | 171 |
| 172 bool PluginList::VersionComparator::operator()(const WebPluginInfo& lhs, |
| 173 const WebPluginInfo& rhs) const { |
| 174 Version lhs_version; |
| 175 Version rhs_version; |
| 176 WebPluginInfo::CreateVersionFromString(lhs.version, &lhs_version); |
| 177 WebPluginInfo::CreateVersionFromString(rhs.version, &rhs_version); |
| 178 if (!lhs_version.IsValid()) |
| 179 lhs_version = Version("0"); |
| 180 if (!rhs_version.IsValid()) |
| 181 rhs_version = Version("0"); |
| 182 |
| 183 return lhs_version.CompareTo(rhs_version) > 0; |
| 184 } |
| 185 |
171 PluginList::PluginList() | 186 PluginList::PluginList() |
172 : loading_state_(LOADING_STATE_NEEDS_REFRESH), | 187 : loading_state_(LOADING_STATE_NEEDS_REFRESH), |
173 plugins_discovery_disabled_(false) { | 188 plugins_discovery_disabled_(false) { |
174 } | 189 } |
175 | 190 |
176 void PluginList::LoadPlugins(bool include_npapi) { | 191 void PluginList::LoadPlugins(bool include_npapi) { |
177 { | 192 { |
178 base::AutoLock lock(lock_); | 193 base::AutoLock lock(lock_); |
179 if (loading_state_ == LOADING_STATE_UP_TO_DATE) | 194 if (loading_state_ == LOADING_STATE_UP_TO_DATE) |
180 return; | 195 return; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 std::vector<WebPluginInfo>* info, | 330 std::vector<WebPluginInfo>* info, |
316 std::vector<std::string>* actual_mime_types) { | 331 std::vector<std::string>* actual_mime_types) { |
317 DCHECK(mime_type == StringToLowerASCII(mime_type)); | 332 DCHECK(mime_type == StringToLowerASCII(mime_type)); |
318 DCHECK(info); | 333 DCHECK(info); |
319 | 334 |
320 if (!use_stale) | 335 if (!use_stale) |
321 LoadPlugins(include_npapi); | 336 LoadPlugins(include_npapi); |
322 base::AutoLock lock(lock_); | 337 base::AutoLock lock(lock_); |
323 if (use_stale) | 338 if (use_stale) |
324 *use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE); | 339 *use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE); |
325 info->clear(); | |
326 if (actual_mime_types) | 340 if (actual_mime_types) |
327 actual_mime_types->clear(); | 341 actual_mime_types->clear(); |
328 | 342 |
329 std::set<base::FilePath> visited_plugins; | 343 std::set<base::FilePath> visited_plugins; |
| 344 // Instead of pushing elements to |info| directly, we add it to |
| 345 // |matched_plugins| first so that they are sorted by version number. |
| 346 // Returning matched plugins in sorted order ensures that the first plugin |
| 347 // that is tried is always the one with the latest version. This helps in the |
| 348 // case when we have more than one plugin for given mime type. If we would |
| 349 // pick the one that is older, we would decide to block it because it's |
| 350 // outdated and wouldn't give the newer plugin a chance to run. |
| 351 std::multiset<WebPluginInfo, VersionComparator> matched_plugins; |
330 | 352 |
331 // Add in plugins by mime type. | 353 // Add in plugins by mime type. |
332 for (size_t i = 0; i < plugins_list_.size(); ++i) { | 354 for (size_t i = 0; i < plugins_list_.size(); ++i) { |
333 if (SupportsType(plugins_list_[i], mime_type, allow_wildcard)) { | 355 if (SupportsType(plugins_list_[i], mime_type, allow_wildcard)) { |
334 base::FilePath path = plugins_list_[i].path; | 356 base::FilePath path = plugins_list_[i].path; |
335 if (visited_plugins.insert(path).second) { | 357 if (visited_plugins.insert(path).second) { |
336 info->push_back(plugins_list_[i]); | 358 matched_plugins.insert(plugins_list_[i]); |
337 if (actual_mime_types) | 359 if (actual_mime_types) |
338 actual_mime_types->push_back(mime_type); | 360 actual_mime_types->push_back(mime_type); |
339 } | 361 } |
340 } | 362 } |
341 } | 363 } |
342 | 364 |
343 // Add in plugins by url. | 365 // Add in plugins by url. |
344 // We do not permit URL-sniff based plug-in MIME type overrides aside from | 366 // We do not permit URL-sniff based plug-in MIME type overrides aside from |
345 // the case where the "type" was initially missing. | 367 // the case where the "type" was initially missing. |
346 // We collected stats to determine this approach isn't a major compat issue, | 368 // We collected stats to determine this approach isn't a major compat issue, |
347 // and we defend against content confusion attacks in various cases, such | 369 // and we defend against content confusion attacks in various cases, such |
348 // as when the user doesn't have the Flash plug-in enabled. | 370 // as when the user doesn't have the Flash plug-in enabled. |
349 std::string path = url.path(); | 371 std::string path = url.path(); |
350 std::string::size_type last_dot = path.rfind('.'); | 372 std::string::size_type last_dot = path.rfind('.'); |
351 if (last_dot != std::string::npos && mime_type.empty()) { | 373 if (last_dot != std::string::npos && mime_type.empty()) { |
352 std::string extension = StringToLowerASCII(std::string(path, last_dot+1)); | 374 std::string extension = StringToLowerASCII(std::string(path, last_dot+1)); |
353 std::string actual_mime_type; | 375 std::string actual_mime_type; |
354 for (size_t i = 0; i < plugins_list_.size(); ++i) { | 376 for (size_t i = 0; i < plugins_list_.size(); ++i) { |
355 if (SupportsExtension(plugins_list_[i], extension, &actual_mime_type)) { | 377 if (SupportsExtension(plugins_list_[i], extension, &actual_mime_type)) { |
356 base::FilePath path = plugins_list_[i].path; | 378 base::FilePath path = plugins_list_[i].path; |
357 if (visited_plugins.insert(path).second) { | 379 if (visited_plugins.insert(path).second) { |
358 info->push_back(plugins_list_[i]); | 380 matched_plugins.insert(plugins_list_[i]); |
359 if (actual_mime_types) | 381 if (actual_mime_types) |
360 actual_mime_types->push_back(actual_mime_type); | 382 actual_mime_types->push_back(actual_mime_type); |
361 } | 383 } |
362 } | 384 } |
363 } | 385 } |
364 } | 386 } |
| 387 |
| 388 // Assign in sorted order. |
| 389 info->assign(matched_plugins.begin(), matched_plugins.end()); |
365 } | 390 } |
366 | 391 |
367 bool PluginList::SupportsType(const WebPluginInfo& plugin, | 392 bool PluginList::SupportsType(const WebPluginInfo& plugin, |
368 const std::string& mime_type, | 393 const std::string& mime_type, |
369 bool allow_wildcard) { | 394 bool allow_wildcard) { |
370 // Webkit will ask for a plugin to handle empty mime types. | 395 // Webkit will ask for a plugin to handle empty mime types. |
371 if (mime_type.empty()) | 396 if (mime_type.empty()) |
372 return false; | 397 return false; |
373 | 398 |
374 for (size_t i = 0; i < plugin.mime_types.size(); ++i) { | 399 for (size_t i = 0; i < plugin.mime_types.size(); ++i) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 plugin_path); | 431 plugin_path); |
407 if (it != extra_plugin_paths_.end()) | 432 if (it != extra_plugin_paths_.end()) |
408 extra_plugin_paths_.erase(it); | 433 extra_plugin_paths_.erase(it); |
409 } | 434 } |
410 | 435 |
411 PluginList::~PluginList() { | 436 PluginList::~PluginList() { |
412 } | 437 } |
413 | 438 |
414 | 439 |
415 } // namespace content | 440 } // namespace content |
OLD | NEW |