329 lines
11 KiB
C++
329 lines
11 KiB
C++
// Copyright 2015 The Chromium Embedded Framework Authors.
|
|
// Portions copyright 2014 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 "libcef/common/content_client.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#include "include/cef_stream.h"
|
|
#include "include/cef_version.h"
|
|
#include "libcef/browser/content_browser_client.h"
|
|
#include "libcef/browser/extensions/pdf_extension_util.h"
|
|
#include "libcef/common/cef_switches.h"
|
|
#include "libcef/common/extensions/extensions_util.h"
|
|
#include "libcef/common/net/scheme_registration.h"
|
|
#include "libcef/common/scheme_registrar_impl.h"
|
|
|
|
#include "base/command_line.h"
|
|
#include "base/files/file_util.h"
|
|
#include "base/json/json_reader.h"
|
|
#include "base/logging.h"
|
|
#include "base/path_service.h"
|
|
#include "base/strings/string_piece.h"
|
|
#include "base/strings/string_split.h"
|
|
#include "base/strings/string_util.h"
|
|
#include "base/strings/stringprintf.h"
|
|
#include "base/strings/utf_string_conversions.h"
|
|
#include "chrome/common/chrome_constants.h"
|
|
#include "chrome/common/chrome_paths.h"
|
|
#include "chrome/common/chrome_switches.h"
|
|
#include "chrome/common/pepper_flash.h"
|
|
#include "content/public/common/content_constants.h"
|
|
#include "content/public/common/content_switches.h"
|
|
#include "content/public/common/pepper_plugin_info.h"
|
|
#include "ppapi/shared_impl/ppapi_permissions.h"
|
|
#include "third_party/widevine/cdm/buildflags.h"
|
|
#include "ui/base/l10n/l10n_util.h"
|
|
#include "ui/base/resource/resource_bundle.h"
|
|
|
|
#if defined(OS_LINUX)
|
|
#include "libcef/common/widevine_loader.h"
|
|
#endif
|
|
|
|
namespace {
|
|
|
|
CefContentClient* g_content_client = nullptr;
|
|
|
|
// The following plugin-related methods are from
|
|
// chrome/common/chrome_content_client.cc
|
|
|
|
const char kPDFPluginExtension[] = "pdf";
|
|
const char kPDFPluginDescription[] = "Portable Document Format";
|
|
const char kPDFPluginOutOfProcessMimeType[] = "application/x-google-chrome-pdf";
|
|
const uint32_t kPDFPluginPermissions =
|
|
ppapi::PERMISSION_PDF | ppapi::PERMISSION_DEV;
|
|
|
|
content::PepperPluginInfo::GetInterfaceFunc g_pdf_get_interface;
|
|
content::PepperPluginInfo::PPP_InitializeModuleFunc g_pdf_initialize_module;
|
|
content::PepperPluginInfo::PPP_ShutdownModuleFunc g_pdf_shutdown_module;
|
|
|
|
// Appends the known built-in plugins to the given vector. Some built-in
|
|
// plugins are "internal" which means they are compiled into the Chrome binary,
|
|
// and some are extra shared libraries distributed with the browser (these are
|
|
// not marked internal, aside from being automatically registered, they're just
|
|
// regular plugins).
|
|
void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
|
|
if (extensions::PdfExtensionEnabled()) {
|
|
content::PepperPluginInfo pdf_info;
|
|
pdf_info.is_internal = true;
|
|
pdf_info.is_out_of_process = true;
|
|
pdf_info.name = extensions::pdf_extension_util::kPdfPluginName;
|
|
pdf_info.description = kPDFPluginDescription;
|
|
pdf_info.path =
|
|
base::FilePath::FromUTF8Unsafe(CefContentClient::kPDFPluginPath);
|
|
content::WebPluginMimeType pdf_mime_type(kPDFPluginOutOfProcessMimeType,
|
|
kPDFPluginExtension,
|
|
kPDFPluginDescription);
|
|
pdf_info.mime_types.push_back(pdf_mime_type);
|
|
pdf_info.internal_entry_points.get_interface = g_pdf_get_interface;
|
|
pdf_info.internal_entry_points.initialize_module = g_pdf_initialize_module;
|
|
pdf_info.internal_entry_points.shutdown_module = g_pdf_shutdown_module;
|
|
pdf_info.permissions = kPDFPluginPermissions;
|
|
plugins->push_back(pdf_info);
|
|
}
|
|
}
|
|
|
|
content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
|
|
const std::string& version) {
|
|
content::PepperPluginInfo plugin;
|
|
|
|
plugin.is_out_of_process = true;
|
|
plugin.name = content::kFlashPluginName;
|
|
plugin.path = path;
|
|
plugin.permissions = kPepperFlashPermissions;
|
|
|
|
std::vector<std::string> flash_version_numbers = base::SplitString(
|
|
version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
|
if (flash_version_numbers.size() < 1)
|
|
flash_version_numbers.push_back("11");
|
|
if (flash_version_numbers.size() < 2)
|
|
flash_version_numbers.push_back("2");
|
|
if (flash_version_numbers.size() < 3)
|
|
flash_version_numbers.push_back("999");
|
|
if (flash_version_numbers.size() < 4)
|
|
flash_version_numbers.push_back("999");
|
|
// E.g., "Shockwave Flash 10.2 r154":
|
|
plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
|
|
flash_version_numbers[1] + " r" +
|
|
flash_version_numbers[2];
|
|
plugin.version = base::JoinString(flash_version_numbers, ".");
|
|
content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType,
|
|
content::kFlashPluginSwfExtension,
|
|
content::kFlashPluginSwfDescription);
|
|
plugin.mime_types.push_back(swf_mime_type);
|
|
content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType,
|
|
content::kFlashPluginSplExtension,
|
|
content::kFlashPluginSplDescription);
|
|
plugin.mime_types.push_back(spl_mime_type);
|
|
|
|
return plugin;
|
|
}
|
|
|
|
void AddPepperFlashFromCommandLine(
|
|
std::vector<content::PepperPluginInfo>* plugins) {
|
|
const base::CommandLine::StringType flash_path =
|
|
base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
|
|
switches::kPpapiFlashPath);
|
|
if (flash_path.empty())
|
|
return;
|
|
|
|
// Also get the version from the command-line. Should be something like 11.2
|
|
// or 11.2.123.45.
|
|
std::string flash_version =
|
|
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
|
|
switches::kPpapiFlashVersion);
|
|
|
|
plugins->push_back(
|
|
CreatePepperFlashInfo(base::FilePath(flash_path), flash_version));
|
|
}
|
|
|
|
bool GetSystemPepperFlash(content::PepperPluginInfo* plugin) {
|
|
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
|
|
|
if (!command_line->HasSwitch(switches::kEnableSystemFlash))
|
|
return false;
|
|
|
|
// Do not try and find System Pepper Flash if there is a specific path on
|
|
// the commmand-line.
|
|
if (command_line->HasSwitch(switches::kPpapiFlashPath))
|
|
return false;
|
|
|
|
base::FilePath flash_filename;
|
|
if (!base::PathService::Get(chrome::FILE_PEPPER_FLASH_SYSTEM_PLUGIN,
|
|
&flash_filename)) {
|
|
return false;
|
|
}
|
|
|
|
base::FilePath manifest_path(
|
|
flash_filename.DirName().AppendASCII("manifest.json"));
|
|
|
|
std::string manifest_data;
|
|
if (!base::ReadFileToString(manifest_path, &manifest_data))
|
|
return false;
|
|
std::unique_ptr<base::Value> manifest_value(base::Value::ToUniquePtrValue(
|
|
std::move(base::JSONReader::Read(manifest_data,
|
|
base::JSON_ALLOW_TRAILING_COMMAS)
|
|
.value())));
|
|
if (!manifest_value.get())
|
|
return false;
|
|
base::DictionaryValue* manifest = nullptr;
|
|
if (!manifest_value->GetAsDictionary(&manifest))
|
|
return false;
|
|
|
|
base::Version version;
|
|
if (!CheckPepperFlashManifest(*manifest, &version))
|
|
return false;
|
|
|
|
*plugin = CreatePepperFlashInfo(flash_filename, version.GetString());
|
|
return true;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
const char CefContentClient::kPDFPluginPath[] = "internal-pdf-viewer";
|
|
|
|
CefContentClient::CefContentClient(CefRefPtr<CefApp> application)
|
|
: application_(application),
|
|
pack_loading_disabled_(false),
|
|
allow_pack_file_load_(false),
|
|
scheme_info_list_locked_(false),
|
|
resource_bundle_delegate_(this) {
|
|
DCHECK(!g_content_client);
|
|
g_content_client = this;
|
|
}
|
|
|
|
CefContentClient::~CefContentClient() {
|
|
g_content_client = nullptr;
|
|
}
|
|
|
|
// static
|
|
CefContentClient* CefContentClient::Get() {
|
|
return g_content_client;
|
|
}
|
|
|
|
void CefContentClient::AddPepperPlugins(
|
|
std::vector<content::PepperPluginInfo>* plugins) {
|
|
ComputeBuiltInPlugins(plugins);
|
|
AddPepperFlashFromCommandLine(plugins);
|
|
|
|
content::PepperPluginInfo plugin;
|
|
if (GetSystemPepperFlash(&plugin))
|
|
plugins->push_back(plugin);
|
|
}
|
|
|
|
void CefContentClient::AddContentDecryptionModules(
|
|
std::vector<content::CdmInfo>* cdms,
|
|
std::vector<media::CdmHostFilePath>* cdm_host_file_paths) {
|
|
#if defined(OS_LINUX)
|
|
#if BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
|
|
CefWidevineLoader::AddContentDecryptionModules(cdms, cdm_host_file_paths);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void CefContentClient::AddAdditionalSchemes(Schemes* schemes) {
|
|
DCHECK(!scheme_info_list_locked_);
|
|
|
|
if (application_.get()) {
|
|
CefSchemeRegistrarImpl schemeRegistrar;
|
|
application_->OnRegisterCustomSchemes(&schemeRegistrar);
|
|
schemeRegistrar.GetSchemes(schemes);
|
|
}
|
|
|
|
scheme::AddInternalSchemes(schemes);
|
|
|
|
scheme_info_list_locked_ = true;
|
|
}
|
|
|
|
base::string16 CefContentClient::GetLocalizedString(int message_id) {
|
|
base::string16 value =
|
|
ui::ResourceBundle::GetSharedInstance().GetLocalizedString(message_id);
|
|
if (value.empty())
|
|
LOG(ERROR) << "No localized string available for id " << message_id;
|
|
|
|
return value;
|
|
}
|
|
|
|
base::string16 CefContentClient::GetLocalizedString(
|
|
int message_id,
|
|
const base::string16& replacement) {
|
|
base::string16 value = l10n_util::GetStringFUTF16(message_id, replacement);
|
|
if (value.empty())
|
|
LOG(ERROR) << "No localized string available for id " << message_id;
|
|
|
|
return value;
|
|
}
|
|
|
|
base::StringPiece CefContentClient::GetDataResource(
|
|
int resource_id,
|
|
ui::ScaleFactor scale_factor) {
|
|
base::StringPiece value =
|
|
ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
|
|
resource_id, scale_factor);
|
|
if (value.empty())
|
|
LOG(ERROR) << "No data resource available for id " << resource_id;
|
|
|
|
return value;
|
|
}
|
|
|
|
base::RefCountedMemory* CefContentClient::GetDataResourceBytes(
|
|
int resource_id) {
|
|
base::RefCountedMemory* value =
|
|
ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
|
|
resource_id);
|
|
if (!value)
|
|
LOG(ERROR) << "No data resource bytes available for id " << resource_id;
|
|
|
|
return value;
|
|
}
|
|
|
|
gfx::Image& CefContentClient::GetNativeImageNamed(int resource_id) {
|
|
gfx::Image& value =
|
|
ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
|
|
if (value.IsEmpty())
|
|
LOG(ERROR) << "No native image available for id " << resource_id;
|
|
|
|
return value;
|
|
}
|
|
|
|
void CefContentClient::AddCustomScheme(const SchemeInfo& scheme_info) {
|
|
DCHECK(!scheme_info_list_locked_);
|
|
scheme_info_list_.push_back(scheme_info);
|
|
|
|
if (CefContentBrowserClient::Get()) {
|
|
CefContentBrowserClient::Get()->RegisterCustomScheme(
|
|
scheme_info.scheme_name);
|
|
}
|
|
}
|
|
|
|
const CefContentClient::SchemeInfoList* CefContentClient::GetCustomSchemes() {
|
|
DCHECK(scheme_info_list_locked_);
|
|
return &scheme_info_list_;
|
|
}
|
|
|
|
bool CefContentClient::HasCustomScheme(const std::string& scheme_name) {
|
|
DCHECK(scheme_info_list_locked_);
|
|
if (scheme_info_list_.empty())
|
|
return false;
|
|
|
|
SchemeInfoList::const_iterator it = scheme_info_list_.begin();
|
|
for (; it != scheme_info_list_.end(); ++it) {
|
|
if (it->scheme_name == scheme_name)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// static
|
|
void CefContentClient::SetPDFEntryFunctions(
|
|
content::PepperPluginInfo::GetInterfaceFunc get_interface,
|
|
content::PepperPluginInfo::PPP_InitializeModuleFunc initialize_module,
|
|
content::PepperPluginInfo::PPP_ShutdownModuleFunc shutdown_module) {
|
|
g_pdf_get_interface = get_interface;
|
|
g_pdf_initialize_module = initialize_module;
|
|
g_pdf_shutdown_module = shutdown_module;
|
|
}
|