Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / plugins / plugin_finder.cc
blob626b0a3980ed24ca0a873ec4874a70598d53fbda
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
3 // found in the LICENSE file.
5 #include "chrome/browser/plugins/plugin_finder.h"
7 #include "base/bind.h"
8 #include "base/json/json_reader.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/prefs/pref_registry_simple.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/stl_util.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/plugins/plugin_metadata.h"
18 #include "chrome/common/pref_names.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/plugin_service.h"
21 #include "grit/browser_resources.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #include "url/gurl.h"
25 #if defined(ENABLE_PLUGIN_INSTALLATION)
26 #include "chrome/browser/plugins/plugin_installer.h"
27 #endif
29 using base::DictionaryValue;
30 using content::PluginService;
32 namespace {
34 typedef std::map<std::string, PluginMetadata*> PluginMap;
36 // Gets the full path of the plugin file as the identifier.
37 std::string GetLongIdentifier(const content::WebPluginInfo& plugin) {
38 return plugin.path.AsUTF8Unsafe();
41 // Gets the base name of the file path as the identifier.
42 std::string GetIdentifier(const content::WebPluginInfo& plugin) {
43 return plugin.path.BaseName().AsUTF8Unsafe();
46 // Gets the plugin group name as the plugin name if it is not empty or
47 // the filename without extension if the name is empty.
48 static base::string16 GetGroupName(const content::WebPluginInfo& plugin) {
49 if (!plugin.name.empty())
50 return plugin.name;
52 return plugin.path.BaseName().RemoveExtension().AsUTF16Unsafe();
55 void LoadMimeTypes(bool matching_mime_types,
56 const base::DictionaryValue* plugin_dict,
57 PluginMetadata* plugin) {
58 const base::ListValue* mime_types = NULL;
59 std::string list_key =
60 matching_mime_types ? "matching_mime_types" : "mime_types";
61 if (!plugin_dict->GetList(list_key, &mime_types))
62 return;
64 bool success = false;
65 for (base::ListValue::const_iterator mime_type_it = mime_types->begin();
66 mime_type_it != mime_types->end(); ++mime_type_it) {
67 std::string mime_type_str;
68 success = (*mime_type_it)->GetAsString(&mime_type_str);
69 DCHECK(success);
70 if (matching_mime_types) {
71 plugin->AddMatchingMimeType(mime_type_str);
72 } else {
73 plugin->AddMimeType(mime_type_str);
78 PluginMetadata* CreatePluginMetadata(
79 const std::string& identifier,
80 const base::DictionaryValue* plugin_dict) {
81 std::string url;
82 bool success = plugin_dict->GetString("url", &url);
83 std::string help_url;
84 plugin_dict->GetString("help_url", &help_url);
85 base::string16 name;
86 success = plugin_dict->GetString("name", &name);
87 DCHECK(success);
88 bool display_url = false;
89 plugin_dict->GetBoolean("displayurl", &display_url);
90 base::string16 group_name_matcher;
91 success = plugin_dict->GetString("group_name_matcher", &group_name_matcher);
92 DCHECK(success);
93 std::string language_str;
94 plugin_dict->GetString("lang", &language_str);
96 PluginMetadata* plugin = new PluginMetadata(identifier,
97 name,
98 display_url,
99 GURL(url),
100 GURL(help_url),
101 group_name_matcher,
102 language_str);
103 const base::ListValue* versions = NULL;
104 if (plugin_dict->GetList("versions", &versions)) {
105 for (base::ListValue::const_iterator it = versions->begin();
106 it != versions->end(); ++it) {
107 base::DictionaryValue* version_dict = NULL;
108 if (!(*it)->GetAsDictionary(&version_dict)) {
109 NOTREACHED();
110 continue;
112 std::string version;
113 success = version_dict->GetString("version", &version);
114 DCHECK(success);
115 std::string status_str;
116 success = version_dict->GetString("status", &status_str);
117 DCHECK(success);
118 PluginMetadata::SecurityStatus status =
119 PluginMetadata::SECURITY_STATUS_UP_TO_DATE;
120 success = PluginMetadata::ParseSecurityStatus(status_str, &status);
121 DCHECK(success);
122 plugin->AddVersion(Version(version), status);
126 LoadMimeTypes(false, plugin_dict, plugin);
127 LoadMimeTypes(true, plugin_dict, plugin);
128 return plugin;
131 } // namespace
133 // static
134 void PluginFinder::RegisterPrefs(PrefRegistrySimple* registry) {
135 registry->RegisterBooleanPref(prefs::kDisablePluginFinder, false);
138 // static
139 PluginFinder* PluginFinder::GetInstance() {
140 // PluginFinder::GetInstance() is the only method that's allowed to call
141 // Singleton<PluginFinder>::get().
142 return Singleton<PluginFinder>::get();
145 PluginFinder::PluginFinder() : version_(-1) {
146 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
149 void PluginFinder::Init() {
150 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
151 // Load the built-in plugin list first. If we have a newer version stored
152 // locally or download one, we will replace this one with it.
153 scoped_ptr<base::DictionaryValue> plugin_list(LoadBuiltInPluginList());
154 DCHECK(plugin_list);
155 ReinitializePlugins(plugin_list.get());
158 // static
159 base::DictionaryValue* PluginFinder::LoadBuiltInPluginList() {
160 base::StringPiece json_resource(
161 ResourceBundle::GetSharedInstance().GetRawDataResource(
162 IDR_PLUGIN_DB_JSON));
163 std::string error_str;
164 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
165 json_resource,
166 base::JSON_PARSE_RFC,
167 NULL,
168 &error_str));
169 if (!value.get()) {
170 DLOG(ERROR) << error_str;
171 return NULL;
173 if (value->GetType() != base::Value::TYPE_DICTIONARY)
174 return NULL;
175 return static_cast<base::DictionaryValue*>(value.release());
178 PluginFinder::~PluginFinder() {
179 #if defined(ENABLE_PLUGIN_INSTALLATION)
180 STLDeleteValues(&installers_);
181 #endif
182 STLDeleteValues(&identifier_plugin_);
185 #if defined(ENABLE_PLUGIN_INSTALLATION)
186 bool PluginFinder::FindPlugin(
187 const std::string& mime_type,
188 const std::string& language,
189 PluginInstaller** installer,
190 scoped_ptr<PluginMetadata>* plugin_metadata) {
191 if (g_browser_process->local_state()->GetBoolean(prefs::kDisablePluginFinder))
192 return false;
194 base::AutoLock lock(mutex_);
195 PluginMap::const_iterator metadata_it = identifier_plugin_.begin();
196 for (; metadata_it != identifier_plugin_.end(); ++metadata_it) {
197 if (language == metadata_it->second->language() &&
198 metadata_it->second->HasMimeType(mime_type)) {
199 *plugin_metadata = metadata_it->second->Clone();
201 std::map<std::string, PluginInstaller*>::const_iterator installer_it =
202 installers_.find(metadata_it->second->identifier());
203 DCHECK(installer_it != installers_.end());
204 *installer = installer_it->second;
205 return true;
208 return false;
211 bool PluginFinder::FindPluginWithIdentifier(
212 const std::string& identifier,
213 PluginInstaller** installer,
214 scoped_ptr<PluginMetadata>* plugin_metadata) {
215 base::AutoLock lock(mutex_);
216 PluginMap::const_iterator metadata_it = identifier_plugin_.find(identifier);
217 if (metadata_it == identifier_plugin_.end())
218 return false;
219 *plugin_metadata = metadata_it->second->Clone();
221 if (installer) {
222 std::map<std::string, PluginInstaller*>::const_iterator installer_it =
223 installers_.find(identifier);
224 if (installer_it == installers_.end())
225 return false;
226 *installer = installer_it->second;
228 return true;
230 #endif
232 void PluginFinder::ReinitializePlugins(
233 const base::DictionaryValue* plugin_list) {
234 base::AutoLock lock(mutex_);
235 int version = 0; // If no version is defined, we default to 0.
236 const char kVersionKey[] = "x-version";
237 plugin_list->GetInteger(kVersionKey, &version);
238 if (version <= version_)
239 return;
241 version_ = version;
243 STLDeleteValues(&identifier_plugin_);
245 for (base::DictionaryValue::Iterator plugin_it(*plugin_list);
246 !plugin_it.IsAtEnd(); plugin_it.Advance()) {
247 const base::DictionaryValue* plugin = NULL;
248 const std::string& identifier = plugin_it.key();
249 if (plugin_list->GetDictionaryWithoutPathExpansion(identifier, &plugin)) {
250 DCHECK(!identifier_plugin_[identifier]);
251 identifier_plugin_[identifier] = CreatePluginMetadata(identifier, plugin);
253 #if defined(ENABLE_PLUGIN_INSTALLATION)
254 if (installers_.find(identifier) == installers_.end())
255 installers_[identifier] = new PluginInstaller();
256 #endif
261 base::string16 PluginFinder::FindPluginNameWithIdentifier(
262 const std::string& identifier) {
263 base::AutoLock lock(mutex_);
264 PluginMap::const_iterator it = identifier_plugin_.find(identifier);
265 base::string16 name;
266 if (it != identifier_plugin_.end())
267 name = it->second->name();
269 return name.empty() ? base::UTF8ToUTF16(identifier) : name;
272 scoped_ptr<PluginMetadata> PluginFinder::GetPluginMetadata(
273 const content::WebPluginInfo& plugin) {
274 base::AutoLock lock(mutex_);
275 for (PluginMap::const_iterator it = identifier_plugin_.begin();
276 it != identifier_plugin_.end(); ++it) {
277 if (!it->second->MatchesPlugin(plugin))
278 continue;
280 return it->second->Clone();
283 // The plugin metadata was not found, create a dummy one holding
284 // the name, identifier and group name only.
285 std::string identifier = GetIdentifier(plugin);
286 PluginMetadata* metadata = new PluginMetadata(identifier,
287 GetGroupName(plugin),
288 false,
289 GURL(),
290 GURL(),
291 plugin.name,
292 std::string());
293 for (size_t i = 0; i < plugin.mime_types.size(); ++i)
294 metadata->AddMatchingMimeType(plugin.mime_types[i].mime_type);
296 DCHECK(metadata->MatchesPlugin(plugin));
297 if (identifier_plugin_.find(identifier) != identifier_plugin_.end())
298 identifier = GetLongIdentifier(plugin);
300 DCHECK(identifier_plugin_.find(identifier) == identifier_plugin_.end());
301 identifier_plugin_[identifier] = metadata;
302 return metadata->Clone();