OLD | NEW |
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 "content/common/plugin_list.h" | 5 #include "content/common/plugin_list.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
16 #include "base/strings/sys_string_conversions.h" | 16 #include "base/strings/sys_string_conversions.h" |
17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
18 #include "build/build_config.h" | 18 #include "build/build_config.h" |
19 #include "content/public/common/content_switches.h" | 19 #include "content/public/common/content_switches.h" |
20 #include "net/base/mime_util.h" | 20 #include "net/base/mime_util.h" |
21 #include "url/gurl.h" | 21 #include "url/gurl.h" |
22 | 22 |
23 #if defined(OS_WIN) | |
24 #include "content/common/plugin_constants_win.h" | |
25 #endif | |
26 | |
27 namespace content { | 23 namespace content { |
28 | 24 |
29 namespace { | 25 namespace { |
30 | 26 |
31 base::LazyInstance<PluginList> g_singleton = LAZY_INSTANCE_INITIALIZER; | 27 base::LazyInstance<PluginList> g_singleton = LAZY_INSTANCE_INITIALIZER; |
32 | 28 |
33 } // namespace | 29 } // namespace |
34 | 30 |
35 // static | 31 // static |
36 PluginList* PluginList::Singleton() { | 32 PluginList* PluginList::Singleton() { |
37 return g_singleton.Pointer(); | 33 return g_singleton.Pointer(); |
38 } | 34 } |
39 | 35 |
40 // static | |
41 bool PluginList::DebugPluginLoading() { | |
42 return base::CommandLine::ForCurrentProcess()->HasSwitch( | |
43 switches::kDebugPluginLoading); | |
44 } | |
45 | |
46 void PluginList::DisablePluginsDiscovery() { | |
47 plugins_discovery_disabled_ = true; | |
48 } | |
49 | |
50 void PluginList::RefreshPlugins() { | 36 void PluginList::RefreshPlugins() { |
51 base::AutoLock lock(lock_); | 37 base::AutoLock lock(lock_); |
52 loading_state_ = LOADING_STATE_NEEDS_REFRESH; | 38 loading_state_ = LOADING_STATE_NEEDS_REFRESH; |
53 } | 39 } |
54 | 40 |
55 void PluginList::AddExtraPluginPath(const base::FilePath& plugin_path) { | |
56 // Chrome OS only loads plugins from /opt/google/chrome/plugins. | |
57 #if !defined(OS_CHROMEOS) | |
58 base::AutoLock lock(lock_); | |
59 extra_plugin_paths_.push_back(plugin_path); | |
60 #endif | |
61 } | |
62 | |
63 void PluginList::RemoveExtraPluginPath(const base::FilePath& plugin_path) { | |
64 base::AutoLock lock(lock_); | |
65 RemoveExtraPluginPathLocked(plugin_path); | |
66 } | |
67 | |
68 void PluginList::AddExtraPluginDir(const base::FilePath& plugin_dir) { | |
69 // Chrome OS only loads plugins from /opt/google/chrome/plugins. | |
70 #if !defined(OS_CHROMEOS) | |
71 base::AutoLock lock(lock_); | |
72 extra_plugin_dirs_.push_back(plugin_dir); | |
73 #endif | |
74 } | |
75 | |
76 void PluginList::RegisterInternalPlugin(const WebPluginInfo& info, | 41 void PluginList::RegisterInternalPlugin(const WebPluginInfo& info, |
77 bool add_at_beginning) { | 42 bool add_at_beginning) { |
78 base::AutoLock lock(lock_); | 43 base::AutoLock lock(lock_); |
79 | 44 |
80 internal_plugins_.push_back(info); | 45 internal_plugins_.push_back(info); |
81 if (add_at_beginning) { | 46 if (add_at_beginning) { |
82 // Newer registrations go earlier in the list so they can override the MIME | 47 // Newer registrations go earlier in the list so they can override the MIME |
83 // types of older registrations. | 48 // types of older registrations. |
84 extra_plugin_paths_.insert(extra_plugin_paths_.begin(), info.path); | 49 extra_plugin_paths_.insert(extra_plugin_paths_.begin(), info.path); |
85 } else { | 50 } else { |
(...skipping 21 matching lines...) Expand all Loading... |
107 | 72 |
108 for (std::vector<WebPluginInfo>::iterator it = internal_plugins_.begin(); | 73 for (std::vector<WebPluginInfo>::iterator it = internal_plugins_.begin(); |
109 it != internal_plugins_.end(); | 74 it != internal_plugins_.end(); |
110 ++it) { | 75 ++it) { |
111 internal_plugins->push_back(*it); | 76 internal_plugins->push_back(*it); |
112 } | 77 } |
113 } | 78 } |
114 | 79 |
115 bool PluginList::ReadPluginInfo(const base::FilePath& filename, | 80 bool PluginList::ReadPluginInfo(const base::FilePath& filename, |
116 WebPluginInfo* info) { | 81 WebPluginInfo* info) { |
117 { | 82 base::AutoLock lock(lock_); |
118 base::AutoLock lock(lock_); | 83 for (const auto& plugin : internal_plugins_) { |
119 for (size_t i = 0; i < internal_plugins_.size(); ++i) { | 84 if (filename == plugin.path) { |
120 if (filename == internal_plugins_[i].path) { | 85 *info = plugin; |
121 *info = internal_plugins_[i]; | 86 return true; |
122 return true; | |
123 } | |
124 } | 87 } |
125 } | 88 } |
126 | 89 return false; |
127 return PluginList::ReadWebPluginInfo(filename, info); | |
128 } | |
129 | |
130 // static | |
131 bool PluginList::ParseMimeTypes( | |
132 const std::string& mime_types_str, | |
133 const std::string& file_extensions_str, | |
134 const base::string16& mime_type_descriptions_str, | |
135 std::vector<WebPluginMimeType>* parsed_mime_types) { | |
136 std::vector<std::string> mime_types = base::SplitString( | |
137 mime_types_str, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
138 std::vector<std::string> file_extensions = base::SplitString( | |
139 file_extensions_str, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
140 std::vector<base::string16> descriptions = base::SplitString( | |
141 mime_type_descriptions_str, base::string16(1, '|'), base::TRIM_WHITESPACE, | |
142 base::SPLIT_WANT_ALL); | |
143 | |
144 parsed_mime_types->clear(); | |
145 | |
146 if (mime_types.empty()) | |
147 return false; | |
148 | |
149 for (size_t i = 0; i < mime_types.size(); ++i) { | |
150 WebPluginMimeType mime_type; | |
151 mime_type.mime_type = base::ToLowerASCII(mime_types[i]); | |
152 if (file_extensions.size() > i) { | |
153 mime_type.file_extensions = base::SplitString( | |
154 file_extensions[i], ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
155 } | |
156 | |
157 if (descriptions.size() > i) { | |
158 mime_type.description = descriptions[i]; | |
159 | |
160 // On Windows, the description likely has a list of file extensions | |
161 // embedded in it (e.g. "SurfWriter file (*.swr)"). Remove an extension | |
162 // list from the description if it is present. | |
163 size_t ext = mime_type.description.find(base::ASCIIToUTF16("(*")); | |
164 if (ext != base::string16::npos) { | |
165 if (ext > 1 && mime_type.description[ext - 1] == ' ') | |
166 ext--; | |
167 | |
168 mime_type.description.erase(ext); | |
169 } | |
170 } | |
171 | |
172 parsed_mime_types->push_back(mime_type); | |
173 } | |
174 | |
175 return true; | |
176 } | 90 } |
177 | 91 |
178 PluginList::PluginList() | 92 PluginList::PluginList() |
179 : loading_state_(LOADING_STATE_NEEDS_REFRESH), | 93 : loading_state_(LOADING_STATE_NEEDS_REFRESH) { |
180 plugins_discovery_disabled_(false) { | |
181 } | 94 } |
182 | 95 |
183 bool PluginList::PrepareForPluginLoading() { | 96 bool PluginList::PrepareForPluginLoading() { |
184 base::AutoLock lock(lock_); | 97 base::AutoLock lock(lock_); |
185 if (loading_state_ == LOADING_STATE_UP_TO_DATE) | 98 if (loading_state_ == LOADING_STATE_UP_TO_DATE) |
186 return false; | 99 return false; |
187 | 100 |
188 loading_state_ = LOADING_STATE_REFRESHING; | 101 loading_state_ = LOADING_STATE_REFRESHING; |
189 return true; | 102 return true; |
190 } | 103 } |
191 | 104 |
192 void PluginList::LoadPlugins(bool include_npapi) { | 105 void PluginList::LoadPlugins() { |
193 if (!PrepareForPluginLoading()) | 106 if (!PrepareForPluginLoading()) |
194 return; | 107 return; |
195 | 108 |
196 std::vector<WebPluginInfo> new_plugins; | 109 std::vector<WebPluginInfo> new_plugins; |
197 base::Closure will_load_callback; | 110 base::Closure will_load_callback; |
198 { | 111 { |
199 base::AutoLock lock(lock_); | 112 base::AutoLock lock(lock_); |
200 will_load_callback = will_load_plugins_callback_; | 113 will_load_callback = will_load_plugins_callback_; |
201 } | 114 } |
202 if (!will_load_callback.is_null()) | 115 if (!will_load_callback.is_null()) |
203 will_load_callback.Run(); | 116 will_load_callback.Run(); |
204 | 117 |
205 std::vector<base::FilePath> plugin_paths; | 118 std::vector<base::FilePath> plugin_paths; |
206 GetPluginPathsToLoad(&plugin_paths, include_npapi); | 119 GetPluginPathsToLoad(&plugin_paths); |
207 | 120 |
208 for (std::vector<base::FilePath>::const_iterator it = plugin_paths.begin(); | 121 for (std::vector<base::FilePath>::const_iterator it = plugin_paths.begin(); |
209 it != plugin_paths.end(); | 122 it != plugin_paths.end(); |
210 ++it) { | 123 ++it) { |
211 WebPluginInfo plugin_info; | 124 WebPluginInfo plugin_info; |
212 LoadPluginIntoPluginList(*it, &new_plugins, &plugin_info); | 125 LoadPluginIntoPluginList(*it, &new_plugins, &plugin_info); |
213 } | 126 } |
214 | 127 |
215 SetPlugins(new_plugins); | 128 SetPlugins(new_plugins); |
216 } | 129 } |
217 | 130 |
218 bool PluginList::LoadPluginIntoPluginList( | 131 bool PluginList::LoadPluginIntoPluginList( |
219 const base::FilePath& path, | 132 const base::FilePath& path, |
220 std::vector<WebPluginInfo>* plugins, | 133 std::vector<WebPluginInfo>* plugins, |
221 WebPluginInfo* plugin_info) { | 134 WebPluginInfo* plugin_info) { |
222 LOG_IF(ERROR, PluginList::DebugPluginLoading()) | |
223 << "Loading plugin " << path.value(); | |
224 if (!ReadPluginInfo(path, plugin_info)) | 135 if (!ReadPluginInfo(path, plugin_info)) |
225 return false; | 136 return false; |
226 | 137 |
227 if (!ShouldLoadPluginUsingPluginList(*plugin_info, plugins)) | 138 // TODO(piman): Do we still need this after NPAPI removal? |
228 return false; | 139 for (size_t i = 0; i < plugin_info->mime_types.size(); ++i) { |
229 | 140 // TODO: don't load global handlers for now. |
230 #if defined(OS_WIN) && !defined(NDEBUG) | 141 // WebKit hands to the Plugin before it tries |
231 if (path.BaseName().value() != L"npspy.dll") // Make an exception for NPSPY | 142 // to handle mimeTypes on its own. |
232 #endif | 143 const std::string &mime_type = plugin_info->mime_types[i].mime_type; |
233 { | 144 if (mime_type == "*") |
234 for (size_t i = 0; i < plugin_info->mime_types.size(); ++i) { | 145 return false; |
235 // TODO: don't load global handlers for now. | |
236 // WebKit hands to the Plugin before it tries | |
237 // to handle mimeTypes on its own. | |
238 const std::string &mime_type = plugin_info->mime_types[i].mime_type; | |
239 if (mime_type == "*") | |
240 return false; | |
241 } | |
242 } | 146 } |
243 plugins->push_back(*plugin_info); | 147 plugins->push_back(*plugin_info); |
244 return true; | 148 return true; |
245 } | 149 } |
246 | 150 |
247 void PluginList::GetPluginPathsToLoad(std::vector<base::FilePath>* plugin_paths, | 151 void PluginList::GetPluginPathsToLoad( |
248 bool include_npapi) { | 152 std::vector<base::FilePath>* plugin_paths) { |
249 // Don't want to hold the lock while loading new plugins, so we don't block | 153 // Don't want to hold the lock while loading new plugins, so we don't block |
250 // other methods if they're called on other threads. | 154 // other methods if they're called on other threads. |
251 std::vector<base::FilePath> extra_plugin_paths; | 155 std::vector<base::FilePath> extra_plugin_paths; |
252 std::vector<base::FilePath> extra_plugin_dirs; | |
253 { | 156 { |
254 base::AutoLock lock(lock_); | 157 base::AutoLock lock(lock_); |
255 extra_plugin_paths = extra_plugin_paths_; | 158 extra_plugin_paths = extra_plugin_paths_; |
256 extra_plugin_dirs = extra_plugin_dirs_; | |
257 } | 159 } |
258 | 160 |
259 for (size_t i = 0; i < extra_plugin_paths.size(); ++i) { | 161 for (size_t i = 0; i < extra_plugin_paths.size(); ++i) { |
260 const base::FilePath& path = extra_plugin_paths[i]; | 162 const base::FilePath& path = extra_plugin_paths[i]; |
261 if (std::find(plugin_paths->begin(), plugin_paths->end(), path) != | 163 if (std::find(plugin_paths->begin(), plugin_paths->end(), path) != |
262 plugin_paths->end()) { | 164 plugin_paths->end()) { |
263 continue; | 165 continue; |
264 } | 166 } |
265 plugin_paths->push_back(path); | 167 plugin_paths->push_back(path); |
266 } | 168 } |
267 | |
268 if (include_npapi) { | |
269 // A bit confusingly, this function is used to load Pepper plugins as well. | |
270 // Those are all internal plugins so we have to use extra_plugin_paths. | |
271 for (size_t i = 0; i < extra_plugin_dirs.size(); ++i) | |
272 GetPluginsInDir(extra_plugin_dirs[i], plugin_paths); | |
273 | |
274 std::vector<base::FilePath> directories_to_scan; | |
275 GetPluginDirectories(&directories_to_scan); | |
276 for (size_t i = 0; i < directories_to_scan.size(); ++i) | |
277 GetPluginsInDir(directories_to_scan[i], plugin_paths); | |
278 | |
279 #if defined(OS_WIN) | |
280 GetPluginPathsFromRegistry(plugin_paths); | |
281 #endif | |
282 } | |
283 } | 169 } |
284 | 170 |
285 void PluginList::SetPlugins(const std::vector<WebPluginInfo>& plugins) { | 171 void PluginList::SetPlugins(const std::vector<WebPluginInfo>& plugins) { |
286 base::AutoLock lock(lock_); | 172 base::AutoLock lock(lock_); |
287 | 173 |
288 // If we haven't been invalidated in the mean time, mark the plugin list as | 174 // If we haven't been invalidated in the mean time, mark the plugin list as |
289 // up-to-date. | 175 // up-to-date. |
290 if (loading_state_ != LOADING_STATE_NEEDS_REFRESH) | 176 if (loading_state_ != LOADING_STATE_NEEDS_REFRESH) |
291 loading_state_ = LOADING_STATE_UP_TO_DATE; | 177 loading_state_ = LOADING_STATE_UP_TO_DATE; |
292 | 178 |
293 plugins_list_ = plugins; | 179 plugins_list_ = plugins; |
294 } | 180 } |
295 | 181 |
296 void PluginList::set_will_load_plugins_callback(const base::Closure& callback) { | 182 void PluginList::set_will_load_plugins_callback(const base::Closure& callback) { |
297 base::AutoLock lock(lock_); | 183 base::AutoLock lock(lock_); |
298 will_load_plugins_callback_ = callback; | 184 will_load_plugins_callback_ = callback; |
299 } | 185 } |
300 | 186 |
301 void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins, | 187 void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) { |
302 bool include_npapi) { | 188 LoadPlugins(); |
303 LoadPlugins(include_npapi); | |
304 base::AutoLock lock(lock_); | 189 base::AutoLock lock(lock_); |
305 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end()); | 190 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end()); |
306 } | 191 } |
307 | 192 |
308 bool PluginList::GetPluginsNoRefresh(std::vector<WebPluginInfo>* plugins) { | 193 bool PluginList::GetPluginsNoRefresh(std::vector<WebPluginInfo>* plugins) { |
309 base::AutoLock lock(lock_); | 194 base::AutoLock lock(lock_); |
310 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end()); | 195 plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end()); |
311 | 196 |
312 return loading_state_ == LOADING_STATE_UP_TO_DATE; | 197 return loading_state_ == LOADING_STATE_UP_TO_DATE; |
313 } | 198 } |
314 | 199 |
315 void PluginList::GetPluginInfoArray( | 200 void PluginList::GetPluginInfoArray( |
316 const GURL& url, | 201 const GURL& url, |
317 const std::string& mime_type, | 202 const std::string& mime_type, |
318 bool allow_wildcard, | 203 bool allow_wildcard, |
319 bool* use_stale, | 204 bool* use_stale, |
320 bool include_npapi, | |
321 std::vector<WebPluginInfo>* info, | 205 std::vector<WebPluginInfo>* info, |
322 std::vector<std::string>* actual_mime_types) { | 206 std::vector<std::string>* actual_mime_types) { |
323 DCHECK(mime_type == base::ToLowerASCII(mime_type)); | 207 DCHECK(mime_type == base::ToLowerASCII(mime_type)); |
324 DCHECK(info); | 208 DCHECK(info); |
325 | 209 |
326 if (!use_stale) | 210 if (!use_stale) |
327 LoadPlugins(include_npapi); | 211 LoadPlugins(); |
328 base::AutoLock lock(lock_); | 212 base::AutoLock lock(lock_); |
329 if (use_stale) | 213 if (use_stale) |
330 *use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE); | 214 *use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE); |
331 info->clear(); | 215 info->clear(); |
332 if (actual_mime_types) | 216 if (actual_mime_types) |
333 actual_mime_types->clear(); | 217 actual_mime_types->clear(); |
334 | 218 |
335 std::set<base::FilePath> visited_plugins; | 219 std::set<base::FilePath> visited_plugins; |
336 | 220 |
337 // Add in plugins by mime type. | 221 // Add in plugins by mime type. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 plugin_path); | 297 plugin_path); |
414 if (it != extra_plugin_paths_.end()) | 298 if (it != extra_plugin_paths_.end()) |
415 extra_plugin_paths_.erase(it); | 299 extra_plugin_paths_.erase(it); |
416 } | 300 } |
417 | 301 |
418 PluginList::~PluginList() { | 302 PluginList::~PluginList() { |
419 } | 303 } |
420 | 304 |
421 | 305 |
422 } // namespace content | 306 } // namespace content |
OLD | NEW |