chromium/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/public/platform/media/key_system_config_selector.h"

#include <optional>
#include <string>
#include <vector>

#include "base/functional/bind.h"
#include "base/strings/pattern.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "media/base/cdm_config.h"
#include "media/base/eme_constants.h"
#include "media/base/key_systems.h"
#include "media/base/media_permission.h"
#include "media/base/media_switches.h"
#include "media/base/mime_util.h"
#include "media/cdm/clear_key_cdm_common.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_encrypted_media_types.h"
#include "third_party/blink/public/platform/web_media_key_system_configuration.h"
#include "third_party/blink/public/platform/web_string.h"

namespace blink {
namespace {

EmeConfig;
EmeConfigRuleState;
EmeFeatureSupport;
EmeInitDataType;
EmeMediaType;
MediaKeysRequirement;
EncryptionScheme;

// Key system strings. Clear Key support is hardcoded in KeySystemConfigSelector
// so media::kClearKeyKeySystem is the real key system string. The rest key
// system strings are for testing purpose only.
const char kSupportedKeySystem[] =;
const char kSupportedSubKeySystem[] =;
const char kUnsupportedKeySystem[] =;

// Robustness strings for kSupportedKeySystem.
const char kSupportedRobustness[] =;
const char kRecommendIdentifierRobustness[] =;
const char kRequireIdentifierRobustness[] =;
const char kDisallowHwSecureCodecRobustness[] =;
const char kRequireHwSecureCodecRobustness[] =;
const char kRequireIdentifierAndHwSecureCodecRobustness[] =;
const char kRequireIdentifierPersistenceAndHwSecureCodecRobustness[] =;
const char kUnsupportedRobustness[] =;

// Test container mime types. Supported types are prefixed with audio/video so
// that the test can perform EmeMediaType check.
const char kSupportedVideoContainer[] =;
const char kSupportedAudioContainer[] =;
const char kUnsupportedContainer[] =;
const char kInvalidContainer[] =;

// The codec strings. Supported types are prefixed with audio/video so
// that the test can perform EmeMediaType check.
// TODO(sandersd): Extended codec variants (requires proprietary codec support).
// TODO(xhwang): Platform Opus is not available on all Android versions, where
// some encrypted Opus related tests may fail. See
// MediaCodecUtil::IsOpusDecoderAvailable() for more details.
const char kSupportedAudioCodec[] =;
const char kSupportedVideoCodec[] =;
const char kUnsupportedCodec[] =;
const char kInvalidCodec[] =;
const char kRequireHwSecureCodec[] =;
const char kDisallowHwSecureCodec[] =;
const char kExtendedVideoCodec[] =;
const char kExtendedVideoCodecStripped[] =;
// A special codec that is supported by the key systems, but is not supported
// in IsSupportedMediaType() when |use_aes_decryptor| is true.
const char kUnsupportedByAesDecryptorCodec[] =;

// Encryption schemes. For testing 'cenc' is supported, while 'cbcs' is not.
// Note that WebMediaKeySystemMediaCapability defaults to kNotSpecified,
// which is treated as 'cenc' by KeySystemConfigSelector.
constexpr EncryptionScheme kSupportedEncryptionScheme =;
constexpr EncryptionScheme kDisallowHwSecureCodecEncryptionScheme =;

media::EncryptionScheme ConvertEncryptionScheme(
    EncryptionScheme encryption_scheme) {}

WebString MakeCodecs(const std::string& a, const std::string& b) {}

WebString GetSupportedVideoCodecs() {}

WebString GetSubsetSupportedVideoCodecs() {}

WebString GetSubsetInvalidVideoCodecs() {}

bool IsValidContainerMimeType(const std::string& container_mime_type) {}

bool IsValidCodec(const std::string& codec) {}

// Returns whether |type| is compatible with |media_type|.
bool IsCompatibleWithEmeMediaType(EmeMediaType media_type,
                                  const std::string& type) {}

// Pretend that we support all |container_mime_type| and |codecs| except for
// those explicitly marked as invalid.
bool IsSupportedMediaType(const std::string& container_mime_type,
                          const std::string& codecs,
                          bool use_aes_decryptor) {}

// The IDL for MediaKeySystemConfiguration specifies some defaults, so
// create a config object that mimics what would be created if an empty
// dictionary was passed in.
WebMediaKeySystemConfiguration EmptyConfiguration() {}

// EME spec requires that at least one of |video_capabilities| and
// |audio_capabilities| be specified. Add a single valid audio capability
// to the EmptyConfiguration().
WebMediaKeySystemConfiguration UsableConfiguration() {}

class FakeKeySystems : public media::KeySystems {};

class FakeMediaPermission : public media::MediaPermission {};

class FakeWebLocalFrameDelegate
    : public KeySystemConfigSelector::WebLocalFrameDelegate {};

}  // namespace

class KeySystemConfigSelectorTest : public testing::Test {};

// --- Basics ---

TEST_F(KeySystemConfigSelectorTest, NoConfigs) {}

TEST_F(KeySystemConfigSelectorTest, DefaultConfig) {}

TEST_F(KeySystemConfigSelectorTest, EmptyConfig) {}

// Most of the tests below assume that the the usable config is valid.
// Tests that touch |video_capabilities| and/or |audio_capabilities| can
// modify the empty config.

TEST_F(KeySystemConfigSelectorTest, UsableConfig) {}

TEST_F(KeySystemConfigSelectorTest, Label) {}

// --- keySystem ---
// Empty is not tested because the empty check is in Blink.

TEST_F(KeySystemConfigSelectorTest, KeySystem_NonAscii) {}

TEST_F(KeySystemConfigSelectorTest, KeySystem_Unsupported) {}

TEST_F(KeySystemConfigSelectorTest, KeySystem_ClearKey) {}

TEST_F(KeySystemConfigSelectorTest, KeySystem_SubKeySystem) {}

// --- Disable EncryptedMedia ---

TEST_F(KeySystemConfigSelectorTest, EncryptedMediaDisabled_ClearKey) {}

TEST_F(KeySystemConfigSelectorTest, EncryptedMediaDisabled_Supported) {}

// --- initDataTypes ---

TEST_F(KeySystemConfigSelectorTest, InitDataTypes_Empty) {}

TEST_F(KeySystemConfigSelectorTest, InitDataTypes_NoneSupported) {}

TEST_F(KeySystemConfigSelectorTest, InitDataTypes_SubsetSupported) {}

// --- distinctiveIdentifier ---

TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_Default) {}

TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_Forced) {}

TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_Blocked) {}

TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_RequestsPermission) {}

TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_RespectsPermission) {}

TEST_F(KeySystemConfigSelectorTest, DistinctiveIdentifier_DefaultCrossOrigin) {}

TEST_F(KeySystemConfigSelectorTest,
       DistinctiveIdentifier_ForcedBlockedByCrossOrigin) {}

TEST_F(KeySystemConfigSelectorTest,
       DistinctiveIdentifier_RequestsPermissionBlockedByCrossOrigin) {}

// --- persistentState ---

TEST_F(KeySystemConfigSelectorTest, PersistentState_Default) {}

TEST_F(KeySystemConfigSelectorTest, PersistentState_Forced) {}

TEST_F(KeySystemConfigSelectorTest, PersistentState_Required) {}

TEST_F(KeySystemConfigSelectorTest, PersistentState_Blocked) {}

TEST_F(KeySystemConfigSelectorTest, PersistentState_BlockedByContentSettings) {}

TEST_F(KeySystemConfigSelectorTest,
       PersistentState_ForcedBlockedByContentSettings) {}

TEST_F(KeySystemConfigSelectorTest,
       PersistentState_RequiredBlockedByContentSettings) {}

// --- sessionTypes ---

TEST_F(KeySystemConfigSelectorTest, SessionTypes_Empty) {}

TEST_F(KeySystemConfigSelectorTest, SessionTypes_SubsetSupported) {}

TEST_F(KeySystemConfigSelectorTest, SessionTypes_AllSupported) {}

TEST_F(KeySystemConfigSelectorTest, SessionTypes_PermissionCanBeRequired) {}

// --- videoCapabilities ---

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Empty) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_ExtendedCodec) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_InvalidContainer) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_UnsupportedContainer) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_IncompatibleContainer) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_InvalidCodec) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_UnsupportedCodec) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_IncompatibleCodec) {}

TEST_F(KeySystemConfigSelectorTest,
       VideoCapabilities_UnsupportedByAesDecryptorCodec_ClearKey) {}

TEST_F(KeySystemConfigSelectorTest,
       VideoCapabilities_UnsupportedByAesDecryptorCodec) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_SubsetSupported) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_AllSupported) {}

// --- videoCapabilities Codecs ---

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Codecs_SubsetInvalid) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Codecs_SubsetSupported) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Codecs_AllSupported) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Missing_Codecs) {}

// --- videoCapabilities Robustness ---

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Robustness_Empty) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Robustness_Supported) {}

TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_Robustness_Unsupported) {}

TEST_F(KeySystemConfigSelectorTest,
       VideoCapabilities_Robustness_PermissionCanBeRequired) {}

TEST_F(KeySystemConfigSelectorTest,
       VideoCapabilities_Robustness_PermissionCanBeRecommended) {}

TEST_F(KeySystemConfigSelectorTest,
       VideoCapabilities_Robustness_PermissionCanBeRecommendedAndGranted) {}

TEST_F(KeySystemConfigSelectorTest,
       VideoCapabilities_Robustness_NoPermissionRecommendedCrossOrigin) {}

TEST_F(KeySystemConfigSelectorTest,
       VideoCapabilities_EncryptionScheme_Supported) {}

TEST_F(KeySystemConfigSelectorTest,
       VideoCapabilities_EncryptionScheme_DisallowHwSecureCodec) {}

// --- HW Secure Codecs and Robustness ---

TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_RequireHwSecureCodec) {}

TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_DisallowHwSecureCodec) {}

TEST_F(KeySystemConfigSelectorTest,
       HwSecureCodec_IncompatibleCodecAndRobustness) {}

TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_CompatibleCodecs) {}

TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_IncompatibleCodecs) {}

TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_CompatibleCapabilityCodec) {}

TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_RequireAndDisallow) {}

TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_DisallowAndRequire) {}

TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_IncompatibleCapabilities) {}

TEST_F(KeySystemConfigSelectorTest,
       HwSecureCodec_UnsupportedCapabilityNotAffectingRules) {}

TEST_F(KeySystemConfigSelectorTest, HwSecureCodec_EncryptionScheme_Supported) {}

TEST_F(KeySystemConfigSelectorTest,
       HwSecureCodec_EncryptionScheme_DisallowHwSecureCodec) {}

// --- Identifier and HW Secure Robustness ---

TEST_F(KeySystemConfigSelectorTest,
       IdentifierAndHwSecureCodec_IncompatibleCodecAndRobustness) {}

TEST_F(KeySystemConfigSelectorTest,
       IdentifierAndHwSecureCodec_IncompatibleCapabilities) {}

TEST_F(KeySystemConfigSelectorTest,
       IdentifierAndHwSecureCodec_UnsupportedCapabilityNotAffectingRules) {}

TEST_F(KeySystemConfigSelectorTest,
       HwSecureCodecAndIdentifier_IdentifierAndHwSecureCodecsDisjoint) {}

// --- Identifier, Persistence and HW Secure Robustness ---

TEST_F(KeySystemConfigSelectorTest,
       IdentifierPersistenceAndHwSecureCodec_Supported) {}

TEST_F(KeySystemConfigSelectorTest,
       IdentifierPersistenceAndHwSecureCodec_NotSupported) {}

// --- audioCapabilities ---
// These are handled by the same code as |videoCapabilities|, so only minimal
// additional testing is done.

TEST_F(KeySystemConfigSelectorTest, AudioCapabilities_SubsetSupported) {}

// --- audioCapabilities and videoCapabilities ---

TEST_F(KeySystemConfigSelectorTest, AudioAndVideoCapabilities_AllSupported) {}

TEST_F(KeySystemConfigSelectorTest,
       AudioAndVideoCapabilities_AudioUnsupported) {}

TEST_F(KeySystemConfigSelectorTest,
       AudioAndVideoCapabilities_VideoUnsupported) {}

// Only "a2" and "v2" are supported types.
TEST_F(KeySystemConfigSelectorTest, AudioAndVideoCapabilities_SubsetSupported) {}

// --- Multiple configurations ---

TEST_F(KeySystemConfigSelectorTest, Configurations_AllSupported) {}

TEST_F(KeySystemConfigSelectorTest, Configurations_SubsetSupported) {}

TEST_F(KeySystemConfigSelectorTest,
       Configurations_FirstRequiresPermission_Allowed) {}

TEST_F(KeySystemConfigSelectorTest,
       Configurations_FirstRequiresPermission_Rejected) {}

// hardware secure decryption preferences
#if BUILDFLAG(IS_WIN)
TEST_F(KeySystemConfigSelectorTest, HardwareDecryption_Allowed) {
  std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
  video_capabilities[0].content_type = "a";
  video_capabilities[0].mime_type = kSupportedVideoContainer;
  video_capabilities[0].codecs = kRequireHwSecureCodec;

  auto config = EmptyConfiguration();
  config.video_capabilities = video_capabilities;
  configs_.push_back(config);

  media_permission_->is_hardware_secure_decryption_allowed = true;
  SelectConfigReturnsConfig();
}

TEST_F(KeySystemConfigSelectorTest, HardwareDecryption_NotAllowed) {
  std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
  video_capabilities[0].content_type = "a";
  video_capabilities[0].mime_type = kSupportedVideoContainer;
  video_capabilities[0].codecs = kRequireHwSecureCodec;

  auto config = EmptyConfiguration();
  config.video_capabilities = video_capabilities;
  configs_.push_back(config);

  media_permission_->is_hardware_secure_decryption_allowed = false;

  if (media::kHardwareSecureDecryptionFallbackPerSite.Get()) {
    SelectConfigReturnsError();
  } else {
    SelectConfigReturnsConfig();
  }
}

TEST_F(KeySystemConfigSelectorTest, NotHardwareSecureDecryption_Allowed) {
  auto config = UsableConfiguration();
  configs_.push_back(config);

  media_permission_->is_hardware_secure_decryption_allowed = false;
  SelectConfig();
}

TEST_F(KeySystemConfigSelectorTest,
       DisableHardwareSecureDecryptionFallbackFeature) {
  std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
  video_capabilities[0].content_type = "a";
  video_capabilities[0].mime_type = kSupportedVideoContainer;
  video_capabilities[0].codecs = kRequireHwSecureCodec;

  auto config = EmptyConfiguration();
  config.video_capabilities = video_capabilities;
  configs_.push_back(config);

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeatureWithParameters(
      media::kHardwareSecureDecryptionFallback, {{"per_site", "false"}});

  media_permission_->is_hardware_secure_decryption_allowed = true;
  SelectConfigReturnsConfig();
  media_permission_->is_hardware_secure_decryption_allowed = false;
  SelectConfigReturnsConfig();
}

TEST_F(KeySystemConfigSelectorTest,
       EnableHardwareSecureDecryptionFallbackFeature) {
  std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1);
  video_capabilities[0].content_type = "a";
  video_capabilities[0].mime_type = kSupportedVideoContainer;
  video_capabilities[0].codecs = kRequireHwSecureCodec;

  auto config = EmptyConfiguration();
  config.video_capabilities = video_capabilities;
  configs_.push_back(config);

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeatureWithParameters(
      media::kHardwareSecureDecryptionFallback, {{"per_site", "true"}});

  media_permission_->is_hardware_secure_decryption_allowed = true;
  SelectConfigReturnsConfig();
  media_permission_->is_hardware_secure_decryption_allowed = false;
  SelectConfigReturnsError();
}
#endif  // BUILDFLAG(IS_WIN)

}  // namespace blink