1 // Copyright 2018 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 "media/renderers/decrypting_renderer.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/test/gmock_callback_support.h"
11 #include "base/test/mock_callback.h"
12 #include "base/test/task_environment.h"
13 #include "media/base/demuxer_stream.h"
14 #include "media/base/media_util.h"
15 #include "media/base/mock_filters.h"
16 #include "media/base/test_helpers.h"
17 #include "media/filters/decrypting_media_resource.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19
20 using ::base::test::RunCallback;
21 using ::base::test::RunOnceCallback;
22 using ::testing::_;
23 using ::testing::AnyNumber;
24 using ::testing::Invoke;
25 using ::testing::Return;
26 using ::testing::ReturnPointee;
27 using ::testing::StrictMock;
28
29 namespace media {
30
31 class CdmContext;
32 class DemuxerStream;
33 class MediaLog;
34
35 class DecryptingRendererTest : public testing::Test {
36 public:
DecryptingRendererTest()37 DecryptingRendererTest() {
38 auto renderer = std::make_unique<StrictMock<MockRenderer>>();
39 renderer_ = renderer.get();
40 decrypting_renderer_ = std::make_unique<DecryptingRenderer>(
41 std::move(renderer), &null_media_log_,
42 task_environment_.GetMainThreadTaskRunner());
43
44 EXPECT_CALL(cdm_context_, GetDecryptor())
45 .WillRepeatedly(Return(&decryptor_));
46 EXPECT_CALL(decryptor_, CanAlwaysDecrypt())
47 .WillRepeatedly(ReturnPointee(&use_aes_decryptor_));
48 EXPECT_CALL(decryptor_, CancelDecrypt(_)).Times(AnyNumber());
49 EXPECT_CALL(decryptor_, RegisterNewKeyCB(_, _)).Times(AnyNumber());
50 EXPECT_CALL(media_resource_, GetAllStreams())
51 .WillRepeatedly(Invoke(this, &DecryptingRendererTest::GetAllStreams));
52 EXPECT_CALL(media_resource_, GetType())
53 .WillRepeatedly(Return(MediaResource::STREAM));
54 }
55
~DecryptingRendererTest()56 ~DecryptingRendererTest() override {
57 // Ensure that the DecryptingRenderer is destructed before other objects
58 // that it internally references but does not own.
59 decrypting_renderer_.reset();
60 }
61
AddStream(DemuxerStream::Type type,bool encrypted)62 void AddStream(DemuxerStream::Type type, bool encrypted) {
63 streams_.push_back(CreateMockDemuxerStream(type, encrypted));
64 }
65
UseAesDecryptor(bool use_aes_decryptor)66 void UseAesDecryptor(bool use_aes_decryptor) {
67 use_aes_decryptor_ = use_aes_decryptor;
68 }
69
GetAllStreams()70 std::vector<DemuxerStream*> GetAllStreams() {
71 std::vector<DemuxerStream*> streams;
72
73 for (auto& stream : streams_) {
74 streams.push_back(stream.get());
75 }
76
77 return streams;
78 }
79
80 protected:
81 // Invoking InitializeRenderer(false) will cause the initialization of the
82 // DecryptingRenderer to halt and an error will be propagated to the media
83 // pipeline.
InitializeDecryptingRendererWithFalse()84 void InitializeDecryptingRendererWithFalse() {
85 decrypting_renderer_->InitializeRenderer(false);
86 }
87
88 bool use_aes_decryptor_ = false;
89 base::test::TaskEnvironment task_environment_;
90 base::MockCallback<CdmAttachedCB> set_cdm_cb_;
91 base::MockOnceCallback<void(PipelineStatus)> renderer_init_cb_;
92 NullMediaLog null_media_log_;
93 StrictMock<MockCdmContext> cdm_context_;
94 StrictMock<MockDecryptor> decryptor_;
95 StrictMock<MockMediaResource> media_resource_;
96 StrictMock<MockRendererClient> renderer_client_;
97 StrictMock<MockRenderer>* renderer_;
98 std::unique_ptr<DecryptingRenderer> decrypting_renderer_;
99 std::vector<std::unique_ptr<StrictMock<MockDemuxerStream>>> streams_;
100 };
101
TEST_F(DecryptingRendererTest,ClearStreams_NoCdm)102 TEST_F(DecryptingRendererTest, ClearStreams_NoCdm) {
103 AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
104 AddStream(DemuxerStream::VIDEO, /* encrypted = */ false);
105
106 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
107 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
108 EXPECT_CALL(renderer_init_cb_, Run(PIPELINE_OK));
109
110 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
111 renderer_init_cb_.Get());
112 task_environment_.RunUntilIdle();
113
114 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
115 }
116
TEST_F(DecryptingRendererTest,ClearStreams_AesDecryptor)117 TEST_F(DecryptingRendererTest, ClearStreams_AesDecryptor) {
118 AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
119 AddStream(DemuxerStream::VIDEO, /* encrypted = */ false);
120 UseAesDecryptor(true);
121
122 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
123 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
124 EXPECT_CALL(set_cdm_cb_, Run(true));
125 EXPECT_CALL(renderer_init_cb_, Run(PIPELINE_OK));
126
127 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
128 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
129 renderer_init_cb_.Get());
130 task_environment_.RunUntilIdle();
131
132 EXPECT_TRUE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
133 }
134
TEST_F(DecryptingRendererTest,ClearStreams_OtherCdm)135 TEST_F(DecryptingRendererTest, ClearStreams_OtherCdm) {
136 AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
137 AddStream(DemuxerStream::VIDEO, /* encrypted = */ false);
138
139 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
140 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
141 EXPECT_CALL(*renderer_, OnSetCdm(_, _)).WillOnce(RunOnceCallback<1>(true));
142 EXPECT_CALL(renderer_init_cb_, Run(PIPELINE_OK));
143 EXPECT_CALL(set_cdm_cb_, Run(true));
144
145 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
146 renderer_init_cb_.Get());
147 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
148 task_environment_.RunUntilIdle();
149
150 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
151 }
152
TEST_F(DecryptingRendererTest,EncryptedStreams_NoCdm)153 TEST_F(DecryptingRendererTest, EncryptedStreams_NoCdm) {
154 AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
155 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
156
157 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
158 renderer_init_cb_.Get());
159 task_environment_.RunUntilIdle();
160
161 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
162 }
163
TEST_F(DecryptingRendererTest,EncryptedStreams_AesDecryptor)164 TEST_F(DecryptingRendererTest, EncryptedStreams_AesDecryptor) {
165 AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
166 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
167 UseAesDecryptor(true);
168
169 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
170 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
171 EXPECT_CALL(renderer_init_cb_, Run(PIPELINE_OK));
172 EXPECT_CALL(set_cdm_cb_, Run(true));
173
174 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
175 renderer_init_cb_.Get());
176 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
177 task_environment_.RunUntilIdle();
178
179 EXPECT_TRUE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
180 }
181
TEST_F(DecryptingRendererTest,EncryptedStreams_OtherCdm)182 TEST_F(DecryptingRendererTest, EncryptedStreams_OtherCdm) {
183 AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
184 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
185
186 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
187 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
188 EXPECT_CALL(*renderer_, OnSetCdm(_, _)).WillOnce(RunOnceCallback<1>(true));
189 EXPECT_CALL(renderer_init_cb_, Run(PIPELINE_OK));
190 EXPECT_CALL(set_cdm_cb_, Run(true));
191
192 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
193 renderer_init_cb_.Get());
194 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
195 task_environment_.RunUntilIdle();
196
197 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
198 }
199
TEST_F(DecryptingRendererTest,EncryptedStreams_AesDecryptor_CdmSetBeforeInit)200 TEST_F(DecryptingRendererTest, EncryptedStreams_AesDecryptor_CdmSetBeforeInit) {
201 AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
202 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
203 UseAesDecryptor(true);
204
205 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
206 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
207 EXPECT_CALL(renderer_init_cb_, Run(PIPELINE_OK));
208 EXPECT_CALL(set_cdm_cb_, Run(true));
209
210 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
211 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
212 renderer_init_cb_.Get());
213 task_environment_.RunUntilIdle();
214
215 EXPECT_TRUE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
216 }
217
TEST_F(DecryptingRendererTest,EncryptedStreams_OtherCdm_CdmSetBeforeInit)218 TEST_F(DecryptingRendererTest, EncryptedStreams_OtherCdm_CdmSetBeforeInit) {
219 AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
220 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
221
222 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
223 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
224 EXPECT_CALL(*renderer_, OnSetCdm(_, _)).WillOnce(RunOnceCallback<1>(true));
225 EXPECT_CALL(renderer_init_cb_, Run(PIPELINE_OK));
226 EXPECT_CALL(set_cdm_cb_, Run(true));
227
228 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
229 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
230 renderer_init_cb_.Get());
231 task_environment_.RunUntilIdle();
232
233 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
234 }
235
TEST_F(DecryptingRendererTest,EncryptedAndClearStream_OtherCdm)236 TEST_F(DecryptingRendererTest, EncryptedAndClearStream_OtherCdm) {
237 AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
238 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
239
240 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
241 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
242 EXPECT_CALL(*renderer_, OnSetCdm(_, _)).WillOnce(RunOnceCallback<1>(true));
243 EXPECT_CALL(renderer_init_cb_, Run(PIPELINE_OK));
244 EXPECT_CALL(set_cdm_cb_, Run(true));
245
246 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
247 renderer_init_cb_.Get());
248 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
249 task_environment_.RunUntilIdle();
250
251 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
252 }
253
TEST_F(DecryptingRendererTest,DecryptingMediaResourceInitFails)254 TEST_F(DecryptingRendererTest, DecryptingMediaResourceInitFails) {
255 AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
256 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
257 UseAesDecryptor(true);
258
259 EXPECT_CALL(renderer_init_cb_, Run(PIPELINE_ERROR_INITIALIZATION_FAILED));
260
261 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
262 renderer_init_cb_.Get());
263 task_environment_.RunUntilIdle();
264
265 // Cause a PIPELINE_ERROR_INITIALIZATION_FAILED error to be passed as a
266 // parameter to the initialization callback.
267 InitializeDecryptingRendererWithFalse();
268 }
269
270 } // namespace media
271