Fix build break
[chromium-blink-merge.git] / chrome / browser / plugins / plugin_finder.cc
blob8b4c519a94965929284c61aba5a98c46e08a3c2b
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.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/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 "googleurl/src/gurl.h"
22 #include "grit/browser_resources.h"
23 #include "ui/base/resource/resource_bundle.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 plug-in file as the identifier.
37 std::string GetLongIdentifier(const webkit::WebPluginInfo& plugin) {
38 return plugin.path.AsUTF8Unsafe();
41 // Gets the base name of the file path as the identifier.
42 std::string GetIdentifier(const webkit::WebPluginInfo& plugin) {
43 return plugin.path.BaseName().AsUTF8Unsafe();
46 // Gets the plug-in group name as the plug-in name if it is not empty or
47 // the filename without extension if the name is empty.
48 static string16 GetGroupName(const webkit::WebPluginInfo& plugin) {
49 if (!plugin.name.empty())
50 return plugin.name;
52 base::FilePath::StringType path =
53 plugin.path.BaseName().RemoveExtension().value();
54 #if defined(OS_POSIX)
55 return UTF8ToUTF16(path);
56 #elif defined(OS_WIN)
57 return WideToUTF16(path);
58 #endif
61 void LoadMimeTypes(bool matching_mime_types,
62 const DictionaryValue* plugin_dict,
63 PluginMetadata* plugin) {
64 const ListValue* mime_types = NULL;
65 std::string list_key =
66 matching_mime_types ? "matching_mime_types" : "mime_types";
67 if (!plugin_dict->GetList(list_key, &mime_types))
68 return;
70 bool success = false;
71 for (ListValue::const_iterator mime_type_it = mime_types->begin();
72 mime_type_it != mime_types->end(); ++mime_type_it) {
73 std::string mime_type_str;
74 success = (*mime_type_it)->GetAsString(&mime_type_str);
75 DCHECK(success);
76 if (matching_mime_types) {
77 plugin->AddMatchingMimeType(mime_type_str);
78 } else {
79 plugin->AddMimeType(mime_type_str);
84 PluginMetadata* CreatePluginMetadata(
85 const std::string& identifier,
86 const DictionaryValue* plugin_dict) {
87 std::string url;
88 bool success = plugin_dict->GetString("url", &url);
89 std::string help_url;
90 plugin_dict->GetString("help_url", &help_url);
91 string16 name;
92 success = plugin_dict->GetString("name", &name);
93 DCHECK(success);
94 bool display_url = false;
95 plugin_dict->GetBoolean("displayurl", &display_url);
96 string16 group_name_matcher;
97 success = plugin_dict->GetString("group_name_matcher", &group_name_matcher);
98 DCHECK(success);
99 std::string language_str;
100 plugin_dict->GetString("lang", &language_str);
102 PluginMetadata* plugin = new PluginMetadata(identifier,
103 name,
104 display_url,
105 GURL(url),
106 GURL(help_url),
107 group_name_matcher,
108 language_str);
109 const ListValue* versions = NULL;
110 if (plugin_dict->GetList("versions", &versions)) {
111 for (ListValue::const_iterator it = versions->begin();
112 it != versions->end(); ++it) {
113 DictionaryValue* version_dict = NULL;
114 if (!(*it)->GetAsDictionary(&version_dict)) {
115 NOTREACHED();
116 continue;
118 std::string version;
119 success = version_dict->GetString("version", &version);
120 DCHECK(success);
121 std::string status_str;
122 success = version_dict->GetString("status", &status_str);
123 DCHECK(success);
124 PluginMetadata::SecurityStatus status =
125 PluginMetadata::SECURITY_STATUS_UP_TO_DATE;
126 success = PluginMetadata::ParseSecurityStatus(status_str, &status);
127 DCHECK(success);
128 plugin->AddVersion(Version(version), status);
132 LoadMimeTypes(false, plugin_dict, plugin);
133 LoadMimeTypes(true, plugin_dict, plugin);
134 return plugin;
137 } // namespace
139 // static
140 void PluginFinder::RegisterPrefs(PrefRegistrySimple* registry) {
141 registry->RegisterBooleanPref(prefs::kDisablePluginFinder, false);
144 // static
145 PluginFinder* PluginFinder::GetInstance() {
146 // PluginFinder::GetInstance() is the only method that's allowed to call
147 // Singleton<PluginFinder>::get().
148 return Singleton<PluginFinder>::get();
151 PluginFinder::PluginFinder() : version_(-1) {
152 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
155 void PluginFinder::Init() {
156 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
157 // Load the built-in plug-in list first. If we have a newer version stored
158 // locally or download one, we will replace this one with it.
159 scoped_ptr<DictionaryValue> plugin_list(LoadBuiltInPluginList());
160 DCHECK(plugin_list);
161 ReinitializePlugins(plugin_list.get());
164 // static
165 DictionaryValue* PluginFinder::LoadBuiltInPluginList() {
166 base::StringPiece json_resource(
167 ResourceBundle::GetSharedInstance().GetRawDataResource(
168 IDR_PLUGIN_DB_JSON));
169 std::string error_str;
170 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
171 json_resource,
172 base::JSON_PARSE_RFC,
173 NULL,
174 &error_str));
175 if (!value.get()) {
176 DLOG(ERROR) << error_str;
177 return NULL;
179 if (value->GetType() != base::Value::TYPE_DICTIONARY)
180 return NULL;
181 return static_cast<base::DictionaryValue*>(value.release());
184 PluginFinder::~PluginFinder() {
185 #if defined(ENABLE_PLUGIN_INSTALLATION)
186 STLDeleteValues(&installers_);
187 #endif
188 STLDeleteValues(&identifier_plugin_);
191 #if defined(ENABLE_PLUGIN_INSTALLATION)
192 bool PluginFinder::FindPlugin(
193 const std::string& mime_type,
194 const std::string& language,
195 PluginInstaller** installer,
196 scoped_ptr<PluginMetadata>* plugin_metadata) {
197 if (g_browser_process->local_state()->GetBoolean(prefs::kDisablePluginFinder))
198 return false;
200 base::AutoLock lock(mutex_);
201 PluginMap::const_iterator metadata_it = identifier_plugin_.begin();
202 for (; metadata_it != identifier_plugin_.end(); ++metadata_it) {
203 if (language == metadata_it->second->language() &&
204 metadata_it->second->HasMimeType(mime_type)) {
205 *plugin_metadata = metadata_it->second->Clone();
207 std::map<std::string, PluginInstaller*>::const_iterator installer_it =
208 installers_.find(metadata_it->second->identifier());
209 DCHECK(installer_it != installers_.end());
210 *installer = installer_it->second;
211 return true;
214 return false;
217 bool PluginFinder::FindPluginWithIdentifier(
218 const std::string& identifier,
219 PluginInstaller** installer,
220 scoped_ptr<PluginMetadata>* plugin_metadata) {
221 base::AutoLock lock(mutex_);
222 PluginMap::const_iterator metadata_it = identifier_plugin_.find(identifier);
223 if (metadata_it == identifier_plugin_.end())
224 return false;
225 *plugin_metadata = metadata_it->second->Clone();
227 if (installer) {
228 std::map<std::string, PluginInstaller*>::const_iterator installer_it =
229 installers_.find(identifier);
230 if (installer_it == installers_.end())
231 return false;
232 *installer = installer_it->second;
234 return true;
236 #endif
238 void PluginFinder::ReinitializePlugins(
239 const base::DictionaryValue* plugin_list) {
240 base::AutoLock lock(mutex_);
241 int version = 0; // If no version is defined, we default to 0.
242 const char kVersionKey[] = "x-version";
243 plugin_list->GetInteger(kVersionKey, &version);
244 if (version <= version_)
245 return;
247 version_ = version;
249 STLDeleteValues(&identifier_plugin_);
250 identifier_plugin_.clear();
252 for (DictionaryValue::Iterator plugin_it(*plugin_list);
253 !plugin_it.IsAtEnd(); plugin_it.Advance()) {
254 const DictionaryValue* plugin = NULL;
255 const std::string& identifier = plugin_it.key();
256 if (plugin_list->GetDictionaryWithoutPathExpansion(identifier, &plugin)) {
257 DCHECK(!identifier_plugin_[identifier]);
258 identifier_plugin_[identifier] = CreatePluginMetadata(identifier, plugin);
260 #if defined(ENABLE_PLUGIN_INSTALLATION)
261 if (installers_.find(identifier) == installers_.end())
262 installers_[identifier] = new PluginInstaller();
263 #endif
268 string16 PluginFinder::FindPluginNameWithIdentifier(
269 const std::string& identifier) {
270 base::AutoLock lock(mutex_);
271 PluginMap::const_iterator it = identifier_plugin_.find(identifier);
272 string16 name;
273 if (it != identifier_plugin_.end())
274 name = it->second->name();
276 return name.empty() ? UTF8ToUTF16(identifier) : name;
279 scoped_ptr<PluginMetadata> PluginFinder::GetPluginMetadata(
280 const webkit::WebPluginInfo& plugin) {
281 base::AutoLock lock(mutex_);
282 for (PluginMap::const_iterator it = identifier_plugin_.begin();
283 it != identifier_plugin_.end(); ++it) {
284 if (!it->second->MatchesPlugin(plugin))
285 continue;
287 return it->second->Clone();
290 // The plug-in metadata was not found, create a dummy one holding
291 // the name, identifier and group name only.
292 std::string identifier = GetIdentifier(plugin);
293 PluginMetadata* metadata = new PluginMetadata(identifier,
294 GetGroupName(plugin),
295 false,
296 GURL(),
297 GURL(),
298 plugin.name,
299 std::string());
300 for (size_t i = 0; i < plugin.mime_types.size(); ++i)
301 metadata->AddMatchingMimeType(plugin.mime_types[i].mime_type);
303 DCHECK(metadata->MatchesPlugin(plugin));
304 if (identifier_plugin_.find(identifier) != identifier_plugin_.end())
305 identifier = GetLongIdentifier(plugin);
307 DCHECK(identifier_plugin_.find(identifier) == identifier_plugin_.end());
308 identifier_plugin_[identifier] = metadata;
309 return metadata->Clone();