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"
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"
29 using base::DictionaryValue
;
30 using content::PluginService
;
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())
52 base::FilePath::StringType path
=
53 plugin
.path
.BaseName().RemoveExtension().value();
55 return UTF8ToUTF16(path
);
57 return WideToUTF16(path
);
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
))
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
);
76 if (matching_mime_types
) {
77 plugin
->AddMatchingMimeType(mime_type_str
);
79 plugin
->AddMimeType(mime_type_str
);
84 PluginMetadata
* CreatePluginMetadata(
85 const std::string
& identifier
,
86 const DictionaryValue
* plugin_dict
) {
88 bool success
= plugin_dict
->GetString("url", &url
);
90 plugin_dict
->GetString("help_url", &help_url
);
92 success
= plugin_dict
->GetString("name", &name
);
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
);
99 std::string language_str
;
100 plugin_dict
->GetString("lang", &language_str
);
102 PluginMetadata
* plugin
= new PluginMetadata(identifier
,
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
)) {
119 success
= version_dict
->GetString("version", &version
);
121 std::string status_str
;
122 success
= version_dict
->GetString("status", &status_str
);
124 PluginMetadata::SecurityStatus status
=
125 PluginMetadata::SECURITY_STATUS_UP_TO_DATE
;
126 success
= PluginMetadata::ParseSecurityStatus(status_str
, &status
);
128 plugin
->AddVersion(Version(version
), status
);
132 LoadMimeTypes(false, plugin_dict
, plugin
);
133 LoadMimeTypes(true, plugin_dict
, plugin
);
140 void PluginFinder::RegisterPrefs(PrefRegistrySimple
* registry
) {
141 registry
->RegisterBooleanPref(prefs::kDisablePluginFinder
, false);
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());
161 ReinitializePlugins(plugin_list
.get());
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(
172 base::JSON_PARSE_RFC
,
176 DLOG(ERROR
) << error_str
;
179 if (value
->GetType() != base::Value::TYPE_DICTIONARY
)
181 return static_cast<base::DictionaryValue
*>(value
.release());
184 PluginFinder::~PluginFinder() {
185 #if defined(ENABLE_PLUGIN_INSTALLATION)
186 STLDeleteValues(&installers_
);
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
))
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
;
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())
225 *plugin_metadata
= metadata_it
->second
->Clone();
228 std::map
<std::string
, PluginInstaller
*>::const_iterator installer_it
=
229 installers_
.find(identifier
);
230 if (installer_it
== installers_
.end())
232 *installer
= installer_it
->second
;
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_
)
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();
268 string16
PluginFinder::FindPluginNameWithIdentifier(
269 const std::string
& identifier
) {
270 base::AutoLock
lock(mutex_
);
271 PluginMap::const_iterator it
= identifier_plugin_
.find(identifier
);
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
))
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
),
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();