Chromium Code Reviews| 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); |
|
piman
2016/04/05 06:00:48
At this point this is pretty much just a roundabou
| |
| 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 |