Commit a8a9143d authored by sandersd's avatar sandersd Committed by Commit bot

Implement robustness strings in requestMediaKeySystemAccess().

BUG=442586,460616

Review URL: https://codereview.chromium.org/1005903003

Cr-Commit-Position: refs/heads/master@{#322219}
parent f1eb0a7e
...@@ -75,22 +75,22 @@ static void AddExternalClearKey( ...@@ -75,22 +75,22 @@ static void AddExternalClearKey(
KeySystemInfo info; KeySystemInfo info;
info.key_system = kExternalClearKeyKeySystem; info.key_system = kExternalClearKeyKeySystem;
info.supported_codecs = media::EME_CODEC_WEBM_ALL;
info.supported_init_data_types = info.supported_init_data_types =
media::EME_INIT_DATA_TYPE_WEBM | media::EME_INIT_DATA_TYPE_KEYIDS; media::EME_INIT_DATA_TYPE_WEBM | media::EME_INIT_DATA_TYPE_KEYIDS;
info.supported_codecs = media::EME_CODEC_WEBM_ALL;
#if defined(USE_PROPRIETARY_CODECS) #if defined(USE_PROPRIETARY_CODECS)
info.supported_codecs |= media::EME_CODEC_MP4_ALL;
info.supported_init_data_types |= media::EME_INIT_DATA_TYPE_CENC; info.supported_init_data_types |= media::EME_INIT_DATA_TYPE_CENC;
info.supported_codecs |= media::EME_CODEC_MP4_ALL;
#endif // defined(USE_PROPRIETARY_CODECS) #endif // defined(USE_PROPRIETARY_CODECS)
info.max_audio_robustness = media::EmeRobustness::EMPTY;
info.max_video_robustness = media::EmeRobustness::EMPTY;
// Persistent sessions are faked. // Persistent sessions are faked.
info.persistent_license_support = media::EME_SESSION_TYPE_SUPPORTED; info.persistent_license_support = media::EME_SESSION_TYPE_SUPPORTED;
info.persistent_release_message_support = info.persistent_release_message_support =
media::EME_SESSION_TYPE_NOT_SUPPORTED; media::EME_SESSION_TYPE_NOT_SUPPORTED;
// TODO(sandersd): Using ALWAYS_ENABLED prevents "not-allowed" from info.persistent_state_support = media::EME_FEATURE_REQUESTABLE;
// succeeding. Change this to REQUESTABLE once the state can be blocked.
// http://crbug.com/457482
info.persistent_state_support = media::EME_FEATURE_ALWAYS_ENABLED;
info.distinctive_identifier_support = media::EME_FEATURE_NOT_SUPPORTED; info.distinctive_identifier_support = media::EME_FEATURE_NOT_SUPPORTED;
info.pepper_type = kExternalClearKeyPepperType; info.pepper_type = kExternalClearKeyPepperType;
...@@ -193,23 +193,20 @@ static void AddPepperBasedWidevine( ...@@ -193,23 +193,20 @@ static void AddPepperBasedWidevine(
cdm::AddWidevineWithCodecs( cdm::AddWidevineWithCodecs(
cdm::WIDEVINE, supported_codecs, cdm::WIDEVINE, supported_codecs,
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
// Persistent licenses are supported if remote attestation succeeds. media::EmeRobustness::HW_SECURE_ALL, // Maximum audio robustness.
media::EME_SESSION_TYPE_SUPPORTED_WITH_PERMISSION, media::EmeRobustness::HW_SECURE_ALL, // Maximim video robustness.
media::EME_SESSION_TYPE_NOT_SUPPORTED, // Persistent release message. // persistent-license.
// TODO(sandersd): Using ALWAYS_ENABLED prevents "not-allowed" from media::EME_SESSION_TYPE_SUPPORTED_WITH_IDENTIFIER,
// succeeding. Change this to REQUESTABLE once the state can be blocked. media::EME_SESSION_TYPE_NOT_SUPPORTED, // persistent-release-message.
// http://crbug.com/457482 media::EME_FEATURE_REQUESTABLE, // Persistent state.
media::EME_FEATURE_ALWAYS_ENABLED, // Persistent state. // Distinctive identifier.
// A distinctive identifier will be available if remote attestation media::EME_FEATURE_REQUESTABLE_WITH_IDENTIFIER,
// succeeds.
media::EME_FEATURE_REQUESTABLE_WITH_PERMISSION,
#else // (Desktop) #else // (Desktop)
media::EME_SESSION_TYPE_NOT_SUPPORTED, // Persistent license. media::EmeRobustness::SW_SECURE_CRYPTO, // Maximum audio robustness.
media::EME_SESSION_TYPE_NOT_SUPPORTED, // Persistent release message. media::EmeRobustness::SW_SECURE_DECODE, // Maximum video robustness.
// TODO(sandersd): Using ALWAYS_ENABLED prevents "not-allowed" from media::EME_SESSION_TYPE_NOT_SUPPORTED, // persistent-license.
// succeeding. Change this to REQUESTABLE once the state can be blocked. media::EME_SESSION_TYPE_NOT_SUPPORTED, // persistent-release-message.
// http://crbug.com/457482 media::EME_FEATURE_REQUESTABLE, // Persistent state.
media::EME_FEATURE_ALWAYS_ENABLED, // Persistent state.
media::EME_FEATURE_NOT_SUPPORTED, // Distinctive identifier. media::EME_FEATURE_NOT_SUPPORTED, // Distinctive identifier.
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
concrete_key_systems); concrete_key_systems);
......
...@@ -22,9 +22,11 @@ void AddKeySystemWithCodecs( ...@@ -22,9 +22,11 @@ void AddKeySystemWithCodecs(
std::vector<::media::KeySystemInfo>* key_systems_info) { std::vector<::media::KeySystemInfo>* key_systems_info) {
::media::KeySystemInfo info; ::media::KeySystemInfo info;
info.key_system = key_system_name; info.key_system = key_system_name;
info.supported_init_data_types = ::media::EME_INIT_DATA_TYPE_CENC;
info.supported_codecs = info.supported_codecs =
::media::EME_CODEC_MP4_AAC | ::media::EME_CODEC_MP4_AVC1; ::media::EME_CODEC_MP4_AAC | ::media::EME_CODEC_MP4_AVC1;
info.supported_init_data_types = ::media::EME_INIT_DATA_TYPE_CENC; info.max_audio_robustness = ::media::EmeRobustness::EMPTY;
info.max_video_robustness = ::media::EmeRobustness::EMPTY;
info.persistent_license_support = ::media::EME_SESSION_TYPE_NOT_SUPPORTED; info.persistent_license_support = ::media::EME_SESSION_TYPE_NOT_SUPPORTED;
info.persistent_release_message_support = info.persistent_release_message_support =
::media::EME_SESSION_TYPE_NOT_SUPPORTED; ::media::EME_SESSION_TYPE_NOT_SUPPORTED;
...@@ -39,8 +41,10 @@ void AddChromecastKeySystems( ...@@ -39,8 +41,10 @@ void AddChromecastKeySystems(
AddWidevineWithCodecs( AddWidevineWithCodecs(
cdm::WIDEVINE, cdm::WIDEVINE,
::media::EME_CODEC_MP4_AAC | ::media::EME_CODEC_MP4_AVC1, ::media::EME_CODEC_MP4_AAC | ::media::EME_CODEC_MP4_AVC1,
::media::EME_SESSION_TYPE_NOT_SUPPORTED, // Persistent license. ::media::EmeRobustness::HW_SECURE_ALL, // Max audio robustness.
::media::EME_SESSION_TYPE_NOT_SUPPORTED, // Persistent release message. ::media::EmeRobustness::HW_SECURE_ALL, // Max video robustness.
::media::EME_SESSION_TYPE_NOT_SUPPORTED, // persistent-license.
::media::EME_SESSION_TYPE_NOT_SUPPORTED, // persistent-release-message.
::media::EME_FEATURE_NOT_SUPPORTED, // Persistent state. ::media::EME_FEATURE_NOT_SUPPORTED, // Persistent state.
::media::EME_FEATURE_ALWAYS_ENABLED, // Distinctive identifier. ::media::EME_FEATURE_ALWAYS_ENABLED, // Distinctive identifier.
key_systems_info); key_systems_info);
......
...@@ -7,14 +7,17 @@ ...@@ -7,14 +7,17 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/command_line.h"
#include "base/logging.h" #include "base/logging.h"
#include "components/cdm/common/cdm_messages_android.h" #include "components/cdm/common/cdm_messages_android.h"
#include "components/cdm/renderer/widevine_key_systems.h" #include "components/cdm/renderer/widevine_key_systems.h"
#include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_thread.h"
#include "media/base/eme_constants.h" #include "media/base/eme_constants.h"
#include "media/base/media_switches.h"
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
using media::EmeRobustness;
using media::KeySystemInfo; using media::KeySystemInfo;
using media::SupportedCodecs; using media::SupportedCodecs;
...@@ -39,24 +42,48 @@ static SupportedKeySystemResponse QueryKeySystemSupport( ...@@ -39,24 +42,48 @@ static SupportedKeySystemResponse QueryKeySystemSupport(
void AddAndroidWidevine(std::vector<KeySystemInfo>* concrete_key_systems) { void AddAndroidWidevine(std::vector<KeySystemInfo>* concrete_key_systems) {
SupportedKeySystemResponse response = QueryKeySystemSupport( SupportedKeySystemResponse response = QueryKeySystemSupport(
kWidevineKeySystem); kWidevineKeySystem);
if (response.compositing_codecs != media::EME_CODEC_NONE) {
// When creating the WIDEVINE key system, BrowserCdmFactoryAndroid configures
// the CDM's security level based on the --mediadrm-enable-non-compositing
// flag (L1 if the flag is enabled, L3 otherwise). Therefore the supported
// codec/robustenss combinations depend on that flag.
// TODO(sandersd): For unprefixed, set the security level based on the
// requested robustness instead of the flag. http://crbug.com/467779
SupportedCodecs codecs = response.compositing_codecs;
EmeRobustness max_audio_robustness = EmeRobustness::SW_SECURE_CRYPTO;
EmeRobustness max_video_robustness = EmeRobustness::SW_SECURE_CRYPTO;
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kMediaDrmEnableNonCompositing)) {
codecs = response.non_compositing_codecs;
max_audio_robustness = EmeRobustness::HW_SECURE_CRYPTO;
max_video_robustness = EmeRobustness::HW_SECURE_ALL;
}
if (codecs != media::EME_CODEC_NONE) {
AddWidevineWithCodecs( AddWidevineWithCodecs(
WIDEVINE, WIDEVINE,
static_cast<SupportedCodecs>(response.compositing_codecs), codecs,
media::EME_SESSION_TYPE_NOT_SUPPORTED, // Persistent license. max_audio_robustness,
media::EME_SESSION_TYPE_NOT_SUPPORTED, // Persistent release message. max_video_robustness,
media::EME_SESSION_TYPE_NOT_SUPPORTED, // persistent-license.
media::EME_SESSION_TYPE_NOT_SUPPORTED, // persistent-release-message.
media::EME_FEATURE_NOT_SUPPORTED, // Persistent state. media::EME_FEATURE_NOT_SUPPORTED, // Persistent state.
media::EME_FEATURE_ALWAYS_ENABLED, // Distinctive identifier. media::EME_FEATURE_ALWAYS_ENABLED, // Distinctive identifier.
concrete_key_systems); concrete_key_systems);
} }
if (response.non_compositing_codecs != media::EME_CODEC_NONE) { // For compatibility with the prefixed API, register a separate L1 key system.
// When creating the WIDEVINE_HR_NON_COMPOSITING key system,
// BrowserCdmFactoryAndroid does not configure the CDM's security level (that
// is, leaves it as L1); therefore only secure codecs are supported.
// TODO(ddorwin): Remove with unprefixed. http://crbug.com/249976 // TODO(ddorwin): Remove with unprefixed. http://crbug.com/249976
if (response.non_compositing_codecs != media::EME_CODEC_NONE) {
AddWidevineWithCodecs( AddWidevineWithCodecs(
WIDEVINE_HR_NON_COMPOSITING, WIDEVINE_HR_NON_COMPOSITING,
static_cast<SupportedCodecs>(response.non_compositing_codecs), response.non_compositing_codecs,
media::EME_SESSION_TYPE_NOT_SUPPORTED, // Persistent license. EmeRobustness::HW_SECURE_CRYPTO, // Max audio robustness.
media::EME_SESSION_TYPE_NOT_SUPPORTED, // Persistent release message. EmeRobustness::HW_SECURE_ALL, // Max video robustness.
media::EME_SESSION_TYPE_NOT_SUPPORTED, // persistent-license.
media::EME_SESSION_TYPE_NOT_SUPPORTED, // persistent-release-message.
media::EME_FEATURE_NOT_SUPPORTED, // Persistent state. media::EME_FEATURE_NOT_SUPPORTED, // Persistent state.
media::EME_FEATURE_ALWAYS_ENABLED, // Distinctive identifier. media::EME_FEATURE_ALWAYS_ENABLED, // Distinctive identifier.
concrete_key_systems); concrete_key_systems);
...@@ -85,6 +112,8 @@ void AddAndroidPlatformKeySystems( ...@@ -85,6 +112,8 @@ void AddAndroidPlatformKeySystems(
if (response.compositing_codecs & media::EME_CODEC_MP4_ALL) if (response.compositing_codecs & media::EME_CODEC_MP4_ALL)
info.supported_init_data_types |= media::EME_INIT_DATA_TYPE_CENC; info.supported_init_data_types |= media::EME_INIT_DATA_TYPE_CENC;
#endif // defined(USE_PROPRIETARY_CODECS) #endif // defined(USE_PROPRIETARY_CODECS)
info.max_audio_robustness = EmeRobustness::EMPTY;
info.max_video_robustness = EmeRobustness::EMPTY;
// Assume the worst case (from a user point of view). // Assume the worst case (from a user point of view).
info.persistent_license_support = media::EME_SESSION_TYPE_NOT_SUPPORTED; info.persistent_license_support = media::EME_SESSION_TYPE_NOT_SUPPORTED;
info.persistent_release_message_support = info.persistent_release_message_support =
......
...@@ -29,6 +29,8 @@ static std::string GetDirectParentName(std::string name) { ...@@ -29,6 +29,8 @@ static std::string GetDirectParentName(std::string name) {
void AddWidevineWithCodecs( void AddWidevineWithCodecs(
WidevineCdmType widevine_cdm_type, WidevineCdmType widevine_cdm_type,
SupportedCodecs supported_codecs, SupportedCodecs supported_codecs,
media::EmeRobustness max_audio_robustness,
media::EmeRobustness max_video_robustness,
media::EmeSessionTypeSupport persistent_license_support, media::EmeSessionTypeSupport persistent_license_support,
media::EmeSessionTypeSupport persistent_release_message_support, media::EmeSessionTypeSupport persistent_release_message_support,
media::EmeFeatureSupport persistent_state_support, media::EmeFeatureSupport persistent_state_support,
...@@ -66,6 +68,8 @@ void AddWidevineWithCodecs( ...@@ -66,6 +68,8 @@ void AddWidevineWithCodecs(
info.supported_init_data_types |= media::EME_INIT_DATA_TYPE_CENC; info.supported_init_data_types |= media::EME_INIT_DATA_TYPE_CENC;
#endif // defined(USE_PROPRIETARY_CODECS) #endif // defined(USE_PROPRIETARY_CODECS)
info.max_audio_robustness = max_audio_robustness;
info.max_video_robustness = max_video_robustness;
info.persistent_license_support = persistent_license_support; info.persistent_license_support = persistent_license_support;
info.persistent_release_message_support = persistent_release_message_support; info.persistent_release_message_support = persistent_release_message_support;
info.persistent_state_support = persistent_state_support; info.persistent_state_support = persistent_state_support;
......
...@@ -22,6 +22,8 @@ enum WidevineCdmType { ...@@ -22,6 +22,8 @@ enum WidevineCdmType {
void AddWidevineWithCodecs( void AddWidevineWithCodecs(
WidevineCdmType widevine_cdm_type, WidevineCdmType widevine_cdm_type,
media::SupportedCodecs supported_codecs, media::SupportedCodecs supported_codecs,
media::EmeRobustness max_audio_robustness,
media::EmeRobustness max_video_robustness,
media::EmeSessionTypeSupport persistent_license_support, media::EmeSessionTypeSupport persistent_license_support,
media::EmeSessionTypeSupport persistent_release_message_support, media::EmeSessionTypeSupport persistent_release_message_support,
media::EmeFeatureSupport persistent_state_support, media::EmeFeatureSupport persistent_state_support,
......
...@@ -27,6 +27,8 @@ class TestContentRendererClient : public ContentRendererClient { ...@@ -27,6 +27,8 @@ class TestContentRendererClient : public ContentRendererClient {
// TODO(sandersd): Was this supposed to be added to the list? // TODO(sandersd): Was this supposed to be added to the list?
media::KeySystemInfo key_system_info; media::KeySystemInfo key_system_info;
key_system_info.key_system = "test.keysystem"; key_system_info.key_system = "test.keysystem";
key_system_info.max_audio_robustness = media::EmeRobustness::EMPTY;
key_system_info.max_video_robustness = media::EmeRobustness::EMPTY;
key_system_info.persistent_license_support = key_system_info.persistent_license_support =
media::EME_SESSION_TYPE_NOT_SUPPORTED; media::EME_SESSION_TYPE_NOT_SUPPORTED;
key_system_info.persistent_release_message_support = key_system_info.persistent_release_message_support =
...@@ -40,6 +42,8 @@ class TestContentRendererClient : public ContentRendererClient { ...@@ -40,6 +42,8 @@ class TestContentRendererClient : public ContentRendererClient {
if (is_extra_key_system_enabled_) { if (is_extra_key_system_enabled_) {
media::KeySystemInfo wv_key_system_info; media::KeySystemInfo wv_key_system_info;
wv_key_system_info.key_system = kWidevineKeySystem; wv_key_system_info.key_system = kWidevineKeySystem;
wv_key_system_info.max_audio_robustness = media::EmeRobustness::EMPTY;
wv_key_system_info.max_video_robustness = media::EmeRobustness::EMPTY;
wv_key_system_info.persistent_license_support = wv_key_system_info.persistent_license_support =
media::EME_SESSION_TYPE_NOT_SUPPORTED; media::EME_SESSION_TYPE_NOT_SUPPORTED;
wv_key_system_info.persistent_release_message_support = wv_key_system_info.persistent_release_message_support =
......
...@@ -34,7 +34,7 @@ scoped_ptr<BrowserCdm> BrowserCdmFactoryAndroid::CreateBrowserCdm( ...@@ -34,7 +34,7 @@ scoped_ptr<BrowserCdm> BrowserCdmFactoryAndroid::CreateBrowserCdm(
} }
// TODO(xhwang/ddorwin): Pass the security level from key system. // TODO(xhwang/ddorwin): Pass the security level from key system.
// http://crbug.com/459400 // http://crbug.com/467779
if (key_system == kWidevineKeySystem) { if (key_system == kWidevineKeySystem) {
MediaDrmBridge::SecurityLevel security_level = MediaDrmBridge::SecurityLevel security_level =
MediaDrmBridge::SECURITY_LEVEL_3; MediaDrmBridge::SECURITY_LEVEL_3;
......
...@@ -55,32 +55,75 @@ enum EmeSessionTypeSupport { ...@@ -55,32 +55,75 @@ enum EmeSessionTypeSupport {
EME_SESSION_TYPE_INVALID, EME_SESSION_TYPE_INVALID,
// The session type is not supported. // The session type is not supported.
EME_SESSION_TYPE_NOT_SUPPORTED, EME_SESSION_TYPE_NOT_SUPPORTED,
// The session type is supported if the encrypted media permission is granted. // The session type is supported if a distinctive identifier is available.
EME_SESSION_TYPE_SUPPORTED_WITH_PERMISSION, EME_SESSION_TYPE_SUPPORTED_WITH_IDENTIFIER,
// The session type is always supported. // The session type is always supported.
EME_SESSION_TYPE_SUPPORTED, EME_SESSION_TYPE_SUPPORTED,
}; };
// Used to declare support for distinctive identifier and persistent state.
enum EmeFeatureSupport { enum EmeFeatureSupport {
// Invalid default value. // Invalid default value.
EME_FEATURE_INVALID, EME_FEATURE_INVALID,
// Access to the feature is not supported at all. // Access to the feature is not supported at all.
EME_FEATURE_NOT_SUPPORTED, EME_FEATURE_NOT_SUPPORTED,
// Access to the feature may be requested if the encrypted media permission is // Access to the feature may be requested if a distinctive identifier is
// granted. // available. (This is the correct choice for declaring support for a
EME_FEATURE_REQUESTABLE_WITH_PERMISSION, // requestable distinctive identifier.)
EME_FEATURE_REQUESTABLE_WITH_IDENTIFIER,
// Access to the feature may be requested. // Access to the feature may be requested.
EME_FEATURE_REQUESTABLE, EME_FEATURE_REQUESTABLE,
// Access to the feature cannot be blocked. // Access to the feature cannot be blocked.
EME_FEATURE_ALWAYS_ENABLED, EME_FEATURE_ALWAYS_ENABLED,
}; };
// Used to query support for distinctive identifier and persistent state.
enum EmeFeatureRequirement { enum EmeFeatureRequirement {
EME_FEATURE_NOT_ALLOWED, EME_FEATURE_NOT_ALLOWED,
EME_FEATURE_OPTIONAL, EME_FEATURE_OPTIONAL,
EME_FEATURE_REQUIRED, EME_FEATURE_REQUIRED,
}; };
enum class EmeMediaType {
AUDIO,
VIDEO,
};
// Robustness values understood by KeySystems.
// Note: KeySystems expects this ordering (in GetRobustnessConfigRule()),
// changes may be required there if this list changes.
enum class EmeRobustness {
INVALID,
EMPTY,
SW_SECURE_CRYPTO,
SW_SECURE_DECODE,
HW_SECURE_CRYPTO,
HW_SECURE_DECODE,
HW_SECURE_ALL,
};
// Configuration rules indicate the configuration state required to support a
// configuration option (note: a configuration option may be disallowing a
// feature). Configuration rules are used to answer queries about distinctive
// identifier, persistent state, and robustness requirements, as well as to
// describe support for different session types.
//
// If in the future there are reasons to request user permission other than
// access to a distinctive identifier, then additional rules should be added.
// Rules are implemented in ConfigState and are otherwise opaque.
enum class EmeConfigRule {
// The configuration option is not supported.
NOT_SUPPORTED,
// The configuration option is supported if a distinctive identifier is
// available.
IDENTIFIER_REQUIRED,
// The configuration option is supported, but the user experience may be
// improved if a distinctive identifier is available.
IDENTIFIER_RECOMMENDED,
// The configuration option is supported without conditions.
SUPPORTED,
};
} // namespace media } // namespace media
#endif // MEDIA_BASE_EME_CONSTANTS_H_ #endif // MEDIA_BASE_EME_CONSTANTS_H_
...@@ -9,6 +9,8 @@ namespace media { ...@@ -9,6 +9,8 @@ namespace media {
KeySystemInfo::KeySystemInfo() KeySystemInfo::KeySystemInfo()
: supported_init_data_types(EME_INIT_DATA_TYPE_NONE), : supported_init_data_types(EME_INIT_DATA_TYPE_NONE),
supported_codecs(EME_CODEC_NONE), supported_codecs(EME_CODEC_NONE),
max_audio_robustness(EmeRobustness::INVALID),
max_video_robustness(EmeRobustness::INVALID),
persistent_license_support(EME_SESSION_TYPE_INVALID), persistent_license_support(EME_SESSION_TYPE_INVALID),
persistent_release_message_support(EME_SESSION_TYPE_INVALID), persistent_release_message_support(EME_SESSION_TYPE_INVALID),
persistent_state_support(EME_FEATURE_INVALID), persistent_state_support(EME_FEATURE_INVALID),
......
...@@ -35,13 +35,10 @@ struct MEDIA_EXPORT KeySystemInfo { ...@@ -35,13 +35,10 @@ struct MEDIA_EXPORT KeySystemInfo {
std::string key_system; std::string key_system;
// Specifies registered initialization data types supported by |key_system|.
SupportedInitDataTypes supported_init_data_types; SupportedInitDataTypes supported_init_data_types;
// Specifies codecs supported by |key_system|.
SupportedCodecs supported_codecs; SupportedCodecs supported_codecs;
EmeRobustness max_audio_robustness;
// Specifies session types and features supported by |key_system|. EmeRobustness max_video_robustness;
EmeSessionTypeSupport persistent_license_support; EmeSessionTypeSupport persistent_license_support;
EmeSessionTypeSupport persistent_release_message_support; EmeSessionTypeSupport persistent_release_message_support;
EmeFeatureSupport persistent_state_support; EmeFeatureSupport persistent_state_support;
......
...@@ -76,6 +76,39 @@ static NamedCodec kCodecStrings[] = { ...@@ -76,6 +76,39 @@ static NamedCodec kCodecStrings[] = {
#endif // defined(USE_PROPRIETARY_CODECS) #endif // defined(USE_PROPRIETARY_CODECS)
}; };
static EmeConfigRule ConvertSessionTypeSupport(
EmeSessionTypeSupport support) {
switch (support) {
case EME_SESSION_TYPE_INVALID:
NOTREACHED();
return EmeConfigRule::NOT_SUPPORTED;
case EME_SESSION_TYPE_NOT_SUPPORTED:
return EmeConfigRule::NOT_SUPPORTED;
case EME_SESSION_TYPE_SUPPORTED_WITH_IDENTIFIER:
return EmeConfigRule::IDENTIFIER_REQUIRED;
case EME_SESSION_TYPE_SUPPORTED:
return EmeConfigRule::SUPPORTED;
}
NOTREACHED();
return EmeConfigRule::NOT_SUPPORTED;
}
static EmeRobustness ConvertRobustness(const std::string& robustness) {
if (robustness.empty())
return EmeRobustness::EMPTY;
if (robustness == "SW_SECURE_CRYPTO")
return EmeRobustness::SW_SECURE_CRYPTO;
if (robustness == "SW_SECURE_DECODE")
return EmeRobustness::SW_SECURE_DECODE;
if (robustness == "HW_SECURE_CRYPTO")
return EmeRobustness::HW_SECURE_CRYPTO;
if (robustness == "HW_SECURE_DECODE")
return EmeRobustness::HW_SECURE_DECODE;
if (robustness == "HW_SECURE_ALL")
return EmeRobustness::HW_SECURE_ALL;
return EmeRobustness::INVALID;
}
static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) { static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) {
KeySystemInfo info; KeySystemInfo info;
info.key_system = kClearKeyKeySystem; info.key_system = kClearKeyKeySystem;
...@@ -103,6 +136,8 @@ static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) { ...@@ -103,6 +136,8 @@ static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) {
info.supported_codecs |= EME_CODEC_MP4_ALL; info.supported_codecs |= EME_CODEC_MP4_ALL;
#endif // defined(USE_PROPRIETARY_CODECS) #endif // defined(USE_PROPRIETARY_CODECS)
info.max_audio_robustness = EmeRobustness::EMPTY;
info.max_video_robustness = EmeRobustness::EMPTY;
info.persistent_license_support = EME_SESSION_TYPE_NOT_SUPPORTED; info.persistent_license_support = EME_SESSION_TYPE_NOT_SUPPORTED;
info.persistent_release_message_support = EME_SESSION_TYPE_NOT_SUPPORTED; info.persistent_release_message_support = EME_SESSION_TYPE_NOT_SUPPORTED;
info.persistent_state_support = EME_FEATURE_NOT_SUPPORTED; info.persistent_state_support = EME_FEATURE_NOT_SUPPORTED;
...@@ -191,23 +226,24 @@ class KeySystems { ...@@ -191,23 +226,24 @@ class KeySystems {
std::string GetPepperType(const std::string& concrete_key_system); std::string GetPepperType(const std::string& concrete_key_system);
#endif #endif
bool IsPersistentLicenseSessionSupported( EmeConfigRule GetRobustnessConfigRule(
const std::string& key_system, const std::string& key_system,
bool is_permission_granted); EmeMediaType media_type,
const std::string& requested_robustness);
bool IsPersistentReleaseMessageSessionSupported( EmeConfigRule GetPersistentLicenseSessionConfigRule(
const std::string& key_system, const std::string& key_system);
bool is_permission_granted);
EmeConfigRule GetPersistentReleaseMessageSessionConfigRule(
const std::string& key_system);
bool IsPersistentStateRequirementSupported( EmeConfigRule GetPersistentStateConfigRule(
const std::string& key_system, const std::string& key_system,
EmeFeatureRequirement requirement, EmeFeatureRequirement requirement);
bool is_permission_granted);
bool IsDistinctiveIdentifierRequirementSupported( EmeConfigRule GetDistinctiveIdentifierConfigRule(
const std::string& key_system, const std::string& key_system,
EmeFeatureRequirement requirement, EmeFeatureRequirement requirement);
bool is_permission_granted);
void AddContainerMask(const std::string& container, uint32 mask); void AddContainerMask(const std::string& container, uint32 mask);
void AddCodecMask(const std::string& codec, uint32 mask); void AddCodecMask(const std::string& codec, uint32 mask);
...@@ -394,45 +430,71 @@ void KeySystems::AddConcreteSupportedKeySystems( ...@@ -394,45 +430,71 @@ void KeySystems::AddConcreteSupportedKeySystems(
for (const KeySystemInfo& info : concrete_key_systems) { for (const KeySystemInfo& info : concrete_key_systems) {
DCHECK(!info.key_system.empty()); DCHECK(!info.key_system.empty());
DCHECK_NE(info.persistent_license_support, EME_SESSION_TYPE_INVALID); DCHECK(info.max_audio_robustness != EmeRobustness::INVALID);
DCHECK_NE(info.persistent_release_message_support, DCHECK(info.max_video_robustness != EmeRobustness::INVALID);
EME_SESSION_TYPE_INVALID); DCHECK(info.persistent_license_support != EME_SESSION_TYPE_INVALID);
// TODO(sandersd): Add REQUESTABLE and REQUESTABLE_WITH_PERMISSION for DCHECK(info.persistent_release_message_support != EME_SESSION_TYPE_INVALID);
// persistent_state_support once we can block access per-CDM-instance DCHECK(info.persistent_state_support != EME_FEATURE_INVALID);
// (http://crbug.com/457482). DCHECK(info.distinctive_identifier_support != EME_FEATURE_INVALID);
DCHECK(info.persistent_state_support == EME_FEATURE_NOT_SUPPORTED ||
info.persistent_state_support == EME_FEATURE_ALWAYS_ENABLED); // Supporting persistent state is a prerequsite for supporting persistent
// TODO(sandersd): Allow REQUESTABLE_WITH_PERMISSION for all key systems on // sessions.
// all platforms once we have proper enforcement (http://crbug.com/457482).
// On Chrome OS, an ID will not be used without permission, but we cannot
// currently prevent the CDM from requesting the permission again when no
// there was no initial prompt. Thus, we block "not-allowed" below.
#if defined(OS_CHROMEOS)
DCHECK(info.distinctive_identifier_support == EME_FEATURE_NOT_SUPPORTED ||
(info.distinctive_identifier_support ==
EME_FEATURE_REQUESTABLE_WITH_PERMISSION &&
info.key_system == kWidevineKeySystem) ||
info.distinctive_identifier_support == EME_FEATURE_ALWAYS_ENABLED);
#else
DCHECK(info.distinctive_identifier_support == EME_FEATURE_NOT_SUPPORTED ||
info.distinctive_identifier_support == EME_FEATURE_ALWAYS_ENABLED);
#endif
if (info.persistent_state_support == EME_FEATURE_NOT_SUPPORTED) { if (info.persistent_state_support == EME_FEATURE_NOT_SUPPORTED) {
DCHECK_EQ(info.persistent_license_support, DCHECK(info.persistent_license_support == EME_SESSION_TYPE_NOT_SUPPORTED);
DCHECK(info.persistent_release_message_support ==
EME_SESSION_TYPE_NOT_SUPPORTED); EME_SESSION_TYPE_NOT_SUPPORTED);
DCHECK_EQ(info.persistent_release_message_support, }
else if (info.persistent_state_support ==
EME_FEATURE_REQUESTABLE_WITH_IDENTIFIER) {
// Must be either NOT_SUPPORTED or SUPPORTED_WITH_IDENTIFIER.
DCHECK(info.persistent_license_support != EME_SESSION_TYPE_SUPPORTED);
DCHECK(info.persistent_release_message_support !=
EME_SESSION_TYPE_SUPPORTED);
}
// persistent-release-message sessions are not currently supported.
// http://crbug.com/448888
DCHECK(info.persistent_release_message_support ==
EME_SESSION_TYPE_NOT_SUPPORTED); EME_SESSION_TYPE_NOT_SUPPORTED);
// Because an optional persistent state value is resolved after an optional
// distinctive identifier, persistent state requiring a distinctive
// identifier may not resolve correctly.
DCHECK(info.persistent_state_support !=
EME_FEATURE_REQUESTABLE_WITH_IDENTIFIER);
// If supported, distinctive identifiers always require permission.
DCHECK(info.distinctive_identifier_support != EME_FEATURE_REQUESTABLE);
// If distinctive identifiers are not supported, then no other features can
// require them.
if (info.distinctive_identifier_support == EME_FEATURE_NOT_SUPPORTED) {
DCHECK(info.persistent_license_support !=
EME_SESSION_TYPE_SUPPORTED_WITH_IDENTIFIER);
DCHECK(info.persistent_release_message_support !=
EME_SESSION_TYPE_SUPPORTED_WITH_IDENTIFIER);
} }
DCHECK(!IsSupportedKeySystem(info.key_system))
<< "Key system '" << info.key_system << "' already registered"; // Distinctive identifiers and persistent state can only be reliably blocked
DCHECK(!parent_key_system_map_.count(info.key_system)) // (and therefore be safely configurable) for Pepper-hosted key systems. For
<< "'" << info.key_system << "' is already registered as a parent"; // other platforms, only non-configurable values are valid.
bool can_block = false;
#if defined(ENABLE_PEPPER_CDMS) #if defined(ENABLE_PEPPER_CDMS)
DCHECK_EQ(info.use_aes_decryptor, info.pepper_type.empty()); DCHECK_EQ(info.use_aes_decryptor, info.pepper_type.empty());
can_block = !info.pepper_type.empty();
#endif #endif
if (!can_block) {
DCHECK(info.distinctive_identifier_support == EME_FEATURE_NOT_SUPPORTED ||
info.distinctive_identifier_support == EME_FEATURE_ALWAYS_ENABLED);
DCHECK(info.persistent_state_support == EME_FEATURE_NOT_SUPPORTED ||
info.persistent_state_support == EME_FEATURE_ALWAYS_ENABLED);
}
DCHECK(!IsSupportedKeySystem(info.key_system))
<< "Key system '" << info.key_system << "' already registered";
DCHECK(!parent_key_system_map_.count(info.key_system))
<< "'" << info.key_system << "' is already registered as a parent";
concrete_key_system_map_[info.key_system] = info; concrete_key_system_map_[info.key_system] = info;
if (!info.parent_key_system.empty()) { if (!info.parent_key_system.empty()) {
DCHECK(!IsConcreteSupportedKeySystem(info.parent_key_system)) DCHECK(!IsConcreteSupportedKeySystem(info.parent_key_system))
<< "Parent '" << info.parent_key_system << "' " << "Parent '" << info.parent_key_system << "' "
...@@ -620,132 +682,172 @@ std::string KeySystems::GetPepperType(const std::string& concrete_key_system) { ...@@ -620,132 +682,172 @@ std::string KeySystems::GetPepperType(const std::string& concrete_key_system) {
} }
#endif #endif
bool KeySystems::IsPersistentLicenseSessionSupported( EmeConfigRule KeySystems::GetRobustnessConfigRule(
const std::string& key_system, const std::string& key_system,
bool is_permission_granted) { EmeMediaType media_type,
const std::string& requested_robustness) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
EmeRobustness robustness = ConvertRobustness(requested_robustness);
if (robustness == EmeRobustness::INVALID)
return EmeConfigRule::NOT_SUPPORTED;
if (robustness == EmeRobustness::EMPTY)
return EmeConfigRule::SUPPORTED;
KeySystemInfoMap::const_iterator key_system_iter = KeySystemInfoMap::const_iterator key_system_iter =
concrete_key_system_map_.find(key_system); concrete_key_system_map_.find(key_system);
if (key_system_iter == concrete_key_system_map_.end()) { if (key_system_iter == concrete_key_system_map_.end()) {
NOTREACHED(); NOTREACHED();
return false; return EmeConfigRule::NOT_SUPPORTED;
} }
switch (key_system_iter->second.persistent_license_support) { EmeRobustness max_robustness = EmeRobustness::INVALID;
case EME_SESSION_TYPE_INVALID: switch (media_type) {
NOTREACHED(); case EmeMediaType::AUDIO:
return false; max_robustness = key_system_iter->second.max_audio_robustness;
case EME_SESSION_TYPE_NOT_SUPPORTED: break;
return false; case EmeMediaType::VIDEO:
case EME_SESSION_TYPE_SUPPORTED_WITH_PERMISSION: max_robustness = key_system_iter->second.max_video_robustness;
return is_permission_granted; break;
case EME_SESSION_TYPE_SUPPORTED:
return true;
} }
NOTREACHED(); // We can compare robustness levels whenever they are not HW_SECURE_CRYPTO
return false; // and SW_SECURE_DECODE in some order. If they are exactly those two then the
// robustness requirement is not supported.
if ((max_robustness == EmeRobustness::HW_SECURE_CRYPTO &&
robustness == EmeRobustness::SW_SECURE_DECODE) ||
(max_robustness == EmeRobustness::SW_SECURE_DECODE &&
robustness == EmeRobustness::HW_SECURE_CRYPTO) ||
robustness > max_robustness) {
return EmeConfigRule::NOT_SUPPORTED;
}
#if defined(OS_CHROMEOS)
if (key_system == kWidevineKeySystem) {
// Hardware security requires remote attestation.
if (robustness >= EmeRobustness::HW_SECURE_CRYPTO)
return EmeConfigRule::IDENTIFIER_REQUIRED;
// For video, recommend remote attestation if HW_SECURE_ALL is available,
// because it enables hardware accelerated decoding.
// TODO(sandersd): Only do this when hardware accelerated decoding is
// available for the requested codecs.
if (media_type == EmeMediaType::VIDEO &&
max_robustness == EmeRobustness::HW_SECURE_ALL) {
return EmeConfigRule::IDENTIFIER_RECOMMENDED;
}
}
#endif // defined(OS_CHROMEOS)
return EmeConfigRule::SUPPORTED;
} }
bool KeySystems::IsPersistentReleaseMessageSessionSupported( EmeConfigRule KeySystems::GetPersistentLicenseSessionConfigRule(
const std::string& key_system, const std::string& key_system) {
bool is_permission_granted) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
KeySystemInfoMap::const_iterator key_system_iter = KeySystemInfoMap::const_iterator key_system_iter =
concrete_key_system_map_.find(key_system); concrete_key_system_map_.find(key_system);
if (key_system_iter == concrete_key_system_map_.end()) { if (key_system_iter == concrete_key_system_map_.end()) {
NOTREACHED(); NOTREACHED();
return false; return EmeConfigRule::NOT_SUPPORTED;
} }
return ConvertSessionTypeSupport(
key_system_iter->second.persistent_license_support);
}
switch (key_system_iter->second.persistent_release_message_support) { EmeConfigRule KeySystems::GetPersistentReleaseMessageSessionConfigRule(
case EME_SESSION_TYPE_INVALID: const std::string& key_system) {
NOTREACHED(); DCHECK(thread_checker_.CalledOnValidThread());
return false;
case EME_SESSION_TYPE_NOT_SUPPORTED:
return false;
case EME_SESSION_TYPE_SUPPORTED_WITH_PERMISSION:
return is_permission_granted;
case EME_SESSION_TYPE_SUPPORTED:
return true;
}
KeySystemInfoMap::const_iterator key_system_iter =
concrete_key_system_map_.find(key_system);
if (key_system_iter == concrete_key_system_map_.end()) {
NOTREACHED(); NOTREACHED();
return false; return EmeConfigRule::NOT_SUPPORTED;
}
return ConvertSessionTypeSupport(
key_system_iter->second.persistent_release_message_support);
} }
bool KeySystems::IsPersistentStateRequirementSupported( EmeConfigRule KeySystems::GetPersistentStateConfigRule(
const std::string& key_system, const std::string& key_system,
EmeFeatureRequirement requirement, EmeFeatureRequirement requirement) {
bool is_permission_granted) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
KeySystemInfoMap::const_iterator key_system_iter = KeySystemInfoMap::const_iterator key_system_iter =
concrete_key_system_map_.find(key_system); concrete_key_system_map_.find(key_system);
if (key_system_iter == concrete_key_system_map_.end()) { if (key_system_iter == concrete_key_system_map_.end()) {
NOTREACHED(); NOTREACHED();
return false; return EmeConfigRule::NOT_SUPPORTED;
} }
switch (key_system_iter->second.persistent_state_support) { // For NOT_ALLOWED and REQUIRED, the result is as expected. For OPTIONAL, we
case EME_FEATURE_INVALID: // return the least restrictive of the two rules; this guarantees that if
NOTREACHED(); // OPTIONAL is accepted, then it can always be resolved to some value. (In
return false; // fact OPTIONAL is always accepted, because the least restrictive rule is
case EME_FEATURE_NOT_SUPPORTED: // always SUPPORTED.)
return requirement != EME_FEATURE_REQUIRED; //
case EME_FEATURE_REQUESTABLE_WITH_PERMISSION: // Note that even if permission is not required for persistent state, it may
return (requirement != EME_FEATURE_REQUIRED) || is_permission_granted; // be required for specific persistent session types.
case EME_FEATURE_REQUESTABLE: //
return true; // NOT_ALLOWED OPTIONAL REQUIRED
case EME_FEATURE_ALWAYS_ENABLED: // NOT_SUPPORTED SUPPORTED SUPPORTED NOT_SUPPORTED
// Persistent state does not require user permission, but the session // REQUESTABLE_WITH_IDENTIFIER SUPPORTED SUPPORTED IDENTIFIER_REQ
// types that use it might. // REQUESTABLE SUPPORTED SUPPORTED SUPPORTED
return requirement != EME_FEATURE_NOT_ALLOWED; // ALWAYS_ENABLED NOT_SUPPORTED SUPPORTED SUPPORTED
EmeFeatureSupport support = key_system_iter->second.persistent_state_support;
if (support == EME_FEATURE_NOT_SUPPORTED &&
requirement == EME_FEATURE_REQUIRED) {
return EmeConfigRule::NOT_SUPPORTED;
} }
if (support == EME_FEATURE_ALWAYS_ENABLED &&
NOTREACHED(); requirement == EME_FEATURE_NOT_ALLOWED) {
return false; return EmeConfigRule::NOT_SUPPORTED;
}
if (support == EME_FEATURE_REQUESTABLE_WITH_IDENTIFIER &&
requirement == EME_FEATURE_REQUIRED) {
return EmeConfigRule::IDENTIFIER_REQUIRED;
}
return EmeConfigRule::SUPPORTED;
} }
bool KeySystems::IsDistinctiveIdentifierRequirementSupported( EmeConfigRule KeySystems::GetDistinctiveIdentifierConfigRule(
const std::string& key_system, const std::string& key_system,
EmeFeatureRequirement requirement, EmeFeatureRequirement requirement) {
bool is_permission_granted) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
KeySystemInfoMap::const_iterator key_system_iter = KeySystemInfoMap::const_iterator key_system_iter =
concrete_key_system_map_.find(key_system); concrete_key_system_map_.find(key_system);
if (key_system_iter == concrete_key_system_map_.end()) { if (key_system_iter == concrete_key_system_map_.end()) {
NOTREACHED(); NOTREACHED();
return false; return EmeConfigRule::NOT_SUPPORTED;
} }
switch (key_system_iter->second.distinctive_identifier_support) { // Permission is required for REQUIRED, but not for NOT_ALLOWED. For OPTIONAL,
case EME_FEATURE_INVALID: // we return the least restrictive of the two rules; this guarantees that if
NOTREACHED(); // OPTIONAL is accepted, then it can always be resolved to some value.
return false; //
case EME_FEATURE_NOT_SUPPORTED: // NOT_ALLOWED OPTIONAL REQUIRED
return requirement != EME_FEATURE_REQUIRED; // NOT_SUPPORTED SUPPORTED SUPPORTED NOT_SUPPORTED
case EME_FEATURE_REQUESTABLE_WITH_PERMISSION: // REQUESTABLE_WITH_IDENTIFIER SUPPORTED SUPPORTED IDENTIFIER_REQ
// TODO(sandersd): Remove this hack once crbug.com/457482 and // ALWAYS_ENABLED NOT_SUPPORTED IDENTIFIER_REQ IDENTIFIER_REQ
// crbug.com/460616 are addressed. EmeFeatureSupport support =
// We cannot currently enforce "not-allowed", so don't allow it. key_system_iter->second.distinctive_identifier_support;
// Note: Removing this check will expose crbug.com/460616. DCHECK(support != EME_FEATURE_REQUESTABLE);
if (requirement == EME_FEATURE_NOT_ALLOWED) if (support == EME_FEATURE_NOT_SUPPORTED &&
return false; requirement == EME_FEATURE_REQUIRED) {
return (requirement != EME_FEATURE_REQUIRED) || is_permission_granted; return EmeConfigRule::NOT_SUPPORTED;
case EME_FEATURE_REQUESTABLE:
NOTREACHED();
return true;
case EME_FEATURE_ALWAYS_ENABLED:
// Distinctive identifiers always require user permission.
return (requirement != EME_FEATURE_NOT_ALLOWED) && is_permission_granted;
} }
if (support == EME_FEATURE_ALWAYS_ENABLED &&
NOTREACHED(); requirement == EME_FEATURE_NOT_ALLOWED) {
return false; return EmeConfigRule::NOT_SUPPORTED;
}
if (support == EME_FEATURE_ALWAYS_ENABLED ||
requirement == EME_FEATURE_REQUIRED) {
return EmeConfigRule::IDENTIFIER_REQUIRED;
}
return EmeConfigRule::SUPPORTED;
} }
void KeySystems::AddContainerMask(const std::string& container, uint32 mask) { void KeySystems::AddContainerMask(const std::string& container, uint32 mask) {
...@@ -850,34 +952,38 @@ std::string GetPepperType(const std::string& concrete_key_system) { ...@@ -850,34 +952,38 @@ std::string GetPepperType(const std::string& concrete_key_system) {
} }
#endif #endif
bool IsPersistentLicenseSessionSupported( EmeConfigRule GetRobustnessConfigRule(
const std::string& key_system, const std::string& key_system,
bool is_permission_granted) { EmeMediaType media_type,
return KeySystems::GetInstance().IsPersistentLicenseSessionSupported( const std::string& robustness) {
key_system, is_permission_granted); return KeySystems::GetInstance().GetRobustnessConfigRule(
key_system, media_type, robustness);
} }
bool IsPersistentReleaseMessageSessionSupported( EmeConfigRule GetPersistentLicenseSessionConfigRule(
const std::string& key_system, const std::string& key_system) {
bool is_permission_granted) { return KeySystems::GetInstance().GetPersistentLicenseSessionConfigRule(
return KeySystems::GetInstance().IsPersistentReleaseMessageSessionSupported( key_system);
key_system, is_permission_granted); }
EmeConfigRule GetPersistentReleaseMessageSessionConfigRule(
const std::string& key_system) {
return KeySystems::GetInstance().GetPersistentReleaseMessageSessionConfigRule(
key_system);
} }
bool IsPersistentStateRequirementSupported( EmeConfigRule GetPersistentStateConfigRule(
const std::string& key_system, const std::string& key_system,
EmeFeatureRequirement requirement, EmeFeatureRequirement requirement) {
bool is_permission_granted) { return KeySystems::GetInstance().GetPersistentStateConfigRule(
return KeySystems::GetInstance().IsPersistentStateRequirementSupported( key_system, requirement);
key_system, requirement, is_permission_granted);
} }
bool IsDistinctiveIdentifierRequirementSupported( EmeConfigRule GetDistinctiveIdentifierConfigRule(
const std::string& key_system, const std::string& key_system,
EmeFeatureRequirement requirement, EmeFeatureRequirement requirement) {
bool is_permission_granted) { return KeySystems::GetInstance().GetDistinctiveIdentifierConfigRule(
return KeySystems::GetInstance().IsDistinctiveIdentifierRequirementSupported( key_system, requirement);
key_system, requirement, is_permission_granted);
} }
// These two functions are for testing purpose only. The declaration in the // These two functions are for testing purpose only. The declaration in the
......
...@@ -85,27 +85,32 @@ MEDIA_EXPORT std::string GetPepperType( ...@@ -85,27 +85,32 @@ MEDIA_EXPORT std::string GetPepperType(
const std::string& concrete_key_system); const std::string& concrete_key_system);
#endif #endif
// Returns whether |key_system| supports persistent-license sessions. // Returns the configuration rule for supporting a robustness requirement.
MEDIA_EXPORT bool IsPersistentLicenseSessionSupported( // TODO(sandersd): Also take a list of codecs, as they may affect the result.
MEDIA_EXPORT EmeConfigRule GetRobustnessConfigRule(
const std::string& key_system, const std::string& key_system,
bool is_permission_granted); EmeMediaType media_type,
const std::string& requested_robustness);
// Returns whether |key_system| supports persistent-release-message sessions. // Returns the configuration rule for supporting persistent-license sessions.
MEDIA_EXPORT bool IsPersistentReleaseMessageSessionSupported( MEDIA_EXPORT EmeConfigRule GetPersistentLicenseSessionConfigRule(
const std::string& key_system, const std::string& key_system);
bool is_permission_granted);
// Returns the configuration rule for supporting persistent-release-message
// sessions.
MEDIA_EXPORT EmeConfigRule GetPersistentReleaseMessageSessionConfigRule(
const std::string& key_system);
// Returns whether |key_system| supports persistent state as requested. // Returns the configuration rule for supporting a persistent state requirement.
MEDIA_EXPORT bool IsPersistentStateRequirementSupported( MEDIA_EXPORT EmeConfigRule GetPersistentStateConfigRule(
const std::string& key_system, const std::string& key_system,
EmeFeatureRequirement requirement, EmeFeatureRequirement requirement);
bool is_permission_granted);
// Returns whether |key_system| supports distinctive identifiers as requested. // Returns the configuration rule for supporting a distinctive identifier
MEDIA_EXPORT bool IsDistinctiveIdentifierRequirementSupported( // requirement.
MEDIA_EXPORT EmeConfigRule GetDistinctiveIdentifierConfigRule(
const std::string& key_system, const std::string& key_system,
EmeFeatureRequirement requirement, EmeFeatureRequirement requirement);
bool is_permission_granted);
#if defined(UNIT_TEST) #if defined(UNIT_TEST)
// Helper functions to add container/codec types for testing purposes. // Helper functions to add container/codec types for testing purposes.
......
...@@ -166,6 +166,8 @@ void TestMediaClient::AddUsesAesKeySystem( ...@@ -166,6 +166,8 @@ void TestMediaClient::AddUsesAesKeySystem(
system.supported_codecs = EME_CODEC_WEBM_ALL; system.supported_codecs = EME_CODEC_WEBM_ALL;
system.supported_codecs |= TEST_CODEC_FOO_ALL; system.supported_codecs |= TEST_CODEC_FOO_ALL;
system.supported_init_data_types = EME_INIT_DATA_TYPE_WEBM; system.supported_init_data_types = EME_INIT_DATA_TYPE_WEBM;
system.max_audio_robustness = EmeRobustness::EMPTY;
system.max_video_robustness = EmeRobustness::EMPTY;
system.persistent_license_support = EME_SESSION_TYPE_NOT_SUPPORTED; system.persistent_license_support = EME_SESSION_TYPE_NOT_SUPPORTED;
system.persistent_release_message_support = EME_SESSION_TYPE_NOT_SUPPORTED; system.persistent_release_message_support = EME_SESSION_TYPE_NOT_SUPPORTED;
system.persistent_state_support = EME_FEATURE_NOT_SUPPORTED; system.persistent_state_support = EME_FEATURE_NOT_SUPPORTED;
...@@ -181,6 +183,8 @@ void TestMediaClient::AddExternalKeySystem( ...@@ -181,6 +183,8 @@ void TestMediaClient::AddExternalKeySystem(
ext.supported_codecs = EME_CODEC_WEBM_ALL; ext.supported_codecs = EME_CODEC_WEBM_ALL;
ext.supported_codecs |= TEST_CODEC_FOO_ALL; ext.supported_codecs |= TEST_CODEC_FOO_ALL;
ext.supported_init_data_types = EME_INIT_DATA_TYPE_WEBM; ext.supported_init_data_types = EME_INIT_DATA_TYPE_WEBM;
ext.max_audio_robustness = EmeRobustness::EMPTY;
ext.max_video_robustness = EmeRobustness::EMPTY;
ext.persistent_license_support = EME_SESSION_TYPE_SUPPORTED; ext.persistent_license_support = EME_SESSION_TYPE_SUPPORTED;
ext.persistent_release_message_support = EME_SESSION_TYPE_NOT_SUPPORTED; ext.persistent_release_message_support = EME_SESSION_TYPE_NOT_SUPPORTED;
ext.persistent_state_support = EME_FEATURE_ALWAYS_ENABLED; ext.persistent_state_support = EME_FEATURE_ALWAYS_ENABLED;
......
...@@ -31,6 +31,101 @@ enum ConfigurationSupport { ...@@ -31,6 +31,101 @@ enum ConfigurationSupport {
CONFIGURATION_SUPPORTED, CONFIGURATION_SUPPORTED,
}; };
// Accumulates configuration rules to determine if a feature (additional
// configuration rule) can be added to an accumulated configuration.
class ConfigState {
public:
ConfigState(bool was_permission_requested, bool is_permission_granted)
: was_permission_requested_(was_permission_requested),
is_permission_granted_(is_permission_granted),
is_identifier_required_(false),
is_identifier_recommended_(false){
}
bool IsPermissionGranted() const {
return is_permission_granted_;
}
// Permission is possible if it has not been denied.
bool IsPermissionPossible() const {
return is_permission_granted_ || !was_permission_requested_;
}
bool IsIdentifierRequired() const {
return is_identifier_required_;
}
bool IsIdentifierRecommended() const {
return is_identifier_recommended_;
}
// Checks whether a rule is compatible with all previously added rules.
bool IsRuleSupported(EmeConfigRule rule) const {
switch (rule) {
case EmeConfigRule::NOT_SUPPORTED:
return false;
case EmeConfigRule::IDENTIFIER_REQUIRED:
return IsPermissionPossible();
case EmeConfigRule::IDENTIFIER_RECOMMENDED:
return true;
case EmeConfigRule::SUPPORTED:
return true;
}
NOTREACHED();
return false;
}
// Checks whether a rule is compatible with all previously added rules, and
// can be accepted without needing to add it to the configuration state. This
// allows considering more rules after the configuration state is final (that
// is, after distinctiveIdentifier has been resolved).
bool IsRuleSupportedWithCurrentState(EmeConfigRule rule) const {
switch (rule) {
case EmeConfigRule::NOT_SUPPORTED:
return false;
case EmeConfigRule::IDENTIFIER_REQUIRED:
return is_permission_granted_;
case EmeConfigRule::IDENTIFIER_RECOMMENDED:
return true;
case EmeConfigRule::SUPPORTED:
return true;
}
NOTREACHED();
return false;
}
// Add a rule to the accumulated configuration state.
void AddRule(EmeConfigRule rule) {
switch (rule) {
case EmeConfigRule::NOT_SUPPORTED:
return;
case EmeConfigRule::IDENTIFIER_REQUIRED:
is_identifier_required_ = true;
return;
case EmeConfigRule::IDENTIFIER_RECOMMENDED:
is_identifier_recommended_ = true;
return;
case EmeConfigRule::SUPPORTED:
return;
}
NOTREACHED();
}
private:
// Whether permission to use a distinctive identifier was requested. If set,
// |is_permission_granted_| represents the final decision.
const bool was_permission_requested_;
// Whether permission to use a distinctive identifier has been granted.
const bool is_permission_granted_;
// Whether a rule has been added that requires a distinctive identifier.
bool is_identifier_required_;
// Whether a rule has been added that recommends a distinctive identifier.
bool is_identifier_recommended_;
};
static bool IsSupportedContentType(const std::string& key_system, static bool IsSupportedContentType(const std::string& key_system,
const std::string& mime_type, const std::string& mime_type,
const std::string& codecs) { const std::string& codecs) {
...@@ -65,23 +160,31 @@ static bool IsSupportedContentType(const std::string& key_system, ...@@ -65,23 +160,31 @@ static bool IsSupportedContentType(const std::string& key_system,
static bool GetSupportedCapabilities( static bool GetSupportedCapabilities(
const std::string& key_system, const std::string& key_system,
const blink::WebVector<blink::WebMediaKeySystemMediaCapability>& const blink::WebVector<blink::WebMediaKeySystemMediaCapability>&
capabilities, requested_media_capabilities,
EmeMediaType media_type,
std::vector<blink::WebMediaKeySystemMediaCapability>* std::vector<blink::WebMediaKeySystemMediaCapability>*
media_type_capabilities) { supported_media_capabilities,
ConfigState* config_state) {
// From // From
// https://w3c.github.io/encrypted-media/#get-supported-capabilities-for-media-type // https://w3c.github.io/encrypted-media/#get-supported-capabilities-for-media-type
// 1. Let accumulated capabilities be partial configuration. // 1. Let local accumulated capabilities be a local copy of partial
// (Skipped as there are no configuration-based codec restrictions.) // configuration.
// 2. Let media type capabilities be empty. // (Skipped as we directly update |config_state|. This is safe because we
DCHECK_EQ(media_type_capabilities->size(), 0ul); // only do so when at least one requested media capability is supported.)
// 3. For each value in capabilities: // 2. Let supported media capabilities be empty.
for (size_t i = 0; i < capabilities.size(); i++) { DCHECK_EQ(supported_media_capabilities->size(), 0ul);
// 3. For each value in requested media capabilities:
for (size_t i = 0; i < requested_media_capabilities.size(); i++) {
// 3.1. Let contentType be the value's contentType member. // 3.1. Let contentType be the value's contentType member.
// 3.2. Let robustness be the value's robustness member. // 3.2. Let robustness be the value's robustness member.
const blink::WebMediaKeySystemMediaCapability& capability = capabilities[i]; const blink::WebMediaKeySystemMediaCapability& capability =
requested_media_capabilities[i];
// 3.3. If contentType is the empty string, return null. // 3.3. If contentType is the empty string, return null.
if (capability.mimeType.isEmpty()) if (capability.mimeType.isEmpty()) {
DVLOG(2) << "Rejecting requested configuration because "
<< "a capability contentType was empty.";
return false; return false;
}
// 3.4-3.11. (Implemented by IsSupportedContentType().) // 3.4-3.11. (Implemented by IsSupportedContentType().)
if (!base::IsStringASCII(capability.mimeType) || if (!base::IsStringASCII(capability.mimeType) ||
!base::IsStringASCII(capability.codecs) || !base::IsStringASCII(capability.codecs) ||
...@@ -91,26 +194,38 @@ static bool GetSupportedCapabilities( ...@@ -91,26 +194,38 @@ static bool GetSupportedCapabilities(
continue; continue;
} }
// 3.12. If robustness is not the empty string, run the following steps: // 3.12. If robustness is not the empty string, run the following steps:
// (Robustness is not supported.)
// TODO(sandersd): Implement robustness. http://crbug.com/442586
if (!capability.robustness.isEmpty()) { if (!capability.robustness.isEmpty()) {
LOG(WARNING) << "Configuration rejected because rubustness strings are " // 3.12.1. If robustness is an unrecognized value or not supported by
<< "not yet supported."; // implementation, continue to the next iteration. String
// comparison is case-sensitive.
if (!base::IsStringASCII(capability.robustness))
continue;
EmeConfigRule robustness_rule = GetRobustnessConfigRule(
key_system, media_type, base::UTF16ToASCII(capability.robustness));
if (!config_state->IsRuleSupported(robustness_rule))
continue; continue;
config_state->AddRule(robustness_rule);
// 3.12.2. Add robustness to configuration.
// (It's already added, we use capability as configuration.)
} }
// 3.13. If the user agent and implementation do not support playback of // 3.13. If the user agent and implementation do not support playback of
// encrypted media data as specified by configuration, including all // encrypted media data as specified by configuration, including all
// media types, in combination with accumulated capabilities, // media types, in combination with local accumulated capabilities,
// continue to the next iteration. // continue to the next iteration.
// (Skipped as there are no configuration-based codec restrictions.) // (This is handled when adding rules to |config_state|.)
// 3.14. Add configuration to media type capabilities. // 3.14. Add configuration to supported media capabilities.
media_type_capabilities->push_back(capability); supported_media_capabilities->push_back(capability);
// 3.15. Add configuration to accumulated capabilities. // 3.15. Add configuration to local accumulated capabilities.
// (Skipped as there are no configuration-based codec restrictions.) // (Skipped as we directly update |config_state|.)
}
// 4. If supported media capabilities is empty, return null.
if (supported_media_capabilities->empty()) {
DVLOG(2) << "Rejecting requested configuration because "
<< "no capabilities were supported.";
return false;
} }
// 4. If media type capabilities is empty, return null.
// 5. Return media type capabilities. // 5. Return media type capabilities.
return !media_type_capabilities->empty(); return true;
} }
static EmeFeatureRequirement ConvertRequirement( static EmeFeatureRequirement ConvertRequirement(
...@@ -131,15 +246,10 @@ static EmeFeatureRequirement ConvertRequirement( ...@@ -131,15 +246,10 @@ static EmeFeatureRequirement ConvertRequirement(
static ConfigurationSupport GetSupportedConfiguration( static ConfigurationSupport GetSupportedConfiguration(
const std::string& key_system, const std::string& key_system,
const blink::WebMediaKeySystemConfiguration& candidate, const blink::WebMediaKeySystemConfiguration& candidate,
blink::WebMediaKeySystemConfiguration* accumulated_configuration,
bool was_permission_requested, bool was_permission_requested,
bool is_permission_granted) { bool is_permission_granted,
DCHECK(was_permission_requested || !is_permission_granted); blink::WebMediaKeySystemConfiguration* accumulated_configuration) {
ConfigState config_state(was_permission_requested, is_permission_granted);
// It is possible to obtain user permission unless permission was already
// requested and denied.
bool is_permission_possible =
!was_permission_requested || is_permission_granted;
// From https://w3c.github.io/encrypted-media/#get-supported-configuration // From https://w3c.github.io/encrypted-media/#get-supported-configuration
// 1. Let accumulated configuration be empty. (Done by caller.) // 1. Let accumulated configuration be empty. (Done by caller.)
...@@ -184,8 +294,11 @@ static ConfigurationSupport GetSupportedConfiguration( ...@@ -184,8 +294,11 @@ static ConfigurationSupport GetSupportedConfiguration(
} }
// 2.3. If supported types is empty, return null. // 2.3. If supported types is empty, return null.
if (supported_types.empty()) if (supported_types.empty()) {
DVLOG(2) << "Rejecting requested configuration because "
<< "no initDataType values were supported.";
return CONFIGURATION_NOT_SUPPORTED; return CONFIGURATION_NOT_SUPPORTED;
}
// 2.4. Add supported types to accumulated configuration. // 2.4. Add supported types to accumulated configuration.
accumulated_configuration->initDataTypes = supported_types; accumulated_configuration->initDataTypes = supported_types;
...@@ -200,12 +313,16 @@ static ConfigurationSupport GetSupportedConfiguration( ...@@ -200,12 +313,16 @@ static ConfigurationSupport GetSupportedConfiguration(
// - "not-allowed": If the implementation requires a Distinctive // - "not-allowed": If the implementation requires a Distinctive
// Identifier in combination with accumulated configuration, return // Identifier in combination with accumulated configuration, return
// null. // null.
EmeFeatureRequirement di_requirement = // We also reject OPTIONAL when distinctive identifiers are ALWAYS_ENABLED and
ConvertRequirement(candidate.distinctiveIdentifier); // permission has already been denied. This would happen anyway at step 11.
if (!IsDistinctiveIdentifierRequirementSupported(key_system, di_requirement, EmeConfigRule di_rule = GetDistinctiveIdentifierConfigRule(
is_permission_possible)) { key_system, ConvertRequirement(candidate.distinctiveIdentifier));
if (!config_state.IsRuleSupported(di_rule)) {
DVLOG(2) << "Rejecting requested configuration because "
<< "the distinctiveIdentifier requirement was not supported.";
return CONFIGURATION_NOT_SUPPORTED; return CONFIGURATION_NOT_SUPPORTED;
} }
config_state.AddRule(di_rule);
// 4. Add the value of the candidate configuration's distinctiveIdentifier // 4. Add the value of the candidate configuration's distinctiveIdentifier
// attribute to accumulated configuration. // attribute to accumulated configuration.
...@@ -219,12 +336,14 @@ static ConfigurationSupport GetSupportedConfiguration( ...@@ -219,12 +336,14 @@ static ConfigurationSupport GetSupportedConfiguration(
// - "optional": Continue. // - "optional": Continue.
// - "not-allowed": If the implementation requires persisting state in // - "not-allowed": If the implementation requires persisting state in
// combination with accumulated configuration, return null. // combination with accumulated configuration, return null.
EmeFeatureRequirement ps_requirement = EmeConfigRule ps_rule = GetPersistentStateConfigRule(
ConvertRequirement(candidate.persistentState); key_system, ConvertRequirement(candidate.persistentState));
if (!IsPersistentStateRequirementSupported(key_system, ps_requirement, if (!config_state.IsRuleSupported(ps_rule)) {
is_permission_possible)) { DVLOG(2) << "Rejecting requested configuration because "
<< "the persistentState requirement was not supported.";
return CONFIGURATION_NOT_SUPPORTED; return CONFIGURATION_NOT_SUPPORTED;
} }
config_state.AddRule(ps_rule);
// 6. Add the value of the candidate configuration's persistentState // 6. Add the value of the candidate configuration's persistentState
// attribute to accumulated configuration. // attribute to accumulated configuration.
...@@ -240,7 +359,8 @@ static ConfigurationSupport GetSupportedConfiguration( ...@@ -240,7 +359,8 @@ static ConfigurationSupport GetSupportedConfiguration(
// 7.2. If video capabilities is null, return null. // 7.2. If video capabilities is null, return null.
std::vector<blink::WebMediaKeySystemMediaCapability> video_capabilities; std::vector<blink::WebMediaKeySystemMediaCapability> video_capabilities;
if (!GetSupportedCapabilities(key_system, candidate.videoCapabilities, if (!GetSupportedCapabilities(key_system, candidate.videoCapabilities,
&video_capabilities)) { EmeMediaType::VIDEO, &video_capabilities,
&config_state)) {
return CONFIGURATION_NOT_SUPPORTED; return CONFIGURATION_NOT_SUPPORTED;
} }
...@@ -258,7 +378,8 @@ static ConfigurationSupport GetSupportedConfiguration( ...@@ -258,7 +378,8 @@ static ConfigurationSupport GetSupportedConfiguration(
// 8.2. If audio capabilities is null, return null. // 8.2. If audio capabilities is null, return null.
std::vector<blink::WebMediaKeySystemMediaCapability> audio_capabilities; std::vector<blink::WebMediaKeySystemMediaCapability> audio_capabilities;
if (!GetSupportedCapabilities(key_system, candidate.audioCapabilities, if (!GetSupportedCapabilities(key_system, candidate.audioCapabilities,
&audio_capabilities)) { EmeMediaType::AUDIO, &audio_capabilities,
&config_state)) {
return CONFIGURATION_NOT_SUPPORTED; return CONFIGURATION_NOT_SUPPORTED;
} }
...@@ -274,20 +395,50 @@ static ConfigurationSupport GetSupportedConfiguration( ...@@ -274,20 +395,50 @@ static ConfigurationSupport GetSupportedConfiguration(
// configuration's distinctiveIdentifier value to "required". // configuration's distinctiveIdentifier value to "required".
// - Otherwise, change accumulated configuration's distinctiveIdentifier // - Otherwise, change accumulated configuration's distinctiveIdentifier
// value to "not-allowed". // value to "not-allowed".
// (Without robustness support, capabilities do not affect this.)
// TODO(sandersd): Implement robustness. http://crbug.com/442586
if (accumulated_configuration->distinctiveIdentifier == if (accumulated_configuration->distinctiveIdentifier ==
blink::WebMediaKeySystemConfiguration::Requirement::Optional) { blink::WebMediaKeySystemConfiguration::Requirement::Optional) {
if (IsDistinctiveIdentifierRequirementSupported( EmeConfigRule not_allowed_rule =
key_system, EME_FEATURE_NOT_ALLOWED, is_permission_possible)) { GetDistinctiveIdentifierConfigRule(key_system, EME_FEATURE_NOT_ALLOWED);
EmeConfigRule required_rule =
GetDistinctiveIdentifierConfigRule(key_system, EME_FEATURE_REQUIRED);
bool not_allowed_supported = config_state.IsRuleSupported(not_allowed_rule);
bool required_supported = config_state.IsRuleSupported(required_rule);
if (not_allowed_supported) {
bool prefer_required = config_state.IsIdentifierRequired() ||
(config_state.IsIdentifierRecommended() &&
config_state.IsPermissionPossible());
if (required_supported && prefer_required) {
accumulated_configuration->distinctiveIdentifier = accumulated_configuration->distinctiveIdentifier =
blink::WebMediaKeySystemConfiguration::Requirement::NotAllowed; blink::WebMediaKeySystemConfiguration::Requirement::Required;
config_state.AddRule(required_rule);
DCHECK(config_state.IsIdentifierRequired());
} else { } else {
accumulated_configuration->distinctiveIdentifier =
blink::WebMediaKeySystemConfiguration::Requirement::NotAllowed;
config_state.AddRule(not_allowed_rule);
}
} else if (required_supported) {
accumulated_configuration->distinctiveIdentifier = accumulated_configuration->distinctiveIdentifier =
blink::WebMediaKeySystemConfiguration::Requirement::Required; blink::WebMediaKeySystemConfiguration::Requirement::Required;
config_state.AddRule(required_rule);
} else {
// We should not have passed step 3.
NOTREACHED();
return CONFIGURATION_NOT_SUPPORTED;
} }
} }
// If permission is required but we couldn't enable it, reject the
// configuration.
if (config_state.IsIdentifierRequired() &&
accumulated_configuration->distinctiveIdentifier !=
blink::WebMediaKeySystemConfiguration::Requirement::Required) {
DVLOG(2) << "Rejecting requested configuration because "
<< "distinctiveIdentifier was implicitly required but "
<< "not allowed.";
return CONFIGURATION_NOT_SUPPORTED;
}
// 10. If accumulated configuration's persistentState value is "optional", // 10. If accumulated configuration's persistentState value is "optional",
// follow the steps for the first matching condition from the following // follow the steps for the first matching condition from the following
// list: // list:
...@@ -298,59 +449,57 @@ static ConfigurationSupport GetSupportedConfiguration( ...@@ -298,59 +449,57 @@ static ConfigurationSupport GetSupportedConfiguration(
// to "not-allowed". // to "not-allowed".
if (accumulated_configuration->persistentState == if (accumulated_configuration->persistentState ==
blink::WebMediaKeySystemConfiguration::Requirement::Optional) { blink::WebMediaKeySystemConfiguration::Requirement::Optional) {
if (IsPersistentStateRequirementSupported( EmeConfigRule not_allowed_rule =
key_system, EME_FEATURE_NOT_ALLOWED, is_permission_possible)) { GetPersistentStateConfigRule(key_system, EME_FEATURE_NOT_ALLOWED);
EmeConfigRule required_rule =
GetPersistentStateConfigRule(key_system, EME_FEATURE_REQUIRED);
// Now that distinctiveIdentifier has been resolved, it is too late to allow
// persistentState to affect the configuration.
bool not_allowed_supported =
config_state.IsRuleSupportedWithCurrentState(not_allowed_rule);
bool required_supported =
config_state.IsRuleSupportedWithCurrentState(required_rule);
if (not_allowed_supported) {
accumulated_configuration->persistentState = accumulated_configuration->persistentState =
blink::WebMediaKeySystemConfiguration::Requirement::NotAllowed; blink::WebMediaKeySystemConfiguration::Requirement::NotAllowed;
} else { } else if (required_supported) {
accumulated_configuration->persistentState = accumulated_configuration->persistentState =
blink::WebMediaKeySystemConfiguration::Requirement::Required; blink::WebMediaKeySystemConfiguration::Requirement::Required;
} else {
// We should not have passed step 5.
NOTREACHED();
return CONFIGURATION_NOT_SUPPORTED;
} }
} }
// 11. If implementation in the configuration specified by the combination of // 11. If implementation in the configuration specified by the combination of
// the values in accumulated configuration is not supported or not allowed // the values in accumulated configuration is not supported or not allowed
// in the origin, return null. // in the origin, return null.
di_requirement = // 12. If accumulated configuration's distinctiveIdentifier value is
ConvertRequirement(accumulated_configuration->distinctiveIdentifier); // "required", [prompt the user for consent].
if (!IsDistinctiveIdentifierRequirementSupported(key_system, di_requirement, if (accumulated_configuration->distinctiveIdentifier ==
is_permission_granted)) { blink::WebMediaKeySystemConfiguration::Requirement::Required) {
if (was_permission_requested) { // The caller is responsible for resolving what to do if permission is
// The optional permission was requested and denied. // required but has been denied (it should treat it as NOT_SUPPORTED).
// TODO(sandersd): Avoid the need for this logic - crbug.com/460616. if (!config_state.IsPermissionGranted())
DCHECK(candidate.distinctiveIdentifier ==
blink::WebMediaKeySystemConfiguration::Requirement::Optional);
DCHECK(di_requirement == EME_FEATURE_REQUIRED);
DCHECK(!is_permission_granted);
accumulated_configuration->distinctiveIdentifier =
blink::WebMediaKeySystemConfiguration::Requirement::NotAllowed;
} else {
return CONFIGURATION_REQUIRES_PERMISSION;
}
}
ps_requirement =
ConvertRequirement(accumulated_configuration->persistentState);
if (!IsPersistentStateRequirementSupported(key_system, ps_requirement,
is_permission_granted)) {
DCHECK(!was_permission_requested); // Should have failed at step 5.
return CONFIGURATION_REQUIRES_PERMISSION; return CONFIGURATION_REQUIRES_PERMISSION;
} }
// 12. Return accumulated configuration. // 13. Return accumulated configuration.
// (As an extra step, we record the available session types so that //
// createSession() can be synchronous.) // We also record the available session types so that createSession() can be
// synchronous.
std::vector<blink::WebEncryptedMediaSessionType> session_types; std::vector<blink::WebEncryptedMediaSessionType> session_types;
session_types.push_back(blink::WebEncryptedMediaSessionType::Temporary); session_types.push_back(blink::WebEncryptedMediaSessionType::Temporary);
if (accumulated_configuration->persistentState == if (accumulated_configuration->persistentState ==
blink::WebMediaKeySystemConfiguration::Requirement::Required) { blink::WebMediaKeySystemConfiguration::Requirement::Required) {
if (IsPersistentLicenseSessionSupported(key_system, if (config_state.IsRuleSupportedWithCurrentState(
is_permission_granted)) { GetPersistentLicenseSessionConfigRule(key_system))) {
session_types.push_back( session_types.push_back(
blink::WebEncryptedMediaSessionType::PersistentLicense); blink::WebEncryptedMediaSessionType::PersistentLicense);
} }
if (IsPersistentReleaseMessageSessionSupported(key_system, if (config_state.IsRuleSupportedWithCurrentState(
is_permission_granted)) { GetPersistentReleaseMessageSessionConfigRule(key_system))) {
session_types.push_back( session_types.push_back(
blink::WebEncryptedMediaSessionType::PersistentReleaseMessage); blink::WebEncryptedMediaSessionType::PersistentReleaseMessage);
} }
...@@ -474,13 +623,17 @@ void WebEncryptedMediaClientImpl::SelectSupportedConfiguration( ...@@ -474,13 +623,17 @@ void WebEncryptedMediaClientImpl::SelectSupportedConfiguration(
// new MediaKeySystemAccess object.] // new MediaKeySystemAccess object.]
blink::WebMediaKeySystemConfiguration accumulated_configuration; blink::WebMediaKeySystemConfiguration accumulated_configuration;
ConfigurationSupport supported = GetSupportedConfiguration( ConfigurationSupport supported = GetSupportedConfiguration(
key_system, candidate_configuration, &accumulated_configuration, key_system, candidate_configuration, was_permission_requested,
was_permission_requested, is_permission_granted); is_permission_granted, &accumulated_configuration);
switch (supported) { switch (supported) {
case CONFIGURATION_NOT_SUPPORTED: case CONFIGURATION_NOT_SUPPORTED:
continue; continue;
case CONFIGURATION_REQUIRES_PERMISSION: case CONFIGURATION_REQUIRES_PERMISSION:
DCHECK(!was_permission_requested); if (was_permission_requested) {
DVLOG(2) << "Rejecting requested configuration because "
<< "permission was denied.";
continue;
}
media_permission_->RequestPermission( media_permission_->RequestPermission(
MediaPermission::PROTECTED_MEDIA_IDENTIFIER, MediaPermission::PROTECTED_MEDIA_IDENTIFIER,
GURL(request.securityOrigin().toString()), GURL(request.securityOrigin().toString()),
......
...@@ -85,8 +85,10 @@ PlayerUtils.registerEMEEventListeners = function(player) { ...@@ -85,8 +85,10 @@ PlayerUtils.registerEMEEventListeners = function(player) {
this.registerDefaultEventListeners(player); this.registerDefaultEventListeners(player);
Utils.timeLog('Setting video media keys: ' + player.testConfig.keySystem); Utils.timeLog('Setting video media keys: ' + player.testConfig.keySystem);
var persistentState = player.testConfig.sessionToLoad ? "required"
: "optional";
return navigator.requestMediaKeySystemAccess( return navigator.requestMediaKeySystemAccess(
player.testConfig.keySystem, [{}]) player.testConfig.keySystem, [{persistentState: persistentState}])
.then(function(access) { return access.createMediaKeys(); }) .then(function(access) { return access.createMediaKeys(); })
.then(function(mediaKeys) { .then(function(mediaKeys) {
return player.video.setMediaKeys(mediaKeys); return player.video.setMediaKeys(mediaKeys);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment