1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/command_line.h"
6#include "base/strings/utf_string_conversions.h"
7#include "base/win/windows_version.h"
8#include "content/browser/media/media_browsertest.h"
9#include "content/public/common/content_switches.h"
10#include "content/public/test/browser_test_utils.h"
11#include "content/shell/browser/shell.h"
12#if defined(OS_ANDROID)
13#include "base/android/build_info.h"
14#endif
15
16// Available key systems.
17const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey";
18
19// Supported media types.
20const char kWebMAudioOnly[] = "audio/webm; codecs=\"vorbis\"";
21const char kWebMVideoOnly[] = "video/webm; codecs=\"vp8\"";
22const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
23
24// EME-specific test results and errors.
25const char kEmeKeyError[] = "KEYERROR";
26const char kEmeNotSupportedError[] = "NOTSUPPORTEDERROR";
27
28const char kDefaultEmePlayer[] = "eme_player.html";
29
30// The type of video src used to load media.
31enum SrcType {
32  SRC,
33  MSE
34};
35
36namespace content {
37
38// MSE is available on all desktop platforms and on Android 4.1 and later.
39static bool IsMSESupported() {
40#if defined(OS_ANDROID)
41  if (base::android::BuildInfo::GetInstance()->sdk_int() < 16) {
42    VLOG(0) << "MSE is only supported in Android 4.1 and later.";
43    return false;
44  }
45#endif  // defined(OS_ANDROID)
46  return true;
47}
48
49// Tests encrypted media playback with a combination of parameters:
50// - char*: Key system name.
51// - bool: True to load media using MSE, otherwise use src.
52class EncryptedMediaTest : public content::MediaBrowserTest,
53    public testing::WithParamInterface<std::tr1::tuple<const char*, SrcType> > {
54 public:
55  // Can only be used in parameterized (*_P) tests.
56  const std::string CurrentKeySystem() {
57    return std::tr1::get<0>(GetParam());
58  }
59
60  // Can only be used in parameterized (*_P) tests.
61  SrcType CurrentSourceType() {
62    return std::tr1::get<1>(GetParam());
63  }
64
65  void TestSimplePlayback(const std::string& encrypted_media,
66                          const std::string& media_type) {
67    RunSimpleEncryptedMediaTest(
68        encrypted_media, media_type, CurrentKeySystem(), CurrentSourceType());
69  }
70
71  void TestFrameSizeChange() {
72    RunEncryptedMediaTest("encrypted_frame_size_change.html",
73                          "frame_size_change-av_enc-v.webm", kWebMAudioVideo,
74                          CurrentKeySystem(), CurrentSourceType(), kEnded);
75  }
76
77  void TestConfigChange() {
78    if (CurrentSourceType() != MSE || !IsMSESupported()) {
79      VLOG(0) << "Skipping test - config change test requires MSE.";
80      return;
81    }
82
83    media::QueryParams query_params;
84    query_params.push_back(std::make_pair("keySystem", CurrentKeySystem()));
85    query_params.push_back(std::make_pair("runEncrypted", "1"));
86    RunMediaTestPage("mse_config_change.html", query_params, kEnded, true);
87  }
88
89  void RunEncryptedMediaTest(const std::string& html_page,
90                             const std::string& media_file,
91                             const std::string& media_type,
92                             const std::string& key_system,
93                             SrcType src_type,
94                             const std::string& expectation) {
95#if defined(OS_ANDROID) && defined(__aarch64__)
96    // Disable EME tests on arm64 due to timeouts: http://crbug.com/418039
97    return;
98#endif
99    if (src_type == MSE && !IsMSESupported()) {
100      VLOG(0) << "Skipping test - MSE not supported.";
101      return;
102    }
103
104    media::QueryParams query_params;
105    query_params.push_back(std::make_pair("mediaFile", media_file));
106    query_params.push_back(std::make_pair("mediaType", media_type));
107    query_params.push_back(std::make_pair("keySystem", key_system));
108    if (src_type == MSE)
109      query_params.push_back(std::make_pair("useMSE", "1"));
110    RunMediaTestPage(html_page, query_params, expectation, true);
111  }
112
113  void RunSimpleEncryptedMediaTest(const std::string& media_file,
114                                   const std::string& media_type,
115                                   const std::string& key_system,
116                                   SrcType src_type) {
117    RunEncryptedMediaTest(kDefaultEmePlayer,
118                          media_file,
119                          media_type,
120                          key_system,
121                          src_type,
122                          kEnded);
123  }
124
125 protected:
126  // We want to fail quickly when a test fails because an error is encountered.
127  virtual void AddWaitForTitles(content::TitleWatcher* title_watcher) OVERRIDE {
128    MediaBrowserTest::AddWaitForTitles(title_watcher);
129    title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kEmeNotSupportedError));
130    title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kEmeKeyError));
131  }
132
133#if defined(OS_ANDROID)
134  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
135    command_line->AppendSwitch(
136        switches::kDisableGestureRequirementForMediaPlayback);
137  }
138#endif
139};
140
141using ::testing::Combine;
142using ::testing::Values;
143
144#if !defined(OS_ANDROID)
145// Encrypted media playback with SRC is not supported on Android.
146INSTANTIATE_TEST_CASE_P(SRC_ClearKey, EncryptedMediaTest,
147                        Combine(Values(kClearKeyKeySystem), Values(SRC)));
148#endif  // !defined(OS_ANDROID)
149
150INSTANTIATE_TEST_CASE_P(MSE_ClearKey, EncryptedMediaTest,
151                        Combine(Values(kClearKeyKeySystem), Values(MSE)));
152
153IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM) {
154  TestSimplePlayback("bear-a_enc-a.webm", kWebMAudioOnly);
155}
156
157IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioClearVideo_WebM) {
158  TestSimplePlayback("bear-320x240-av_enc-a.webm", kWebMAudioVideo);
159}
160
161IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM) {
162  TestSimplePlayback("bear-320x240-av_enc-av.webm", kWebMAudioVideo);
163}
164
165IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM) {
166  TestSimplePlayback("bear-320x240-v_enc-v.webm", kWebMVideoOnly);
167}
168
169IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM) {
170  TestSimplePlayback("bear-320x240-av_enc-v.webm", kWebMAudioVideo);
171}
172
173IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo) {
174  TestConfigChange();
175}
176
177IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameSizeChangeVideo) {
178  // Times out on Windows XP. http://crbug.com/171937
179#if defined(OS_WIN)
180  if (base::win::GetVersion() < base::win::VERSION_VISTA)
181    return;
182#endif
183  TestFrameSizeChange();
184}
185
186IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, UnknownKeySystemThrowsException) {
187  RunEncryptedMediaTest(kDefaultEmePlayer,
188                        "bear-a_enc-a.webm",
189                        kWebMAudioOnly,
190                        "com.example.foo",
191                        MSE,
192                        kEmeNotSupportedError);
193}
194
195}  // namespace content
196