1 // Copyright 2020 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 "chromeos/components/cdm_factory_daemon/content_decryption_module_adapter.h"
6 
7 #include <algorithm>
8 
9 #include "base/logging.h"
10 #include "base/test/mock_callback.h"
11 #include "base/test/task_environment.h"
12 #include "media/base/decoder_buffer.h"
13 #include "media/base/mock_filters.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 using DaemonCdm = chromeos::cdm::mojom::ContentDecryptionModule;
18 using testing::_;
19 using testing::IsNull;
20 
21 namespace chromeos {
22 
23 namespace {
24 
25 constexpr char kFakeEmeInitData[] = "fake_init_data";
26 const std::vector<uint8_t> kFakeEncryptedData = {42, 22, 26, 13, 7, 16, 8, 2};
27 const std::vector<uint8_t> kFakeSideData = {36, 24, 36};
28 constexpr char kFakeKeyId[] = "fake_key_id";
29 constexpr char kFakeIv[] = "fake_iv_16_bytes";
30 constexpr char kFakeServiceCertificate[] = "fake_service_cert";
31 constexpr char kFakeSessionId1[] = "fakeSid1";
32 constexpr char kFakeSessionId2[] = "fakeSid2";
33 constexpr char kFakeSessionUpdate[] = "fake_session_update";
34 
35 constexpr int64_t kFakeTimestampSec = 42;
36 constexpr int64_t kFakeDurationSec = 64;
37 
38 template <size_t size>
ToVector(const char (& array)[size])39 std::vector<uint8_t> ToVector(const char (&array)[size]) {
40   return std::vector<uint8_t>(array, array + size - 1);
41 }
42 
43 MATCHER_P(MatchesDecoderBuffer, buffer, "") {
44   DCHECK(arg);
45   return arg->MatchesForTesting(*buffer);
46 }
47 
48 MATCHER_P(MatchesDecryptConfig, config, "") {
49   DCHECK(arg);
50   return arg.Equals(*config);
51 }
52 
53 // Mock of the mojo implementation on the Chrome OS side.
54 class MockDaemonCdm : public cdm::mojom::ContentDecryptionModule {
55  public:
MockDaemonCdm(mojo::PendingAssociatedReceiver<ContentDecryptionModule> pending_receiver)56   MockDaemonCdm(mojo::PendingAssociatedReceiver<ContentDecryptionModule>
57                     pending_receiver) {
58     receiver_.Bind(std::move(pending_receiver));
59   }
60   ~MockDaemonCdm() = default;
61 
62   MOCK_METHOD(void,
63               SetServerCertificate,
64               (const std::vector<uint8_t>&, SetServerCertificateCallback));
65   MOCK_METHOD(void,
66               GetStatusForPolicy,
67               (media::HdcpVersion, GetStatusForPolicyCallback));
68   MOCK_METHOD(void,
69               CreateSessionAndGenerateRequest,
70               (media::CdmSessionType,
71                media::EmeInitDataType,
72                const std::vector<uint8_t>&,
73                CreateSessionAndGenerateRequestCallback));
74   MOCK_METHOD(void,
75               LoadSession,
76               (media::CdmSessionType, const std::string&, LoadSessionCallback));
77   MOCK_METHOD(void,
78               UpdateSession,
79               (const std::string&,
80                const std::vector<uint8_t>&,
81                UpdateSessionCallback));
82   MOCK_METHOD(void, CloseSession, (const std::string&, CloseSessionCallback));
83   MOCK_METHOD(void, RemoveSession, (const std::string&, RemoveSessionCallback));
84   MOCK_METHOD(void,
85               Decrypt,
86               (const std::vector<uint8_t>&,
87                cdm::mojom::DecryptConfigPtr,
88                DecryptCallback));
89   MOCK_METHOD(void,
90               GetHwKeyData,
91               (cdm::mojom::DecryptConfigPtr,
92                const std::vector<uint8_t>&,
93                GetHwKeyDataCallback callback));
94 
95  private:
96   mojo::AssociatedReceiver<ContentDecryptionModule> receiver_{this};
97 };
98 
CreatePromise(bool success)99 cdm::mojom::CdmPromiseResultPtr CreatePromise(bool success) {
100   cdm::mojom::CdmPromiseResultPtr promise = cdm::mojom::CdmPromiseResult::New();
101   promise->success = success;
102   if (!success) {
103     promise->error_message = "error";
104   }
105   return promise;
106 }
107 
CreateDecoderBuffer(const std::vector<uint8_t> data)108 scoped_refptr<media::DecoderBuffer> CreateDecoderBuffer(
109     const std::vector<uint8_t> data) {
110   scoped_refptr<media::DecoderBuffer> buffer = media::DecoderBuffer::CopyFrom(
111       data.data(), data.size(), kFakeSideData.data(), kFakeSideData.size());
112   buffer->set_timestamp(base::TimeDelta::FromSeconds(kFakeTimestampSec));
113   buffer->set_duration(base::TimeDelta::FromSeconds(kFakeDurationSec));
114   return buffer;
115 }
116 
CloneDecoderBuffer(scoped_refptr<media::DecoderBuffer> buffer_in)117 scoped_refptr<media::DecoderBuffer> CloneDecoderBuffer(
118     scoped_refptr<media::DecoderBuffer> buffer_in) {
119   scoped_refptr<media::DecoderBuffer> buffer_out =
120       media::DecoderBuffer::CopyFrom(buffer_in->data(), buffer_in->data_size(),
121                                      buffer_in->side_data(),
122                                      buffer_in->side_data_size());
123   buffer_out->set_timestamp(buffer_in->timestamp());
124   buffer_out->set_duration(buffer_in->duration());
125   if (buffer_in->decrypt_config())
126     buffer_out->set_decrypt_config(buffer_in->decrypt_config()->Clone());
127   buffer_out->set_is_key_frame(buffer_in->is_key_frame());
128   return buffer_out;
129 }
130 
131 }  // namespace
132 
133 class ContentDecryptionModuleAdapterTest : public testing::Test {
134  protected:
ContentDecryptionModuleAdapterTest()135   ContentDecryptionModuleAdapterTest() {
136     mojo::AssociatedRemote<cdm::mojom::ContentDecryptionModule> daemon_cdm_mojo;
137     mock_daemon_cdm_ = std::make_unique<MockDaemonCdm>(
138         daemon_cdm_mojo.BindNewEndpointAndPassDedicatedReceiver());
139     cdm_adapter_ = base::WrapRefCounted<ContentDecryptionModuleAdapter>(
140         new ContentDecryptionModuleAdapter(
141             nullptr /* storage */, std::move(daemon_cdm_mojo),
142             mock_session_message_cb_.Get(), mock_session_closed_cb_.Get(),
143             mock_session_keys_change_cb_.Get(),
144             mock_session_expiration_update_cb_.Get()));
145   }
146 
~ContentDecryptionModuleAdapterTest()147   ~ContentDecryptionModuleAdapterTest() override {
148     // Destroy the CdmAdapter first so it can invoke any session closed
149     // callbacks on destruction before we destroy the callback mockers.
150     cdm_adapter_.reset();
151   }
152 
LoadSession()153   void LoadSession() {
154     EXPECT_CALL(*mock_daemon_cdm_,
155                 LoadSession(media::CdmSessionType::kPersistentLicense,
156                             kFakeSessionId1, _))
157         .WillOnce([](media::CdmSessionType session_type,
158                      const std::string& session_id,
159                      MockDaemonCdm::LoadSessionCallback callback) {
160           std::move(callback).Run(CreatePromise(true), kFakeSessionId2);
161         });
162     std::string session_id;
163     std::unique_ptr<media::MockCdmSessionPromise> promise =
164         std::make_unique<media::MockCdmSessionPromise>(true, &session_id);
165     cdm_adapter_->LoadSession(media::CdmSessionType::kPersistentLicense,
166                               kFakeSessionId1, std::move(promise));
167     base::RunLoop().RunUntilIdle();
168     EXPECT_EQ(session_id, kFakeSessionId2);
169   }
170 
171   scoped_refptr<ContentDecryptionModuleAdapter> cdm_adapter_;
172   std::unique_ptr<MockDaemonCdm> mock_daemon_cdm_;
173 
174   base::MockCallback<media::SessionMessageCB> mock_session_message_cb_;
175   base::MockCallback<media::SessionClosedCB> mock_session_closed_cb_;
176   base::MockCallback<media::SessionKeysChangeCB> mock_session_keys_change_cb_;
177   base::MockCallback<media::SessionExpirationUpdateCB>
178       mock_session_expiration_update_cb_;
179 
180  private:
181   base::test::TaskEnvironment task_environment_;
182 };
183 
TEST_F(ContentDecryptionModuleAdapterTest,GetClientInterface)184 TEST_F(ContentDecryptionModuleAdapterTest, GetClientInterface) {
185   auto pending_remote = cdm_adapter_->GetClientInterface();
186   EXPECT_TRUE(pending_remote.is_valid());
187   // If we try to get it again, it should fail.
188   ASSERT_DEATH(cdm_adapter_->GetClientInterface(), "");
189 }
190 
TEST_F(ContentDecryptionModuleAdapterTest,SetServerCertificate_Failure)191 TEST_F(ContentDecryptionModuleAdapterTest, SetServerCertificate_Failure) {
192   EXPECT_CALL(*mock_daemon_cdm_,
193               SetServerCertificate(ToVector(kFakeServiceCertificate), _))
194       .WillOnce([](const std::vector<uint8_t>& cert,
195                    MockDaemonCdm::SetServerCertificateCallback callback) {
196         std::move(callback).Run(CreatePromise(false));
197       });
198   std::unique_ptr<media::MockCdmPromise> promise =
199       std::make_unique<media::MockCdmPromise>(false);
200   cdm_adapter_->SetServerCertificate(ToVector(kFakeServiceCertificate),
201                                      std::move(promise));
202   base::RunLoop().RunUntilIdle();
203 }
204 
TEST_F(ContentDecryptionModuleAdapterTest,SetServerCertificate_Success)205 TEST_F(ContentDecryptionModuleAdapterTest, SetServerCertificate_Success) {
206   EXPECT_CALL(*mock_daemon_cdm_,
207               SetServerCertificate(ToVector(kFakeServiceCertificate), _))
208       .WillOnce([](const std::vector<uint8_t>& cert,
209                    MockDaemonCdm::SetServerCertificateCallback callback) {
210         std::move(callback).Run(CreatePromise(true));
211       });
212   std::unique_ptr<media::MockCdmPromise> promise =
213       std::make_unique<media::MockCdmPromise>(true);
214   cdm_adapter_->SetServerCertificate(ToVector(kFakeServiceCertificate),
215                                      std::move(promise));
216   base::RunLoop().RunUntilIdle();
217 }
218 
TEST_F(ContentDecryptionModuleAdapterTest,GetStatusForPolicy_Failure)219 TEST_F(ContentDecryptionModuleAdapterTest, GetStatusForPolicy_Failure) {
220   EXPECT_CALL(*mock_daemon_cdm_,
221               GetStatusForPolicy(media::HdcpVersion::kHdcpVersion1_4, _))
222       .WillOnce([](media::HdcpVersion hdcp_version,
223                    MockDaemonCdm::GetStatusForPolicyCallback callback) {
224         std::move(callback).Run(
225             CreatePromise(false),
226             media::CdmKeyInformation::KeyStatus::OUTPUT_RESTRICTED);
227       });
228   media::CdmKeyInformation::KeyStatus key_status;
229   std::unique_ptr<media::MockCdmKeyStatusPromise> promise =
230       std::make_unique<media::MockCdmKeyStatusPromise>(false, &key_status);
231   cdm_adapter_->GetStatusForPolicy(media::HdcpVersion::kHdcpVersion1_4,
232                                    std::move(promise));
233   base::RunLoop().RunUntilIdle();
234 }
235 
TEST_F(ContentDecryptionModuleAdapterTest,GetStatusForPolicy_SuccessRestricted)236 TEST_F(ContentDecryptionModuleAdapterTest,
237        GetStatusForPolicy_SuccessRestricted) {
238   EXPECT_CALL(*mock_daemon_cdm_,
239               GetStatusForPolicy(media::HdcpVersion::kHdcpVersion2_2, _))
240       .WillOnce([](media::HdcpVersion hdcp_version,
241                    MockDaemonCdm::GetStatusForPolicyCallback callback) {
242         std::move(callback).Run(
243             CreatePromise(true),
244             media::CdmKeyInformation::KeyStatus::OUTPUT_RESTRICTED);
245       });
246   media::CdmKeyInformation::KeyStatus key_status;
247   std::unique_ptr<media::MockCdmKeyStatusPromise> promise =
248       std::make_unique<media::MockCdmKeyStatusPromise>(true, &key_status);
249   cdm_adapter_->GetStatusForPolicy(media::HdcpVersion::kHdcpVersion2_2,
250                                    std::move(promise));
251   base::RunLoop().RunUntilIdle();
252   EXPECT_EQ(key_status, media::CdmKeyInformation::KeyStatus::OUTPUT_RESTRICTED);
253 }
254 
TEST_F(ContentDecryptionModuleAdapterTest,GetStatusForPolicy_SuccessUsable)255 TEST_F(ContentDecryptionModuleAdapterTest, GetStatusForPolicy_SuccessUsable) {
256   EXPECT_CALL(*mock_daemon_cdm_,
257               GetStatusForPolicy(media::HdcpVersion::kHdcpVersion2_0, _))
258       .WillOnce([](media::HdcpVersion hdcp_version,
259                    MockDaemonCdm::GetStatusForPolicyCallback callback) {
260         std::move(callback).Run(CreatePromise(true),
261                                 media::CdmKeyInformation::KeyStatus::USABLE);
262       });
263   media::CdmKeyInformation::KeyStatus key_status;
264   std::unique_ptr<media::MockCdmKeyStatusPromise> promise =
265       std::make_unique<media::MockCdmKeyStatusPromise>(true, &key_status);
266   cdm_adapter_->GetStatusForPolicy(media::HdcpVersion::kHdcpVersion2_0,
267                                    std::move(promise));
268   base::RunLoop().RunUntilIdle();
269   EXPECT_EQ(key_status, media::CdmKeyInformation::KeyStatus::USABLE);
270 }
271 
TEST_F(ContentDecryptionModuleAdapterTest,CreateSessionAndGenerateRequest_Failure)272 TEST_F(ContentDecryptionModuleAdapterTest,
273        CreateSessionAndGenerateRequest_Failure) {
274   EXPECT_CALL(*mock_daemon_cdm_,
275               CreateSessionAndGenerateRequest(media::CdmSessionType::kTemporary,
276                                               media::EmeInitDataType::CENC,
277                                               ToVector(kFakeEmeInitData), _))
278       .WillOnce(
279           [](media::CdmSessionType session_type,
280              media::EmeInitDataType init_type,
281              const std::vector<uint8_t>& init_data,
282              MockDaemonCdm::CreateSessionAndGenerateRequestCallback callback) {
283             std::move(callback).Run(CreatePromise(false), "");
284           });
285   std::string session_id;
286   std::unique_ptr<media::MockCdmSessionPromise> promise =
287       std::make_unique<media::MockCdmSessionPromise>(false, &session_id);
288   cdm_adapter_->CreateSessionAndGenerateRequest(
289       media::CdmSessionType::kTemporary, media::EmeInitDataType::CENC,
290       ToVector(kFakeEmeInitData), std::move(promise));
291   base::RunLoop().RunUntilIdle();
292 }
293 
TEST_F(ContentDecryptionModuleAdapterTest,CreateSessionAndGenerateRequest_Success)294 TEST_F(ContentDecryptionModuleAdapterTest,
295        CreateSessionAndGenerateRequest_Success) {
296   EXPECT_CALL(*mock_daemon_cdm_,
297               CreateSessionAndGenerateRequest(media::CdmSessionType::kTemporary,
298                                               media::EmeInitDataType::CENC,
299                                               ToVector(kFakeEmeInitData), _))
300       .WillOnce(
301           [](media::CdmSessionType session_type,
302              media::EmeInitDataType init_type,
303              const std::vector<uint8_t>& init_data,
304              MockDaemonCdm::CreateSessionAndGenerateRequestCallback callback) {
305             std::move(callback).Run(CreatePromise(true), kFakeSessionId1);
306           });
307   std::string session_id;
308   std::unique_ptr<media::MockCdmSessionPromise> promise =
309       std::make_unique<media::MockCdmSessionPromise>(true, &session_id);
310   cdm_adapter_->CreateSessionAndGenerateRequest(
311       media::CdmSessionType::kTemporary, media::EmeInitDataType::CENC,
312       ToVector(kFakeEmeInitData), std::move(promise));
313   // We should also be getting a session closed callback for any open sessions.
314   EXPECT_CALL(mock_session_closed_cb_, Run(kFakeSessionId1));
315   base::RunLoop().RunUntilIdle();
316   EXPECT_EQ(session_id, kFakeSessionId1);
317 }
318 
TEST_F(ContentDecryptionModuleAdapterTest,LoadSession_Failure)319 TEST_F(ContentDecryptionModuleAdapterTest, LoadSession_Failure) {
320   EXPECT_CALL(*mock_daemon_cdm_,
321               LoadSession(media::CdmSessionType::kPersistentLicense,
322                           kFakeSessionId1, _))
323       .WillOnce([](media::CdmSessionType session_type,
324                    const std::string& session_id,
325                    MockDaemonCdm::LoadSessionCallback callback) {
326         std::move(callback).Run(CreatePromise(false), "");
327       });
328   std::string session_id;
329   std::unique_ptr<media::MockCdmSessionPromise> promise =
330       std::make_unique<media::MockCdmSessionPromise>(false, &session_id);
331   cdm_adapter_->LoadSession(media::CdmSessionType::kPersistentLicense,
332                             kFakeSessionId1, std::move(promise));
333   base::RunLoop().RunUntilIdle();
334 }
335 
TEST_F(ContentDecryptionModuleAdapterTest,LoadSession_Success)336 TEST_F(ContentDecryptionModuleAdapterTest, LoadSession_Success) {
337   LoadSession();
338   // We should also be getting a session closed callback for any open sessions.
339   EXPECT_CALL(mock_session_closed_cb_, Run(kFakeSessionId2));
340 }
341 
TEST_F(ContentDecryptionModuleAdapterTest,UpdateSession_Failure)342 TEST_F(ContentDecryptionModuleAdapterTest, UpdateSession_Failure) {
343   EXPECT_CALL(*mock_daemon_cdm_,
344               UpdateSession(kFakeSessionId1, ToVector(kFakeSessionUpdate), _))
345       .WillOnce([](const std::string& session_id,
346                    const std::vector<uint8_t>& response,
347                    MockDaemonCdm::UpdateSessionCallback callback) {
348         std::move(callback).Run(CreatePromise(false));
349       });
350   std::unique_ptr<media::MockCdmPromise> promise =
351       std::make_unique<media::MockCdmPromise>(false);
352   cdm_adapter_->UpdateSession(kFakeSessionId1, ToVector(kFakeSessionUpdate),
353                               std::move(promise));
354   base::RunLoop().RunUntilIdle();
355 }
356 
TEST_F(ContentDecryptionModuleAdapterTest,UpdateSession_Success)357 TEST_F(ContentDecryptionModuleAdapterTest, UpdateSession_Success) {
358   EXPECT_CALL(*mock_daemon_cdm_,
359               UpdateSession(kFakeSessionId1, ToVector(kFakeSessionUpdate), _))
360       .WillOnce([](const std::string& session_id,
361                    const std::vector<uint8_t>& response,
362                    MockDaemonCdm::UpdateSessionCallback callback) {
363         std::move(callback).Run(CreatePromise(true));
364       });
365   std::unique_ptr<media::MockCdmPromise> promise =
366       std::make_unique<media::MockCdmPromise>(true);
367   cdm_adapter_->UpdateSession(kFakeSessionId1, ToVector(kFakeSessionUpdate),
368                               std::move(promise));
369   base::RunLoop().RunUntilIdle();
370 }
371 
TEST_F(ContentDecryptionModuleAdapterTest,CloseSession_Failure)372 TEST_F(ContentDecryptionModuleAdapterTest, CloseSession_Failure) {
373   EXPECT_CALL(*mock_daemon_cdm_, CloseSession(kFakeSessionId1, _))
374       .WillOnce([](const std::string& session_id,
375                    MockDaemonCdm::CloseSessionCallback callback) {
376         std::move(callback).Run(CreatePromise(false));
377       });
378   std::unique_ptr<media::MockCdmPromise> promise =
379       std::make_unique<media::MockCdmPromise>(false);
380   cdm_adapter_->CloseSession(kFakeSessionId1, std::move(promise));
381   base::RunLoop().RunUntilIdle();
382 }
383 
TEST_F(ContentDecryptionModuleAdapterTest,CloseSession_Success)384 TEST_F(ContentDecryptionModuleAdapterTest, CloseSession_Success) {
385   EXPECT_CALL(*mock_daemon_cdm_, CloseSession(kFakeSessionId1, _))
386       .WillOnce([](const std::string& session_id,
387                    MockDaemonCdm::CloseSessionCallback callback) {
388         std::move(callback).Run(CreatePromise(true));
389       });
390   std::unique_ptr<media::MockCdmPromise> promise =
391       std::make_unique<media::MockCdmPromise>(true);
392   cdm_adapter_->CloseSession(kFakeSessionId1, std::move(promise));
393   base::RunLoop().RunUntilIdle();
394 }
395 
TEST_F(ContentDecryptionModuleAdapterTest,RemoveSession_Failure)396 TEST_F(ContentDecryptionModuleAdapterTest, RemoveSession_Failure) {
397   EXPECT_CALL(*mock_daemon_cdm_, RemoveSession(kFakeSessionId1, _))
398       .WillOnce([](const std::string& session_id,
399                    MockDaemonCdm::RemoveSessionCallback callback) {
400         std::move(callback).Run(CreatePromise(false));
401       });
402   std::unique_ptr<media::MockCdmPromise> promise =
403       std::make_unique<media::MockCdmPromise>(false);
404   cdm_adapter_->RemoveSession(kFakeSessionId1, std::move(promise));
405   base::RunLoop().RunUntilIdle();
406 }
407 
TEST_F(ContentDecryptionModuleAdapterTest,RemoveSession_Success)408 TEST_F(ContentDecryptionModuleAdapterTest, RemoveSession_Success) {
409   EXPECT_CALL(*mock_daemon_cdm_, RemoveSession(kFakeSessionId1, _))
410       .WillOnce([](const std::string& session_id,
411                    MockDaemonCdm::RemoveSessionCallback callback) {
412         std::move(callback).Run(CreatePromise(true));
413       });
414   std::unique_ptr<media::MockCdmPromise> promise =
415       std::make_unique<media::MockCdmPromise>(true);
416   cdm_adapter_->RemoveSession(kFakeSessionId1, std::move(promise));
417   base::RunLoop().RunUntilIdle();
418 }
419 
TEST_F(ContentDecryptionModuleAdapterTest,OnSessionMessage)420 TEST_F(ContentDecryptionModuleAdapterTest, OnSessionMessage) {
421   EXPECT_CALL(mock_session_message_cb_,
422               Run(kFakeSessionId1, media::CdmMessageType::LICENSE_REQUEST,
423                   ToVector(kFakeSessionUpdate)));
424   cdm_adapter_->OnSessionMessage(kFakeSessionId1,
425                                  media::CdmMessageType::LICENSE_REQUEST,
426                                  ToVector(kFakeSessionUpdate));
427 }
428 
TEST_F(ContentDecryptionModuleAdapterTest,OnSessionClosed)429 TEST_F(ContentDecryptionModuleAdapterTest, OnSessionClosed) {
430   LoadSession();
431   EXPECT_CALL(mock_session_closed_cb_, Run(kFakeSessionId2));
432   cdm_adapter_->OnSessionClosed(kFakeSessionId2);
433 }
434 
TEST_F(ContentDecryptionModuleAdapterTest,OnSessionKeysChange)435 TEST_F(ContentDecryptionModuleAdapterTest, OnSessionKeysChange) {
436   EXPECT_CALL(mock_session_keys_change_cb_, Run(kFakeSessionId1, true, _));
437   cdm_adapter_->OnSessionKeysChange(kFakeSessionId1, true, {});
438 }
439 
TEST_F(ContentDecryptionModuleAdapterTest,OnSessionExpirationUpdate)440 TEST_F(ContentDecryptionModuleAdapterTest, OnSessionExpirationUpdate) {
441   constexpr double kFakeExpiration = 123456;
442   EXPECT_CALL(mock_session_expiration_update_cb_,
443               Run(kFakeSessionId2, base::Time::FromDoubleT(kFakeExpiration)));
444   cdm_adapter_->OnSessionExpirationUpdate(kFakeSessionId2, kFakeExpiration);
445 }
446 
TEST_F(ContentDecryptionModuleAdapterTest,RegisterNewKeyCB)447 TEST_F(ContentDecryptionModuleAdapterTest, RegisterNewKeyCB) {
448   base::MockCallback<media::CdmContext::EventCB> event_cb_1;
449   base::MockCallback<media::CdmContext::EventCB> event_cb_2;
450   auto cb_registration_1 = cdm_adapter_->RegisterEventCB(event_cb_1.Get());
451   auto cb_registration_2 = cdm_adapter_->RegisterEventCB(event_cb_2.Get());
452 
453   // All registered event callbacks should be invoked.
454   EXPECT_CALL(event_cb_1,
455               Run(media::CdmContext::Event::kHasAdditionalUsableKey));
456   EXPECT_CALL(event_cb_2,
457               Run(media::CdmContext::Event::kHasAdditionalUsableKey));
458   EXPECT_CALL(mock_session_keys_change_cb_, Run(kFakeSessionId1, true, _));
459   cdm_adapter_->OnSessionKeysChange(kFakeSessionId1, true, {});
460   base::RunLoop().RunUntilIdle();
461 
462   // If no keys change, no registered event callbacks should be invoked.
463   EXPECT_CALL(event_cb_1, Run(_)).Times(0);
464   EXPECT_CALL(event_cb_2, Run(_)).Times(0);
465   EXPECT_CALL(mock_session_keys_change_cb_, Run(kFakeSessionId1, false, _));
466   cdm_adapter_->OnSessionKeysChange(kFakeSessionId1, false, {});
467   base::RunLoop().RunUntilIdle();
468 }
469 
TEST_F(ContentDecryptionModuleAdapterTest,Decrypt_Unencrypted)470 TEST_F(ContentDecryptionModuleAdapterTest, Decrypt_Unencrypted) {
471   EXPECT_CALL(*mock_daemon_cdm_, Decrypt(_, _, _)).Times(0);
472   scoped_refptr<media::DecoderBuffer> encrypted_buffer =
473       CreateDecoderBuffer(kFakeEncryptedData);
474   encrypted_buffer->set_is_key_frame(true);
475   scoped_refptr<media::DecoderBuffer> decrypted_buffer =
476       CloneDecoderBuffer(encrypted_buffer);
477   base::MockCallback<media::Decryptor::DecryptCB> callback;
478   EXPECT_CALL(callback, Run(media::Decryptor::kSuccess,
479                             MatchesDecoderBuffer(decrypted_buffer)));
480   cdm_adapter_->Decrypt(media::Decryptor::kVideo, encrypted_buffer,
481                         callback.Get());
482 }
483 
TEST_F(ContentDecryptionModuleAdapterTest,Decrypt_NoSubsamples)484 TEST_F(ContentDecryptionModuleAdapterTest, Decrypt_NoSubsamples) {
485   cdm::mojom::DecryptConfigPtr expected_decrypt_config =
486       cdm::mojom::DecryptConfig::New(
487           media::EncryptionScheme::kCbcs, kFakeKeyId, kFakeIv,
488           std::vector<cdm::mojom::SubsampleEntryPtr>(),
489           media::EncryptionPattern(6, 9));
490   EXPECT_CALL(*mock_daemon_cdm_,
491               Decrypt(kFakeEncryptedData,
492                       MatchesDecryptConfig(&expected_decrypt_config), _))
493       .WillOnce([](const std::vector<uint8_t>& data,
494                    cdm::mojom::DecryptConfigPtr decrypt_config,
495                    MockDaemonCdm::DecryptCallback callback) {
496         // For decryption, just reverse the data.
497         std::vector<uint8_t> decrypted = data;
498         std::reverse(std::begin(decrypted), std::end(decrypted));
499         std::move(callback).Run(media::Decryptor::kSuccess,
500                                 std::move(decrypted));
501       });
502   std::vector<uint8_t> decrypted_data = kFakeEncryptedData;
503   std::reverse(std::begin(decrypted_data), std::end(decrypted_data));
504   scoped_refptr<media::DecoderBuffer> decrypted_buffer =
505       CreateDecoderBuffer(decrypted_data);
506   decrypted_buffer->set_is_key_frame(true);
507 
508   base::MockCallback<media::Decryptor::DecryptCB> callback;
509   EXPECT_CALL(callback, Run(media::Decryptor::kSuccess,
510                             MatchesDecoderBuffer(decrypted_buffer)));
511   scoped_refptr<media::DecoderBuffer> encrypted_buffer =
512       CreateDecoderBuffer(kFakeEncryptedData);
513   encrypted_buffer->set_is_key_frame(true);
514   encrypted_buffer->set_decrypt_config(media::DecryptConfig::CreateCbcsConfig(
515       kFakeKeyId, kFakeIv, {}, media::EncryptionPattern(6, 9)));
516   cdm_adapter_->Decrypt(media::Decryptor::kVideo, encrypted_buffer,
517                         callback.Get());
518   base::RunLoop().RunUntilIdle();
519 }
520 
TEST_F(ContentDecryptionModuleAdapterTest,Decrypt_Failure)521 TEST_F(ContentDecryptionModuleAdapterTest, Decrypt_Failure) {
522   EXPECT_CALL(*mock_daemon_cdm_, Decrypt(_, _, _))
523       .WillOnce([](const std::vector<uint8_t>& data,
524                    cdm::mojom::DecryptConfigPtr decrypt_config,
525                    MockDaemonCdm::DecryptCallback callback) {
526         std::move(callback).Run(media::Decryptor::kError, {});
527       });
528   base::MockCallback<media::Decryptor::DecryptCB> callback;
529   EXPECT_CALL(callback, Run(media::Decryptor::kError, IsNull()));
530   scoped_refptr<media::DecoderBuffer> encrypted_buffer =
531       CreateDecoderBuffer(kFakeEncryptedData);
532   encrypted_buffer->set_decrypt_config(media::DecryptConfig::CreateCbcsConfig(
533       kFakeKeyId, kFakeIv, {}, media::EncryptionPattern(6, 9)));
534   cdm_adapter_->Decrypt(media::Decryptor::kVideo, encrypted_buffer,
535                         callback.Get());
536   base::RunLoop().RunUntilIdle();
537 }
538 
TEST_F(ContentDecryptionModuleAdapterTest,Decrypt_NoKey)539 TEST_F(ContentDecryptionModuleAdapterTest, Decrypt_NoKey) {
540   EXPECT_CALL(*mock_daemon_cdm_, Decrypt(_, _, _))
541       .WillOnce([](const std::vector<uint8_t>& data,
542                    cdm::mojom::DecryptConfigPtr decrypt_config,
543                    MockDaemonCdm::DecryptCallback callback) {
544         std::move(callback).Run(media::Decryptor::kNoKey, {});
545       });
546   base::MockCallback<media::Decryptor::DecryptCB> callback;
547   EXPECT_CALL(callback, Run(media::Decryptor::kNoKey, IsNull()));
548   scoped_refptr<media::DecoderBuffer> encrypted_buffer =
549       CreateDecoderBuffer(kFakeEncryptedData);
550   encrypted_buffer->set_decrypt_config(media::DecryptConfig::CreateCbcsConfig(
551       kFakeKeyId, kFakeIv, {}, media::EncryptionPattern(6, 9)));
552   cdm_adapter_->Decrypt(media::Decryptor::kVideo, encrypted_buffer,
553                         callback.Get());
554   base::RunLoop().RunUntilIdle();
555 }
556 
TEST_F(ContentDecryptionModuleAdapterTest,Decrypt_MismatchedSubsamples)557 TEST_F(ContentDecryptionModuleAdapterTest, Decrypt_MismatchedSubsamples) {
558   EXPECT_CALL(*mock_daemon_cdm_, Decrypt(_, _, _)).Times(0);
559   base::MockCallback<media::Decryptor::DecryptCB> callback;
560   EXPECT_CALL(callback, Run(media::Decryptor::kError, IsNull()));
561   scoped_refptr<media::DecoderBuffer> encrypted_buffer =
562       CreateDecoderBuffer(kFakeEncryptedData);
563   encrypted_buffer->set_decrypt_config(media::DecryptConfig::CreateCencConfig(
564       kFakeKeyId, kFakeIv, {media::SubsampleEntry(1, 1)}));
565   cdm_adapter_->Decrypt(media::Decryptor::kVideo, encrypted_buffer,
566                         callback.Get());
567   base::RunLoop().RunUntilIdle();
568 }
569 
TEST_F(ContentDecryptionModuleAdapterTest,Decrypt_InvalidSizeReturned)570 TEST_F(ContentDecryptionModuleAdapterTest, Decrypt_InvalidSizeReturned) {
571   EXPECT_CALL(*mock_daemon_cdm_, Decrypt(_, _, _))
572       .WillOnce([](const std::vector<uint8_t>& data,
573                    cdm::mojom::DecryptConfigPtr decrypt_config,
574                    MockDaemonCdm::DecryptCallback callback) {
575         std::move(callback).Run(media::Decryptor::kSuccess, {1});
576       });
577   base::MockCallback<media::Decryptor::DecryptCB> callback;
578   EXPECT_CALL(callback, Run(media::Decryptor::kError, IsNull()));
579   scoped_refptr<media::DecoderBuffer> encrypted_buffer =
580       CreateDecoderBuffer(kFakeEncryptedData);
581   encrypted_buffer->set_decrypt_config(media::DecryptConfig::CreateCbcsConfig(
582       kFakeKeyId, kFakeIv, {}, media::EncryptionPattern(4, 4)));
583   cdm_adapter_->Decrypt(media::Decryptor::kVideo, encrypted_buffer,
584                         callback.Get());
585   base::RunLoop().RunUntilIdle();
586 }
587 
TEST_F(ContentDecryptionModuleAdapterTest,Decrypt_NoEncryptedSubsamples)588 TEST_F(ContentDecryptionModuleAdapterTest, Decrypt_NoEncryptedSubsamples) {
589   EXPECT_CALL(*mock_daemon_cdm_, Decrypt(_, _, _)).Times(0);
590   scoped_refptr<media::DecoderBuffer> encrypted_buffer =
591       CreateDecoderBuffer(kFakeEncryptedData);
592   encrypted_buffer->set_decrypt_config(media::DecryptConfig::CreateCencConfig(
593       kFakeKeyId, kFakeIv,
594       {media::SubsampleEntry(kFakeEncryptedData.size(), 0)}));
595   scoped_refptr<media::DecoderBuffer> decrypted_buffer =
596       CloneDecoderBuffer(encrypted_buffer);
597   decrypted_buffer->set_decrypt_config(nullptr);
598   base::MockCallback<media::Decryptor::DecryptCB> callback;
599   EXPECT_CALL(callback, Run(media::Decryptor::kSuccess,
600                             MatchesDecoderBuffer(decrypted_buffer)));
601   cdm_adapter_->Decrypt(media::Decryptor::kVideo, encrypted_buffer,
602                         callback.Get());
603 }
604 
TEST_F(ContentDecryptionModuleAdapterTest,Decrypt_SubsampledCenc)605 TEST_F(ContentDecryptionModuleAdapterTest, Decrypt_SubsampledCenc) {
606   cdm::mojom::DecryptConfigPtr expected_decrypt_config =
607       cdm::mojom::DecryptConfig::New(
608           media::EncryptionScheme::kCenc, kFakeKeyId, kFakeIv,
609           std::vector<cdm::mojom::SubsampleEntryPtr>(), base::nullopt);
610   EXPECT_CALL(*mock_daemon_cdm_,
611               Decrypt(std::vector<uint8_t>(kFakeEncryptedData.begin() + 3,
612                                            kFakeEncryptedData.end()),
613                       MatchesDecryptConfig(&expected_decrypt_config), _))
614       .WillOnce([](const std::vector<uint8_t>& data,
615                    cdm::mojom::DecryptConfigPtr decrypt_config,
616                    MockDaemonCdm::DecryptCallback callback) {
617         // For decryption, just reverse the data.
618         std::vector<uint8_t> decrypted = data;
619         std::reverse(std::begin(decrypted), std::end(decrypted));
620         std::move(callback).Run(media::Decryptor::kSuccess,
621                                 std::move(decrypted));
622       });
623   std::vector<uint8_t> decrypted_data = kFakeEncryptedData;
624   std::reverse(std::begin(decrypted_data) + 3, std::end(decrypted_data));
625   scoped_refptr<media::DecoderBuffer> decrypted_buffer =
626       CreateDecoderBuffer(decrypted_data);
627   decrypted_buffer->set_is_key_frame(true);
628   base::MockCallback<media::Decryptor::DecryptCB> callback;
629   EXPECT_CALL(callback, Run(media::Decryptor::kSuccess,
630                             MatchesDecoderBuffer(decrypted_buffer)));
631   scoped_refptr<media::DecoderBuffer> encrypted_buffer =
632       CreateDecoderBuffer(kFakeEncryptedData);
633   encrypted_buffer->set_is_key_frame(true);
634   encrypted_buffer->set_decrypt_config(media::DecryptConfig::CreateCencConfig(
635       kFakeKeyId, kFakeIv, {media::SubsampleEntry(3, 5)}));
636   cdm_adapter_->Decrypt(media::Decryptor::kVideo, encrypted_buffer,
637                         callback.Get());
638   base::RunLoop().RunUntilIdle();
639 }
640 
TEST_F(ContentDecryptionModuleAdapterTest,Decrypt_SubsampledCbcs)641 TEST_F(ContentDecryptionModuleAdapterTest, Decrypt_SubsampledCbcs) {
642   cdm::mojom::DecryptConfigPtr expected_decrypt_config =
643       cdm::mojom::DecryptConfig::New(
644           media::EncryptionScheme::kCbcs, kFakeKeyId, kFakeIv,
645           std::vector<cdm::mojom::SubsampleEntryPtr>(), base::nullopt);
646   expected_decrypt_config->subsamples.emplace_back(
647       cdm::mojom::SubsampleEntry::New(1, 2));
648   expected_decrypt_config->subsamples.emplace_back(
649       cdm::mojom::SubsampleEntry::New(2, 3));
650   EXPECT_CALL(*mock_daemon_cdm_,
651               Decrypt(kFakeEncryptedData,
652                       MatchesDecryptConfig(&expected_decrypt_config), _))
653       .WillOnce([](const std::vector<uint8_t>& data,
654                    cdm::mojom::DecryptConfigPtr decrypt_config,
655                    MockDaemonCdm::DecryptCallback callback) {
656         // For decryption, just reverse the data.
657         std::vector<uint8_t> decrypted = data;
658         std::reverse(std::begin(decrypted), std::end(decrypted));
659         std::move(callback).Run(media::Decryptor::kSuccess,
660                                 std::move(decrypted));
661       });
662   std::vector<uint8_t> decrypted_data = kFakeEncryptedData;
663   std::reverse(std::begin(decrypted_data), std::end(decrypted_data));
664   scoped_refptr<media::DecoderBuffer> decrypted_buffer =
665       CreateDecoderBuffer(decrypted_data);
666   decrypted_buffer->set_is_key_frame(true);
667   base::MockCallback<media::Decryptor::DecryptCB> callback;
668   EXPECT_CALL(callback, Run(media::Decryptor::kSuccess,
669                             MatchesDecoderBuffer(decrypted_buffer)));
670   scoped_refptr<media::DecoderBuffer> encrypted_buffer =
671       CreateDecoderBuffer(kFakeEncryptedData);
672   encrypted_buffer->set_is_key_frame(true);
673   encrypted_buffer->set_decrypt_config(media::DecryptConfig::CreateCbcsConfig(
674       kFakeKeyId, kFakeIv,
675       {media::SubsampleEntry(1, 2), media::SubsampleEntry(2, 3)},
676       base::nullopt));
677   cdm_adapter_->Decrypt(media::Decryptor::kVideo, encrypted_buffer,
678                         callback.Get());
679   base::RunLoop().RunUntilIdle();
680 }
681 
TEST_F(ContentDecryptionModuleAdapterTest,Decrypt_CancelDecrypt)682 TEST_F(ContentDecryptionModuleAdapterTest, Decrypt_CancelDecrypt) {
683   EXPECT_CALL(*mock_daemon_cdm_, Decrypt(_, _, _))
684       .WillOnce([](const std::vector<uint8_t>& data,
685                    cdm::mojom::DecryptConfigPtr decrypt_config,
686                    MockDaemonCdm::DecryptCallback callback) {
687         std::move(callback).Run(media::Decryptor::kSuccess, data);
688       });
689   scoped_refptr<media::DecoderBuffer> buffer =
690       CreateDecoderBuffer(kFakeEncryptedData);
691   buffer->set_decrypt_config(media::DecryptConfig::CreateCbcsConfig(
692       kFakeKeyId, kFakeIv, {}, media::EncryptionPattern(6, 9)));
693   base::MockCallback<media::Decryptor::DecryptCB> callback;
694   EXPECT_CALL(callback, Run(media::Decryptor::kSuccess, IsNull())).Times(1);
695   cdm_adapter_->Decrypt(media::Decryptor::kAudio, buffer, callback.Get());
696   cdm_adapter_->CancelDecrypt(media::Decryptor::kAudio);
697   base::RunLoop().RunUntilIdle();
698 }
699 
700 }  // namespace chromeos
701