| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "content/common/pepper_plugin_list.h" | 
 |  | 
 | #include <stddef.h> | 
 | #include <stdint.h> | 
 |  | 
 | #include "base/command_line.h" | 
 | #include "base/files/file_util.h" | 
 | #include "base/strings/string_split.h" | 
 | #include "base/strings/string_util.h" | 
 | #include "base/strings/utf_string_conversions.h" | 
 | #include "build/build_config.h" | 
 | #include "content/public/common/content_client.h" | 
 | #include "content/public/common/content_switches.h" | 
 | #include "content/public/common/pepper_plugin_info.h" | 
 | #include "ppapi/shared_impl/ppapi_permissions.h" | 
 |  | 
 | namespace content { | 
 | namespace { | 
 |  | 
 | // The maximum number of plugins allowed to be registered from command line. | 
 | const size_t kMaxPluginsToRegisterFromCommandLine = 64; | 
 |  | 
 | // Appends any plugins from the command line to the given vector. | 
 | void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) { | 
 |   // On Linux, once we're sandboxed, we can't know if a plugin is available or | 
 |   // not. But (on Linux) this function is always called once before we're | 
 |   // sandboxed. So when this function is called for the first time we set a | 
 |   // flag if the plugin file is available. Then we can skip the check on file | 
 |   // existence in subsequent calls if the flag is set. | 
 |   // NOTE: In theory we could have unlimited number of plugins registered in | 
 |   // command line. But in practice, 64 plugins should be more than enough. | 
 |   static uint64_t skip_file_check_flags = 0; | 
 |   static_assert( | 
 |       kMaxPluginsToRegisterFromCommandLine <= sizeof(skip_file_check_flags) * 8, | 
 |       "max plugins to register from command line exceeds limit"); | 
 |  | 
 |   bool out_of_process = true; | 
 |   if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 
 |           switches::kPpapiInProcess)) | 
 |     out_of_process = false; | 
 |  | 
 |   const std::string value = | 
 |       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 
 |           switches::kRegisterPepperPlugins); | 
 |   if (value.empty()) | 
 |     return; | 
 |  | 
 |   // FORMAT: | 
 |   // command-line = <plugin-entry> + *( LWS + "," + LWS + <plugin-entry> ) | 
 |   // plugin-entry = | 
 |   //    <file-path> + | 
 |   //    ["#" + <name> + ["#" + <description> + ["#" + <version>]]] + | 
 |   //    *1( LWS + ";" + LWS + <mime-type-data> ) | 
 |   // mime-type-data = <mime-type> + [ LWS + "#" + LWS + <extension> ] | 
 |   std::vector<std::string> modules = base::SplitString( | 
 |       value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 
 |  | 
 |   size_t plugins_to_register = modules.size(); | 
 |   if (plugins_to_register > kMaxPluginsToRegisterFromCommandLine) { | 
 |     DVLOG(1) << plugins_to_register << " pepper plugins registered from" | 
 |              << " command line which exceeds the limit (maximum " | 
 |              << kMaxPluginsToRegisterFromCommandLine << " plugins allowed)"; | 
 |     plugins_to_register = kMaxPluginsToRegisterFromCommandLine; | 
 |   } | 
 |  | 
 |   for (size_t i = 0; i < plugins_to_register; ++i) { | 
 |     std::vector<std::string> parts = base::SplitString( | 
 |         modules[i], ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 
 |     if (parts.size() < 2) { | 
 |       DVLOG(1) << "Required mime-type not found"; | 
 |       continue; | 
 |     } | 
 |  | 
 |     std::vector<std::string> name_parts = base::SplitString( | 
 |         parts[0], "#", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 
 |  | 
 |     PepperPluginInfo plugin; | 
 |     plugin.is_out_of_process = out_of_process; | 
 | #if defined(OS_WIN) | 
 |     // This means we can't provide plugins from non-ASCII paths, but | 
 |     // since this switch is only for development I don't think that's | 
 |     // too awful. | 
 |     plugin.path = base::FilePath(base::ASCIIToUTF16(name_parts[0])); | 
 | #else | 
 |     plugin.path = base::FilePath(name_parts[0]); | 
 | #endif | 
 |  | 
 |     uint64_t index_mask = 1ULL << i; | 
 |     if (!(skip_file_check_flags & index_mask)) { | 
 |       if (base::PathExists(plugin.path)) { | 
 |         skip_file_check_flags |= index_mask; | 
 |       } else { | 
 |         DVLOG(1) << "Plugin doesn't exist: " << plugin.path.MaybeAsASCII(); | 
 |         continue; | 
 |       } | 
 |     } | 
 |  | 
 |     if (name_parts.size() > 1) | 
 |       plugin.name = name_parts[1]; | 
 |     if (name_parts.size() > 2) | 
 |       plugin.description = name_parts[2]; | 
 |     if (name_parts.size() > 3) | 
 |       plugin.version = name_parts[3]; | 
 |     for (size_t j = 1; j < parts.size(); ++j) { | 
 |       std::vector<std::string> mime_parts = base::SplitString( | 
 |           parts[j], "#", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 
 |       DCHECK_GE(mime_parts.size(), 1u); | 
 |       std::string mime_extension; | 
 |       if (mime_parts.size() > 1) | 
 |         mime_extension = mime_parts[1]; | 
 |       WebPluginMimeType mime_type(mime_parts[0], | 
 |                                   mime_extension, | 
 |                                   plugin.description); | 
 |       plugin.mime_types.push_back(mime_type); | 
 |     } | 
 |  | 
 |     // If the plugin name is empty, use the filename. | 
 |     if (plugin.name.empty()) { | 
 |       plugin.name = | 
 |           base::UTF16ToUTF8(plugin.path.BaseName().LossyDisplayName()); | 
 |     } | 
 |  | 
 |     // Command-line plugins get full permissions. | 
 |     plugin.permissions = ppapi::PERMISSION_ALL_BITS; | 
 |  | 
 |     plugins->push_back(plugin); | 
 |   } | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | bool MakePepperPluginInfo(const WebPluginInfo& webplugin_info, | 
 |                           PepperPluginInfo* pepper_info) { | 
 |   if (!webplugin_info.is_pepper_plugin()) | 
 |     return false; | 
 |  | 
 |   pepper_info->is_out_of_process = | 
 |       webplugin_info.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS; | 
 |  | 
 |   pepper_info->path = base::FilePath(webplugin_info.path); | 
 |   pepper_info->name = base::UTF16ToASCII(webplugin_info.name); | 
 |   pepper_info->description = base::UTF16ToASCII(webplugin_info.desc); | 
 |   pepper_info->version = base::UTF16ToASCII(webplugin_info.version); | 
 |   pepper_info->mime_types = webplugin_info.mime_types; | 
 |   pepper_info->permissions = webplugin_info.pepper_permissions; | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | void ComputePepperPluginList(std::vector<PepperPluginInfo>* plugins) { | 
 |   GetContentClient()->AddPepperPlugins(plugins); | 
 |   ComputePluginsFromCommandLine(plugins); | 
 | } | 
 |  | 
 | }  // namespace content |