Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(282)

Side by Side Diff: chrome/browser/plugin_finder.cc

Issue 10910168: Separate plugin_metadata from plugin_installer, thread-safe plugin_finder (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: . Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "chrome/browser/plugin_finder.h" 5 #include "chrome/browser/plugin_finder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "base/sys_string_conversions.h" 11 #include "base/sys_string_conversions.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h" 14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/plugin_installer.h" 15 #include "chrome/browser/plugin_metadata.h"
16 #include "chrome/browser/prefs/pref_service.h" 16 #include "chrome/browser/prefs/pref_service.h"
17 #include "chrome/common/pref_names.h" 17 #include "chrome/common/pref_names.h"
18 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/plugin_service.h" 19 #include "content/public/browser/plugin_service.h"
20 #include "googleurl/src/gurl.h" 20 #include "googleurl/src/gurl.h"
21 #include "grit/browser_resources.h" 21 #include "grit/browser_resources.h"
22 #include "ui/base/layout.h" 22 #include "ui/base/layout.h"
23 #include "ui/base/resource/resource_bundle.h" 23 #include "ui/base/resource/resource_bundle.h"
24 24
25 #if defined(ENABLE_PLUGIN_INSTALLATION)
26 #include "chrome/browser/plugin_installer.h"
27 #endif
28
25 using base::DictionaryValue; 29 using base::DictionaryValue;
26 using content::PluginService; 30 using content::PluginService;
27 31
28 namespace { 32 namespace {
29 33
30 // Gets the base name of the file path as the identifier. 34 // Gets the base name of the file path as the identifier.
31 static std::string GetIdentifier(const webkit::WebPluginInfo& plugin) { 35 static std::string GetIdentifier(const webkit::WebPluginInfo& plugin) {
32 #if defined(OS_POSIX) 36 #if defined(OS_POSIX)
33 return plugin.path.BaseName().value(); 37 return plugin.path.BaseName().value();
34 #elif defined(OS_WIN) 38 #elif defined(OS_WIN)
35 return base::SysWideToUTF8(plugin.path.BaseName().value()); 39 return base::SysWideToUTF8(plugin.path.BaseName().value());
36 #endif 40 #endif
37 } 41 }
38 42
39 // Gets the plug-in group name as the plug-in name if it is not empty or 43 // Gets the plug-in group name as the plug-in name if it is not empty or
40 // the filename without extension if the name is empty. 44 // the filename without extension if the name is empty.
41 static string16 GetGroupName(const webkit::WebPluginInfo& plugin) { 45 static string16 GetGroupName(const webkit::WebPluginInfo& plugin) {
42 if (!plugin.name.empty()) 46 if (!plugin.name.empty())
43 return plugin.name; 47 return plugin.name;
44 48
45 FilePath::StringType path = plugin.path.BaseName().RemoveExtension().value(); 49 FilePath::StringType path = plugin.path.BaseName().RemoveExtension().value();
46 #if defined(OS_POSIX) 50 #if defined(OS_POSIX)
47 return UTF8ToUTF16(path); 51 return UTF8ToUTF16(path);
48 #elif defined(OS_WIN) 52 #elif defined(OS_WIN)
49 return WideToUTF16(path); 53 return WideToUTF16(path);
50 #endif 54 #endif
51 } 55 }
52 56
53 // A callback barrier used to enforce the execution of a callback function
54 // only when two different asynchronous callbacks are done execution.
55 // The first asynchronous callback gets a PluginFinder instance and the
56 // second asynchronous callback gets a list of plugins.
57 class PluginFinderCallbackBarrier
58 : public base::RefCountedThreadSafe<PluginFinderCallbackBarrier> {
59 public:
60 typedef base::Callback<void(const PluginFinder::PluginVector&)>
61 PluginsCallback;
62
63 explicit PluginFinderCallbackBarrier(
64 const PluginFinder::CombinedCallback& callback)
65 : callback_(callback),
66 finder_(NULL) {
67 DCHECK(!callback_.is_null());
68 }
69
70 base::Callback<void(PluginFinder*)> CreatePluginFinderCallback() {
71 return base::Bind(&PluginFinderCallbackBarrier::GotPluginFinder, this);
72 }
73
74 PluginsCallback CreatePluginsCallback() {
75 return base::Bind(&PluginFinderCallbackBarrier::GotPlugins, this);
76 }
77
78 private:
79 friend class base::RefCountedThreadSafe<PluginFinderCallbackBarrier>;
80
81 ~PluginFinderCallbackBarrier() {
82 DCHECK(callback_.is_null());
83 }
84
85 void GotPlugins(const PluginFinder::PluginVector& plugins) {
86 plugins_.reset(new PluginFinder::PluginVector(plugins));
87 MaybeRunCallback();
88 }
89
90 void GotPluginFinder(PluginFinder* finder) {
91 finder_ = finder;
92 MaybeRunCallback();
93 }
94
95 // Executes the callback only when both asynchronous methods have finished
96 // their executions. This is identified by having non-null values in both
97 // |finder_| and |plugins_|.
98 void MaybeRunCallback() {
99 if (!finder_ || !plugins_.get())
100 return;
101
102 callback_.Run(*plugins_, finder_);
103 callback_.Reset();
104 }
105
106 PluginFinder::CombinedCallback callback_;
107 PluginFinder* finder_;
108 scoped_ptr<PluginFinder::PluginVector> plugins_;
109 };
110
111 } // namespace 57 } // namespace
112 58
113 // static 59 // TODO(ibraaaa): DELETE. http://crbug.com/124396
114 void PluginFinder::GetPluginsAndPluginFinder(
115 const PluginFinder::CombinedCallback& cb) {
116 scoped_refptr<PluginFinderCallbackBarrier> barrier =
117 new PluginFinderCallbackBarrier(cb);
118
119 PluginFinder::Get(barrier->CreatePluginFinderCallback());
120 PluginService::GetInstance()->GetPlugins(barrier->CreatePluginsCallback());
121 }
122
123 // static 60 // static
124 void PluginFinder::Get(const base::Callback<void(PluginFinder*)>& cb) { 61 void PluginFinder::Get(const base::Callback<void(PluginFinder*)>& cb) {
125 // At a later point we might want to do intialization here that needs to be 62 // At a later point we might want to do intialization here that needs to be
126 // done asynchronously, like loading the plug-in list from disk or from a URL. 63 // done asynchronously, like loading the plug-in list from disk or from a URL.
127 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(cb, GetInstance())); 64 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(cb, GetInstance()));
128 } 65 }
129 66
130 // static 67 // static
131 PluginFinder* PluginFinder::GetInstance() { 68 PluginFinder* PluginFinder::GetInstance() {
132 // PluginFinder::GetInstance() is the only method that's allowed to call 69 // PluginFinder::GetInstance() is the only method that's allowed to call
133 // Singleton<PluginFinder>::get(). 70 // Singleton<PluginFinder>::get().
134 return Singleton<PluginFinder>::get(); 71 return Singleton<PluginFinder>::get();
135 } 72 }
136 73
137 PluginFinder::PluginFinder() : plugin_list_(LoadPluginList()) { 74 PluginFinder::PluginFinder() {
138 if (!plugin_list_.get()) 75 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
139 plugin_list_.reset(new DictionaryValue()); 76 }
77
78 // TODO(ibraaaa): initialize |plugin_list_| from Local State.
79 // http://crbug.com/124396
80 void PluginFinder::Init() {
81 plugin_list_.reset(LoadPluginList());
82
83 for (DictionaryValue::Iterator plugin_it(*plugin_list_);
84 plugin_it.HasNext(); plugin_it.Advance()) {
85 DictionaryValue* plugin = NULL;
86 const std::string& identifier = plugin_it.key();
87 if (plugin_list_->GetDictionaryWithoutPathExpansion(identifier, &plugin)) {
88 PluginMetadata* metadata = CreatePluginMetadata(identifier, plugin);
89 identifier_plugin_[identifier] = metadata;
90
91 #if defined(ENABLE_PLUGIN_INSTALLATION)
92 installers_[identifier] = new PluginInstaller(metadata);
93 #endif
94 }
95 }
140 } 96 }
141 97
142 // static 98 // static
143 DictionaryValue* PluginFinder::LoadPluginList() { 99 DictionaryValue* PluginFinder::LoadPluginList() {
144 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) 100 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
145 base::StringPiece json_resource( 101 base::StringPiece json_resource(
146 ResourceBundle::GetSharedInstance().GetRawDataResource( 102 ResourceBundle::GetSharedInstance().GetRawDataResource(
147 IDR_PLUGIN_DB_JSON, ui::SCALE_FACTOR_NONE)); 103 IDR_PLUGIN_DB_JSON, ui::SCALE_FACTOR_NONE));
148 std::string error_str; 104 std::string error_str;
149 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError( 105 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
150 json_resource, 106 json_resource,
151 base::JSON_PARSE_RFC, 107 base::JSON_PARSE_RFC,
152 NULL, 108 NULL,
153 &error_str)); 109 &error_str));
154 if (!value.get()) { 110 if (!value.get()) {
155 DLOG(ERROR) << error_str; 111 DLOG(ERROR) << error_str;
156 return NULL; 112 return NULL;
157 } 113 }
158 if (value->GetType() != base::Value::TYPE_DICTIONARY) 114 if (value->GetType() != base::Value::TYPE_DICTIONARY)
159 return NULL; 115 return NULL;
160 return static_cast<base::DictionaryValue*>(value.release()); 116 return static_cast<base::DictionaryValue*>(value.release());
161 #else 117 #else
162 return new DictionaryValue(); 118 return new DictionaryValue();
163 #endif 119 #endif
164 } 120 }
165 121
166 PluginFinder::~PluginFinder() { 122 PluginFinder::~PluginFinder() {
123 #if defined(ENABLE_PLUGIN_INSTALLATION)
167 STLDeleteValues(&installers_); 124 STLDeleteValues(&installers_);
125 #endif
126 STLDeleteValues(&identifier_plugin_);
168 } 127 }
169 128
129 #if defined(ENABLE_PLUGIN_INSTALLATION)
170 PluginInstaller* PluginFinder::FindPlugin(const std::string& mime_type, 130 PluginInstaller* PluginFinder::FindPlugin(const std::string& mime_type,
171 const std::string& language) { 131 const std::string& language) {
172 if (g_browser_process->local_state()->GetBoolean(prefs::kDisablePluginFinder)) 132 if (g_browser_process->local_state()->GetBoolean(prefs::kDisablePluginFinder))
173 return NULL; 133 return NULL;
174 for (DictionaryValue::Iterator plugin_it(*plugin_list_); 134 for (DictionaryValue::Iterator plugin_it(*plugin_list_);
175 plugin_it.HasNext(); plugin_it.Advance()) { 135 plugin_it.HasNext(); plugin_it.Advance()) {
176 const DictionaryValue* plugin = NULL; 136 const DictionaryValue* plugin = NULL;
177 if (!plugin_it.value().GetAsDictionary(&plugin)) { 137 if (!plugin_it.value().GetAsDictionary(&plugin)) {
178 NOTREACHED(); 138 NOTREACHED();
179 continue; 139 continue;
180 } 140 }
181 std::string language_str; 141 std::string language_str;
182 bool success = plugin->GetString("lang", &language_str); 142 bool success = plugin->GetString("lang", &language_str);
183 if (language_str != language) 143 if (language_str != language)
184 continue; 144 continue;
185 const ListValue* mime_types = NULL; 145 const ListValue* mime_types = NULL;
186 plugin->GetList("mime_types", &mime_types); 146 plugin->GetList("mime_types", &mime_types);
187 DCHECK(success); 147 DCHECK(success);
188 for (ListValue::const_iterator mime_type_it = mime_types->begin(); 148 for (ListValue::const_iterator mime_type_it = mime_types->begin();
189 mime_type_it != mime_types->end(); ++mime_type_it) { 149 mime_type_it != mime_types->end(); ++mime_type_it) {
190 std::string mime_type_str; 150 std::string mime_type_str;
191 success = (*mime_type_it)->GetAsString(&mime_type_str); 151 success = (*mime_type_it)->GetAsString(&mime_type_str);
192 DCHECK(success); 152 DCHECK(success);
193 if (mime_type_str == mime_type) { 153 if (mime_type_str == mime_type) {
194 std::string identifier = plugin_it.key(); 154 std::string identifier = plugin_it.key();
195 std::map<std::string, PluginInstaller*>::const_iterator installer = 155 {
196 installers_.find(identifier); 156 base::AutoLock lock(mutex_);
197 if (installer != installers_.end()) 157 std::map<std::string, PluginInstaller*>::const_iterator installer =
158 installers_.find(identifier);
159 DCHECK(installer != installers_.end());
198 return installer->second; 160 return installer->second;
199 return CreateInstaller(identifier, plugin); 161 }
200 } 162 }
201 } 163 }
202 } 164 }
203 return NULL; 165 return NULL;
204 } 166 }
205 167
206 PluginInstaller* PluginFinder::FindPluginWithIdentifier( 168 PluginInstaller* PluginFinder::FindPluginWithIdentifier(
207 const std::string& identifier) { 169 const std::string& identifier) {
170 base::AutoLock lock(mutex_);
208 std::map<std::string, PluginInstaller*>::const_iterator it = 171 std::map<std::string, PluginInstaller*>::const_iterator it =
209 installers_.find(identifier); 172 installers_.find(identifier);
210 if (it != installers_.end()) 173 if (it != installers_.end())
211 return it->second; 174 return it->second;
212 DictionaryValue* plugin = NULL; 175
213 if (plugin_list_->GetDictionaryWithoutPathExpansion(identifier, &plugin)) 176 return NULL;
214 return CreateInstaller(identifier, plugin); 177 }
178 #endif
179
180 PluginMetadata* PluginFinder::FindPluginMetadataWithIdentifier(
181 const std::string& identifier) {
182 base::AutoLock lock(mutex_);
183 std::map<std::string, PluginMetadata*>::const_iterator it =
184 identifier_plugin_.find(identifier);
185 if (it != identifier_plugin_.end())
186 return it->second;
187
215 return NULL; 188 return NULL;
216 } 189 }
217 190
218 PluginInstaller* PluginFinder::CreateInstaller( 191 PluginMetadata* PluginFinder::CreatePluginMetadata(
219 const std::string& identifier, 192 const std::string& identifier,
220 const DictionaryValue* plugin_dict) { 193 const DictionaryValue* plugin_dict) {
221 DCHECK(!installers_[identifier]); 194 DCHECK(!identifier_plugin_[identifier]);
222 std::string url; 195 std::string url;
223 bool success = plugin_dict->GetString("url", &url); 196 bool success = plugin_dict->GetString("url", &url);
224 std::string help_url; 197 std::string help_url;
225 plugin_dict->GetString("help_url", &help_url); 198 plugin_dict->GetString("help_url", &help_url);
226 string16 name; 199 string16 name;
227 success = plugin_dict->GetString("name", &name); 200 success = plugin_dict->GetString("name", &name);
228 DCHECK(success); 201 DCHECK(success);
229 bool display_url = false; 202 bool display_url = false;
230 plugin_dict->GetBoolean("displayurl", &display_url); 203 plugin_dict->GetBoolean("displayurl", &display_url);
231 string16 group_name_matcher; 204 string16 group_name_matcher;
232 success = plugin_dict->GetString("group_name_matcher", &group_name_matcher); 205 success = plugin_dict->GetString("group_name_matcher", &group_name_matcher);
233 DCHECK(success); 206 DCHECK(success);
234 207
235 PluginInstaller* installer = new PluginInstaller(identifier, 208 PluginMetadata* plugin = new PluginMetadata(identifier,
236 name, 209 name,
237 display_url, 210 display_url,
238 GURL(url), 211 GURL(url),
239 GURL(help_url), 212 GURL(help_url),
240 group_name_matcher); 213 group_name_matcher);
241 const ListValue* versions = NULL; 214 const ListValue* versions = NULL;
242 if (plugin_dict->GetList("versions", &versions)) { 215 if (plugin_dict->GetList("versions", &versions)) {
243 for (ListValue::const_iterator it = versions->begin(); 216 for (ListValue::const_iterator it = versions->begin();
244 it != versions->end(); ++it) { 217 it != versions->end(); ++it) {
245 DictionaryValue* version_dict = NULL; 218 DictionaryValue* version_dict = NULL;
246 if (!(*it)->GetAsDictionary(&version_dict)) { 219 if (!(*it)->GetAsDictionary(&version_dict)) {
247 NOTREACHED(); 220 NOTREACHED();
248 continue; 221 continue;
249 } 222 }
250 std::string version; 223 std::string version;
251 success = version_dict->GetString("version", &version); 224 success = version_dict->GetString("version", &version);
252 DCHECK(success); 225 DCHECK(success);
253 std::string status_str; 226 std::string status_str;
254 success = version_dict->GetString("status", &status_str); 227 success = version_dict->GetString("status", &status_str);
255 DCHECK(success); 228 DCHECK(success);
256 PluginInstaller::SecurityStatus status = 229 PluginMetadata::SecurityStatus status =
257 PluginInstaller::SECURITY_STATUS_UP_TO_DATE; 230 PluginMetadata::SECURITY_STATUS_UP_TO_DATE;
258 success = PluginInstaller::ParseSecurityStatus(status_str, &status); 231 success = PluginMetadata::ParseSecurityStatus(status_str, &status);
259 DCHECK(success); 232 DCHECK(success);
260 installer->AddVersion(Version(version), status); 233 plugin->AddVersion(Version(version), status);
261 } 234 }
262 } 235 }
263 236
264 installers_[identifier] = installer; 237 return plugin;
265 return installer;
266 } 238 }
267 239
268 PluginInstaller* PluginFinder::GetPluginInstaller( 240 PluginMetadata* PluginFinder::GetPluginMetadata(
269 const webkit::WebPluginInfo& plugin) { 241 const webkit::WebPluginInfo& plugin) {
270 if (name_installers_.find(plugin.name) != name_installers_.end()) 242 base::AutoLock lock(mutex_);
271 return name_installers_[plugin.name]; 243 if (name_plugin_.find(plugin.name) != name_plugin_.end())
244 return name_plugin_[plugin.name];
272 245
273 for (DictionaryValue::Iterator plugin_it(*plugin_list_); 246 // Use the group name matcher to find the plug-in metadata we want.
274 plugin_it.HasNext(); plugin_it.Advance()) { 247 for (std::map<std::string, PluginMetadata*>::const_iterator it =
275 // This method triggers the lazy initialization for all PluginInstallers. 248 identifier_plugin_.begin(); it != identifier_plugin_.end(); ++it) {
276 FindPluginWithIdentifier(plugin_it.key());
277 }
278
279 // Use the group name matcher to find the plug-in installer we want.
280 for (std::map<std::string, PluginInstaller*>::const_iterator it =
281 installers_.begin(); it != installers_.end(); ++it) {
282 if (!it->second->MatchesPlugin(plugin)) 249 if (!it->second->MatchesPlugin(plugin))
283 continue; 250 continue;
284 251
285 name_installers_[plugin.name] = it->second; 252 name_plugin_[plugin.name] = it->second;
286 return it->second; 253 return it->second;
287 } 254 }
288 255
289 // The plug-in installer was not found, create a dummy one holding 256 // The plug-in metadata was not found, create a dummy one holding
290 // the name, identifier and group name only. 257 // the name, identifier and group name only.
291 std::string identifier = GetIdentifier(plugin); 258 std::string identifier = GetIdentifier(plugin);
292 PluginInstaller* installer = new PluginInstaller(identifier, 259 PluginMetadata* metadata = new PluginMetadata(identifier,
293 GetGroupName(plugin), 260 GetGroupName(plugin),
294 false, GURL(), GURL(), 261 false, GURL(), GURL(),
295 GetGroupName(plugin)); 262 GetGroupName(plugin));
296 installers_[identifier] = installer; 263
297 name_installers_[plugin.name] = installer; 264 name_plugin_[plugin.name] = metadata;
298 return installer; 265 identifier_plugin_[identifier] = metadata;
266 return metadata;
299 } 267 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698