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

Side by Side Diff: webkit/plugins/npapi/plugin_list.cc

Issue 19761007: Move NPAPI implementation out of webkit/plugins/npapi and into content. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: fix mac Created 7 years, 5 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 | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "webkit/plugins/npapi/plugin_list.h"
6
7 #include <algorithm>
8
9 #include "base/command_line.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "net/base/mime_util.h"
17 #include "url/gurl.h"
18 #include "webkit/plugins/npapi/plugin_utils.h"
19 #include "webkit/plugins/plugin_switches.h"
20
21 #if defined(OS_WIN)
22 #include "webkit/plugins/npapi/plugin_constants_win.h"
23 #endif
24
25 namespace {
26
27 using webkit::npapi::PluginList;
28
29 const char kApplicationOctetStream[] = "application/octet-stream";
30
31 base::LazyInstance<PluginList> g_singleton = LAZY_INSTANCE_INITIALIZER;
32
33 bool AllowMimeTypeMismatch(const std::string& orig_mime_type,
34 const std::string& actual_mime_type) {
35 if (orig_mime_type == actual_mime_type) {
36 NOTREACHED();
37 return true;
38 }
39
40 // We do not permit URL-sniff based plug-in MIME type overrides aside from
41 // the case where the "type" was initially missing or generic
42 // (application/octet-stream).
43 // We collected stats to determine this approach isn't a major compat issue,
44 // and we defend against content confusion attacks in various cases, such
45 // as when the user doesn't have the Flash plug-in enabled.
46 bool allow = orig_mime_type.empty() ||
47 orig_mime_type == kApplicationOctetStream;
48 LOG_IF(INFO, !allow) << "Ignoring plugin with unexpected MIME type "
49 << actual_mime_type << " (expected " << orig_mime_type
50 << ")";
51 return allow;
52 }
53
54 } // namespace
55
56 namespace webkit {
57 namespace npapi {
58
59 // static
60 PluginList* PluginList::Singleton() {
61 return g_singleton.Pointer();
62 }
63
64 // static
65 bool PluginList::DebugPluginLoading() {
66 return CommandLine::ForCurrentProcess()->HasSwitch(
67 switches::kDebugPluginLoading);
68 }
69
70 void PluginList::DisablePluginsDiscovery() {
71 plugins_discovery_disabled_ = true;
72 }
73
74 void PluginList::RefreshPlugins() {
75 base::AutoLock lock(lock_);
76 loading_state_ = LOADING_STATE_NEEDS_REFRESH;
77 }
78
79 void PluginList::AddExtraPluginPath(const base::FilePath& plugin_path) {
80 if (!NPAPIPluginsSupported()) {
81 // TODO(jam): remove and just have CHECK once we're sure this doesn't get
82 // triggered.
83 DLOG(INFO) << "NPAPI plugins not supported";
84 return;
85 }
86
87 // Chrome OS only loads plugins from /opt/google/chrome/plugins.
88 #if !defined(OS_CHROMEOS)
89 base::AutoLock lock(lock_);
90 extra_plugin_paths_.push_back(plugin_path);
91 #endif
92 }
93
94 void PluginList::RemoveExtraPluginPath(const base::FilePath& plugin_path) {
95 base::AutoLock lock(lock_);
96 std::vector<base::FilePath>::iterator it =
97 std::find(extra_plugin_paths_.begin(), extra_plugin_paths_.end(),
98 plugin_path);
99 if (it != extra_plugin_paths_.end())
100 extra_plugin_paths_.erase(it);
101 }
102
103 void PluginList::AddExtraPluginDir(const base::FilePath& plugin_dir) {
104 // Chrome OS only loads plugins from /opt/google/chrome/plugins.
105 #if !defined(OS_CHROMEOS)
106 base::AutoLock lock(lock_);
107 extra_plugin_dirs_.push_back(plugin_dir);
108 #endif
109 }
110
111 void PluginList::RegisterInternalPlugin(const webkit::WebPluginInfo& info,
112 bool add_at_beginning) {
113 if (!NPAPIPluginsSupported() &&
114 info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
115 DLOG(INFO) << "Don't register NPAPI plugins when they're not supported";
116 return;
117 }
118
119 base::AutoLock lock(lock_);
120
121 internal_plugins_.push_back(info);
122 if (add_at_beginning) {
123 // Newer registrations go earlier in the list so they can override the MIME
124 // types of older registrations.
125 extra_plugin_paths_.insert(extra_plugin_paths_.begin(), info.path);
126 } else {
127 extra_plugin_paths_.push_back(info.path);
128 }
129 }
130
131 void PluginList::UnregisterInternalPlugin(const base::FilePath& path) {
132 base::AutoLock lock(lock_);
133 for (size_t i = 0; i < internal_plugins_.size(); i++) {
134 if (internal_plugins_[i].path == path) {
135 internal_plugins_.erase(internal_plugins_.begin() + i);
136 return;
137 }
138 }
139 NOTREACHED();
140 }
141
142 void PluginList::GetInternalPlugins(
143 std::vector<webkit::WebPluginInfo>* internal_plugins) {
144 base::AutoLock lock(lock_);
145
146 for (std::vector<webkit::WebPluginInfo>::iterator it =
147 internal_plugins_.begin();
148 it != internal_plugins_.end();
149 ++it) {
150 internal_plugins->push_back(*it);
151 }
152 }
153
154 bool PluginList::ReadPluginInfo(const base::FilePath& filename,
155 webkit::WebPluginInfo* info) {
156 {
157 base::AutoLock lock(lock_);
158 for (size_t i = 0; i < internal_plugins_.size(); ++i) {
159 if (filename == internal_plugins_[i].path) {
160 *info = internal_plugins_[i];
161 return true;
162 }
163 }
164 }
165
166 return PluginList::ReadWebPluginInfo(filename, info);
167 }
168
169 // static
170 bool PluginList::ParseMimeTypes(
171 const std::string& mime_types_str,
172 const std::string& file_extensions_str,
173 const base::string16& mime_type_descriptions_str,
174 std::vector<webkit::WebPluginMimeType>* parsed_mime_types) {
175 std::vector<std::string> mime_types, file_extensions;
176 std::vector<base::string16> descriptions;
177 base::SplitString(mime_types_str, '|', &mime_types);
178 base::SplitString(file_extensions_str, '|', &file_extensions);
179 base::SplitString(mime_type_descriptions_str, '|', &descriptions);
180
181 parsed_mime_types->clear();
182
183 if (mime_types.empty())
184 return false;
185
186 for (size_t i = 0; i < mime_types.size(); ++i) {
187 WebPluginMimeType mime_type;
188 mime_type.mime_type = StringToLowerASCII(mime_types[i]);
189 if (file_extensions.size() > i)
190 base::SplitString(file_extensions[i], ',', &mime_type.file_extensions);
191
192 if (descriptions.size() > i) {
193 mime_type.description = descriptions[i];
194
195 // On Windows, the description likely has a list of file extensions
196 // embedded in it (e.g. "SurfWriter file (*.swr)"). Remove an extension
197 // list from the description if it is present.
198 size_t ext = mime_type.description.find(ASCIIToUTF16("(*"));
199 if (ext != base::string16::npos) {
200 if (ext > 1 && mime_type.description[ext - 1] == ' ')
201 ext--;
202
203 mime_type.description.erase(ext);
204 }
205 }
206
207 parsed_mime_types->push_back(mime_type);
208 }
209
210 return true;
211 }
212
213 PluginList::PluginList()
214 : loading_state_(LOADING_STATE_NEEDS_REFRESH),
215 plugins_discovery_disabled_(false) {
216 }
217
218 void PluginList::LoadPluginsIntoPluginListInternal(
219 std::vector<webkit::WebPluginInfo>* plugins) {
220 base::Closure will_load_callback;
221 {
222 base::AutoLock lock(lock_);
223 will_load_callback = will_load_plugins_callback_;
224 }
225 if (!will_load_callback.is_null())
226 will_load_callback.Run();
227
228 std::vector<base::FilePath> plugin_paths;
229 GetPluginPathsToLoad(&plugin_paths);
230
231 for (std::vector<base::FilePath>::const_iterator it = plugin_paths.begin();
232 it != plugin_paths.end();
233 ++it) {
234 WebPluginInfo plugin_info;
235 LoadPluginIntoPluginList(*it, plugins, &plugin_info);
236 }
237 }
238
239 void PluginList::LoadPlugins() {
240 {
241 base::AutoLock lock(lock_);
242 if (loading_state_ == LOADING_STATE_UP_TO_DATE)
243 return;
244
245 loading_state_ = LOADING_STATE_REFRESHING;
246 }
247
248 std::vector<webkit::WebPluginInfo> new_plugins;
249 // Do the actual loading of the plugins.
250 LoadPluginsIntoPluginListInternal(&new_plugins);
251
252 base::AutoLock lock(lock_);
253 plugins_list_.swap(new_plugins);
254
255 // If we haven't been invalidated in the mean time, mark the plug-in list as
256 // up-to-date.
257 if (loading_state_ != LOADING_STATE_NEEDS_REFRESH)
258 loading_state_ = LOADING_STATE_UP_TO_DATE;
259 }
260
261 bool PluginList::LoadPluginIntoPluginList(
262 const base::FilePath& path,
263 std::vector<webkit::WebPluginInfo>* plugins,
264 WebPluginInfo* plugin_info) {
265 LOG_IF(ERROR, PluginList::DebugPluginLoading())
266 << "Loading plugin " << path.value();
267 if (!ReadPluginInfo(path, plugin_info))
268 return false;
269
270 if (!ShouldLoadPluginUsingPluginList(*plugin_info, plugins))
271 return false;
272
273 #if defined(OS_WIN) && !defined(NDEBUG)
274 if (path.BaseName().value() != L"npspy.dll") // Make an exception for NPSPY
275 #endif
276 {
277 for (size_t i = 0; i < plugin_info->mime_types.size(); ++i) {
278 // TODO: don't load global handlers for now.
279 // WebKit hands to the Plugin before it tries
280 // to handle mimeTypes on its own.
281 const std::string &mime_type = plugin_info->mime_types[i].mime_type;
282 if (mime_type == "*")
283 return false;
284 }
285 }
286 plugins->push_back(*plugin_info);
287 return true;
288 }
289
290 void PluginList::GetPluginPathsToLoad(std::vector<base::FilePath>* plugin_paths) {
291 // Don't want to hold the lock while loading new plugins, so we don't block
292 // other methods if they're called on other threads.
293 std::vector<base::FilePath> extra_plugin_paths;
294 std::vector<base::FilePath> extra_plugin_dirs;
295 {
296 base::AutoLock lock(lock_);
297 extra_plugin_paths = extra_plugin_paths_;
298 extra_plugin_dirs = extra_plugin_dirs_;
299 }
300
301 for (size_t i = 0; i < extra_plugin_paths.size(); ++i) {
302 const base::FilePath& path = extra_plugin_paths[i];
303 if (std::find(plugin_paths->begin(), plugin_paths->end(), path) !=
304 plugin_paths->end()) {
305 continue;
306 }
307 plugin_paths->push_back(path);
308 }
309
310 if (NPAPIPluginsSupported()) {
311 // A bit confusingly, this function is used to load Pepper plugins as well.
312 // Those are all internal plugins so we have to use extra_plugin_paths.
313 for (size_t i = 0; i < extra_plugin_dirs.size(); ++i)
314 GetPluginsInDir(extra_plugin_dirs[i], plugin_paths);
315
316 std::vector<base::FilePath> directories_to_scan;
317 GetPluginDirectories(&directories_to_scan);
318 for (size_t i = 0; i < directories_to_scan.size(); ++i)
319 GetPluginsInDir(directories_to_scan[i], plugin_paths);
320
321 #if defined(OS_WIN)
322 GetPluginPathsFromRegistry(plugin_paths);
323 #endif
324 }
325 }
326
327 void PluginList::SetPlugins(const std::vector<webkit::WebPluginInfo>& plugins) {
328 base::AutoLock lock(lock_);
329
330 DCHECK_NE(LOADING_STATE_REFRESHING, loading_state_);
331 loading_state_ = LOADING_STATE_UP_TO_DATE;
332
333 plugins_list_.clear();
334 plugins_list_.insert(plugins_list_.end(), plugins.begin(), plugins.end());
335 }
336
337 void PluginList::set_will_load_plugins_callback(const base::Closure& callback) {
338 base::AutoLock lock(lock_);
339 will_load_plugins_callback_ = callback;
340 }
341
342 void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) {
343 LoadPlugins();
344 base::AutoLock lock(lock_);
345 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
346 }
347
348 bool PluginList::GetPluginsNoRefresh(
349 std::vector<webkit::WebPluginInfo>* plugins) {
350 base::AutoLock lock(lock_);
351 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
352
353 return loading_state_ == LOADING_STATE_UP_TO_DATE;
354 }
355
356 void PluginList::GetPluginInfoArray(
357 const GURL& url,
358 const std::string& mime_type,
359 bool allow_wildcard,
360 bool* use_stale,
361 std::vector<webkit::WebPluginInfo>* info,
362 std::vector<std::string>* actual_mime_types) {
363 DCHECK(mime_type == StringToLowerASCII(mime_type));
364 DCHECK(info);
365
366 if (!use_stale)
367 LoadPlugins();
368 base::AutoLock lock(lock_);
369 if (use_stale)
370 *use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE);
371 info->clear();
372 if (actual_mime_types)
373 actual_mime_types->clear();
374
375 std::set<base::FilePath> visited_plugins;
376
377 // Add in plugins by mime type.
378 for (size_t i = 0; i < plugins_list_.size(); ++i) {
379 if (SupportsType(plugins_list_[i], mime_type, allow_wildcard)) {
380 base::FilePath path = plugins_list_[i].path;
381 if (visited_plugins.insert(path).second) {
382 info->push_back(plugins_list_[i]);
383 if (actual_mime_types)
384 actual_mime_types->push_back(mime_type);
385 }
386 }
387 }
388
389 // Add in plugins by url.
390 std::string path = url.path();
391 std::string::size_type last_dot = path.rfind('.');
392 if (last_dot != std::string::npos) {
393 std::string extension = StringToLowerASCII(std::string(path, last_dot+1));
394 std::string actual_mime_type;
395 for (size_t i = 0; i < plugins_list_.size(); ++i) {
396 if (SupportsExtension(plugins_list_[i], extension, &actual_mime_type)) {
397 base::FilePath path = plugins_list_[i].path;
398 if (visited_plugins.insert(path).second &&
399 AllowMimeTypeMismatch(mime_type, actual_mime_type)) {
400 info->push_back(plugins_list_[i]);
401 if (actual_mime_types)
402 actual_mime_types->push_back(actual_mime_type);
403 }
404 }
405 }
406 }
407 }
408
409 bool PluginList::SupportsType(const webkit::WebPluginInfo& plugin,
410 const std::string& mime_type,
411 bool allow_wildcard) {
412 // Webkit will ask for a plugin to handle empty mime types.
413 if (mime_type.empty())
414 return false;
415
416 for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
417 const webkit::WebPluginMimeType& mime_info = plugin.mime_types[i];
418 if (net::MatchesMimeType(mime_info.mime_type, mime_type)) {
419 if (!allow_wildcard && mime_info.mime_type == "*")
420 continue;
421 return true;
422 }
423 }
424 return false;
425 }
426
427 bool PluginList::SupportsExtension(const webkit::WebPluginInfo& plugin,
428 const std::string& extension,
429 std::string* actual_mime_type) {
430 for (size_t i = 0; i < plugin.mime_types.size(); ++i) {
431 const webkit::WebPluginMimeType& mime_type = plugin.mime_types[i];
432 for (size_t j = 0; j < mime_type.file_extensions.size(); ++j) {
433 if (mime_type.file_extensions[j] == extension) {
434 if (actual_mime_type)
435 *actual_mime_type = mime_type.mime_type;
436 return true;
437 }
438 }
439 }
440 return false;
441 }
442
443 PluginList::~PluginList() {
444 }
445
446
447 } // namespace npapi
448 } // namespace webkit
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698