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

@@ -7,8 +7,6 @@
#include <algorithm>
#include <string>
#include "include/wrapper/cef_stream_resource_handler.h"
namespace client {
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 "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() {

View File

@@ -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
//

View File

@@ -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},

View File

@@ -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);

View File

@@ -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

View File

@@ -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

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://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>

View File

@@ -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"