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

Side by Side Diff: chrome/browser/plugins/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, 2 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/plugins/plugin_finder.h" 5 #include "chrome/browser/plugins/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/plugins/plugin_installer.h" 15 #include "chrome/browser/plugins/plugin_installer.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/plugins/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() {
75 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
76 }
77
78 // TODO(ibraaaa): initialize |plugin_list_| from Local State.
79 // http://crbug.com/124396
80 void PluginFinder::Init() {
81 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
82 plugin_list_.reset(LoadPluginList());
138 if (!plugin_list_.get()) 83 if (!plugin_list_.get())
139 plugin_list_.reset(new DictionaryValue()); 84 plugin_list_.reset(new DictionaryValue());
85
86 for (DictionaryValue::Iterator plugin_it(*plugin_list_);
87 plugin_it.HasNext(); plugin_it.Advance()) {
88 DictionaryValue* plugin = NULL;
89 const std::string& identifier = plugin_it.key();
90 if (plugin_list_->GetDictionaryWithoutPathExpansion(identifier, &plugin)) {
91 PluginMetadata* metadata = CreatePluginMetadata(identifier, plugin);
92 identifier_plugin_[identifier] = metadata;
93
94 #if defined(ENABLE_PLUGIN_INSTALLATION)
95 installers_[identifier] = new PluginInstaller(metadata);
96 #endif
97 }
98 }
140 } 99 }
141 100
142 // static 101 // static
143 DictionaryValue* PluginFinder::LoadPluginList() { 102 DictionaryValue* PluginFinder::LoadPluginList() {
144 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) 103 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
145 base::StringPiece json_resource( 104 base::StringPiece json_resource(
146 ResourceBundle::GetSharedInstance().GetRawDataResource( 105 ResourceBundle::GetSharedInstance().GetRawDataResource(
147 IDR_PLUGIN_DB_JSON, ui::SCALE_FACTOR_NONE)); 106 IDR_PLUGIN_DB_JSON, ui::SCALE_FACTOR_NONE));
148 std::string error_str; 107 std::string error_str;
149 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError( 108 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
150 json_resource, 109 json_resource,
151 base::JSON_PARSE_RFC, 110 base::JSON_PARSE_RFC,
152 NULL, 111 NULL,
153 &error_str)); 112 &error_str));
154 if (!value.get()) { 113 if (!value.get()) {
155 DLOG(ERROR) << error_str; 114 DLOG(ERROR) << error_str;
156 return NULL; 115 return NULL;
157 } 116 }
158 if (value->GetType() != base::Value::TYPE_DICTIONARY) 117 if (value->GetType() != base::Value::TYPE_DICTIONARY)
159 return NULL; 118 return NULL;
160 return static_cast<base::DictionaryValue*>(value.release()); 119 return static_cast<base::DictionaryValue*>(value.release());
161 #else 120 #else
162 return new DictionaryValue(); 121 return new DictionaryValue();
163 #endif 122 #endif
164 } 123 }
165 124
166 PluginFinder::~PluginFinder() { 125 PluginFinder::~PluginFinder() {
126 #if defined(ENABLE_PLUGIN_INSTALLATION)
167 STLDeleteValues(&installers_); 127 STLDeleteValues(&installers_);
128 #endif
129 STLDeleteValues(&identifier_plugin_);
168 } 130 }
169 131
132 #if defined(ENABLE_PLUGIN_INSTALLATION)
170 PluginInstaller* PluginFinder::FindPlugin(const std::string& mime_type, 133 PluginInstaller* PluginFinder::FindPlugin(const std::string& mime_type,
171 const std::string& language) { 134 const std::string& language) {
172 if (g_browser_process->local_state()->GetBoolean(prefs::kDisablePluginFinder)) 135 if (g_browser_process->local_state()->GetBoolean(prefs::kDisablePluginFinder))
173 return NULL; 136 return NULL;
174 for (DictionaryValue::Iterator plugin_it(*plugin_list_); 137 for (DictionaryValue::Iterator plugin_it(*plugin_list_);
175 plugin_it.HasNext(); plugin_it.Advance()) { 138 plugin_it.HasNext(); plugin_it.Advance()) {
176 const DictionaryValue* plugin = NULL; 139 const DictionaryValue* plugin = NULL;
177 if (!plugin_it.value().GetAsDictionary(&plugin)) { 140 if (!plugin_it.value().GetAsDictionary(&plugin)) {
178 NOTREACHED(); 141 NOTREACHED();
179 continue; 142 continue;
180 } 143 }
181 std::string language_str; 144 std::string language_str;
182 bool success = plugin->GetString("lang", &language_str); 145 bool success = plugin->GetString("lang", &language_str);
183 if (language_str != language) 146 if (language_str != language)
184 continue; 147 continue;
185 const ListValue* mime_types = NULL; 148 const ListValue* mime_types = NULL;
186 plugin->GetList("mime_types", &mime_types); 149 plugin->GetList("mime_types", &mime_types);
187 DCHECK(success); 150 DCHECK(success);
188 for (ListValue::const_iterator mime_type_it = mime_types->begin(); 151 for (ListValue::const_iterator mime_type_it = mime_types->begin();
189 mime_type_it != mime_types->end(); ++mime_type_it) { 152 mime_type_it != mime_types->end(); ++mime_type_it) {
190 std::string mime_type_str; 153 std::string mime_type_str;
191 success = (*mime_type_it)->GetAsString(&mime_type_str); 154 success = (*mime_type_it)->GetAsString(&mime_type_str);
192 DCHECK(success); 155 DCHECK(success);
193 if (mime_type_str == mime_type) { 156 if (mime_type_str == mime_type) {
194 std::string identifier = plugin_it.key(); 157 std::string identifier = plugin_it.key();
195 std::map<std::string, PluginInstaller*>::const_iterator installer = 158 {
196 installers_.find(identifier); 159 base::AutoLock lock(mutex_);
197 if (installer != installers_.end()) 160 std::map<std::string, PluginInstaller*>::const_iterator installer =
161 installers_.find(identifier);
162 DCHECK(installer != installers_.end());
198 return installer->second; 163 return installer->second;
199 return CreateInstaller(identifier, plugin); 164 }
200 } 165 }
201 } 166 }
202 } 167 }
203 return NULL; 168 return NULL;
204 } 169 }
205 170
206 PluginInstaller* PluginFinder::FindPluginWithIdentifier( 171 PluginInstaller* PluginFinder::FindPluginWithIdentifier(
207 const std::string& identifier) { 172 const std::string& identifier) {
173 base::AutoLock lock(mutex_);
208 std::map<std::string, PluginInstaller*>::const_iterator it = 174 std::map<std::string, PluginInstaller*>::const_iterator it =
209 installers_.find(identifier); 175 installers_.find(identifier);
210 if (it != installers_.end()) 176 if (it != installers_.end())
211 return it->second; 177 return it->second;
212 DictionaryValue* plugin = NULL; 178
213 if (plugin_list_->GetDictionaryWithoutPathExpansion(identifier, &plugin)) 179 return NULL;
214 return CreateInstaller(identifier, plugin); 180 }
181 #endif
182
183 PluginMetadata* PluginFinder::FindPluginMetadataWithIdentifier(
184 const std::string& identifier) {
185 base::AutoLock lock(mutex_);
186 std::map<std::string, PluginMetadata*>::const_iterator it =
187 identifier_plugin_.find(identifier);
188 if (it != identifier_plugin_.end())
189 return it->second;
190
215 return NULL; 191 return NULL;
216 } 192 }
217 193
218 PluginInstaller* PluginFinder::CreateInstaller( 194 PluginMetadata* PluginFinder::CreatePluginMetadata(
219 const std::string& identifier, 195 const std::string& identifier,
220 const DictionaryValue* plugin_dict) { 196 const DictionaryValue* plugin_dict) {
221 DCHECK(!installers_[identifier]); 197 DCHECK(!identifier_plugin_[identifier]);
222 std::string url; 198 std::string url;
223 bool success = plugin_dict->GetString("url", &url); 199 bool success = plugin_dict->GetString("url", &url);
224 std::string help_url; 200 std::string help_url;
225 plugin_dict->GetString("help_url", &help_url); 201 plugin_dict->GetString("help_url", &help_url);
226 string16 name; 202 string16 name;
227 success = plugin_dict->GetString("name", &name); 203 success = plugin_dict->GetString("name", &name);
228 DCHECK(success); 204 DCHECK(success);
229 bool display_url = false; 205 bool display_url = false;
230 plugin_dict->GetBoolean("displayurl", &display_url); 206 plugin_dict->GetBoolean("displayurl", &display_url);
231 string16 group_name_matcher; 207 string16 group_name_matcher;
232 success = plugin_dict->GetString("group_name_matcher", &group_name_matcher); 208 success = plugin_dict->GetString("group_name_matcher", &group_name_matcher);
233 DCHECK(success); 209 DCHECK(success);
234 210
235 PluginInstaller* installer = new PluginInstaller(identifier, 211 PluginMetadata* plugin = new PluginMetadata(identifier,
236 name, 212 name,
237 display_url, 213 display_url,
238 GURL(url), 214 GURL(url),
239 GURL(help_url), 215 GURL(help_url),
240 group_name_matcher); 216 group_name_matcher);
241 const ListValue* versions = NULL; 217 const ListValue* versions = NULL;
242 if (plugin_dict->GetList("versions", &versions)) { 218 if (plugin_dict->GetList("versions", &versions)) {
243 for (ListValue::const_iterator it = versions->begin(); 219 for (ListValue::const_iterator it = versions->begin();
244 it != versions->end(); ++it) { 220 it != versions->end(); ++it) {
245 DictionaryValue* version_dict = NULL; 221 DictionaryValue* version_dict = NULL;
246 if (!(*it)->GetAsDictionary(&version_dict)) { 222 if (!(*it)->GetAsDictionary(&version_dict)) {
247 NOTREACHED(); 223 NOTREACHED();
248 continue; 224 continue;
249 } 225 }
250 std::string version; 226 std::string version;
251 success = version_dict->GetString("version", &version); 227 success = version_dict->GetString("version", &version);
252 DCHECK(success); 228 DCHECK(success);
253 std::string status_str; 229 std::string status_str;
254 success = version_dict->GetString("status", &status_str); 230 success = version_dict->GetString("status", &status_str);
255 DCHECK(success); 231 DCHECK(success);
256 PluginInstaller::SecurityStatus status = 232 PluginMetadata::SecurityStatus status =
257 PluginInstaller::SECURITY_STATUS_UP_TO_DATE; 233 PluginMetadata::SECURITY_STATUS_UP_TO_DATE;
258 success = PluginInstaller::ParseSecurityStatus(status_str, &status); 234 success = PluginMetadata::ParseSecurityStatus(status_str, &status);
259 DCHECK(success); 235 DCHECK(success);
260 installer->AddVersion(Version(version), status); 236 plugin->AddVersion(Version(version), status);
261 } 237 }
262 } 238 }
263 239
264 installers_[identifier] = installer; 240 return plugin;
265 return installer;
266 } 241 }
267 242
268 PluginInstaller* PluginFinder::GetPluginInstaller( 243 PluginMetadata* PluginFinder::GetPluginMetadata(
269 const webkit::WebPluginInfo& plugin) { 244 const webkit::WebPluginInfo& plugin) {
270 if (name_installers_.find(plugin.name) != name_installers_.end()) 245 base::AutoLock lock(mutex_);
271 return name_installers_[plugin.name]; 246 if (name_plugin_.find(plugin.name) != name_plugin_.end())
247 return name_plugin_[plugin.name];
272 248
273 for (DictionaryValue::Iterator plugin_it(*plugin_list_); 249 // Use the group name matcher to find the plug-in metadata we want.
274 plugin_it.HasNext(); plugin_it.Advance()) { 250 for (std::map<std::string, PluginMetadata*>::const_iterator it =
275 // This method triggers the lazy initialization for all PluginInstallers. 251 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)) 252 if (!it->second->MatchesPlugin(plugin))
283 continue; 253 continue;
284 254
285 name_installers_[plugin.name] = it->second; 255 name_plugin_[plugin.name] = it->second;
286 return it->second; 256 return it->second;
287 } 257 }
288 258
289 // The plug-in installer was not found, create a dummy one holding 259 // The plug-in metadata was not found, create a dummy one holding
290 // the name, identifier and group name only. 260 // the name, identifier and group name only.
291 std::string identifier = GetIdentifier(plugin); 261 std::string identifier = GetIdentifier(plugin);
292 PluginInstaller* installer = new PluginInstaller(identifier, 262 PluginMetadata* metadata = new PluginMetadata(identifier,
293 GetGroupName(plugin), 263 GetGroupName(plugin),
294 false, GURL(), GURL(), 264 false, GURL(), GURL(),
295 GetGroupName(plugin)); 265 GetGroupName(plugin));
296 installers_[identifier] = installer; 266
297 name_installers_[plugin.name] = installer; 267 name_plugin_[plugin.name] = metadata;
298 return installer; 268 identifier_plugin_[identifier] = metadata;
269 return metadata;
299 } 270 }
OLDNEW
« no previous file with comments | « chrome/browser/plugins/plugin_finder.h ('k') | chrome/browser/plugins/plugin_finder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698