mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
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:
@@ -7,8 +7,6 @@
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "include/wrapper/cef_stream_resource_handler.h"
|
||||
|
||||
namespace client {
|
||||
namespace binding_test {
|
||||
|
||||
|
120
tests/cefclient/browser/drm_test.cc
Normal file
120
tests/cefclient/browser/drm_test.cc
Normal 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
|
20
tests/cefclient/browser/drm_test.h
Normal file
20
tests/cefclient/browser/drm_test.h
Normal 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_
|
@@ -5,6 +5,7 @@
|
||||
#include "cefclient/browser/main_context_impl.h"
|
||||
|
||||
#include "include/cef_parser.h"
|
||||
#include "include/cef_web_plugin.h"
|
||||
#include "cefclient/common/client_switches.h"
|
||||
|
||||
namespace client {
|
||||
@@ -79,6 +80,16 @@ MainContextImpl::MainContextImpl(CefRefPtr<CefCommandLine> command_line,
|
||||
main_url_ = "http://tests/draggable";
|
||||
}
|
||||
#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() {
|
||||
|
@@ -46,24 +46,25 @@
|
||||
#define IDS_BINDING_HTML 1000
|
||||
#define IDS_DIALOGS_HTML 1001
|
||||
#define IDS_DRAGGABLE_HTML 1002
|
||||
#define IDS_LOCALSTORAGE_HTML 1003
|
||||
#define IDS_LOGO_PNG 1004
|
||||
#define IDS_MENU_ICON_1X_PNG 1005
|
||||
#define IDS_MENU_ICON_2X_PNG 1006
|
||||
#define IDS_OSRTEST_HTML 1007
|
||||
#define IDS_OTHER_TESTS_HTML 1008
|
||||
#define IDS_PDF_HTML 1009
|
||||
#define IDS_PDF_PDF 1010
|
||||
#define IDS_PERFORMANCE_HTML 1011
|
||||
#define IDS_PERFORMANCE2_HTML 1012
|
||||
#define IDS_PREFERENCES_HTML 1013
|
||||
#define IDS_RESPONSE_FILTER_HTML 1014
|
||||
#define IDS_TRANSPARENCY_HTML 1015
|
||||
#define IDS_URLREQUEST_HTML 1016
|
||||
#define IDS_WINDOW_HTML 1017
|
||||
#define IDS_WINDOW_ICON_1X_PNG 1018
|
||||
#define IDS_WINDOW_ICON_2X_PNG 1019
|
||||
#define IDS_XMLHTTPREQUEST_HTML 1020
|
||||
#define IDS_DRM_HTML 1003
|
||||
#define IDS_LOCALSTORAGE_HTML 1004
|
||||
#define IDS_LOGO_PNG 1005
|
||||
#define IDS_MENU_ICON_1X_PNG 1006
|
||||
#define IDS_MENU_ICON_2X_PNG 1007
|
||||
#define IDS_OSRTEST_HTML 1008
|
||||
#define IDS_OTHER_TESTS_HTML 1009
|
||||
#define IDS_PDF_HTML 1010
|
||||
#define IDS_PDF_PDF 1011
|
||||
#define IDS_PERFORMANCE_HTML 1012
|
||||
#define IDS_PERFORMANCE2_HTML 1013
|
||||
#define IDS_PREFERENCES_HTML 1014
|
||||
#define IDS_RESPONSE_FILTER_HTML 1015
|
||||
#define IDS_TRANSPARENCY_HTML 1016
|
||||
#define IDS_URLREQUEST_HTML 1017
|
||||
#define IDS_WINDOW_HTML 1018
|
||||
#define IDS_WINDOW_ICON_1X_PNG 1019
|
||||
#define IDS_WINDOW_ICON_2X_PNG 1020
|
||||
#define IDS_XMLHTTPREQUEST_HTML 1021
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
|
@@ -40,6 +40,7 @@ int GetResourceId(const char* resource_name) {
|
||||
{"binding.html", IDS_BINDING_HTML},
|
||||
{"dialogs.html", IDS_DIALOGS_HTML},
|
||||
{"draggable.html", IDS_DRAGGABLE_HTML},
|
||||
{"drm.html", IDS_DRM_HTML},
|
||||
{"logo.png", IDS_LOGO_PNG},
|
||||
{"localstorage.html", IDS_LOCALSTORAGE_HTML},
|
||||
{"menu_icon.1x.png", IDS_MENU_ICON_1X_PNG},
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "include/wrapper/cef_stream_resource_handler.h"
|
||||
#include "cefclient/browser/binding_test.h"
|
||||
#include "cefclient/browser/dialog_test.h"
|
||||
#include "cefclient/browser/drm_test.h"
|
||||
#include "cefclient/browser/main_context.h"
|
||||
#include "cefclient/browser/preferences_test.h"
|
||||
#include "cefclient/browser/resource.h"
|
||||
@@ -715,6 +716,9 @@ void CreateMessageHandlers(MessageHandlerSet& handlers) {
|
||||
// Create the dialog test handlers.
|
||||
dialog_test::CreateMessageHandlers(handlers);
|
||||
|
||||
// Create the drm test handlers.
|
||||
drm_test::CreateMessageHandlers(handlers);
|
||||
|
||||
// Create the preferences test handlers.
|
||||
preferences_test::CreateMessageHandlers(handlers);
|
||||
|
||||
|
@@ -34,6 +34,7 @@ const char kFilterURL[] = "filter-url";
|
||||
const char kUseViews[] = "use-views";
|
||||
const char kHideFrame[] = "hide-frame";
|
||||
const char kHideControls[] = "hide-controls";
|
||||
const char kWidevineCdmPath[] = "widevine-cdm-path";
|
||||
|
||||
} // namespace switches
|
||||
} // namespace client
|
||||
|
@@ -28,6 +28,7 @@ extern const char kFilterURL[];
|
||||
extern const char kUseViews[];
|
||||
extern const char kHideFrame[];
|
||||
extern const char kHideControls[];
|
||||
extern const char kWidevineCdmPath[];
|
||||
|
||||
} // namespace switches
|
||||
} // namespace client
|
||||
|
126
tests/cefclient/resources/drm.html
Normal file
126
tests/cefclient/resources/drm.html
Normal 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=<path>" 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>
|
@@ -11,6 +11,7 @@
|
||||
<li><a href="http://tests/dialogs">Dialogs</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/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://html5demos.com/geo">Geolocation</a></li>
|
||||
<li><a href="http://www.html5test.com">HTML5 Feature Test</a></li>
|
||||
|
@@ -32,6 +32,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
IDS_BINDING_HTML BINARY "..\\binding.html"
|
||||
IDS_DIALOGS_HTML BINARY "..\\dialogs.html"
|
||||
IDS_DRAGGABLE_HTML BINARY "..\\draggable.html"
|
||||
IDS_DRM_HTML BINARY "..\\drm.html"
|
||||
IDS_LOCALSTORAGE_HTML BINARY "..\\localstorage.html"
|
||||
IDS_LOGO_PNG BINARY "..\\logo.png"
|
||||
IDS_MENU_ICON_1X_PNG BINARY "..\\menu_icon.1x.png"
|
||||
|
Reference in New Issue
Block a user