15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/common/plugin_list.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/sys_string_conversions.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
16ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "content/public/common/content_switches.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/mime_util.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/common/plugin_constants_win.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace content {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochbase::LazyInstance<PluginList> g_singleton = LAZY_INSTANCE_INITIALIZER;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginList* PluginList::Singleton() {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_singleton.Pointer();
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginList::DebugPluginLoading() {
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return base::CommandLine::ForCurrentProcess()->HasSwitch(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switches::kDebugPluginLoading);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void PluginList::DisablePluginsDiscovery() {
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  plugins_discovery_disabled_ = true;
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginList::RefreshPlugins() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loading_state_ = LOADING_STATE_NEEDS_REFRESH;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PluginList::AddExtraPluginPath(const base::FilePath& plugin_path) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chrome OS only loads plugins from /opt/google/chrome/plugins.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_CHROMEOS)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra_plugin_paths_.push_back(plugin_path);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PluginList::RemoveExtraPluginPath(const base::FilePath& plugin_path) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  RemoveExtraPluginPathLocked(plugin_path);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PluginList::AddExtraPluginDir(const base::FilePath& plugin_dir) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chrome OS only loads plugins from /opt/google/chrome/plugins.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_CHROMEOS)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra_plugin_dirs_.push_back(plugin_dir);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PluginList::RegisterInternalPlugin(const WebPluginInfo& info,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        bool add_at_beginning) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  internal_plugins_.push_back(info);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (add_at_beginning) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Newer registrations go earlier in the list so they can override the MIME
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // types of older registrations.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extra_plugin_paths_.insert(extra_plugin_paths_.begin(), info.path);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extra_plugin_paths_.push_back(info.path);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PluginList::UnregisterInternalPlugin(const base::FilePath& path) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool found = false;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < internal_plugins_.size(); i++) {
91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (internal_plugins_[i].path == path) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      internal_plugins_.erase(internal_plugins_.begin() + i);
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      found = true;
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      break;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(found);
98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  RemoveExtraPluginPathLocked(path);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginList::GetInternalPlugins(
102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    std::vector<WebPluginInfo>* internal_plugins) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (std::vector<WebPluginInfo>::iterator it = internal_plugins_.begin();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != internal_plugins_.end();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
108ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    internal_plugins->push_back(*it);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool PluginList::ReadPluginInfo(const base::FilePath& filename,
113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                WebPluginInfo* info) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(lock_);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < internal_plugins_.size(); ++i) {
117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (filename == internal_plugins_[i].path) {
118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        *info = internal_plugins_[i];
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return PluginList::ReadWebPluginInfo(filename, info);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginList::ParseMimeTypes(
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& mime_types_str,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& file_extensions_str,
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::string16& mime_type_descriptions_str,
132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    std::vector<WebPluginMimeType>* parsed_mime_types) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> mime_types, file_extensions;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<base::string16> descriptions;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(mime_types_str, '|', &mime_types);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(file_extensions_str, '|', &file_extensions);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(mime_type_descriptions_str, '|', &descriptions);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parsed_mime_types->clear();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mime_types.empty())
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < mime_types.size(); ++i) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebPluginMimeType mime_type;
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    mime_type.mime_type = base::StringToLowerASCII(mime_types[i]);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_extensions.size() > i)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::SplitString(file_extensions[i], ',', &mime_type.file_extensions);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (descriptions.size() > i) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mime_type.description = descriptions[i];
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // On Windows, the description likely has a list of file extensions
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // embedded in it (e.g. "SurfWriter file (*.swr)"). Remove an extension
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // list from the description if it is present.
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size_t ext = mime_type.description.find(base::ASCIIToUTF16("(*"));
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (ext != base::string16::npos) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ext > 1 && mime_type.description[ext - 1] == ' ')
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ext--;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mime_type.description.erase(ext);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parsed_mime_types->push_back(mime_type);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginList::PluginList()
1729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    : loading_state_(LOADING_STATE_NEEDS_REFRESH),
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      plugins_discovery_disabled_(false) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool PluginList::PrepareForPluginLoading() {
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::AutoLock lock(lock_);
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (loading_state_ == LOADING_STATE_UP_TO_DATE)
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
180ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  loading_state_ = LOADING_STATE_REFRESHING;
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PluginList::LoadPlugins(bool include_npapi) {
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!PrepareForPluginLoading())
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::vector<WebPluginInfo> new_plugins;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure will_load_callback;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(lock_);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    will_load_callback = will_load_plugins_callback_;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!will_load_callback.is_null())
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    will_load_callback.Run();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::FilePath> plugin_paths;
199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  GetPluginPathsToLoad(&plugin_paths, include_npapi);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<base::FilePath>::const_iterator it = plugin_paths.begin();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != plugin_paths.end();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebPluginInfo plugin_info;
205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LoadPluginIntoPluginList(*it, &new_plugins, &plugin_info);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetPlugins(new_plugins);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PluginList::LoadPluginIntoPluginList(
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path,
213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    std::vector<WebPluginInfo>* plugins,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebPluginInfo* plugin_info) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, PluginList::DebugPluginLoading())
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Loading plugin " << path.value();
217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!ReadPluginInfo(path, plugin_info))
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldLoadPluginUsingPluginList(*plugin_info, plugins))
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) && !defined(NDEBUG)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path.BaseName().value() != L"npspy.dll")  // Make an exception for NPSPY
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < plugin_info->mime_types.size(); ++i) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO: don't load global handlers for now.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // WebKit hands to the Plugin before it tries
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to handle mimeTypes on its own.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string &mime_type = plugin_info->mime_types[i].mime_type;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (mime_type == "*")
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  plugins->push_back(*plugin_info);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PluginList::GetPluginPathsToLoad(std::vector<base::FilePath>* plugin_paths,
241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                      bool include_npapi) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't want to hold the lock while loading new plugins, so we don't block
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // other methods if they're called on other threads.
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::FilePath> extra_plugin_paths;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::FilePath> extra_plugin_dirs;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(lock_);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extra_plugin_paths = extra_plugin_paths_;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extra_plugin_dirs = extra_plugin_dirs_;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < extra_plugin_paths.size(); ++i) {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path = extra_plugin_paths[i];
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (std::find(plugin_paths->begin(), plugin_paths->end(), path) !=
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        plugin_paths->end()) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plugin_paths->push_back(path);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (include_npapi) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // A bit confusingly, this function is used to load Pepper plugins as well.
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Those are all internal plugins so we have to use extra_plugin_paths.
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < extra_plugin_dirs.size(); ++i)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPluginsInDir(extra_plugin_dirs[i], plugin_paths);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<base::FilePath> directories_to_scan;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GetPluginDirectories(&directories_to_scan);
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < directories_to_scan.size(); ++i)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPluginsInDir(directories_to_scan[i], plugin_paths);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
2737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    GetPluginPathsFromRegistry(plugin_paths);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
278ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PluginList::SetPlugins(const std::vector<WebPluginInfo>& plugins) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If we haven't been invalidated in the mean time, mark the plug-in list as
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // up-to-date.
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (loading_state_ != LOADING_STATE_NEEDS_REFRESH)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    loading_state_ = LOADING_STATE_UP_TO_DATE;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  plugins_list_ = plugins;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginList::set_will_load_plugins_callback(const base::Closure& callback) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  will_load_plugins_callback_ = callback;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins,
295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                            bool include_npapi) {
296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  LoadPlugins(include_npapi);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool PluginList::GetPluginsNoRefresh(std::vector<WebPluginInfo>* plugins) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return loading_state_ == LOADING_STATE_UP_TO_DATE;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PluginList::GetPluginInfoArray(
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& mime_type,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool allow_wildcard,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* use_stale,
313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    bool include_npapi,
314ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    std::vector<WebPluginInfo>* info,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string>* actual_mime_types) {
3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(mime_type == base::StringToLowerASCII(mime_type));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(info);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!use_stale)
320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LoadPlugins(include_npapi);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(lock_);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_stale)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->clear();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (actual_mime_types)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    actual_mime_types->clear();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::set<base::FilePath> visited_plugins;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add in plugins by mime type.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < plugins_list_.size(); ++i) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SupportsType(plugins_list_[i], mime_type, allow_wildcard)) {
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath path = plugins_list_[i].path;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (visited_plugins.insert(path).second) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        info->push_back(plugins_list_[i]);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (actual_mime_types)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          actual_mime_types->push_back(mime_type);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add in plugins by url.
343a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // We do not permit URL-sniff based plug-in MIME type overrides aside from
344a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // the case where the "type" was initially missing.
345a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // We collected stats to determine this approach isn't a major compat issue,
346a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // and we defend against content confusion attacks in various cases, such
347a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // as when the user doesn't have the Flash plug-in enabled.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string path = url.path();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::size_type last_dot = path.rfind('.');
350a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if (last_dot != std::string::npos && mime_type.empty()) {
3516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    std::string extension =
3526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        base::StringToLowerASCII(std::string(path, last_dot+1));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string actual_mime_type;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < plugins_list_.size(); ++i) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (SupportsExtension(plugins_list_[i], extension, &actual_mime_type)) {
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::FilePath path = plugins_list_[i].path;
357a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        if (visited_plugins.insert(path).second) {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          info->push_back(plugins_list_[i]);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (actual_mime_types)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            actual_mime_types->push_back(actual_mime_type);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool PluginList::SupportsType(const WebPluginInfo& plugin,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string& mime_type,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool allow_wildcard) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Webkit will ask for a plugin to handle empty mime types.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mime_type.empty())
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
375ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const WebPluginMimeType& mime_info = plugin.mime_types[i];
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net::MatchesMimeType(mime_info.mime_type, mime_type)) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!allow_wildcard && mime_info.mime_type == "*")
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool PluginList::SupportsExtension(const WebPluginInfo& plugin,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& extension,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   std::string* actual_mime_type) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
389ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const WebPluginMimeType& mime_type = plugin.mime_types[i];
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < mime_type.file_extensions.size(); ++j) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (mime_type.file_extensions[j] == extension) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (actual_mime_type)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *actual_mime_type = mime_type.mime_type;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
401d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void PluginList::RemoveExtraPluginPathLocked(
402d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const base::FilePath& plugin_path) {
403d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  lock_.AssertAcquired();
404d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::vector<base::FilePath>::iterator it =
405d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      std::find(extra_plugin_paths_.begin(), extra_plugin_paths_.end(),
406d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                plugin_path);
407d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (it != extra_plugin_paths_.end())
408d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    extra_plugin_paths_.erase(it);
409d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
410d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PluginList::~PluginList() {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}  // namespace content
416