Add CefRegisterWidevineCdm function and remove component updater support (issue #2009)

Mac: Check in widevinecdmadapter.plugin binary until Widevine GN build errors are resolved (https://crbug.com/626436).
This commit is contained in:
Marshall Greenblatt
2016-10-14 11:56:41 -04:00
parent b338bf9392
commit a1fc6f1ad0
44 changed files with 1263 additions and 391 deletions

View File

@ -233,8 +233,6 @@ static_library("libcef_static") {
"libcef/browser/chrome_profile_manager_stub.h", "libcef/browser/chrome_profile_manager_stub.h",
"libcef/browser/chrome_profile_stub.cc", "libcef/browser/chrome_profile_stub.cc",
"libcef/browser/chrome_profile_stub.h", "libcef/browser/chrome_profile_stub.h",
"libcef/browser/component_updater/cef_component_updater_configurator.cc",
"libcef/browser/component_updater/cef_component_updater_configurator.h",
"libcef/browser/content_browser_client.cc", "libcef/browser/content_browser_client.cc",
"libcef/browser/content_browser_client.h", "libcef/browser/content_browser_client.h",
"libcef/browser/context.cc", "libcef/browser/context.cc",
@ -468,6 +466,8 @@ static_library("libcef_static") {
"libcef/common/value_base.h", "libcef/common/value_base.h",
"libcef/common/values_impl.cc", "libcef/common/values_impl.cc",
"libcef/common/values_impl.h", "libcef/common/values_impl.h",
"libcef/common/widevine_loader.cc",
"libcef/common/widevine_loader.h",
"libcef/renderer/browser_impl.cc", "libcef/renderer/browser_impl.cc",
"libcef/renderer/browser_impl.h", "libcef/renderer/browser_impl.h",
"libcef/renderer/content_renderer_client.cc", "libcef/renderer/content_renderer_client.cc",
@ -564,7 +564,6 @@ static_library("libcef_static") {
"//chrome/common", "//chrome/common",
"//chrome/renderer", "//chrome/renderer",
"//components/cdm/renderer", "//components/cdm/renderer",
"//components/component_updater",
"//components/content_settings/core/browser", "//components/content_settings/core/browser",
"//components/content_settings/core/common", "//components/content_settings/core/common",
"//components/crash/content/app:app_breakpad_mac_win_to_be_deleted", "//components/crash/content/app:app_breakpad_mac_win_to_be_deleted",

View File

@ -318,6 +318,8 @@
'libcef_dll/cpptoc/process_message_cpptoc.h', 'libcef_dll/cpptoc/process_message_cpptoc.h',
'libcef_dll/ctocpp/read_handler_ctocpp.cc', 'libcef_dll/ctocpp/read_handler_ctocpp.cc',
'libcef_dll/ctocpp/read_handler_ctocpp.h', 'libcef_dll/ctocpp/read_handler_ctocpp.h',
'libcef_dll/ctocpp/register_cdm_callback_ctocpp.cc',
'libcef_dll/ctocpp/register_cdm_callback_ctocpp.h',
'libcef_dll/ctocpp/render_handler_ctocpp.cc', 'libcef_dll/ctocpp/render_handler_ctocpp.cc',
'libcef_dll/ctocpp/render_handler_ctocpp.h', 'libcef_dll/ctocpp/render_handler_ctocpp.h',
'libcef_dll/ctocpp/render_process_handler_ctocpp.cc', 'libcef_dll/ctocpp/render_process_handler_ctocpp.cc',
@ -570,6 +572,8 @@
'libcef_dll/ctocpp/process_message_ctocpp.h', 'libcef_dll/ctocpp/process_message_ctocpp.h',
'libcef_dll/cpptoc/read_handler_cpptoc.cc', 'libcef_dll/cpptoc/read_handler_cpptoc.cc',
'libcef_dll/cpptoc/read_handler_cpptoc.h', 'libcef_dll/cpptoc/read_handler_cpptoc.h',
'libcef_dll/cpptoc/register_cdm_callback_cpptoc.cc',
'libcef_dll/cpptoc/register_cdm_callback_cpptoc.h',
'libcef_dll/cpptoc/render_handler_cpptoc.cc', 'libcef_dll/cpptoc/render_handler_cpptoc.cc',
'libcef_dll/cpptoc/render_handler_cpptoc.h', 'libcef_dll/cpptoc/render_handler_cpptoc.h',
'libcef_dll/cpptoc/render_process_handler_cpptoc.cc', 'libcef_dll/cpptoc/render_process_handler_cpptoc.cc',

View File

@ -150,6 +150,8 @@
'tests/cefclient/browser/client_types.h', 'tests/cefclient/browser/client_types.h',
'tests/cefclient/browser/dialog_test.cc', 'tests/cefclient/browser/dialog_test.cc',
'tests/cefclient/browser/dialog_test.h', 'tests/cefclient/browser/dialog_test.h',
'tests/cefclient/browser/drm_test.cc',
'tests/cefclient/browser/drm_test.h',
'tests/cefclient/browser/geometry_util.cc', 'tests/cefclient/browser/geometry_util.cc',
'tests/cefclient/browser/geometry_util.h', 'tests/cefclient/browser/geometry_util.h',
'tests/cefclient/browser/main_context.cc', 'tests/cefclient/browser/main_context.cc',
@ -215,6 +217,7 @@
'tests/cefclient/resources/binding.html', 'tests/cefclient/resources/binding.html',
'tests/cefclient/resources/dialogs.html', 'tests/cefclient/resources/dialogs.html',
'tests/cefclient/resources/draggable.html', 'tests/cefclient/resources/draggable.html',
'tests/cefclient/resources/drm.html',
'tests/cefclient/resources/localstorage.html', 'tests/cefclient/resources/localstorage.html',
'tests/cefclient/resources/logo.png', 'tests/cefclient/resources/logo.png',
'tests/cefclient/resources/menu_icon.1x.png', 'tests/cefclient/resources/menu_icon.1x.png',

View File

@ -127,6 +127,29 @@ typedef struct _cef_web_plugin_unstable_callback_t {
} cef_web_plugin_unstable_callback_t; } cef_web_plugin_unstable_callback_t;
///
// Implement this structure to receive notification when CDM registration is
// complete. The functions of this structure will be called on the browser
// process UI thread.
///
typedef struct _cef_register_cdm_callback_t {
///
// Base structure.
///
cef_base_t base;
///
// Method that will be called when CDM registration is complete. |result| will
// be CEF_CDM_REGISTRATION_ERROR_NONE if registration completed successfully.
// Otherwise, |result| and |error_message| will contain additional information
// about why registration failed.
///
void (CEF_CALLBACK *on_cdm_registration_complete)(
struct _cef_register_cdm_callback_t* self,
cef_cdm_registration_error_t result, const cef_string_t* error_message);
} cef_register_cdm_callback_t;
/// ///
// Visit web plugin information. Can be called on any thread in the browser // Visit web plugin information. Can be called on any thread in the browser
// process. // process.
@ -161,6 +184,54 @@ CEF_EXPORT void cef_register_web_plugin_crash(const cef_string_t* path);
CEF_EXPORT void cef_is_web_plugin_unstable(const cef_string_t* path, CEF_EXPORT void cef_is_web_plugin_unstable(const cef_string_t* path,
cef_web_plugin_unstable_callback_t* callback); cef_web_plugin_unstable_callback_t* callback);
///
// Register the Widevine CDM plugin.
//
// The client application is responsible for downloading an appropriate
// platform-specific CDM binary distribution from Google, extracting the
// contents, and building the required directory structure on the local machine.
// The cef_browser_host_t::StartDownload function and CefZipArchive structure
// can be used to implement this functionality in CEF. Contact Google via
// https://www.widevine.com/contact.html for details on CDM download.
//
// |path| is a directory that must contain the following files:
// 1. manifest.json file from the CDM binary distribution (see below).
// 2. widevinecdm file from the CDM binary distribution (e.g.
// widevinecdm.dll on on Windows, libwidevinecdm.dylib on OS X,
// libwidevinecdm.so on Linux).
// 3. widevidecdmadapter file from the CEF binary distribution (e.g.
// widevinecdmadapter.dll on Windows, widevinecdmadapter.plugin on OS X,
// libwidevinecdmadapter.so on Linux).
//
// If any of these files are missing or if the manifest file has incorrect
// contents the registration will fail and |callback| will receive a |result|
// value of CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS.
//
// The manifest.json file must contain the following keys:
// A. "os": Supported OS (e.g. "mac", "win" or "linux").
// B. "arch": Supported architecture (e.g. "ia32" or "x64").
// C. "x-cdm-module-versions": Module API version (e.g. "4").
// D. "x-cdm-interface-versions": Interface API version (e.g. "8").
// E. "x-cdm-host-versions": Host API version (e.g. "8").
// F. "version": CDM version (e.g. "1.4.8.903").
// G. "x-cdm-codecs": List of supported codecs (e.g. "vp8,vp9.0,avc1").
//
// A through E are used to verify compatibility with the current Chromium
// version. If the CDM is not compatible the registration will fail and
// |callback| will receive a |result| value of
// CEF_CDM_REGISTRATION_ERROR_INCOMPATIBLE.
//
// |callback| will be executed asynchronously once registration is complete.
//
// On Linux this function must be called before cef_initialize() and the
// registration cannot be changed during runtime. If registration is not
// supported at the time that cef_register_widevine_cdm() is called then
// |callback| will receive a |result| value of
// CEF_CDM_REGISTRATION_ERROR_NOT_SUPPORTED.
///
CEF_EXPORT void cef_register_widevine_cdm(const cef_string_t* path,
cef_register_cdm_callback_t* callback);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -144,5 +144,71 @@ class CefWebPluginUnstableCallback : public virtual CefBase {
void CefIsWebPluginUnstable(const CefString& path, void CefIsWebPluginUnstable(const CefString& path,
CefRefPtr<CefWebPluginUnstableCallback> callback); CefRefPtr<CefWebPluginUnstableCallback> callback);
///
// Implement this interface to receive notification when CDM registration is
// complete. The methods of this class will be called on the browser process
// UI thread.
///
/*--cef(source=client)--*/
class CefRegisterCdmCallback : public virtual CefBase {
public:
///
// Method that will be called when CDM registration is complete. |result|
// will be CEF_CDM_REGISTRATION_ERROR_NONE if registration completed
// successfully. Otherwise, |result| and |error_message| will contain
// additional information about why registration failed.
///
/*--cef(optional_param=error_message)--*/
virtual void OnCdmRegistrationComplete(cef_cdm_registration_error_t result,
const CefString& error_message) =0;
};
///
// Register the Widevine CDM plugin.
//
// The client application is responsible for downloading an appropriate
// platform-specific CDM binary distribution from Google, extracting the
// contents, and building the required directory structure on the local machine.
// The CefBrowserHost::StartDownload method and CefZipArchive class can be used
// to implement this functionality in CEF. Contact Google via
// https://www.widevine.com/contact.html for details on CDM download.
//
// |path| is a directory that must contain the following files:
// 1. manifest.json file from the CDM binary distribution (see below).
// 2. widevinecdm file from the CDM binary distribution (e.g.
// widevinecdm.dll on on Windows, libwidevinecdm.dylib on OS X,
// libwidevinecdm.so on Linux).
// 3. widevidecdmadapter file from the CEF binary distribution (e.g.
// widevinecdmadapter.dll on Windows, widevinecdmadapter.plugin on OS X,
// libwidevinecdmadapter.so on Linux).
//
// If any of these files are missing or if the manifest file has incorrect
// contents the registration will fail and |callback| will receive a |result|
// value of CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS.
//
// The manifest.json file must contain the following keys:
// A. "os": Supported OS (e.g. "mac", "win" or "linux").
// B. "arch": Supported architecture (e.g. "ia32" or "x64").
// C. "x-cdm-module-versions": Module API version (e.g. "4").
// D. "x-cdm-interface-versions": Interface API version (e.g. "8").
// E. "x-cdm-host-versions": Host API version (e.g. "8").
// F. "version": CDM version (e.g. "1.4.8.903").
// G. "x-cdm-codecs": List of supported codecs (e.g. "vp8,vp9.0,avc1").
//
// A through E are used to verify compatibility with the current Chromium
// version. If the CDM is not compatible the registration will fail and
// |callback| will receive a |result| value of
// CEF_CDM_REGISTRATION_ERROR_INCOMPATIBLE.
//
// |callback| will be executed asynchronously once registration is complete.
//
// On Linux this function must be called before CefInitialize() and the
// registration cannot be changed during runtime. If registration is not
// supported at the time that CefRegisterWidevineCdm() is called then |callback|
// will receive a |result| value of CEF_CDM_REGISTRATION_ERROR_NOT_SUPPORTED.
///
/*--cef(optional_param=callback)--*/
void CefRegisterWidevineCdm(const CefString& path,
CefRefPtr<CefRegisterCdmCallback> callback);
#endif // CEF_INCLUDE_CEF_WEB_PLUGIN_H_ #endif // CEF_INCLUDE_CEF_WEB_PLUGIN_H_

View File

@ -2657,6 +2657,31 @@ typedef enum {
SSL_CONTENT_RAN_INSECURE_CONTENT = 1 << 1, SSL_CONTENT_RAN_INSECURE_CONTENT = 1 << 1,
} cef_ssl_content_status_t; } cef_ssl_content_status_t;
///
// Error codes for CDM registration. See cef_web_plugin.h for details.
///
typedef enum {
///
// No error. Registration completed successfully.
///
CEF_CDM_REGISTRATION_ERROR_NONE,
///
// Required files or manifest contents are missing.
///
CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS,
///
// The CDM is incompatible with the current Chromium version.
///
CEF_CDM_REGISTRATION_ERROR_INCOMPATIBLE,
///
// CDM registration is not supported at this time.
///
CEF_CDM_REGISTRATION_ERROR_NOT_SUPPORTED,
} cef_cdm_registration_error_t;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -7,33 +7,13 @@
#include "libcef/browser/browser_context_impl.h" #include "libcef/browser/browser_context_impl.h"
#include "libcef/browser/chrome_profile_manager_stub.h" #include "libcef/browser/chrome_profile_manager_stub.h"
#include "libcef/browser/component_updater/cef_component_updater_configurator.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/thread_util.h" #include "libcef/browser/thread_util.h"
#include "libcef/common/cef_switches.h" #include "libcef/common/cef_switches.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/component_updater/widevine_cdm_component_installer.h"
#include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/printing/print_job_manager.h"
#include "components/component_updater/component_updater_service.h"
#include "components/update_client/configurator.h"
#include "ui/message_center/message_center.h" #include "ui/message_center/message_center.h"
namespace {
void RegisterComponentsForUpdate(
component_updater::ComponentUpdateService* cus) {
base::ThreadRestrictions::ScopedAllowIO scoped_allow_io;
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWidevineCdm)) {
RegisterWidevineCdmComponent(cus);
}
}
} // namespace
ChromeBrowserProcessStub::ChromeBrowserProcessStub() ChromeBrowserProcessStub::ChromeBrowserProcessStub()
: initialized_(false), : initialized_(false),
shutdown_(false), shutdown_(false),
@ -57,19 +37,6 @@ void ChromeBrowserProcessStub::Initialize() {
profile_manager_.reset(new ChromeProfileManagerStub()); profile_manager_.reset(new ChromeProfileManagerStub());
event_router_forwarder_ = new extensions::EventRouterForwarder(); event_router_forwarder_ = new extensions::EventRouterForwarder();
// Creating the component updater does not do anything initially. Components
// need to be registered and Start() needs to be called.
scoped_refptr<CefBrowserContextImpl> browser_context =
CefContentBrowserClient::Get()->browser_context();
scoped_refptr<update_client::Configurator> configurator =
component_updater::MakeCefComponentUpdaterConfigurator(
base::CommandLine::ForCurrentProcess(),
browser_context->request_context().get(),
browser_context->GetPrefs());
component_updater_.reset(component_updater::ComponentUpdateServiceFactory(
configurator).release());
RegisterComponentsForUpdate(component_updater_.get());
initialized_ = true; initialized_ = true;
} }
@ -86,7 +53,6 @@ void ChromeBrowserProcessStub::Shutdown() {
profile_manager_.reset(); profile_manager_.reset();
event_router_forwarder_ = nullptr; event_router_forwarder_ = nullptr;
component_updater_.reset();
shutdown_ = true; shutdown_ = true;
} }
@ -299,7 +265,8 @@ net_log::ChromeNetLog* ChromeBrowserProcessStub::net_log() {
component_updater::ComponentUpdateService* component_updater::ComponentUpdateService*
ChromeBrowserProcessStub::component_updater() { ChromeBrowserProcessStub::component_updater() {
return component_updater_.get(); NOTIMPLEMENTED();
return NULL;
} }
CRLSetFetcher* ChromeBrowserProcessStub::crl_set_fetcher() { CRLSetFetcher* ChromeBrowserProcessStub::crl_set_fetcher() {

View File

@ -17,10 +17,6 @@
#include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/incognito_helpers.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
namespace component_updater {
class ComponentUpdateService;
}
class ChromeProfileManagerStub; class ChromeProfileManagerStub;
class BackgroundModeManager { class BackgroundModeManager {
@ -126,7 +122,6 @@ class ChromeBrowserProcessStub : public BrowserProcess,
std::unique_ptr<printing::PrintJobManager> print_job_manager_; std::unique_ptr<printing::PrintJobManager> print_job_manager_;
std::unique_ptr<ChromeProfileManagerStub> profile_manager_; std::unique_ptr<ChromeProfileManagerStub> profile_manager_;
scoped_refptr<extensions::EventRouterForwarder> event_router_forwarder_; scoped_refptr<extensions::EventRouterForwarder> event_router_forwarder_;
std::unique_ptr<component_updater::ComponentUpdateService> component_updater_;
DISALLOW_COPY_AND_ASSIGN(ChromeBrowserProcessStub); DISALLOW_COPY_AND_ASSIGN(ChromeBrowserProcessStub);
}; };

View File

@ -1,182 +0,0 @@
// 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/browser/component_updater/cef_component_updater_configurator.h"
#include "include/cef_version.h"
#include "base/version.h"
#include "chrome/common/pref_names.h"
#include "components/component_updater/configurator_impl.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/update_client/component_patcher_operation.h"
#include "content/public/browser/browser_thread.h"
namespace component_updater {
namespace {
class CefConfigurator : public update_client::Configurator {
public:
CefConfigurator(const base::CommandLine* cmdline,
net::URLRequestContextGetter* url_request_getter,
PrefService* pref_service);
int InitialDelay() const override;
int NextCheckDelay() const override;
int StepDelay() const override;
int OnDemandDelay() const override;
int UpdateDelay() const override;
std::vector<GURL> UpdateUrl() const override;
std::vector<GURL> PingUrl() const override;
base::Version GetBrowserVersion() const override;
std::string GetChannel() const override;
std::string GetBrand() const override;
std::string GetLang() const override;
std::string GetOSLongName() const override;
std::string ExtraRequestParams() const override;
std::string GetDownloadPreference() const override;
net::URLRequestContextGetter* RequestContext() const override;
scoped_refptr<update_client::OutOfProcessPatcher>
CreateOutOfProcessPatcher() const override;
bool EnabledDeltas() const override;
bool EnabledComponentUpdates() const override;
bool EnabledBackgroundDownloader() const override;
bool EnabledCupSigning() const override;
scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner()
const override;
PrefService* GetPrefService() const override;
private:
friend class base::RefCountedThreadSafe<CefConfigurator>;
~CefConfigurator() override {}
ConfiguratorImpl configurator_impl_;
PrefService* pref_service_;
};
CefConfigurator::CefConfigurator(
const base::CommandLine* cmdline,
net::URLRequestContextGetter* url_request_getter,
PrefService* pref_service)
: configurator_impl_(cmdline, url_request_getter, false),
pref_service_(pref_service) {
DCHECK(pref_service_);
}
int CefConfigurator::InitialDelay() const {
return configurator_impl_.InitialDelay();
}
int CefConfigurator::NextCheckDelay() const {
return configurator_impl_.NextCheckDelay();
}
int CefConfigurator::StepDelay() const {
return configurator_impl_.StepDelay();
}
int CefConfigurator::OnDemandDelay() const {
return configurator_impl_.OnDemandDelay();
}
int CefConfigurator::UpdateDelay() const {
return configurator_impl_.UpdateDelay();
}
std::vector<GURL> CefConfigurator::UpdateUrl() const {
return configurator_impl_.UpdateUrl();
}
std::vector<GURL> CefConfigurator::PingUrl() const {
return configurator_impl_.PingUrl();
}
base::Version CefConfigurator::GetBrowserVersion() const {
return configurator_impl_.GetBrowserVersion();
}
std::string CefConfigurator::GetChannel() const {
return std::string();
}
std::string CefConfigurator::GetBrand() const {
return std::string();
}
std::string CefConfigurator::GetLang() const {
return std::string();
}
std::string CefConfigurator::GetOSLongName() const {
return configurator_impl_.GetOSLongName();
}
std::string CefConfigurator::ExtraRequestParams() const {
return configurator_impl_.ExtraRequestParams();
}
std::string CefConfigurator::GetDownloadPreference() const {
return std::string();
}
net::URLRequestContextGetter* CefConfigurator::RequestContext() const {
return configurator_impl_.RequestContext();
}
scoped_refptr<update_client::OutOfProcessPatcher>
CefConfigurator::CreateOutOfProcessPatcher() const {
return nullptr;
}
bool CefConfigurator::EnabledDeltas() const {
return configurator_impl_.EnabledDeltas();
}
bool CefConfigurator::EnabledComponentUpdates() const {
return pref_service_->GetBoolean(prefs::kComponentUpdatesEnabled);
}
bool CefConfigurator::EnabledBackgroundDownloader() const {
return configurator_impl_.EnabledBackgroundDownloader();
}
bool CefConfigurator::EnabledCupSigning() const {
return configurator_impl_.EnabledCupSigning();
}
// Returns a task runner to run blocking tasks. The task runner continues to run
// after the browser shuts down, until the OS terminates the process. This
// imposes certain requirements for the code using the task runner, such as
// not accessing any global browser state while the code is running.
scoped_refptr<base::SequencedTaskRunner>
CefConfigurator::GetSequencedTaskRunner() const {
return content::BrowserThread::GetBlockingPool()
->GetSequencedTaskRunnerWithShutdownBehavior(
base::SequencedWorkerPool::GetSequenceToken(),
base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
}
PrefService* CefConfigurator::GetPrefService() const {
return pref_service_;
}
} // namespace
void RegisterPrefsForCefComponentUpdaterConfigurator(
PrefRegistrySimple* registry) {
// The component updates are enabled by default, if the preference is not set.
registry->RegisterBooleanPref(prefs::kComponentUpdatesEnabled, true);
}
scoped_refptr<update_client::Configurator>
MakeCefComponentUpdaterConfigurator(
const base::CommandLine* cmdline,
net::URLRequestContextGetter* context_getter,
PrefService* pref_service) {
return new CefConfigurator(cmdline, context_getter, pref_service);
}
} // namespace component_updater

View File

@ -1,39 +0,0 @@
// 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.
#ifndef LIBCEF_BROWSER_COMPONENT_UPDATER_CEF_COMPONENT_UPDATER_CONFIGURATOR_H_
#define LIBCEF_BROWSER_COMPONENT_UPDATER_CEF_COMPONENT_UPDATER_CONFIGURATOR_H_
#include "base/memory/ref_counted.h"
#include "components/update_client/configurator.h"
namespace base {
class CommandLine;
}
namespace net {
class URLRequestContextGetter;
}
class PrefRegistrySimple;
class PrefService;
namespace component_updater {
// Registers preferences associated with the component updater configurator
// for CEF. The preferences must be registered with the local pref store
// before they can be queried by the configurator instance.
// This function is called before MakeCefComponentUpdaterConfigurator.
void RegisterPrefsForCefComponentUpdaterConfigurator(
PrefRegistrySimple* registry);
scoped_refptr<update_client::Configurator>
MakeCefComponentUpdaterConfigurator(
const base::CommandLine* cmdline,
net::URLRequestContextGetter* context_getter,
PrefService* pref_service);
} // namespace component_updater
#endif // LIBCEF_BROWSER_COMPONENT_UPDATER_CEF_COMPONENT_UPDATER_CONFIGURATOR_H_

View File

@ -75,6 +75,10 @@
#include "ui/base/ui_base_switches.h" #include "ui/base/ui_base_switches.h"
#include "url/gurl.h" #include "url/gurl.h"
#if defined(OS_LINUX)
#include "libcef/common/widevine_loader.h"
#endif
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
#include "components/spellcheck/browser/spellcheck_message_filter_platform.h" #include "components/spellcheck/browser/spellcheck_message_filter_platform.h"
#endif #endif
@ -574,8 +578,6 @@ void CefContentBrowserClient::AppendExtraCommandLineSwitches(
switches::kPpapiFlashPath, switches::kPpapiFlashPath,
switches::kPpapiFlashVersion, switches::kPpapiFlashVersion,
switches::kUncaughtExceptionStackSize, switches::kUncaughtExceptionStackSize,
switches::kWidevineCdmPath,
switches::kWidevineCdmVersion,
}; };
command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames, command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
arraysize(kSwitchNames)); arraysize(kSwitchNames));
@ -597,17 +599,25 @@ void CefContentBrowserClient::AppendExtraCommandLineSwitches(
#if defined(OS_LINUX) #if defined(OS_LINUX)
if (process_type == switches::kZygoteProcess) { if (process_type == switches::kZygoteProcess) {
// Propagate the following switches to the zygone command line (along with // Propagate the following switches to the zygote command line (along with
// any associated values) if present in the browser command line. // any associated values) if present in the browser command line.
static const char* const kSwitchNames[] = { static const char* const kSwitchNames[] = {
switches::kPpapiFlashPath, switches::kPpapiFlashPath,
switches::kPpapiFlashVersion, switches::kPpapiFlashVersion,
switches::kWidevineCdmPath,
switches::kWidevineCdmVersion,
}; };
command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames, command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
arraysize(kSwitchNames)); arraysize(kSwitchNames));
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
if (!browser_cmd->HasSwitch(switches::kNoSandbox)) {
// Pass the Widevine CDM path to the Zygote process. See comments in
// CefWidevineLoader::AddPepperPlugins.
const base::FilePath& cdm_path = CefWidevineLoader::GetInstance()->path();
if (!cdm_path.empty())
command_line->AppendSwitchPath(switches::kWidevineCdmPath, cdm_path);
}
#endif
if (browser_cmd->HasSwitch(switches::kBrowserSubprocessPath)) { if (browser_cmd->HasSwitch(switches::kBrowserSubprocessPath)) {
// Force use of the sub-process executable path for the zygote process. // Force use of the sub-process executable path for the zygote process.
const base::FilePath& subprocess_path = const base::FilePath& subprocess_path =

View File

@ -13,6 +13,7 @@
#include "libcef/browser/trace_subscriber.h" #include "libcef/browser/trace_subscriber.h"
#include "libcef/common/cef_switches.h" #include "libcef/common/cef_switches.h"
#include "libcef/common/main_delegate.h" #include "libcef/common/main_delegate.h"
#include "libcef/common/widevine_loader.h"
#include "libcef/renderer/content_renderer_client.h" #include "libcef/renderer/content_renderer_client.h"
#include "base/base_switches.h" #include "base/base_switches.h"
@ -376,6 +377,10 @@ void CefContext::OnContextInitialized() {
static_cast<ChromeBrowserProcessStub*>(g_browser_process)->Initialize(); static_cast<ChromeBrowserProcessStub*>(g_browser_process)->Initialize();
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
CefWidevineLoader::GetInstance()->OnContextInitialized();
#endif
// Notify the handler. // Notify the handler.
CefRefPtr<CefApp> app = CefContentClient::Get()->application(); CefRefPtr<CefApp> app = CefContentClient::Get()->application();
if (app.get()) { if (app.get()) {

View File

@ -4,7 +4,6 @@
#include "libcef/browser/prefs/browser_prefs.h" #include "libcef/browser/prefs/browser_prefs.h"
#include "libcef/browser/component_updater/cef_component_updater_configurator.h"
#include "libcef/browser/media_capture_devices_dispatcher.h" #include "libcef/browser/media_capture_devices_dispatcher.h"
#include "libcef/browser/net/url_request_context_getter_impl.h" #include "libcef/browser/net/url_request_context_getter_impl.h"
#include "libcef/browser/prefs/renderer_prefs.h" #include "libcef/browser/prefs/renderer_prefs.h"
@ -173,8 +172,6 @@ std::unique_ptr<PrefService> CreatePrefService(
renderer_prefs::RegisterProfilePrefs(registry.get()); renderer_prefs::RegisterProfilePrefs(registry.get());
update_client::RegisterPrefs(registry.get()); update_client::RegisterPrefs(registry.get());
content_settings::CookieSettings::RegisterProfilePrefs(registry.get()); content_settings::CookieSettings::RegisterProfilePrefs(registry.get());
component_updater::RegisterPrefsForCefComponentUpdaterConfigurator(
registry.get());
// Print preferences. // Print preferences.
registry->RegisterBooleanPref(prefs::kPrintingEnabled, true); registry->RegisterBooleanPref(prefs::kPrintingEnabled, true);

View File

@ -3,8 +3,10 @@
// can be found in the LICENSE file. // can be found in the LICENSE file.
#include "libcef/browser/web_plugin_impl.h" #include "libcef/browser/web_plugin_impl.h"
#include "libcef/browser/context.h" #include "libcef/browser/context.h"
#include "libcef/browser/thread_util.h" #include "libcef/browser/thread_util.h"
#include "libcef/common/widevine_loader.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
@ -28,6 +30,22 @@ void PluginsCallbackImpl(
} }
} }
#if !(defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)) || \
defined(OS_LINUX)
void DeliverWidevineCdmError(const std::string& error_message,
CefRefPtr<CefRegisterCdmCallback> callback) {
LOG(ERROR) << error_message;
if (callback.get()) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefRegisterCdmCallback::OnCdmRegistrationComplete,
callback.get(), CEF_CDM_REGISTRATION_ERROR_NOT_SUPPORTED,
error_message));
}
}
#endif
} // namespace } // namespace
@ -150,3 +168,24 @@ void CefIsWebPluginUnstable(
CEF_POST_TASK(CEF_IOT, base::Bind(CefIsWebPluginUnstable, path, callback)); CEF_POST_TASK(CEF_IOT, base::Bind(CefIsWebPluginUnstable, path, callback));
} }
} }
void CefRegisterWidevineCdm(const CefString& path,
CefRefPtr<CefRegisterCdmCallback> callback) {
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
#if defined(OS_LINUX)
// Enforce the requirement that CefRegisterWidevineCdm() is called before
// CefInitialize() on Linux. See comments in
// CefWidevineLoader::AddPepperPlugins for details.
if (CONTEXT_STATE_VALID()) {
DeliverWidevineCdmError(
"Widevine registration is not supported after context initialization",
callback);
return;
}
#endif // defined(OS_LINUX)
CefWidevineLoader::GetInstance()->LoadWidevineCdm(path, callback);
#else
DeliverWidevineCdmError("Widevine registration is not supported", callback);
#endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
}

View File

@ -106,15 +106,9 @@ const char kDisableScrollBounce[] = "disable-scroll-bounce";
// Disable the PDF extension. // Disable the PDF extension.
const char kDisablePdfExtension[] = "disable-pdf-extension"; const char kDisablePdfExtension[] = "disable-pdf-extension";
// Enable Widevine CDM.
const char kEnableWidevineCdm[] = "enable-widevine-cdm";
// Path to Widevine CDM binaries. // Path to Widevine CDM binaries.
const char kWidevineCdmPath[] = "widevine-cdm-path"; const char kWidevineCdmPath[] = "widevine-cdm-path";
// Widevine CDM version.
const char kWidevineCdmVersion[] = "widevine-cdm-version";
// Default plugin policy action. // Default plugin policy action.
const char kPluginPolicy[] = "plugin-policy"; const char kPluginPolicy[] = "plugin-policy";
// Allow the content. This is the default value. // Allow the content. This is the default value.

View File

@ -45,9 +45,7 @@ extern const char kOverrideSpellCheckLang[];
extern const char kEnableSystemFlash[]; extern const char kEnableSystemFlash[];
extern const char kDisableScrollBounce[]; extern const char kDisableScrollBounce[];
extern const char kDisablePdfExtension[]; extern const char kDisablePdfExtension[];
extern const char kEnableWidevineCdm[];
extern const char kWidevineCdmPath[]; extern const char kWidevineCdmPath[];
extern const char kWidevineCdmVersion[];
extern const char kPluginPolicy[]; extern const char kPluginPolicy[];
extern const char kPluginPolicy_Allow[]; extern const char kPluginPolicy_Allow[];
extern const char kPluginPolicy_Detect[]; extern const char kPluginPolicy_Detect[];

View File

@ -37,12 +37,8 @@
#include "ppapi/shared_impl/ppapi_permissions.h" #include "ppapi/shared_impl/ppapi_permissions.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. #if defined(OS_LINUX)
#include "libcef/common/widevine_loader.h"
// The following must be after widevine_cdm_version.h.
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) && \
!defined(WIDEVINE_CDM_IS_COMPONENT)
#include "chrome/common/widevine_cdm_constants.h"
#endif #endif
namespace { namespace {
@ -182,67 +178,6 @@ bool GetSystemPepperFlash(content::PepperPluginInfo* plugin) {
return true; return true;
} }
void AddWidevineCdmFromCommandLine(
std::vector<content::PepperPluginInfo>* plugins) {
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) && \
!defined(WIDEVINE_CDM_IS_COMPONENT)
static bool skip_widevine_cdm_file_check = false;
base::FilePath widevine_cdm_path =
base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kWidevineCdmPath);
if (!widevine_cdm_path.empty()) {
widevine_cdm_path =
widevine_cdm_path.AppendASCII(kWidevineCdmAdapterFileName);
}
// Also get the version from the command-line. Should be something like
// 1.4.8.824.
const std::string& widevine_cdm_version =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kWidevineCdmVersion);
if (!widevine_cdm_path.empty() && !widevine_cdm_version.empty()) {
if (skip_widevine_cdm_file_check || base::PathExists(widevine_cdm_path)) {
content::PepperPluginInfo widevine_cdm;
widevine_cdm.is_out_of_process = true;
widevine_cdm.path = widevine_cdm_path;
widevine_cdm.name = kWidevineCdmDisplayName;
widevine_cdm.description = kWidevineCdmDescription +
std::string(" (version: ") +
widevine_cdm_version + ")";
widevine_cdm.version = widevine_cdm_version;
content::WebPluginMimeType widevine_cdm_mime_type(
kWidevineCdmPluginMimeType,
kWidevineCdmPluginExtension,
kWidevineCdmPluginMimeTypeDescription);
// Add the supported codecs as if they came from the component manifest.
// This list must match the CDM that is being shipped with Chrome.
std::vector<std::string> codecs;
codecs.push_back(kCdmSupportedCodecVp8);
codecs.push_back(kCdmSupportedCodecVp9);
#if defined(USE_PROPRIETARY_CODECS)
codecs.push_back(kCdmSupportedCodecAvc1);
#endif // defined(USE_PROPRIETARY_CODECS)
std::string codec_string = base::JoinString(
codecs, std::string(1, kCdmSupportedCodecsValueDelimiter));
widevine_cdm_mime_type.additional_param_names.push_back(
base::ASCIIToUTF16(kCdmSupportedCodecsParamName));
widevine_cdm_mime_type.additional_param_values.push_back(
base::ASCIIToUTF16(codec_string));
widevine_cdm.mime_types.push_back(widevine_cdm_mime_type);
widevine_cdm.permissions = kWidevineCdmPluginPermissions;
plugins->push_back(widevine_cdm);
skip_widevine_cdm_file_check = true;
}
}
#endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) &&
// !defined(WIDEVINE_CDM_IS_COMPONENT)
}
} // namespace } // namespace
const char CefContentClient::kPDFPluginPath[] = "internal-pdf-viewer"; const char CefContentClient::kPDFPluginPath[] = "internal-pdf-viewer";
@ -269,7 +204,12 @@ void CefContentClient::AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) { std::vector<content::PepperPluginInfo>* plugins) {
ComputeBuiltInPlugins(plugins); ComputeBuiltInPlugins(plugins);
AddPepperFlashFromCommandLine(plugins); AddPepperFlashFromCommandLine(plugins);
AddWidevineCdmFromCommandLine(plugins);
#if defined(OS_LINUX)
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
CefWidevineLoader::AddPepperPlugins(plugins);
#endif
#endif
content::PepperPluginInfo plugin; content::PepperPluginInfo plugin;
if (GetSystemPepperFlash(&plugin)) if (GetSystemPepperFlash(&plugin))

View File

@ -27,7 +27,6 @@
#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "components/component_updater/component_updater_paths.h"
#include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_pattern.h"
#include "content/public/browser/browser_main_runner.h" #include "content/public/browser/browser_main_runner.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
@ -41,8 +40,6 @@
#include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h" #include "ui/base/ui_base_switches.h"
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
#include "ipc/ipc_message.h" // For IPC_MESSAGE_LOG_ENABLED. #include "ipc/ipc_message.h" // For IPC_MESSAGE_LOG_ENABLED.
#if defined(IPC_MESSAGE_LOG_ENABLED) #if defined(IPC_MESSAGE_LOG_ENABLED)
@ -559,26 +556,6 @@ void CefMainDelegate::PreSandboxStartup() {
user_data_path.AppendASCII("Dictionaries"), user_data_path.AppendASCII("Dictionaries"),
false, // May not be an absolute path. false, // May not be an absolute path.
true); // Create if necessary. true); // Create if necessary.
const base::FilePath& resources_path = GetResourcesFilePath();
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
const base::FilePath& widevine_plugin_path =
resources_path.AppendASCII(kWidevineCdmAdapterFileName);
if (base::PathExists(widevine_plugin_path)) {
PathService::Override(chrome::FILE_WIDEVINE_CDM_ADAPTER,
widevine_plugin_path);
}
#endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
// Paths to find pre-installed components.
PathService::Override(chrome::DIR_COMPONENTS, resources_path);
PathService::Override(chrome::DIR_INTERNAL_PLUGINS, resources_path);
// Register paths to be used by the component updater.
component_updater::RegisterPathProvider(chrome::DIR_COMPONENTS,
chrome::DIR_INTERNAL_PLUGINS,
chrome::DIR_USER_DATA);
} }
if (command_line->HasSwitch(switches::kDisablePackLoading)) if (command_line->HasSwitch(switches::kDisablePackLoading))

View File

@ -0,0 +1,406 @@
// Copyright 2016 The Chromium Embedded Framework Authors. Portions copyright
// 2013 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/widevine_loader.h"
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
#include "libcef/browser/context.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/cef_switches.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/json/json_string_value_serializer.h"
#include "base/memory/ptr_util.h"
#include "base/native_library.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/widevine_cdm_constants.h"
#include "content/browser/plugin_service_impl.h"
#include "content/public/browser/cdm_service.h"
#include "content/public/common/cdm_info.h"
#include "content/public/common/content_switches.h"
#include "media/cdm/supported_cdm_versions.h"
namespace {
base::LazyInstance<CefWidevineLoader>::Leaky g_widevine_loader =
LAZY_INSTANCE_INITIALIZER;
// Based on chrome/browser/component_updater/widevine_cdm_component_installer.cc
// Name of the Widevine CDM OS in the component manifest.
const char kWidevineCdmOs[] =
#if defined(OS_MACOSX)
"mac";
#elif defined(OS_WIN)
"win";
#else // OS_LINUX, etc. TODO(viettrungluu): Separate out Chrome OS and Android?
"linux";
#endif
// Name of the Widevine CDM architecture in the component manifest.
const char kWidevineCdmArch[] =
#if defined(ARCH_CPU_X86)
"ia32"; // This differs from the component updater which uses "x86".
#elif defined(ARCH_CPU_X86_64)
"x64";
#else // TODO(viettrungluu): Support an ARM check?
"???";
#endif
// The CDM OS and architecture.
const char kCdmOsName[] = "os";
const char kCdmArchName[] = "arch";
// The CDM version (e.g. "1.4.8.903").
const char kCdmVersionName[] = "version";
// The CDM manifest includes several custom values, all beginning with "x-cdm-".
// All values are strings.
// All values that are lists are delimited by commas. No trailing commas.
// For example, "1,2,4".
const char kCdmValueDelimiter = ',';
static_assert(kCdmValueDelimiter == kCdmSupportedCodecsValueDelimiter,
"cdm delimiters must match");
// The following entries are required.
// Interface versions are lists of integers (e.g. "1" or "1,2,4").
// These are checked in this file before registering the CDM.
// All match the interface versions from content_decryption_module.h that the
// CDM supports.
// Matches CDM_MODULE_VERSION.
const char kCdmModuleVersionsName[] = "x-cdm-module-versions";
// Matches supported ContentDecryptionModule_* version(s).
const char kCdmInterfaceVersionsName[] = "x-cdm-interface-versions";
// Matches supported Host_* version(s).
const char kCdmHostVersionsName[] = "x-cdm-host-versions";
// The codecs list is a list of simple codec names (e.g. "vp8,vorbis").
// The list is passed to other parts of Chrome.
const char kCdmCodecsListName[] = "x-cdm-codecs";
std::unique_ptr<base::DictionaryValue> ParseManifestFile(
const base::FilePath& manifest_path) {
CEF_REQUIRE_FILET();
// Manifest file should be < 1kb. Read at most 2kb.
std::string manifest_contents;
if (!base::ReadFileToStringWithMaxSize(manifest_path, &manifest_contents,
2048)) {
return nullptr;
}
JSONStringValueDeserializer deserializer(manifest_contents);
std::unique_ptr<base::Value> manifest(deserializer.Deserialize(NULL, NULL));
if (!manifest.get() || !manifest->IsType(base::Value::TYPE_DICTIONARY))
return nullptr;
// Transfer ownership to the caller.
return base::WrapUnique(
static_cast<base::DictionaryValue*>(manifest.release()));
}
std::string GetManifestValue(const base::DictionaryValue& manifest,
const std::string& key,
std::string* error_message) {
std::stringstream ss;
std::string value;
if (!manifest.GetString(key, &value)) {
ss << "Manifest missing " << key;
*error_message = ss.str();
} else if (value.empty()) {
ss << "Manifest has empty " << key;
*error_message = ss.str();
}
return value;
}
typedef bool (*VersionCheckFunc)(int version);
bool CheckForCompatibleVersion(const base::DictionaryValue& manifest,
const std::string version_name,
VersionCheckFunc version_check_func,
std::string* error_message) {
std::string versions_string =
GetManifestValue(manifest, version_name, error_message);
if (versions_string.empty())
return false;
for (const base::StringPiece& ver_str : base::SplitStringPiece(
versions_string, std::string(1, kCdmValueDelimiter),
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
int version = 0;
if (base::StringToInt(ver_str, &version))
if (version_check_func(version))
return true;
}
std::stringstream ss;
ss << "Manifest has no supported " << version_name << " in '" <<
versions_string << "'";
*error_message = ss.str();
return false;
}
// Returns whether the CDM's OS/platform and module/interface/host API versions,
// as specified in the manifest, are compatible with this Chromium binary.
bool IsCompatibleWithChrome(const base::DictionaryValue& manifest,
std::string* error_message) {
return GetManifestValue(manifest, kCdmOsName, error_message) ==
kWidevineCdmOs &&
GetManifestValue(manifest, kCdmArchName, error_message) ==
kWidevineCdmArch &&
CheckForCompatibleVersion(manifest,
kCdmModuleVersionsName,
media::IsSupportedCdmModuleVersion,
error_message) &&
CheckForCompatibleVersion(manifest,
kCdmInterfaceVersionsName,
media::IsSupportedCdmInterfaceVersion,
error_message) &&
CheckForCompatibleVersion(manifest,
kCdmHostVersionsName,
media::IsSupportedCdmHostVersion,
error_message);
}
// Populate the PepperPluginInfo structure.
void GetPluginInfo(const base::FilePath& cdm_adapter_path,
const base::FilePath& cdm_path,
const std::string& cdm_version,
const std::string& cdm_codecs,
content::PepperPluginInfo* widevine_cdm) {
widevine_cdm->is_out_of_process = true;
widevine_cdm->path = cdm_adapter_path;
widevine_cdm->name = kWidevineCdmDisplayName;
widevine_cdm->description = kWidevineCdmDescription +
std::string(" (version: ") +
cdm_version + ")";
widevine_cdm->version = cdm_version;
content::WebPluginMimeType widevine_cdm_mime_type(
kWidevineCdmPluginMimeType,
kWidevineCdmPluginExtension,
kWidevineCdmPluginMimeTypeDescription);
widevine_cdm_mime_type.additional_param_names.push_back(
base::ASCIIToUTF16(kCdmSupportedCodecsParamName));
widevine_cdm_mime_type.additional_param_values.push_back(
base::ASCIIToUTF16(cdm_codecs));
widevine_cdm->mime_types.push_back(widevine_cdm_mime_type);
widevine_cdm->permissions = kWidevineCdmPluginPermissions;
}
// Verify and load the contents of |base_path|.
cef_cdm_registration_error_t LoadWidevineCdmInfo(
const base::FilePath& base_path,
base::FilePath* cdm_adapter_path,
base::FilePath* cdm_path,
std::string* cdm_version,
std::string* cdm_codecs,
std::string* error_message) {
std::stringstream ss;
*cdm_adapter_path = base_path.AppendASCII(kWidevineCdmAdapterFileName);
if (!base::PathExists(*cdm_adapter_path)) {
ss << "Missing adapter file " << cdm_adapter_path->value();
*error_message = ss.str();
return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
}
*cdm_path = base_path.AppendASCII(
base::GetNativeLibraryName(kWidevineCdmLibraryName));
if (!base::PathExists(*cdm_path)) {
ss << "Missing file " << cdm_path->value();
*error_message = ss.str();
return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
}
base::FilePath manifest_path = base_path.AppendASCII("manifest.json");
if (!base::PathExists(manifest_path)) {
ss << "Missing manifest file " << manifest_path.value();
*error_message = ss.str();
return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
}
std::unique_ptr<base::DictionaryValue> manifest =
ParseManifestFile(manifest_path);
if (!manifest) {
ss << "Failed to parse manifest file " << manifest_path.value();
*error_message = ss.str();
return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
}
if (!IsCompatibleWithChrome(*manifest, error_message))
return CEF_CDM_REGISTRATION_ERROR_INCOMPATIBLE;
*cdm_version = GetManifestValue(*manifest, kCdmVersionName, error_message);
if (cdm_version->empty())
return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
*cdm_codecs = GetManifestValue(*manifest, kCdmCodecsListName, error_message);
if (cdm_codecs->empty())
return CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS;
return CEF_CDM_REGISTRATION_ERROR_NONE;
}
void DeliverWidevineCdmCallback(cef_cdm_registration_error_t result,
const std::string& error_message,
CefRefPtr<CefRegisterCdmCallback> callback) {
CEF_REQUIRE_UIT();
if (result != CEF_CDM_REGISTRATION_ERROR_NONE)
LOG(ERROR) << "Widevine CDM registration failed; " << error_message;
if (callback)
callback->OnCdmRegistrationComplete(result, error_message);
}
void RegisterWidevineCdmOnUIThread(
const base::FilePath& cdm_adapter_path,
const base::FilePath& cdm_path,
const std::string& cdm_version,
const std::string& cdm_codecs,
CefRefPtr<CefRegisterCdmCallback> callback) {
CEF_REQUIRE_UIT();
content::PepperPluginInfo widevine_cdm;
GetPluginInfo(cdm_adapter_path, cdm_path, cdm_version, cdm_codecs,
&widevine_cdm);
// true = Add to beginning of list to override any existing registrations.
content::PluginService::GetInstance()->RegisterInternalPlugin(
widevine_cdm.ToWebPluginInfo(), true);
// Tell the browser to refresh the plugin list. Then tell all renderers to
// update their plugin list caches.
content::PluginService::GetInstance()->RefreshPlugins();
content::PluginService::GetInstance()->PurgePluginListCache(NULL, false);
// Also register Widevine with the CdmService.
const std::vector<std::string> codecs = base::SplitString(
cdm_codecs, std::string(1, kCdmSupportedCodecsValueDelimiter),
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
content::CdmService::GetInstance()->RegisterCdm(content::CdmInfo(
kWidevineCdmType, base::Version(cdm_version), cdm_path, codecs));
DeliverWidevineCdmCallback(CEF_CDM_REGISTRATION_ERROR_NONE, std::string(),
callback);
}
void LoadWidevineCdmInfoOnFileThread(
const base::FilePath& base_path,
CefRefPtr<CefRegisterCdmCallback> callback) {
CEF_REQUIRE_FILET();
base::FilePath cdm_adapter_path;
base::FilePath cdm_path;
std::string cdm_version;
std::string cdm_codecs;
std::string error_message;
cef_cdm_registration_error_t result =
LoadWidevineCdmInfo(base_path, &cdm_adapter_path, &cdm_path, &cdm_version,
&cdm_codecs, &error_message);
if (result != CEF_CDM_REGISTRATION_ERROR_NONE) {
CEF_POST_TASK(CEF_UIT, base::Bind(DeliverWidevineCdmCallback, result,
error_message, callback));
return;
}
// Continue execution on the UI thread.
CEF_POST_TASK(CEF_UIT,
base::Bind(RegisterWidevineCdmOnUIThread, cdm_adapter_path, cdm_path,
cdm_version, cdm_codecs, callback));
}
} // namespace
// static
CefWidevineLoader* CefWidevineLoader::GetInstance() {
return &g_widevine_loader.Get();
}
void CefWidevineLoader::LoadWidevineCdm(
const base::FilePath& path,
CefRefPtr<CefRegisterCdmCallback> callback) {
if (!CONTEXT_STATE_VALID()) {
// Loading will proceed from OnContextInitialized().
load_pending_ = true;
path_ = path;
callback_ = callback;
return;
}
// Continue execution on the FILE thread.
CEF_POST_TASK(CEF_FILET,
base::Bind(LoadWidevineCdmInfoOnFileThread, path, callback));
}
void CefWidevineLoader::OnContextInitialized() {
CEF_REQUIRE_UIT();
if (load_pending_) {
load_pending_ = false;
LoadWidevineCdm(path_, callback_);
callback_ = nullptr;
}
}
#if defined(OS_LINUX)
// static
void CefWidevineLoader::AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) {
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
// Perform early plugin registration in the zygote process when the sandbox is
// enabled to avoid "cannot open shared object file: Operation not permitted"
// errors during plugin loading. This is because the Zygote process must pre-
// load all plugins before initializing the sandbox.
if (command_line.GetSwitchValueASCII(switches::kProcessType) !=
switches::kZygoteProcess ||
command_line.HasSwitch(switches::kNoSandbox)) {
return;
}
// The Widevine CDM path is passed to the zygote process via
// CefContentBrowserClient::AppendExtraCommandLineSwitches.
const base::FilePath& base_path = command_line.GetSwitchValuePath(
switches::kWidevineCdmPath);
if (base_path.empty())
return;
// Load contents of the plugin directory synchronously. This only occurs once
// on zygote process startup so should not have a huge performance penalty.
base::FilePath cdm_adapter_path;
base::FilePath cdm_path;
std::string cdm_version;
std::string cdm_codecs;
std::string error_message;
cef_cdm_registration_error_t result =
LoadWidevineCdmInfo(base_path, &cdm_adapter_path, &cdm_path, &cdm_version,
&cdm_codecs, &error_message);
if (result != CEF_CDM_REGISTRATION_ERROR_NONE) {
LOG(ERROR) << "Widevine CDM registration failed; " << error_message;
return;
}
content::PepperPluginInfo widevine_cdm;
GetPluginInfo(cdm_adapter_path, cdm_path, cdm_version, cdm_codecs,
&widevine_cdm);
plugins->push_back(widevine_cdm);
}
#endif // defined(OS_LINUX)
CefWidevineLoader::CefWidevineLoader() {
}
CefWidevineLoader::~CefWidevineLoader() {
}
#endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)

View File

@ -0,0 +1,64 @@
// Copyright 2016 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
#ifndef CEF_LIBCEF_COMMON_WIDEVINE_LOADER_H_
#define CEF_LIBCEF_COMMON_WIDEVINE_LOADER_H_
#pragma once
#include "build/build_config.h"
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
#include <vector>
#include "include/cef_web_plugin.h"
#include "base/lazy_instance.h"
namespace content {
struct PepperPluginInfo;
}
class CefWidevineLoader {
public:
// Returns the singleton instance of this object.
static CefWidevineLoader* GetInstance();
// Load the Widevine CDM. May be called before or after context creation. See
// comments in cef_web_plugin.h.
void LoadWidevineCdm(const base::FilePath& path,
CefRefPtr<CefRegisterCdmCallback> callback);
// Plugin registration is triggered here if LoadWidevineCdm() was called
// before context creation.
void OnContextInitialized();
#if defined(OS_LINUX)
// The zygote process which is used when the sandbox is enabled on Linux
// requires early loading of pepper plugins. Other processes will receive
// load notification in the usual way.
// Called from CefContentClient::AddPepperPlugins.
static void AddPepperPlugins(std::vector<content::PepperPluginInfo>* plugins);
const base::FilePath& path() { return path_; }
#endif
private:
friend struct base::DefaultLazyInstanceTraits<CefWidevineLoader>;
// Members are only accessed before context initialization or on the UI
// thread.
bool load_pending_ = false;
base::FilePath path_;
CefRefPtr<CefRegisterCdmCallback> callback_;
CefWidevineLoader();
~CefWidevineLoader();
};
#endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
#endif // CEF_LIBCEF_COMMON_WIDEVINE_LOADER_H_

View File

@ -0,0 +1,60 @@
// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/register_cdm_callback_cpptoc.h"
namespace {
// MEMBER FUNCTIONS - Body may be edited by hand.
void CEF_CALLBACK register_cdm_callback_on_cdm_registration_complete(
struct _cef_register_cdm_callback_t* self,
cef_cdm_registration_error_t result, const cef_string_t* error_message) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Unverified params: error_message
// Execute
CefRegisterCdmCallbackCppToC::Get(self)->OnCdmRegistrationComplete(
result,
CefString(error_message));
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
CefRegisterCdmCallbackCppToC::CefRegisterCdmCallbackCppToC() {
GetStruct()->on_cdm_registration_complete =
register_cdm_callback_on_cdm_registration_complete;
}
template<> CefRefPtr<CefRegisterCdmCallback> CefCppToC<CefRegisterCdmCallbackCppToC,
CefRegisterCdmCallback, cef_register_cdm_callback_t>::UnwrapDerived(
CefWrapperType type, cef_register_cdm_callback_t* s) {
NOTREACHED() << "Unexpected class type: " << type;
return NULL;
}
#if DCHECK_IS_ON()
template<> base::AtomicRefCount CefCppToC<CefRegisterCdmCallbackCppToC,
CefRegisterCdmCallback, cef_register_cdm_callback_t>::DebugObjCt = 0;
#endif
template<> CefWrapperType CefCppToC<CefRegisterCdmCallbackCppToC,
CefRegisterCdmCallback, cef_register_cdm_callback_t>::kWrapperType =
WT_REGISTER_CDM_CALLBACK;

View File

@ -0,0 +1,37 @@
// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_REGISTER_CDM_CALLBACK_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_REGISTER_CDM_CALLBACK_CPPTOC_H_
#pragma once
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include "include/cef_web_plugin.h"
#include "include/capi/cef_web_plugin_capi.h"
#include "include/cef_browser.h"
#include "include/capi/cef_browser_capi.h"
#include "libcef_dll/cpptoc/cpptoc.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed wrapper-side only.
class CefRegisterCdmCallbackCppToC
: public CefCppToC<CefRegisterCdmCallbackCppToC, CefRegisterCdmCallback,
cef_register_cdm_callback_t> {
public:
CefRegisterCdmCallbackCppToC();
};
#endif // USING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CPPTOC_REGISTER_CDM_CALLBACK_CPPTOC_H_

View File

@ -0,0 +1,54 @@
// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/ctocpp/register_cdm_callback_ctocpp.h"
// VIRTUAL METHODS - Body may be edited by hand.
void CefRegisterCdmCallbackCToCpp::OnCdmRegistrationComplete(
cef_cdm_registration_error_t result, const CefString& error_message) {
cef_register_cdm_callback_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_cdm_registration_complete))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: error_message
// Execute
_struct->on_cdm_registration_complete(_struct,
result,
error_message.GetStruct());
}
// CONSTRUCTOR - Do not edit by hand.
CefRegisterCdmCallbackCToCpp::CefRegisterCdmCallbackCToCpp() {
}
template<> cef_register_cdm_callback_t* CefCToCpp<CefRegisterCdmCallbackCToCpp,
CefRegisterCdmCallback, cef_register_cdm_callback_t>::UnwrapDerived(
CefWrapperType type, CefRegisterCdmCallback* c) {
NOTREACHED() << "Unexpected class type: " << type;
return NULL;
}
#if DCHECK_IS_ON()
template<> base::AtomicRefCount CefCToCpp<CefRegisterCdmCallbackCToCpp,
CefRegisterCdmCallback, cef_register_cdm_callback_t>::DebugObjCt = 0;
#endif
template<> CefWrapperType CefCToCpp<CefRegisterCdmCallbackCToCpp,
CefRegisterCdmCallback, cef_register_cdm_callback_t>::kWrapperType =
WT_REGISTER_CDM_CALLBACK;

View File

@ -0,0 +1,41 @@
// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_REGISTER_CDM_CALLBACK_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_REGISTER_CDM_CALLBACK_CTOCPP_H_
#pragma once
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include "include/cef_web_plugin.h"
#include "include/capi/cef_web_plugin_capi.h"
#include "include/cef_browser.h"
#include "include/capi/cef_browser_capi.h"
#include "libcef_dll/ctocpp/ctocpp.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed DLL-side only.
class CefRegisterCdmCallbackCToCpp
: public CefCToCpp<CefRegisterCdmCallbackCToCpp, CefRegisterCdmCallback,
cef_register_cdm_callback_t> {
public:
CefRegisterCdmCallbackCToCpp();
// CefRegisterCdmCallback methods.
void OnCdmRegistrationComplete(cef_cdm_registration_error_t result,
const CefString& error_message) override;
};
#endif // BUILDING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CTOCPP_REGISTER_CDM_CALLBACK_CTOCPP_H_

View File

@ -123,6 +123,7 @@
#include "libcef_dll/ctocpp/pdf_print_callback_ctocpp.h" #include "libcef_dll/ctocpp/pdf_print_callback_ctocpp.h"
#include "libcef_dll/ctocpp/print_handler_ctocpp.h" #include "libcef_dll/ctocpp/print_handler_ctocpp.h"
#include "libcef_dll/ctocpp/read_handler_ctocpp.h" #include "libcef_dll/ctocpp/read_handler_ctocpp.h"
#include "libcef_dll/ctocpp/register_cdm_callback_ctocpp.h"
#include "libcef_dll/ctocpp/render_handler_ctocpp.h" #include "libcef_dll/ctocpp/render_handler_ctocpp.h"
#include "libcef_dll/ctocpp/render_process_handler_ctocpp.h" #include "libcef_dll/ctocpp/render_process_handler_ctocpp.h"
#include "libcef_dll/ctocpp/request_handler_ctocpp.h" #include "libcef_dll/ctocpp/request_handler_ctocpp.h"
@ -287,6 +288,7 @@ CEF_EXPORT void cef_shutdown() {
DCHECK(base::AtomicRefCountIsZero(&CefPrintSettingsCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefPrintSettingsCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefProcessMessageCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefProcessMessageCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefReadHandlerCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefReadHandlerCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefRegisterCdmCallbackCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefRenderHandlerCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefRenderHandlerCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero( DCHECK(base::AtomicRefCountIsZero(
&CefRenderProcessHandlerCToCpp::DebugObjCt)); &CefRenderProcessHandlerCToCpp::DebugObjCt));
@ -992,3 +994,19 @@ CEF_EXPORT void cef_is_web_plugin_unstable(const cef_string_t* path,
CefWebPluginUnstableCallbackCToCpp::Wrap(callback)); CefWebPluginUnstableCallbackCToCpp::Wrap(callback));
} }
CEF_EXPORT void cef_register_widevine_cdm(const cef_string_t* path,
struct _cef_register_cdm_callback_t* callback) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: path; type: string_byref_const
DCHECK(path);
if (!path)
return;
// Unverified params: callback
// Execute
CefRegisterWidevineCdm(
CefString(path),
CefRegisterCdmCallbackCToCpp::Wrap(callback));
}

View File

@ -65,6 +65,7 @@
#include "libcef_dll/cpptoc/pdf_print_callback_cpptoc.h" #include "libcef_dll/cpptoc/pdf_print_callback_cpptoc.h"
#include "libcef_dll/cpptoc/print_handler_cpptoc.h" #include "libcef_dll/cpptoc/print_handler_cpptoc.h"
#include "libcef_dll/cpptoc/read_handler_cpptoc.h" #include "libcef_dll/cpptoc/read_handler_cpptoc.h"
#include "libcef_dll/cpptoc/register_cdm_callback_cpptoc.h"
#include "libcef_dll/cpptoc/render_handler_cpptoc.h" #include "libcef_dll/cpptoc/render_handler_cpptoc.h"
#include "libcef_dll/cpptoc/render_process_handler_cpptoc.h" #include "libcef_dll/cpptoc/render_process_handler_cpptoc.h"
#include "libcef_dll/cpptoc/request_handler_cpptoc.h" #include "libcef_dll/cpptoc/request_handler_cpptoc.h"
@ -279,6 +280,7 @@ CEF_GLOBAL void CefShutdown() {
DCHECK(base::AtomicRefCountIsZero(&CefPrintSettingsCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefPrintSettingsCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefProcessMessageCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefProcessMessageCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefReadHandlerCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefReadHandlerCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefRegisterCdmCallbackCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefRenderHandlerCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefRenderHandlerCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero( DCHECK(base::AtomicRefCountIsZero(
&CefRenderProcessHandlerCppToC::DebugObjCt)); &CefRenderProcessHandlerCppToC::DebugObjCt));
@ -935,3 +937,19 @@ CEF_GLOBAL void CefIsWebPluginUnstable(const CefString& path,
CefWebPluginUnstableCallbackCppToC::Wrap(callback)); CefWebPluginUnstableCallbackCppToC::Wrap(callback));
} }
CEF_GLOBAL void CefRegisterWidevineCdm(const CefString& path,
CefRefPtr<CefRegisterCdmCallback> callback) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: path; type: string_byref_const
DCHECK(!path.empty());
if (path.empty())
return;
// Unverified params: callback
// Execute
cef_register_widevine_cdm(
path.GetStruct(),
CefRegisterCdmCallbackCppToC::Wrap(callback));
}

View File

@ -85,6 +85,7 @@ enum CefWrapperType {
WT_PRINT_SETTINGS, WT_PRINT_SETTINGS,
WT_PROCESS_MESSAGE, WT_PROCESS_MESSAGE,
WT_READ_HANDLER, WT_READ_HANDLER,
WT_REGISTER_CDM_CALLBACK,
WT_RENDER_HANDLER, WT_RENDER_HANDLER,
WT_RENDER_PROCESS_HANDLER, WT_RENDER_PROCESS_HANDLER,
WT_REQUEST, WT_REQUEST,

View File

@ -7,8 +7,6 @@
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include "include/wrapper/cef_stream_resource_handler.h"
namespace client { namespace client {
namespace binding_test { namespace binding_test {

View File

@ -0,0 +1,120 @@
// Copyright (c) 2016 The Chromium Embedded Framework 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 "cefclient/browser/drm_test.h"
#include <algorithm>
#include <string>
#include "include/cef_parser.h"
#include "include/cef_web_plugin.h"
namespace client {
namespace drm_test {
namespace {
// Application-specific error codes.
const int kMessageFormatError = 1;
const int kCdmLoadError = 2;
const char kTestUrl[] = "http://tests/drm";
const char kWidevineCdmPathKey[] = "widevine_cdm_path";
// Callback executed once CDM registration is complete.
class CdmCallback : public CefRegisterCdmCallback {
public:
CdmCallback(CefRefPtr<CefMessageRouterBrowserSide::Callback> callback)
: callback_(callback) {
}
void OnCdmRegistrationComplete(cef_cdm_registration_error_t result,
const CefString& error_message) OVERRIDE {
if (result == CEF_CDM_REGISTRATION_ERROR_NONE)
callback_->Success("");
else
callback_->Failure(kCdmLoadError, error_message);
callback_ = nullptr;
}
private:
CefRefPtr<CefMessageRouterBrowserSide::Callback> callback_;
IMPLEMENT_REFCOUNTING(CdmCallback);
DISALLOW_COPY_AND_ASSIGN(CdmCallback);
};
// Handle messages in the browser process.
class Handler : public CefMessageRouterBrowserSide::Handler {
public:
Handler() {}
// Called due to cefQuery execution in binding.html.
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) OVERRIDE {
// Only handle messages from the test URL.
const std::string& url = frame->GetURL();
if (url.find(kTestUrl) != 0)
return false;
// Parse |request| as a JSON dictionary.
CefRefPtr<CefDictionaryValue> request_dict = ParseJSON(request);
if (!request_dict) {
callback->Failure(kMessageFormatError, "Incorrect message format");
return true;
}
// Verify the "widevine_cdm_path" key.
if (!VerifyKey(request_dict, kWidevineCdmPathKey, VTYPE_STRING, callback))
return true;
const std::string& widevine_cdm_path =
request_dict->GetString(kWidevineCdmPathKey);
if (widevine_cdm_path.empty()) {
callback->Failure(kMessageFormatError, "Empty widevine CDM path");
return true;
}
// Register the Widvine CDM.
CefRegisterWidevineCdm(widevine_cdm_path, new CdmCallback(callback));
return true;
}
private:
// Convert a JSON string to a dictionary value.
static CefRefPtr<CefDictionaryValue> ParseJSON(const CefString& string) {
CefRefPtr<CefValue> value = CefParseJSON(string, JSON_PARSER_RFC);
if (value.get() && value->GetType() == VTYPE_DICTIONARY)
return value->GetDictionary();
return NULL;
}
// Verify that |key| exists in |dictionary| and has type |value_type|. Fails
// |callback| and returns false on failure.
static bool VerifyKey(CefRefPtr<CefDictionaryValue> dictionary,
const char* key,
cef_value_type_t value_type,
CefRefPtr<Callback> callback) {
if (!dictionary->HasKey(key) || dictionary->GetType(key) != value_type) {
callback->Failure(kMessageFormatError,
"Missing or incorrectly formatted message key: " +
std::string(key));
return false;
}
return true;
}
};
} // namespace
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
handlers.insert(new Handler());
}
} // namespace drm_test
} // namespace client

View File

@ -0,0 +1,20 @@
// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_DRM_TEST_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_DRM_TEST_H_
#pragma once
#include "cefclient/browser/test_runner.h"
namespace client {
namespace drm_test {
// Create message handlers. Called from test_runner.cc.
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
} // namespace drm_test
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_DRM_TEST_H_

View File

@ -5,6 +5,7 @@
#include "cefclient/browser/main_context_impl.h" #include "cefclient/browser/main_context_impl.h"
#include "include/cef_parser.h" #include "include/cef_parser.h"
#include "include/cef_web_plugin.h"
#include "cefclient/common/client_switches.h" #include "cefclient/common/client_switches.h"
namespace client { namespace client {
@ -79,6 +80,16 @@ MainContextImpl::MainContextImpl(CefRefPtr<CefCommandLine> command_line,
main_url_ = "http://tests/draggable"; main_url_ = "http://tests/draggable";
} }
#endif // defined(OS_WIN) || defined(OS_LINUX) #endif // defined(OS_WIN) || defined(OS_LINUX)
const std::string& cdm_path =
command_line_->GetSwitchValue(switches::kWidevineCdmPath);
if (!cdm_path.empty()) {
// Register the Widevine CDM at the specified path. See comments in
// cef_web_plugin.h for details. It's safe to call this method before
// CefInitialize(), and calling it before CefInitialize() is required on
// Linux.
CefRegisterWidevineCdm(cdm_path, NULL);
}
} }
MainContextImpl::~MainContextImpl() { MainContextImpl::~MainContextImpl() {

View File

@ -46,24 +46,25 @@
#define IDS_BINDING_HTML 1000 #define IDS_BINDING_HTML 1000
#define IDS_DIALOGS_HTML 1001 #define IDS_DIALOGS_HTML 1001
#define IDS_DRAGGABLE_HTML 1002 #define IDS_DRAGGABLE_HTML 1002
#define IDS_LOCALSTORAGE_HTML 1003 #define IDS_DRM_HTML 1003
#define IDS_LOGO_PNG 1004 #define IDS_LOCALSTORAGE_HTML 1004
#define IDS_MENU_ICON_1X_PNG 1005 #define IDS_LOGO_PNG 1005
#define IDS_MENU_ICON_2X_PNG 1006 #define IDS_MENU_ICON_1X_PNG 1006
#define IDS_OSRTEST_HTML 1007 #define IDS_MENU_ICON_2X_PNG 1007
#define IDS_OTHER_TESTS_HTML 1008 #define IDS_OSRTEST_HTML 1008
#define IDS_PDF_HTML 1009 #define IDS_OTHER_TESTS_HTML 1009
#define IDS_PDF_PDF 1010 #define IDS_PDF_HTML 1010
#define IDS_PERFORMANCE_HTML 1011 #define IDS_PDF_PDF 1011
#define IDS_PERFORMANCE2_HTML 1012 #define IDS_PERFORMANCE_HTML 1012
#define IDS_PREFERENCES_HTML 1013 #define IDS_PERFORMANCE2_HTML 1013
#define IDS_RESPONSE_FILTER_HTML 1014 #define IDS_PREFERENCES_HTML 1014
#define IDS_TRANSPARENCY_HTML 1015 #define IDS_RESPONSE_FILTER_HTML 1015
#define IDS_URLREQUEST_HTML 1016 #define IDS_TRANSPARENCY_HTML 1016
#define IDS_WINDOW_HTML 1017 #define IDS_URLREQUEST_HTML 1017
#define IDS_WINDOW_ICON_1X_PNG 1018 #define IDS_WINDOW_HTML 1018
#define IDS_WINDOW_ICON_2X_PNG 1019 #define IDS_WINDOW_ICON_1X_PNG 1019
#define IDS_XMLHTTPREQUEST_HTML 1020 #define IDS_WINDOW_ICON_2X_PNG 1020
#define IDS_XMLHTTPREQUEST_HTML 1021
// Next default values for new objects // Next default values for new objects
// //

View File

@ -40,6 +40,7 @@ int GetResourceId(const char* resource_name) {
{"binding.html", IDS_BINDING_HTML}, {"binding.html", IDS_BINDING_HTML},
{"dialogs.html", IDS_DIALOGS_HTML}, {"dialogs.html", IDS_DIALOGS_HTML},
{"draggable.html", IDS_DRAGGABLE_HTML}, {"draggable.html", IDS_DRAGGABLE_HTML},
{"drm.html", IDS_DRM_HTML},
{"logo.png", IDS_LOGO_PNG}, {"logo.png", IDS_LOGO_PNG},
{"localstorage.html", IDS_LOCALSTORAGE_HTML}, {"localstorage.html", IDS_LOCALSTORAGE_HTML},
{"menu_icon.1x.png", IDS_MENU_ICON_1X_PNG}, {"menu_icon.1x.png", IDS_MENU_ICON_1X_PNG},

View File

@ -15,6 +15,7 @@
#include "include/wrapper/cef_stream_resource_handler.h" #include "include/wrapper/cef_stream_resource_handler.h"
#include "cefclient/browser/binding_test.h" #include "cefclient/browser/binding_test.h"
#include "cefclient/browser/dialog_test.h" #include "cefclient/browser/dialog_test.h"
#include "cefclient/browser/drm_test.h"
#include "cefclient/browser/main_context.h" #include "cefclient/browser/main_context.h"
#include "cefclient/browser/preferences_test.h" #include "cefclient/browser/preferences_test.h"
#include "cefclient/browser/resource.h" #include "cefclient/browser/resource.h"
@ -715,6 +716,9 @@ void CreateMessageHandlers(MessageHandlerSet& handlers) {
// Create the dialog test handlers. // Create the dialog test handlers.
dialog_test::CreateMessageHandlers(handlers); dialog_test::CreateMessageHandlers(handlers);
// Create the drm test handlers.
drm_test::CreateMessageHandlers(handlers);
// Create the preferences test handlers. // Create the preferences test handlers.
preferences_test::CreateMessageHandlers(handlers); preferences_test::CreateMessageHandlers(handlers);

View File

@ -34,6 +34,7 @@ const char kFilterURL[] = "filter-url";
const char kUseViews[] = "use-views"; const char kUseViews[] = "use-views";
const char kHideFrame[] = "hide-frame"; const char kHideFrame[] = "hide-frame";
const char kHideControls[] = "hide-controls"; const char kHideControls[] = "hide-controls";
const char kWidevineCdmPath[] = "widevine-cdm-path";
} // namespace switches } // namespace switches
} // namespace client } // namespace client

View File

@ -28,6 +28,7 @@ extern const char kFilterURL[];
extern const char kUseViews[]; extern const char kUseViews[];
extern const char kHideFrame[]; extern const char kHideFrame[];
extern const char kHideControls[]; extern const char kHideControls[];
extern const char kWidevineCdmPath[];
} // namespace switches } // namespace switches
} // namespace client } // namespace client

View File

@ -0,0 +1,126 @@
<html>
<head>
<title>DRM Test</title>
<script language="JavaScript">
// Based on DRM detection code from https://github.com/google/shaka-player
function probeSupport() {
var tests = [];
var testKeySystems = [
'org.w3.clearkey',
'com.widevine.alpha',
];
var basicVideoCapabilities = [
{ contentType: 'video/mp4; codecs="avc1.42E01E"' },
{ contentType: 'video/webm; codecs="vp9"' }
];
var basicConfig = {
videoCapabilities: basicVideoCapabilities
};
var offlineConfig = {
videoCapabilities: basicVideoCapabilities,
persistentState: 'required',
sessionTypes: ['persistent-license']
};
// Try the offline config first, then fall back to the basic config.
var configs = [offlineConfig, basicConfig];
var support = {};
testKeySystems.forEach(function(keySystem) {
var p = navigator.requestMediaKeySystemAccess(keySystem, configs)
.then(function(access) {
// We can't (yet) trust every browser to report the session types they
// support in access.getConfiguration(). Therefore, we create a
// MediaKeys object and try to create an offline session.
// https://goo.gl/gtYT3z, https://goo.gl/rvnB1g, https://goo.gl/z0URJ0
var mediaKeys = access.createMediaKeys();
var persistentState = false;
try {
// This will throw if persistent licenses are not supported.
mediaKeys.createSession('persistent-license');
persistentState = true;
} catch (e) {}
support[keySystem] = {persistentState: persistentState};
}, function() {
support[keySystem] = null;
});
tests.push(p);
});
return Promise.all(tests).then(function() {
return support;
});
}
function getWidevineCdmInfo() {
if (!('Widevine Content Decryption Module' in navigator.plugins)) {
return "Widevine CDM plugin not loaded.";
}
var plugin = navigator.plugins['Widevine Content Decryption Module'];
return "Widevine CDM plugin:\n" + JSON.stringify({
"name": plugin.name,
"filename": plugin.filename,
"description": plugin.description,
}, null, ' ')
}
function printSupport(support) {
var output = document.getElementById('output');
output.textContent = getWidevineCdmInfo() + "\n\nDRM Support:\n" + support;
}
function doTest() {
probeSupport().then(function(support) {
printSupport(JSON.stringify(support, null, ' '));
});
}
// Send a message to the browser process.
function sendMessage() {
// Create the request object.
var request = {};
request.widevine_cdm_path =
document.getElementById("widevine_cdm_path").value;
// Results in a call to the OnQuery method in drm_test.cpp
window.cefQuery({
request: JSON.stringify(request),
onSuccess: function(response) {
alert('Widevine CDM plugin loaded successfully!');
// Registration succeeded so test again.
doTest();
},
onFailure: function(error_code, error_message) {
alert(error_message + ' (' + error_code + ')');
}
});
}
</script>
</head>
<body bgcolor="white" onload="doTest()">
Important notes:
<ul>
<li>Clearkey support is built in and should always be enabled.</li>
<li>Widevine support requires CDM binaries that must be downloaded from Google. Contact Google <a href="https://www.widevine.com/contact.html">here</a> for details.</li>
<li>Widevine support is enabled by calling the CefRegisterWidevineCdm() function. See comments in cef_web_plugin.h for usage.</li>
<li>The CefRegisterWidevineCdm() function can be called during runtime on Windows and OS X to register Widevine binaries. Use the below form to test this capability.</li>
<li>Calling CefRegisterWidevineCdm() before CefInitialize() is required on Linux.</li>
<li>Cefclient will call CefRegisterWidevineCdm() before CefInitialize() if "--widevine-cdm-path=&lt;path&gt;" is specified on the command-line.</li>
<li>View extended media support information <a href="https://shaka-player-demo.appspot.com/support.html">here</a>.</li>
<li>Test DRM video playback <a href="https://shaka-player-demo.appspot.com/demo/">here</a>. Select an "asset" that includes Clearkey or Widevine in the name.</li>
</ul>
<form>
Widevine CDM Path: <input type="text" id="widevine_cdm_path" value="" size="40">
<input type="button" onclick="sendMessage();" value="Load CDM">
</form>
<pre id="output"></pre>
</body>
</html>

View File

@ -11,6 +11,7 @@
<li><a href="http://tests/dialogs">Dialogs</a></li> <li><a href="http://tests/dialogs">Dialogs</a></li>
<li><a href="http://html5demos.com/drag">Drag & Drop</a></li> <li><a href="http://html5demos.com/drag">Drag & Drop</a></li>
<li><a href="http://tests/draggable">Draggable Regions</a></li> <li><a href="http://tests/draggable">Draggable Regions</a></li>
<li><a href="http://tests/drm">DRM (Clearkey, Widevine)</a></li>
<li><a href="http://www.adobe.com/software/flash/about/">Flash Plugin</a> - requires "enable-system-flash" flag on Win/Mac and "ppapi-flash-path", "ppapi-flash-version" flags on Linux</li> <li><a href="http://www.adobe.com/software/flash/about/">Flash Plugin</a> - requires "enable-system-flash" flag on Win/Mac and "ppapi-flash-path", "ppapi-flash-version" flags on Linux</li>
<li><a href="http://html5demos.com/geo">Geolocation</a></li> <li><a href="http://html5demos.com/geo">Geolocation</a></li>
<li><a href="http://www.html5test.com">HTML5 Feature Test</a></li> <li><a href="http://www.html5test.com">HTML5 Feature Test</a></li>

View File

@ -32,6 +32,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
IDS_BINDING_HTML BINARY "..\\binding.html" IDS_BINDING_HTML BINARY "..\\binding.html"
IDS_DIALOGS_HTML BINARY "..\\dialogs.html" IDS_DIALOGS_HTML BINARY "..\\dialogs.html"
IDS_DRAGGABLE_HTML BINARY "..\\draggable.html" IDS_DRAGGABLE_HTML BINARY "..\\draggable.html"
IDS_DRM_HTML BINARY "..\\drm.html"
IDS_LOCALSTORAGE_HTML BINARY "..\\localstorage.html" IDS_LOCALSTORAGE_HTML BINARY "..\\localstorage.html"
IDS_LOGO_PNG BINARY "..\\logo.png" IDS_LOGO_PNG BINARY "..\\logo.png"
IDS_MENU_ICON_1X_PNG BINARY "..\\menu_icon.1x.png" IDS_MENU_ICON_1X_PNG BINARY "..\\menu_icon.1x.png"

View File

@ -56,3 +56,8 @@ run but any related functionality may become broken or disabled.
* devtools_resources.pak * devtools_resources.pak
This file contains non-localized resources required for Chrome Developer This file contains non-localized resources required for Chrome Developer
Tools. Without this file Chrome Developer Tools will not function. Tools. Without this file Chrome Developer Tools will not function.
* Widevine CDM support.
* libwidevinecdmadapter.so
Without this file playback of Widevine projected content will not function.
See the CefRegisterWidevineCdm() function in cef_web_plugin.h for usage.

View File

@ -103,3 +103,8 @@ run but any related functionality may become broken or disabled.
* Chromium Embedded Framework.framework/Resources/crash_report_sender * Chromium Embedded Framework.framework/Resources/crash_report_sender
* Chromium Embedded Framework.framework/Resources/Info.plist * Chromium Embedded Framework.framework/Resources/Info.plist
Without these files breakpad support (crash reporting) will not function. Without these files breakpad support (crash reporting) will not function.
* Widevine CDM support.
* widevinecdmadapter.plugin
Without this file playback of Widevine projected content will not function.
See the CefRegisterWidevineCdm() function in cef_web_plugin.h for usage.

Binary file not shown.

View File

@ -62,3 +62,8 @@ run but any related functionality may become broken or disabled.
* libGLESv2.dll * libGLESv2.dll
Without these files HTML5 accelerated content like 2D canvas, 3D CSS and WebGL Without these files HTML5 accelerated content like 2D canvas, 3D CSS and WebGL
will not function. will not function.
* Widevine CDM support.
* widevinecdmadapter.dll
Without this file playback of Widevine projected content will not function.
See the CefRegisterWidevineCdm() function in cef_web_plugin.h for usage.

View File

@ -637,6 +637,7 @@ elif platform == 'macosx':
make_dir(dst_dir, options.quiet) make_dir(dst_dir, options.quiet)
copy_dir(os.path.join(build_dir, 'cefclient.app/Contents/Frameworks/%s.framework' % framework_name), \ copy_dir(os.path.join(build_dir, 'cefclient.app/Contents/Frameworks/%s.framework' % framework_name), \
os.path.join(dst_dir, '%s.framework' % framework_name), options.quiet) os.path.join(dst_dir, '%s.framework' % framework_name), options.quiet)
copy_file(os.path.join(script_dir, 'distrib/mac/widevinecdmadapter.plugin'), dst_dir, options.quiet)
if not options.nosymbols: if not options.nosymbols:
# create the symbol output directory # create the symbol output directory
@ -657,6 +658,7 @@ elif platform == 'macosx':
if mode != 'client': if mode != 'client':
copy_dir(os.path.join(build_dir, 'cefclient.app/Contents/Frameworks/%s.framework' % framework_name), \ copy_dir(os.path.join(build_dir, 'cefclient.app/Contents/Frameworks/%s.framework' % framework_name), \
os.path.join(dst_dir, '%s.framework' % framework_name), options.quiet) os.path.join(dst_dir, '%s.framework' % framework_name), options.quiet)
copy_file(os.path.join(script_dir, 'distrib/mac/widevinecdmadapter.plugin'), dst_dir, options.quiet)
else: else:
copy_dir(os.path.join(build_dir, 'cefclient.app'), os.path.join(dst_dir, 'cefclient.app'), options.quiet) copy_dir(os.path.join(build_dir, 'cefclient.app'), os.path.join(dst_dir, 'cefclient.app'), options.quiet)
@ -718,6 +720,7 @@ elif platform == 'linux':
make_dir(dst_dir, options.quiet) make_dir(dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'chrome_sandbox'), os.path.join(dst_dir, 'chrome-sandbox'), options.quiet) copy_file(os.path.join(build_dir, 'chrome_sandbox'), os.path.join(dst_dir, 'chrome-sandbox'), options.quiet)
copy_file(libcef_path, dst_dir, options.quiet) copy_file(libcef_path, dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'libwidevinecdmadapter.so'), dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'natives_blob.bin'), dst_dir, options.quiet) copy_file(os.path.join(build_dir, 'natives_blob.bin'), dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'snapshot_blob.bin'), dst_dir, options.quiet) copy_file(os.path.join(build_dir, 'snapshot_blob.bin'), dst_dir, options.quiet)
else: else:
@ -735,6 +738,7 @@ elif platform == 'linux':
copy_file(os.path.join(build_dir, 'cefsimple'), dst_dir, options.quiet) copy_file(os.path.join(build_dir, 'cefsimple'), dst_dir, options.quiet)
copy_file(libcef_path, dst_dir, options.quiet) copy_file(libcef_path, dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'chrome_sandbox'), os.path.join(dst_dir, 'chrome-sandbox'), options.quiet) copy_file(os.path.join(build_dir, 'chrome_sandbox'), os.path.join(dst_dir, 'chrome-sandbox'), options.quiet)
copy_file(os.path.join(build_dir, 'libwidevinecdmadapter.so'), dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'natives_blob.bin'), dst_dir, options.quiet) copy_file(os.path.join(build_dir, 'natives_blob.bin'), dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'snapshot_blob.bin'), dst_dir, options.quiet) copy_file(os.path.join(build_dir, 'snapshot_blob.bin'), dst_dir, options.quiet)
else: else: