chromium/chrome/browser/media/encrypted_media_supported_types_browsertest.cc

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

#include <stddef.h>

#include <string>
#include <tuple>
#include <vector>

#include "base/base_switches.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/media/clear_key_cdm_test_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/test_launcher_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "media/base/media_switches.h"
#include "media/base/supported_types.h"
#include "media/base/test_data_util.h"
#include "media/cdm/clear_key_cdm_common.h"
#include "media/media_buildflags.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/widevine/cdm/buildflags.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/dbus/constants/dbus_switches.h"
#endif

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
#include "chrome/browser/ash/settings/stub_cros_settings_provider.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

#if BUILDFLAG(IS_ANDROID)
#error This file needs to be updated to run on Android.
#endif

namespace {

const char* kClearKey =;
const char* kExternalClearKey =;

const char kWidevine[] =;
const char kWidevineExperiment[] =;
const char kWidevineExperiment2[] =;

const char kAudioWebMMimeType[] =;
const char kVideoWebMMimeType[] =;
const char kAudioMP4MimeType[] =;
const char kVideoMP4MimeType[] =;

// These are the expected titles set by checkKeySystemWithMediaMimeType()
// in test_key_system_instantiation.html. Other titles are possible, but
// they are unexpected and will be logged with the failure. kUnsupportedResult
// is the actual message generated by navigator.requestMediaKeySystemAccess(),
// and will need to be updated if that code is modified.
const char kSuccessResult[] =;
const char16_t kSuccessResult16[] =;
const char kUnsupportedResult[] =;
const char16_t kUnsupportedResult16[] =;
const char16_t kUnexpectedResult16[] =;

#define EXPECT_SUCCESS(test)
#define EXPECT_UNSUPPORTED(test)

// Any support is acceptable. This can be used around new CDM check-in time
// where test expectations can change based on the new CDM's capability.
// For any usage of EXPECT_ANY, add a TODO explaining the plan to fix it.
#define EXPECT_ANY(test)

#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
#define EXPECT_AC3
#else
#define EXPECT_AC3
#endif  // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)

#if BUILDFLAG(ENABLE_AV1_DECODER)
#define EXPECT_AV1
#else
#define EXPECT_AV1
#endif

#if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
#define EXPECT_DTS
#else
#define EXPECT_DTS
#endif  // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)

#if BUILDFLAG(USE_PROPRIETARY_CODECS)
#define EXPECT_PROPRIETARY
#else
#define EXPECT_PROPRIETARY
#endif

// Expectations for External Clear Key.
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
#define EXPECT_ECK
#define EXPECT_ECK_AC3
#define EXPECT_ECK_AV1
#define EXPECT_ECK_DTS
#define EXPECT_ECK_PROPRIETARY
#else
#define EXPECT_ECK
#define EXPECT_ECK_AC3
#define EXPECT_ECK_AV1
#define EXPECT_ECK_DTS
#define EXPECT_ECK_PROPRIETARY
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

// Expectations for Widevine.
#if BUILDFLAG(BUNDLE_WIDEVINE_CDM)
#define EXPECT_WV
#define EXPECT_WV_AC3
#define EXPECT_WV_AV1
#define EXPECT_WV_DTS
#define EXPECT_WV_PROPRIETARY
#else
#define EXPECT_WV
#define EXPECT_WV_AC3
#define EXPECT_WV_AV1
#define EXPECT_WV_DTS
#define EXPECT_WV_PROPRIETARY
#endif  // BUILDFLAG(BUNDLE_WIDEVINE_CDM)

// For Widevine key system with software secure robustness, persistent license
// session is supported on Windows and Mac. On ChromeOS, it is supported when
// the protected media identifier permission is allowed. See
// kUnsafelyAllowProtectedMediaIdentifierForDomain used below.
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
#define EXPECT_WV_SW_SECURE_PERSISTENT_SESSION
#else
#define EXPECT_WV_SW_SECURE_PERSISTENT_SESSION
#endif

// For Widevine key system with hardware secure robustness, persistent license
// session is only supported on ChromeOS when the protected media identifier
// permission is allowed. See kUnsafelyAllowProtectedMediaIdentifierForDomain
// used below.
#if BUILDFLAG(IS_CHROMEOS_ASH)
#define EXPECT_WV_HW_SECURE_PERSISTENT_SESSION
#else
#define EXPECT_WV_HW_SECURE_PERSISTENT_SESSION
#endif

}  // namespace

class EncryptedMediaSupportedTypesTest : public InProcessBrowserTest {};

// For ClearKey, nothing additional is required.
class EncryptedMediaSupportedTypesClearKeyTest
    : public EncryptedMediaSupportedTypesTest {};

// For ExternalClearKey tests, ensure that the ClearKey adapter is loaded.
class EncryptedMediaSupportedTypesExternalClearKeyTest
    : public EncryptedMediaSupportedTypesTest {};

// By default, the External Clear Key (ECK) key system is not supported even if
// present. This test case tests this behavior by not enabling
// kExternalClearKeyForTesting. Even registering the Clear Key CDM does not
// enable the ECK key system support.
class EncryptedMediaSupportedTypesExternalClearKeyNotEnabledTest
    : public EncryptedMediaSupportedTypesTest {};

class EncryptedMediaSupportedTypesWidevineTest
    : public EncryptedMediaSupportedTypesTest {};

#if BUILDFLAG(IS_CHROMEOS)
class EncryptedMediaSupportedTypesDevModeTest
    : public EncryptedMediaSupportedTypesTest {
 public:
  EncryptedMediaSupportedTypesDevModeTest(
      const EncryptedMediaSupportedTypesDevModeTest&) = delete;
  EncryptedMediaSupportedTypesDevModeTest& operator=(
      const EncryptedMediaSupportedTypesDevModeTest&) = delete;

 protected:
  EncryptedMediaSupportedTypesDevModeTest() = default;

  void SetUpCommandLine(base::CommandLine* command_line) override {
    EncryptedMediaSupportedTypesTest::SetUpCommandLine(command_line);
    // Expect Persistent licences to not be supported since switch for dev mode
    // is turned on.
    command_line->AppendSwitch(chromeos::switches::kSystemDevMode);
  }
};

class EncryptedMediaSupportedTypesRAAllowedTest
    : public EncryptedMediaSupportedTypesTest {
 public:
  EncryptedMediaSupportedTypesRAAllowedTest(
      const EncryptedMediaSupportedTypesRAAllowedTest&) = delete;
  EncryptedMediaSupportedTypesRAAllowedTest& operator=(
      const EncryptedMediaSupportedTypesRAAllowedTest&) = delete;

 protected:
  EncryptedMediaSupportedTypesRAAllowedTest() = default;

  void SetUpCommandLine(base::CommandLine* command_line) override {
    EncryptedMediaSupportedTypesTest::SetUpCommandLine(command_line);
    // Expect Persistent licences to be supported since switch for dev mode
    // is turned on alongside the AllowRAinDevMode
    command_line->AppendSwitch(chromeos::switches::kSystemDevMode);
    command_line->AppendSwitch(switches::kAllowRAInDevMode);
  }
};
#endif  // BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_CHROMEOS_ASH)
class EncryptedMediaSupportedTypesRAForContentBlockedTest
    : public EncryptedMediaSupportedTypesTest {
 public:
  EncryptedMediaSupportedTypesRAForContentBlockedTest(
      const EncryptedMediaSupportedTypesRAForContentBlockedTest&) = delete;
  EncryptedMediaSupportedTypesRAForContentBlockedTest& operator=(
      const EncryptedMediaSupportedTypesRAForContentBlockedTest&) = delete;

 protected:
  EncryptedMediaSupportedTypesRAForContentBlockedTest() = default;
};
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

class EncryptedMediaSupportedTypesWidevineHwSecureTest
    : public EncryptedMediaSupportedTypesWidevineTest {};

class EncryptedMediaSupportedTypesWidevineHwSecureForceClearLeadSupportTest
    : public EncryptedMediaSupportedTypesWidevineTest {};

class EncryptedMediaSupportedTypesWidevineHwSecureExperimentTest
    : public EncryptedMediaSupportedTypesWidevineTest {};

class EncryptedMediaSupportedTypesWidevineHwSecureDefaultAndExperimentTest
    : public EncryptedMediaSupportedTypesWidevineTest {};

#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
// Registers ClearKey CDM with the wrong path (filename).
class EncryptedMediaSupportedTypesClearKeyCdmRegisteredWithWrongPathTest
    : public EncryptedMediaSupportedTypesTest {};
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Basic) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, NoCodecs) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest,
                       InvalidKeySystems) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Video_WebM) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Audio_WebM) {}

// TODO(crbug.com/40915599): Flaky on "Mac12 Tests" builder.
#if BUILDFLAG(IS_MAC)
#define MAYBE_Video_MP4
#else
#define MAYBE_Video_MP4
#endif
IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest,
                       MAYBE_Video_MP4) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Audio_MP4) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, SessionType) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest, Robustness) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesClearKeyTest,
                       EncryptionScheme) {}

//
// External Clear Key
//

// When BUILDFLAG(ENABLE_LIBRARY_CDMS), this also tests the library CDM check.
IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Basic) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       NoCodecs) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       InvalidKeySystems) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Video_WebM) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Audio_WebM) {}

// TODO(crbug.com/40915599): Flaky on "Mac12 Tests" builder.
#if BUILDFLAG(IS_MAC)
#define MAYBE_Video_MP4
#else
#define MAYBE_Video_MP4
#endif
IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       MAYBE_Video_MP4) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Audio_MP4) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       SessionType) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       Robustness) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesExternalClearKeyTest,
                       EncryptionScheme) {}

// External Clear Key is disabled by default.
IN_PROC_BROWSER_TEST_F(
    EncryptedMediaSupportedTypesExternalClearKeyNotEnabledTest,
    Basic) {}

//
// Widevine
//

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Basic) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest,
                       InvalidKeySystems) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, NoCodecs) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Video_WebM) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Audio_WebM) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Video_MP4) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Audio_MP4) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, SessionType) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest, Robustness) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest,
                       EncryptionScheme) {}

#if BUILDFLAG(IS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesDevModeTest, SessionType) {
  // Temporary session always supported.
  EXPECT_WV(IsSessionTypeSupported(kWidevine, SessionType::kTemporary));

  // Persistent license session should not be supported while system is
  // on dev mode.
  EXPECT_UNSUPPORTED(
      IsSessionTypeSupported(kWidevine, SessionType::kPersistentLicense));
}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesRAAllowedTest, SessionType) {
  // Temporary session always supported.
  EXPECT_WV(IsSessionTypeSupported(kWidevine, SessionType::kTemporary));

  // Persistent license session should be supported if the flag
  // `kAllowRAInDevMode` is attached while the system is on dev mode.
  EXPECT_WV_SW_SECURE_PERSISTENT_SESSION(
      IsSessionTypeSupported(kWidevine, SessionType::kPersistentLicense));
}
#endif  // BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesRAForContentBlockedTest,
                       SessionType) {
  // Temporary session always supported.
  EXPECT_WV(IsSessionTypeSupported(kWidevine, SessionType::kTemporary));

  auto settings_helper =
      std::make_unique<ash::ScopedCrosSettingsTestHelper>(false);
  settings_helper->ReplaceDeviceSettingsProviderWithStub();

  // Persistent license session should be supported as long as the policy
  // 'kAttestationForContentProtectionEnabled' is set to true.
  settings_helper->SetBoolean(ash::kAttestationForContentProtectionEnabled,
                              true);
  EXPECT_WV_SW_SECURE_PERSISTENT_SESSION(
      IsSessionTypeSupported(kWidevine, SessionType::kPersistentLicense));

  // Persistent license session should be not supported as long as the policy
  // 'kAttestationForContentProtectionEnabled' is set to false.
  settings_helper->SetBoolean(ash::kAttestationForContentProtectionEnabled,
                              false);
  EXPECT_UNSUPPORTED(
      IsSessionTypeSupported(kWidevine, SessionType::kPersistentLicense));
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

// EncryptedMediaSupportedTypesWidevineHwSecureTest tests Widevine with hardware
// secure decryption support.
// - ChromeOS: HW_SECURE_ALL are supported by default which is not affected by
// feature media::kHardwareSecureDecryption.
// - Linux/Mac/Windows: Feature media::kHardwareSecureDecryption is enabled, and
// command line switch kOverrideHardwareSecureCodecsForTesting is used to always
// enable vp8 and vp9, and disable avc1; always enable 'cenc' and disable
// 'cbcs'/'cbcs-1-9', for HW_SECURE* robustness levels. With the switch, real
// hardware capabilities are not checked for the stability of tests.

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineHwSecureTest,
                       Robustness) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineHwSecureTest,
                       EncryptionScheme) {}

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineHwSecureTest,
                       SessionType) {}

#if BUILDFLAG(ENABLE_PLATFORM_ENCRYPTED_DOLBY_VISION)
IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineHwSecureTest,
                       DolbyVision) {
  EXPECT_WV(IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType,
                                   dolby_vision_codecs(),
                                   SessionType::kTemporary, "HW_SECURE_ALL"));
}
#endif  // BUILDFLAG(ENABLE_PLATFORM_ENCRYPTED_DOLBY_VISION)

// Widevine experiment key systems should not be supported without the
// `kHardwareSecureDecryptionExperiment` feature enabled.
IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineHwSecureTest,
                       WidevineExperiment) {}

IN_PROC_BROWSER_TEST_F(
    EncryptedMediaSupportedTypesWidevineHwSecureForceClearLeadSupportTest,
    SupportedCodecs) {}

IN_PROC_BROWSER_TEST_F(
    EncryptedMediaSupportedTypesWidevineHwSecureExperimentTest,
    Robustness) {}

IN_PROC_BROWSER_TEST_F(
    EncryptedMediaSupportedTypesWidevineHwSecureExperimentTest,
    SupportedCodecs) {}

IN_PROC_BROWSER_TEST_F(
    EncryptedMediaSupportedTypesWidevineHwSecureDefaultAndExperimentTest,
    Robustness) {}

// Widevine key system should only support codecs that support
// clear lead.
IN_PROC_BROWSER_TEST_F(
    EncryptedMediaSupportedTypesWidevineHwSecureDefaultAndExperimentTest,
    SupportedCodecs) {}

//
// Misc failure test cases.
//

#if BUILDFLAG(ENABLE_LIBRARY_CDMS)

IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesTest,
                       ClearKeyCdmNotRegistered) {}

IN_PROC_BROWSER_TEST_F(
    EncryptedMediaSupportedTypesClearKeyCdmRegisteredWithWrongPathTest,
    Basic) {}

#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)