chromium/content/browser/media/encrypted_media_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 <tuple>

#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/media/media_browsertest.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "media/base/media.h"
#include "media/base/media_switches.h"
#include "media/base/test_data_util.h"
#include "media/cdm/clear_key_cdm_common.h"
#include "media/media_buildflags.h"
#include "media/mojo/buildflags.h"

#if BUILDFLAG(IS_ANDROID)
#include "base/android/build_info.h"
#include "media/base/android/media_codec_util.h"
#endif

#if BUILDFLAG(IS_WIN)
#include "base/win/windows_version.h"
#endif

// External Clear Key is a test-only key system that has mostly the same
// functionality as Clear Key key system. Unlike Clear Key, which is implemented
// by AesDecryptor in the render process directly, External Clear Key is
// implemented by hosting a CDM that supports Clear Key (e.g. AesDecryptor) in a
// remote processes to cover the code path used by a real production CDM, which
// is otherwise hard to cover by tests.
// - When ENABLE_LIBRARY_CDMS is true, a "Clear Key CDM" that implements the
//   "Library CDM API" is hosted in the CDM/utility process to do decryption and
//   decoding. This covers MojoCdm, MojoDecryptor, CdmAdapter, CdmFileIO etc.
//   See //media/cdm/library_cdm/clear_key_cdm/README.md.
// - Otherwise when ENABLE_MOJO_CDM is true, External Clear Key is supported in
//   content/shell/ by using MojoCdm with AesDecryptor running in a remote
//   process, e.g. GPU or Browser, as specified by |mojo_media_host|. The
//   connection between the media pipeline and the CDM varies on different
//   platforms. For example, the media pipeline could choose the default
//   RendererImpl in the render process, which can use the remote CDM to do
//   decryption via MojoDecryptor. The media pipeline could also choose
//   MojoRenderer, which hosts a RendererImpl in the remote process, which uses
//   the Decryptor exposed by the AesDecryptor directly in the remote process.
//   See TestMojoMediaClient for details on this path.

// TODO (b/263310318) Enable on Android when Clear Key issues on Android are
// fixed.
#if BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(ENABLE_LIBRARY_CDMS)
#define SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL
#endif

namespace content {

// EME-specific test results and errors.
const char16_t kEmeKeyError[] =;
const char kEmeNotSupportedError[] =;
const char16_t kEmeNotSupportedError16[] =;

const char kDefaultEmePlayer[] =;
const char kDefaultMseOnlyEmePlayer[] =;

// The type of video src used to load media.
enum class SrcType {};

// Must be in sync with CONFIG_CHANGE_TYPE in eme_player_js/global.js
enum class ConfigChangeType {};

// Tests encrypted media playback with a combination of parameters:
// - char*: Key system name.
// - SrcType: The type of video src used to load media, MSE or SRC.
// It is okay to run this test as a non-parameterized test, in this case,
// GetParam() should not be called.
class EncryptedMediaTest
    : public MediaBrowserTest,
      public testing::WithParamInterface<std::tuple<const char*, SrcType>> {};

Combine;
Values;

INSTANTIATE_TEST_SUITE_P();

INSTANTIATE_TEST_SUITE_P();

#if defined(SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL)
INSTANTIATE_TEST_SUITE_P(SRC_ExternalClearKey,
                         EncryptedMediaTest,
                         Combine(Values(media::kExternalClearKeyKeySystem),
                                 Values(SrcType::SRC)));

INSTANTIATE_TEST_SUITE_P(MSE_ExternalClearKey,
                         EncryptedMediaTest,
                         Combine(Values(media::kExternalClearKeyKeySystem),
                                 Values(SrcType::MSE)));
#endif

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioClearVideo_WebM) {}

// TODO(crbug.com/40784898): Flaky on Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_Playback_VideoAudio_WebM
#else
#define MAYBE_Playback_VideoAudio_WebM
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, MAYBE_Playback_VideoAudio_WebM) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM) {}

// TODO(crbug.com/40116008): Flaky on multiple platforms.
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       DISABLED_Playback_VideoOnly_WebM_Fullsample) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM_Subsample) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM) {}

// TODO(crbug.com/40784898): Flaky on Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_Playback_VideoAudio_WebM_Opus
#else
#define MAYBE_Playback_VideoAudio_WebM_Opus
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       MAYBE_Playback_VideoAudio_WebM_Opus) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM_Opus) {}

// TODO(crbug.com/40863269): Flaky on Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_Playback_VideoClearAudio_WebM_Opus
#else
#define MAYBE_Playback_VideoClearAudio_WebM_Opus
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       MAYBE_Playback_VideoClearAudio_WebM_Opus) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4_FLAC) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4_OPUS) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) {}

// TODO(crbug.com/40513452): Decide when it's supported on Android.
#if !BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_FUCHSIA) && defined(ARCH_CPU_ARM_FAMILY))
// TODO(crbug.com/40187305): Failing on Mac.
// TODO(crbug.com/40208879): Failing on Fuchsia arm.
#define MAYBE_Playback_VideoOnly_WebM_VP9Profile2
#else
#define MAYBE_Playback_VideoOnly_WebM_VP9Profile2
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       MAYBE_Playback_VideoOnly_WebM_VP9Profile2) {}

#if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_FUCHSIA) && defined(ARCH_CPU_ARM_FAMILY))
// TODO(crbug.com/40805145): Failing on Mac.
// TODO(crbug.com/40208879): Failing on Fuchsia arm.
#define MAYBE_Playback_VideoOnly_MP4_VP9Profile2
#else
#define MAYBE_Playback_VideoOnly_MP4_VP9Profile2
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       MAYBE_Playback_VideoOnly_MP4_VP9Profile2) {}
#endif  // !BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(ENABLE_AV1_DECODER)
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM_AV1) {}

// TODO(crbug.com/40863206): Flaky on Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_Playback_VideoOnly_WebM_AV1_10bit
#else
#define MAYBE_Playback_VideoOnly_WebM_AV1_10bit
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       MAYBE_Playback_VideoOnly_WebM_AV1_10bit) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_AV1) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_AV1_10bit) {}
#endif  // BUILDFLAG(ENABLE_AV1_DECODER)

// Strictly speaking this is not an "encrypted" media test. Keep it here for
// completeness.
// TODO(crbug.com/330190697): Flaky on Fuchsia, deflake and re-enable the test.
#if BUILDFLAG(IS_FUCHSIA)
#define MAYBE_ConfigChangeVideo_ClearToClear
#else
#define MAYBE_ConfigChangeVideo_ClearToClear
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       MAYBE_ConfigChangeVideo_ClearToClear) {}

// Failed on Android, see https://crbug.com/1014540.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_ConfigChangeVideo_ClearToEncrypted
#else
#define MAYBE_ConfigChangeVideo_ClearToEncrypted
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       MAYBE_ConfigChangeVideo_ClearToEncrypted) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo_EncryptedToClear) {}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       ConfigChangeVideo_EncryptedToEncrypted) {}

// Fails on Android (https://crbug.com/778245 and https://crbug.com/1023638).
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_FrameSizeChangeVideo
#else
#define MAYBE_FrameSizeChangeVideo
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, MAYBE_FrameSizeChangeVideo) {}

#if BUILDFLAG(USE_PROPRIETARY_CODECS)
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CENC) {
  RunMultipleFileTest("bear-640x360-v_frag-cenc.mp4",
                      "bear-640x360-a_frag-cenc.mp4", media::kEndedTitle);
}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CBC1) {
  RunMultipleFileTest("bear-640x360-v_frag-cbc1.mp4", std::string(),
                      media::kErrorTitle);
}

// TODO(crbug.com/40863223): Flaky on Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_Playback_Encryption_CENS
#else
#define MAYBE_Playback_Encryption_CENS
#endif
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, MAYBE_Playback_Encryption_CENS) {
  RunMultipleFileTest("bear-640x360-v_frag-cens.mp4", std::string(),
                      media::kErrorTitle);
}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_Encryption_CBCS) {
  RunMultipleFileTest("bear-640x360-v_frag-cbcs.mp4",
                      "bear-640x360-a_frag-cbcs.mp4", media::kEndedTitle);
}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       Playback_Encryption_CBCS_Video_CENC_Audio) {
  RunMultipleFileTest("bear-640x360-v_frag-cbcs.mp4",
                      "bear-640x360-a_frag-cenc.mp4", media::kEndedTitle);
}

IN_PROC_BROWSER_TEST_P(EncryptedMediaTest,
                       Playback_Encryption_CENC_Video_CBCS_Audio) {
  RunMultipleFileTest("bear-640x360-v_frag-cenc.mp4",
                      "bear-640x360-a_frag-cbcs.mp4", media::kEndedTitle);
}
#endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)

IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, UnknownKeySystemThrowsException) {}

}  // namespace content