1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/renderers/decrypting_renderer.h"
7 #include "base/functional/bind.h"
8 #include "base/functional/callback_helpers.h"
9 #include "base/memory/raw_ptr.h"
10 #include "base/task/single_thread_task_runner.h"
11 #include "base/test/gmock_callback_support.h"
12 #include "base/test/mock_callback.h"
13 #include "base/test/task_environment.h"
14 #include "media/base/demuxer_stream.h"
15 #include "media/base/media_util.h"
16 #include "media/base/mock_filters.h"
17 #include "media/base/test_helpers.h"
18 #include "media/filters/decrypting_media_resource.h"
19 #include "testing/gmock/include/gmock/gmock.h"
21 using ::base::test::RunCallback;
22 using ::base::test::RunOnceCallback;
24 using ::testing::AnyNumber;
25 using ::testing::Invoke;
26 using ::testing::Return;
27 using ::testing::ReturnPointee;
28 using ::testing::StrictMock;
36 class DecryptingRendererTest : public testing::Test {
38 DecryptingRendererTest() {
39 auto renderer = std::make_unique<StrictMock<MockRenderer>>();
40 renderer_ = renderer.get();
41 decrypting_renderer_ = std::make_unique<DecryptingRenderer>(
42 std::move(renderer), &null_media_log_,
43 task_environment_.GetMainThreadTaskRunner());
45 EXPECT_CALL(cdm_context_, RegisterEventCB(_)).Times(AnyNumber());
46 EXPECT_CALL(cdm_context_, GetDecryptor())
47 .WillRepeatedly(Return(&decryptor_));
48 EXPECT_CALL(decryptor_, CanAlwaysDecrypt())
49 .WillRepeatedly(ReturnPointee(&use_aes_decryptor_));
50 EXPECT_CALL(decryptor_, CancelDecrypt(_)).Times(AnyNumber());
51 EXPECT_CALL(media_resource_, GetAllStreams())
52 .WillRepeatedly(Invoke(this, &DecryptingRendererTest::GetAllStreams));
53 EXPECT_CALL(media_resource_, GetType())
54 .WillRepeatedly(Return(MediaResource::Type::kStream));
57 ~DecryptingRendererTest() override {
58 // Ensure that the DecryptingRenderer is destructed before other objects
59 // that it internally references but does not own.
60 decrypting_renderer_.reset();
63 void AddStream(DemuxerStream::Type type, bool encrypted) {
64 streams_.push_back(CreateMockDemuxerStream(type, encrypted));
67 void UseAesDecryptor(bool use_aes_decryptor) {
68 use_aes_decryptor_ = use_aes_decryptor;
71 std::vector<DemuxerStream*> GetAllStreams() {
72 std::vector<DemuxerStream*> streams;
74 for (auto& stream : streams_) {
75 streams.push_back(stream.get());
82 // Invoking InitializeRenderer(false) will cause the initialization of the
83 // DecryptingRenderer to halt and an error will be propagated to the media
85 void InitializeDecryptingRendererWithFalse() {
86 decrypting_renderer_->InitializeRenderer(false);
89 bool use_aes_decryptor_ = false;
90 base::test::TaskEnvironment task_environment_;
91 base::MockCallback<Renderer::CdmAttachedCB> set_cdm_cb_;
92 base::MockOnceCallback<void(PipelineStatus)> renderer_init_cb_;
93 NullMediaLog null_media_log_;
94 StrictMock<MockCdmContext> cdm_context_;
95 StrictMock<MockDecryptor> decryptor_;
96 StrictMock<MockMediaResource> media_resource_;
97 StrictMock<MockRendererClient> renderer_client_;
98 raw_ptr<StrictMock<MockRenderer>, DanglingUntriaged> renderer_;
99 std::unique_ptr<DecryptingRenderer> decrypting_renderer_;
100 std::vector<std::unique_ptr<StrictMock<MockDemuxerStream>>> streams_;
103 TEST_F(DecryptingRendererTest, ClearStreams_NoCdm) {
104 AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
105 AddStream(DemuxerStream::VIDEO, /* encrypted = */ false);
107 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
108 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
109 EXPECT_CALL(renderer_init_cb_, Run(HasStatusCode(PIPELINE_OK)));
111 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
112 renderer_init_cb_.Get());
113 task_environment_.RunUntilIdle();
115 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
118 TEST_F(DecryptingRendererTest, ClearStreams_AesDecryptor) {
119 AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
120 AddStream(DemuxerStream::VIDEO, /* encrypted = */ false);
121 UseAesDecryptor(true);
123 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
124 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
125 EXPECT_CALL(set_cdm_cb_, Run(true));
126 EXPECT_CALL(renderer_init_cb_, Run(HasStatusCode(PIPELINE_OK)));
128 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
129 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
130 renderer_init_cb_.Get());
131 task_environment_.RunUntilIdle();
133 EXPECT_TRUE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
136 TEST_F(DecryptingRendererTest, ClearStreams_OtherCdm) {
137 AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
138 AddStream(DemuxerStream::VIDEO, /* encrypted = */ false);
140 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
141 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
142 EXPECT_CALL(*renderer_, OnSetCdm(_, _)).WillOnce(RunOnceCallback<1>(true));
143 EXPECT_CALL(renderer_init_cb_, Run(HasStatusCode(PIPELINE_OK)));
144 EXPECT_CALL(set_cdm_cb_, Run(true));
146 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
147 renderer_init_cb_.Get());
148 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
149 task_environment_.RunUntilIdle();
151 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
154 TEST_F(DecryptingRendererTest, EncryptedStreams_NoCdm) {
155 AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
156 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
158 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
159 renderer_init_cb_.Get());
160 task_environment_.RunUntilIdle();
162 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
165 TEST_F(DecryptingRendererTest, EncryptedStreams_AesDecryptor) {
166 AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
167 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
168 UseAesDecryptor(true);
170 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
171 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
172 EXPECT_CALL(renderer_init_cb_, Run(HasStatusCode(PIPELINE_OK)));
173 EXPECT_CALL(set_cdm_cb_, Run(true));
175 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
176 renderer_init_cb_.Get());
177 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
178 task_environment_.RunUntilIdle();
180 EXPECT_TRUE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
183 TEST_F(DecryptingRendererTest, EncryptedStreams_OtherCdm) {
184 AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
185 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
187 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
188 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
189 EXPECT_CALL(*renderer_, OnSetCdm(_, _)).WillOnce(RunOnceCallback<1>(true));
190 EXPECT_CALL(renderer_init_cb_, Run(HasStatusCode(PIPELINE_OK)));
191 EXPECT_CALL(set_cdm_cb_, Run(true));
193 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
194 renderer_init_cb_.Get());
195 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
196 task_environment_.RunUntilIdle();
198 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
201 TEST_F(DecryptingRendererTest, EncryptedStreams_AesDecryptor_CdmSetBeforeInit) {
202 AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
203 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
204 UseAesDecryptor(true);
206 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
207 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
208 EXPECT_CALL(renderer_init_cb_, Run(HasStatusCode(PIPELINE_OK)));
209 EXPECT_CALL(set_cdm_cb_, Run(true));
211 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
212 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
213 renderer_init_cb_.Get());
214 task_environment_.RunUntilIdle();
216 EXPECT_TRUE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
219 TEST_F(DecryptingRendererTest, EncryptedStreams_OtherCdm_CdmSetBeforeInit) {
220 AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
221 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
223 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
224 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
225 EXPECT_CALL(*renderer_, OnSetCdm(_, _)).WillOnce(RunOnceCallback<1>(true));
226 EXPECT_CALL(renderer_init_cb_, Run(HasStatusCode(PIPELINE_OK)));
227 EXPECT_CALL(set_cdm_cb_, Run(true));
229 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
230 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
231 renderer_init_cb_.Get());
232 task_environment_.RunUntilIdle();
234 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
237 TEST_F(DecryptingRendererTest, EncryptedAndClearStream_OtherCdm) {
238 AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
239 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
241 EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
242 .WillOnce(RunOnceCallback<2>(PIPELINE_OK));
243 EXPECT_CALL(*renderer_, OnSetCdm(_, _)).WillOnce(RunOnceCallback<1>(true));
244 EXPECT_CALL(renderer_init_cb_, Run(HasStatusCode(PIPELINE_OK)));
245 EXPECT_CALL(set_cdm_cb_, Run(true));
247 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
248 renderer_init_cb_.Get());
249 decrypting_renderer_->SetCdm(&cdm_context_, set_cdm_cb_.Get());
250 task_environment_.RunUntilIdle();
252 EXPECT_FALSE(decrypting_renderer_->HasDecryptingMediaResourceForTesting());
255 TEST_F(DecryptingRendererTest, DecryptingMediaResourceInitFails) {
256 AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
257 AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
258 UseAesDecryptor(true);
260 EXPECT_CALL(renderer_init_cb_,
261 Run(HasStatusCode(PIPELINE_ERROR_INITIALIZATION_FAILED)));
263 decrypting_renderer_->Initialize(&media_resource_, &renderer_client_,
264 renderer_init_cb_.Get());
265 task_environment_.RunUntilIdle();
267 // Cause a PIPELINE_ERROR_INITIALIZATION_FAILED error to be passed as a
268 // parameter to the initialization callback.
269 InitializeDecryptingRendererWithFalse();