#include "content/common/pepper_plugin_registry.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/native_library.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
#include "webkit/plugins/npapi/plugin_list.h"
namespace {
void ComputePluginsFromCommandLine(
std::vector<content::PepperPluginInfo>* plugins) {
bool out_of_process =
CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiOutOfProcess);
const std::string value =
CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kRegisterPepperPlugins);
if (value.empty())
return;
std::vector<std::string> modules;
base::SplitString(value, ',', &modules);
for (size_t i = 0; i < modules.size(); ++i) {
std::vector<std::string> parts;
base::SplitString(modules[i], ';', &parts);
if (parts.size() < 2) {
DLOG(ERROR) << "Required mime-type not found";
continue;
}
std::vector<std::string> name_parts;
base::SplitString(parts[0], '#', &name_parts);
content::PepperPluginInfo plugin;
plugin.is_out_of_process = out_of_process;
#if defined(OS_WIN)
plugin.path = FilePath(ASCIIToUTF16(name_parts[0]));
#else
plugin.path = FilePath(name_parts[0]);
#endif
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) {
webkit::WebPluginMimeType mime_type(parts[j],
std::string(),
plugin.description);
plugin.mime_types.push_back(mime_type);
}
plugin.permissions = ppapi::PERMISSION_DEV |
ppapi::PERMISSION_PRIVATE |
ppapi::PERMISSION_BYPASS_USER_GESTURE;
plugins->push_back(plugin);
}
}
}
webkit::WebPluginInfo content::PepperPluginInfo::ToWebPluginInfo() const {
webkit::WebPluginInfo info;
info.type = is_out_of_process ?
(is_sandboxed ?
webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS :
webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED) :
webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS;
info.name = name.empty() ?
path.BaseName().LossyDisplayName() : UTF8ToUTF16(name);
info.path = path;
info.version = ASCIIToUTF16(version);
info.desc = ASCIIToUTF16(description);
info.mime_types = mime_types;
info.pepper_permissions = permissions;
LOG(INFO) << "PepperPluginInfo::ToWebPluginInfo \""
<< UTF16ToUTF8(info.path.LossyDisplayName()) << "\" "
<< "permissions = " << permissions;
return info;
}
bool MakePepperPluginInfo(const webkit::WebPluginInfo& webplugin_info,
content::PepperPluginInfo* pepper_info) {
if (!webkit::IsPepperPlugin(webplugin_info))
return false;
pepper_info->is_out_of_process = webkit::IsOutOfProcessPlugin(webplugin_info);
pepper_info->is_sandboxed = webplugin_info.type !=
webkit::WebPluginInfo::PLUGIN_TYPE_PEPPER_UNSANDBOXED;
pepper_info->path = FilePath(webplugin_info.path);
pepper_info->name = UTF16ToASCII(webplugin_info.name);
pepper_info->description = UTF16ToASCII(webplugin_info.desc);
pepper_info->version = UTF16ToASCII(webplugin_info.version);
pepper_info->mime_types = webplugin_info.mime_types;
pepper_info->permissions = webplugin_info.pepper_permissions;
LOG(INFO) << "PepperPluginInfo::ToWebPluginInfo \""
<< UTF16ToUTF8(pepper_info->path.LossyDisplayName()) << "\" "
<< "permissions = " << pepper_info->permissions;
return true;
}
PepperPluginRegistry* PepperPluginRegistry::GetInstance() {
static PepperPluginRegistry* registry = NULL;
if (!registry)
registry = new PepperPluginRegistry;
return registry;
}
void PepperPluginRegistry::ComputeList(
std::vector<content::PepperPluginInfo>* plugins) {
content::GetContentClient()->AddPepperPlugins(plugins);
ComputePluginsFromCommandLine(plugins);
}
void PepperPluginRegistry::PreloadModules() {
std::vector<content::PepperPluginInfo> plugins;
ComputeList(&plugins);
for (size_t i = 0; i < plugins.size(); ++i) {
if (!plugins[i].is_internal && plugins[i].is_sandboxed) {
std::string error;
base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path,
&error);
DLOG_IF(WARNING, !library) << "Unable to load plugin "
<< plugins[i].path.value() << " "
<< error;
(void)library;
}
}
}
const content::PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin(
const webkit::WebPluginInfo& info) {
for (size_t i = 0; i < plugin_list_.size(); ++i) {
if (info.path == plugin_list_[i].path)
return &plugin_list_[i];
}
content::PepperPluginInfo plugin;
if (!MakePepperPluginInfo(info, &plugin))
return NULL;
plugin_list_.push_back(plugin);
return &plugin_list_[plugin_list_.size() - 1];
}
webkit::ppapi::PluginModule* PepperPluginRegistry::GetLiveModule(
const FilePath& path) {
NonOwningModuleMap::iterator it = live_modules_.find(path);
if (it == live_modules_.end())
return NULL;
return it->second;
}
void PepperPluginRegistry::AddLiveModule(const FilePath& path,
webkit::ppapi::PluginModule* module) {
DCHECK(live_modules_.find(path) == live_modules_.end());
live_modules_[path] = module;
}
void PepperPluginRegistry::PluginModuleDead(
webkit::ppapi::PluginModule* dead_module) {
for (NonOwningModuleMap::iterator i = live_modules_.begin();
i != live_modules_.end(); ++i) {
if (i->second == dead_module) {
live_modules_.erase(i);
return;
}
}
NOTREACHED();
}
PepperPluginRegistry::~PepperPluginRegistry() {
preloaded_modules_.clear();
DCHECK(live_modules_.empty());
}
PepperPluginRegistry::PepperPluginRegistry() {
ComputeList(&plugin_list_);
for (size_t i = 0; i < plugin_list_.size(); i++) {
const content::PepperPluginInfo& current = plugin_list_[i];
if (current.is_out_of_process)
continue;
LOG(INFO) << "PepperPluginRegistry::PepperPluginRegistry \""
<< UTF16ToUTF8(current.path.LossyDisplayName()) << "\" "
<< " permissions =" << current.permissions;
scoped_refptr<webkit::ppapi::PluginModule> module =
new webkit::ppapi::PluginModule(current.name, current.path, this,
ppapi::PpapiPermissions(current.permissions));
AddLiveModule(current.path, module);
if (current.is_internal) {
if (!module->InitAsInternalPlugin(current.internal_entry_points)) {
DLOG(ERROR) << "Failed to load pepper module: " << current.path.value();
continue;
}
} else {
if (!module->InitAsLibrary(current.path)) {
DLOG(ERROR) << "Failed to load pepper module: " << current.path.value();
continue;
}
}
preloaded_modules_[current.path] = module;
}
}