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 <utility>
8 
9 #include "base/bind.h"
10 #include "base/time/time.h"
11 #include "media/base/cdm_promise.h"
12 #include "media/base/decoder_buffer.h"
13 #include "media/base/eme_constants.h"
14 #include "media/base/subsample_entry.h"
15 
16 namespace {
17 
18 // Copy the cypher bytes as specified by |subsamples| from |src| to |dst|.
19 // Clear bytes contained in |src| that are specified by |subsamples| will be
20 // skipped. This is used when copying all the protected data out of a sample.
21 //
22 // NOTE: Before invoking this call the |subsamples| data must have been verified
23 // against the length of the |src| array to ensure we won't go out of bounds or
24 // have overflow. This can be done with media::VerifySubsamplesMatchSize.
ExtractSubsampleCypherBytes(const std::vector<media::SubsampleEntry> & subsamples,const uint8_t * src,uint8_t * dst)25 void ExtractSubsampleCypherBytes(
26     const std::vector<media::SubsampleEntry>& subsamples,
27     const uint8_t* src,
28     uint8_t* dst) {
29   for (const auto& subsample : subsamples) {
30     src += subsample.clear_bytes;
31     memcpy(dst, src, subsample.cypher_bytes);
32     src += subsample.cypher_bytes;
33     dst += subsample.cypher_bytes;
34   }
35 }
36 
37 // Copy the cypher bytes as specified by |subsamples| from |src| to |dst|.
38 // Any clear bytes mentioned in |subsamples| will be skipped in |dst|. This is
39 // used when copying the decrypted bytes back into the buffer, replacing the
40 // encrypted portions.
41 //
42 // NOTE: Before invoking this call the |subsamples| data must have been verified
43 // against the length of the |src| array to ensure we won't go out of bounds or
44 // have overflow. This can be done with media::VerifySubsamplesMatchSize.
InsertSubsampleCypherBytes(const std::vector<media::SubsampleEntry> & subsamples,const uint8_t * src,uint8_t * dst)45 void InsertSubsampleCypherBytes(
46     const std::vector<media::SubsampleEntry>& subsamples,
47     const uint8_t* src,
48     uint8_t* dst) {
49   for (const auto& subsample : subsamples) {
50     dst += subsample.clear_bytes;
51     memcpy(dst, src, subsample.cypher_bytes);
52     src += subsample.cypher_bytes;
53     dst += subsample.cypher_bytes;
54   }
55 }
56 
57 // Copy the decrypted data into the output buffer. The buffer will contain
58 // all of the data if there was no subsampling or if we were doing CBCS with
59 // multiple subsamples. Otherwise we need to copy based on the subsampling.
CopyDecryptedDataToDecoderBuffer(scoped_refptr<media::DecoderBuffer> encrypted,const std::vector<uint8_t> & decrypted_data)60 scoped_refptr<media::DecoderBuffer> CopyDecryptedDataToDecoderBuffer(
61     scoped_refptr<media::DecoderBuffer> encrypted,
62     const std::vector<uint8_t>& decrypted_data) {
63   scoped_refptr<media::DecoderBuffer> decrypted;
64   if (encrypted->decrypt_config()->subsamples().empty() ||
65       (encrypted->decrypt_config()->encryption_scheme() ==
66            media::EncryptionScheme::kCbcs &&
67        encrypted->decrypt_config()->subsamples().size() > 1)) {
68     decrypted = media::DecoderBuffer::CopyFrom(decrypted_data.data(),
69                                                decrypted_data.size());
70   } else {
71     decrypted = media::DecoderBuffer::CopyFrom(encrypted->data(),
72                                                encrypted->data_size());
73     InsertSubsampleCypherBytes(encrypted->decrypt_config()->subsamples(),
74                                decrypted_data.data(),
75                                decrypted->writable_data());
76   }
77 
78   // Copy the auxiliary fields.
79   decrypted->set_timestamp(encrypted->timestamp());
80   decrypted->set_duration(encrypted->duration());
81   decrypted->set_is_key_frame(encrypted->is_key_frame());
82   decrypted->CopySideDataFrom(encrypted->side_data(),
83                               encrypted->side_data_size());
84   return decrypted;
85 }
86 
RejectPromiseConnectionLost(std::unique_ptr<media::CdmPromise> promise)87 void RejectPromiseConnectionLost(std::unique_ptr<media::CdmPromise> promise) {
88   promise->reject(media::CdmPromise::Exception::INVALID_STATE_ERROR, 0,
89                   "Mojo connection lost");
90 }
91 
92 }  // namespace
93 
94 namespace chromeos {
95 
ContentDecryptionModuleAdapter(std::unique_ptr<CdmStorageAdapter> storage,mojo::AssociatedRemote<cdm::mojom::ContentDecryptionModule> cros_cdm_remote,const media::SessionMessageCB & session_message_cb,const media::SessionClosedCB & session_closed_cb,const media::SessionKeysChangeCB & session_keys_change_cb,const media::SessionExpirationUpdateCB & session_expiration_update_cb)96 ContentDecryptionModuleAdapter::ContentDecryptionModuleAdapter(
97     std::unique_ptr<CdmStorageAdapter> storage,
98     mojo::AssociatedRemote<cdm::mojom::ContentDecryptionModule> cros_cdm_remote,
99     const media::SessionMessageCB& session_message_cb,
100     const media::SessionClosedCB& session_closed_cb,
101     const media::SessionKeysChangeCB& session_keys_change_cb,
102     const media::SessionExpirationUpdateCB& session_expiration_update_cb)
103     : storage_(std::move(storage)),
104       cros_cdm_remote_(std::move(cros_cdm_remote)),
105       session_message_cb_(session_message_cb),
106       session_closed_cb_(session_closed_cb),
107       session_keys_change_cb_(session_keys_change_cb),
108       session_expiration_update_cb_(session_expiration_update_cb),
109       mojo_task_runner_(base::SequencedTaskRunnerHandle::Get()) {
110   DVLOG(1) << "Created ContentDecryptionModuleAdapter";
111   cros_cdm_remote_.set_disconnect_handler(
112       base::BindOnce(&ContentDecryptionModuleAdapter::OnConnectionError,
113                      base::Unretained(this)));
114 }
115 
116 mojo::PendingAssociatedRemote<cdm::mojom::ContentDecryptionModuleClient>
GetClientInterface()117 ContentDecryptionModuleAdapter::GetClientInterface() {
118   CHECK(!cros_client_receiver_.is_bound());
119   auto ret = cros_client_receiver_.BindNewEndpointAndPassRemote();
120   cros_client_receiver_.set_disconnect_handler(
121       base::BindOnce(&ContentDecryptionModuleAdapter::OnConnectionError,
122                      base::Unretained(this)));
123   return ret;
124 }
125 
SetServerCertificate(const std::vector<uint8_t> & certificate_data,std::unique_ptr<media::SimpleCdmPromise> promise)126 void ContentDecryptionModuleAdapter::SetServerCertificate(
127     const std::vector<uint8_t>& certificate_data,
128     std::unique_ptr<media::SimpleCdmPromise> promise) {
129   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
130   DVLOG(2) << __func__;
131   if (!cros_cdm_remote_) {
132     RejectPromiseConnectionLost(std::move(promise));
133     return;
134   }
135   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
136   cros_cdm_remote_->SetServerCertificate(
137       certificate_data,
138       base::BindOnce(&ContentDecryptionModuleAdapter::OnSimplePromiseResult,
139                      base::Unretained(this), promise_id));
140 }
141 
GetStatusForPolicy(media::HdcpVersion min_hdcp_version,std::unique_ptr<media::KeyStatusCdmPromise> promise)142 void ContentDecryptionModuleAdapter::GetStatusForPolicy(
143     media::HdcpVersion min_hdcp_version,
144     std::unique_ptr<media::KeyStatusCdmPromise> promise) {
145   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
146   DVLOG(2) << __func__;
147   if (!cros_cdm_remote_) {
148     RejectPromiseConnectionLost(std::move(promise));
149     return;
150   }
151   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
152   cros_cdm_remote_->GetStatusForPolicy(
153       min_hdcp_version,
154       base::BindOnce(&ContentDecryptionModuleAdapter::OnGetStatusForPolicy,
155                      base::Unretained(this), promise_id));
156 }
157 
CreateSessionAndGenerateRequest(media::CdmSessionType session_type,media::EmeInitDataType init_data_type,const std::vector<uint8_t> & init_data,std::unique_ptr<media::NewSessionCdmPromise> promise)158 void ContentDecryptionModuleAdapter::CreateSessionAndGenerateRequest(
159     media::CdmSessionType session_type,
160     media::EmeInitDataType init_data_type,
161     const std::vector<uint8_t>& init_data,
162     std::unique_ptr<media::NewSessionCdmPromise> promise) {
163   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
164   DVLOG(2) << __func__;
165   if (!cros_cdm_remote_) {
166     RejectPromiseConnectionLost(std::move(promise));
167     return;
168   }
169   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
170   cros_cdm_remote_->CreateSessionAndGenerateRequest(
171       session_type, init_data_type, init_data,
172       base::BindOnce(&ContentDecryptionModuleAdapter::OnSessionPromiseResult,
173                      base::Unretained(this), promise_id));
174 }
175 
LoadSession(media::CdmSessionType session_type,const std::string & session_id,std::unique_ptr<media::NewSessionCdmPromise> promise)176 void ContentDecryptionModuleAdapter::LoadSession(
177     media::CdmSessionType session_type,
178     const std::string& session_id,
179     std::unique_ptr<media::NewSessionCdmPromise> promise) {
180   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
181   DVLOG(2) << __func__;
182   if (!cros_cdm_remote_) {
183     RejectPromiseConnectionLost(std::move(promise));
184     return;
185   }
186   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
187   cros_cdm_remote_->LoadSession(
188       session_type, session_id,
189       base::BindOnce(&ContentDecryptionModuleAdapter::OnSessionPromiseResult,
190                      base::Unretained(this), promise_id));
191 }
192 
UpdateSession(const std::string & session_id,const std::vector<uint8_t> & response,std::unique_ptr<media::SimpleCdmPromise> promise)193 void ContentDecryptionModuleAdapter::UpdateSession(
194     const std::string& session_id,
195     const std::vector<uint8_t>& response,
196     std::unique_ptr<media::SimpleCdmPromise> promise) {
197   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
198   DVLOG(2) << __func__;
199   if (!cros_cdm_remote_) {
200     RejectPromiseConnectionLost(std::move(promise));
201     return;
202   }
203   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
204   cros_cdm_remote_->UpdateSession(
205       session_id, response,
206       base::BindOnce(&ContentDecryptionModuleAdapter::OnSimplePromiseResult,
207                      base::Unretained(this), promise_id));
208 }
209 
CloseSession(const std::string & session_id,std::unique_ptr<media::SimpleCdmPromise> promise)210 void ContentDecryptionModuleAdapter::CloseSession(
211     const std::string& session_id,
212     std::unique_ptr<media::SimpleCdmPromise> promise) {
213   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
214   DVLOG(2) << __func__;
215   if (!cros_cdm_remote_) {
216     RejectPromiseConnectionLost(std::move(promise));
217     return;
218   }
219   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
220   cros_cdm_remote_->CloseSession(
221       session_id,
222       base::BindOnce(&ContentDecryptionModuleAdapter::OnSimplePromiseResult,
223                      base::Unretained(this), promise_id));
224 }
225 
RemoveSession(const std::string & session_id,std::unique_ptr<media::SimpleCdmPromise> promise)226 void ContentDecryptionModuleAdapter::RemoveSession(
227     const std::string& session_id,
228     std::unique_ptr<media::SimpleCdmPromise> promise) {
229   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
230   DVLOG(2) << __func__;
231   if (!cros_cdm_remote_) {
232     RejectPromiseConnectionLost(std::move(promise));
233     return;
234   }
235   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
236   cros_cdm_remote_->RemoveSession(
237       session_id,
238       base::BindOnce(&ContentDecryptionModuleAdapter::OnSimplePromiseResult,
239                      base::Unretained(this), promise_id));
240 }
241 
GetCdmContext()242 media::CdmContext* ContentDecryptionModuleAdapter::GetCdmContext() {
243   return this;
244 }
245 
246 std::unique_ptr<media::CallbackRegistration>
RegisterEventCB(EventCB event_cb)247 ContentDecryptionModuleAdapter::RegisterEventCB(EventCB event_cb) {
248   return event_callbacks_.Register(std::move(event_cb));
249 }
250 
GetDecryptor()251 media::Decryptor* ContentDecryptionModuleAdapter::GetDecryptor() {
252   return this;
253 }
254 
GetChromeOsCdmContext()255 ChromeOsCdmContext* ContentDecryptionModuleAdapter::GetChromeOsCdmContext() {
256   return this;
257 }
258 
GetHwKeyData(const media::DecryptConfig * decrypt_config,const std::vector<uint8_t> & hw_identifier,GetHwKeyDataCB callback)259 void ContentDecryptionModuleAdapter::GetHwKeyData(
260     const media::DecryptConfig* decrypt_config,
261     const std::vector<uint8_t>& hw_identifier,
262     GetHwKeyDataCB callback) {
263   // This can get called from decoder threads or mojo threads, so we may need
264   // to repost the task.
265   if (!mojo_task_runner_->RunsTasksInCurrentSequence()) {
266     mojo_task_runner_->PostTask(
267         FROM_HERE, base::BindOnce(&ContentDecryptionModuleAdapter::GetHwKeyData,
268                                   weak_factory_.GetWeakPtr(), decrypt_config,
269                                   hw_identifier, std::move(callback)));
270     return;
271   }
272   if (!cros_cdm_remote_) {
273     std::move(callback).Run(media::Decryptor::Status::kError,
274                             std::vector<uint8_t>());
275     return;
276   }
277   auto cros_decrypt_config = cdm::mojom::DecryptConfig::New();
278   cros_decrypt_config->key_id = decrypt_config->key_id();
279   cros_decrypt_config->iv = decrypt_config->iv();
280   cros_decrypt_config->encryption_scheme = decrypt_config->encryption_scheme();
281 
282   cros_cdm_remote_->GetHwKeyData(std::move(cros_decrypt_config), hw_identifier,
283                                  std::move(callback));
284 }
285 
OnSessionMessage(const std::string & session_id,media::CdmMessageType message_type,const std::vector<uint8_t> & message)286 void ContentDecryptionModuleAdapter::OnSessionMessage(
287     const std::string& session_id,
288     media::CdmMessageType message_type,
289     const std::vector<uint8_t>& message) {
290   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
291   DVLOG(2) << __func__;
292   session_message_cb_.Run(session_id, message_type, message);
293 }
294 
OnSessionClosed(const std::string & session_id)295 void ContentDecryptionModuleAdapter::OnSessionClosed(
296     const std::string& session_id) {
297   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
298   DVLOG(2) << __func__;
299   cdm_session_tracker_.RemoveSession(session_id);
300   session_closed_cb_.Run(session_id);
301 }
302 
OnSessionKeysChange(const std::string & session_id,bool has_additional_usable_key,std::vector<std::unique_ptr<media::CdmKeyInformation>> keys_info)303 void ContentDecryptionModuleAdapter::OnSessionKeysChange(
304     const std::string& session_id,
305     bool has_additional_usable_key,
306     std::vector<std::unique_ptr<media::CdmKeyInformation>> keys_info) {
307   DVLOG(2) << __func__
308            << " has_additional_usable_key: " << has_additional_usable_key;
309   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
310 
311   if (has_additional_usable_key)
312     event_callbacks_.Notify(Event::kHasAdditionalUsableKey);
313 
314   session_keys_change_cb_.Run(session_id, has_additional_usable_key,
315                               std::move(keys_info));
316 }
317 
OnSessionExpirationUpdate(const std::string & session_id,double new_expiry_time_sec)318 void ContentDecryptionModuleAdapter::OnSessionExpirationUpdate(
319     const std::string& session_id,
320     double new_expiry_time_sec) {
321   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
322   session_expiration_update_cb_.Run(
323       session_id, base::Time::FromDoubleT(new_expiry_time_sec));
324 }
325 
Decrypt(StreamType stream_type,scoped_refptr<media::DecoderBuffer> encrypted,DecryptCB decrypt_cb)326 void ContentDecryptionModuleAdapter::Decrypt(
327     StreamType stream_type,
328     scoped_refptr<media::DecoderBuffer> encrypted,
329     DecryptCB decrypt_cb) {
330   // This can get called from decoder threads or mojo threads, so we may need
331   // to repost the task.
332   if (!mojo_task_runner_->RunsTasksInCurrentSequence()) {
333     mojo_task_runner_->PostTask(
334         FROM_HERE, base::BindOnce(&ContentDecryptionModuleAdapter::Decrypt,
335                                   weak_factory_.GetWeakPtr(), stream_type,
336                                   encrypted, std::move(decrypt_cb)));
337     return;
338   }
339   DVLOG(2) << __func__ << ": " << encrypted->AsHumanReadableString(true);
340   if (!cros_cdm_remote_) {
341     std::move(decrypt_cb).Run(media::Decryptor::kError, nullptr);
342     return;
343   }
344 
345   const media::DecryptConfig* decrypt_config = encrypted->decrypt_config();
346   if (!decrypt_config) {
347     // If there is no DecryptConfig, then the data is unencrypted so return it
348     // immediately.
349     std::move(decrypt_cb).Run(kSuccess, encrypted);
350     return;
351   }
352 
353   cdm::mojom::DecryptConfigPtr cros_decrypt_config(
354       cdm::mojom::DecryptConfig::New());
355   cros_decrypt_config->key_id = decrypt_config->key_id();
356   cros_decrypt_config->iv = decrypt_config->iv();
357   if (decrypt_config->HasPattern()) {
358     cros_decrypt_config->encryption_pattern =
359         decrypt_config->encryption_pattern().value();
360   }
361   cros_decrypt_config->encryption_scheme = decrypt_config->encryption_scheme();
362 
363   const std::vector<media::SubsampleEntry>& subsamples =
364       decrypt_config->subsamples();
365   if (subsamples.empty()) {
366     StoreDecryptCallback(stream_type, std::move(decrypt_cb));
367     // No subsamples specified, request decryption of entire block.
368     // TODO(jkardatzke): Evaluate the performance cost here of copying the data
369     // and see if want to use something like MojoDecoderBufferWriter instead.
370     cros_cdm_remote_->Decrypt(
371         std::vector<uint8_t>(encrypted->data(),
372                              encrypted->data() + encrypted->data_size()),
373         std::move(cros_decrypt_config),
374         base::BindOnce(&ContentDecryptionModuleAdapter::OnDecrypt,
375                        base::Unretained(this), stream_type, encrypted,
376                        encrypted->data_size()));
377     return;
378   }
379 
380   if (!VerifySubsamplesMatchSize(subsamples, encrypted->data_size())) {
381     LOG(ERROR) << "Subsample sizes do not match input size";
382     std::move(decrypt_cb).Run(kError, nullptr);
383     return;
384   }
385 
386   // Compute the size of the encrypted portion. Overflow, etc. checked by
387   // the call to VerifySubsamplesMatchSize().
388   size_t total_encrypted_size = 0;
389   for (const auto& subsample : subsamples)
390     total_encrypted_size += subsample.cypher_bytes;
391 
392   // No need to decrypt if there is no encrypted data.
393   if (total_encrypted_size == 0) {
394     encrypted->set_decrypt_config(nullptr);
395     std::move(decrypt_cb).Run(kSuccess, encrypted);
396     return;
397   }
398 
399   StoreDecryptCallback(stream_type, std::move(decrypt_cb));
400 
401   // For CENC, the encrypted portions of all subsamples must form a contiguous
402   // block, such that an encrypted subsample that ends away from a block
403   // boundary is immediately followed by the start of the next encrypted
404   // subsample. We copy all encrypted subsamples to a contiguous buffer, decrypt
405   // them, then copy the decrypted bytes over the encrypted bytes in the output.
406   // For CBCS, if there is more than one sample, then we need to pass the
407   // subsample information or otherwise we would need to call decrypt for each
408   // individual subsample since each subsample uses the same IV and it can't be
409   // decrypted as one large block like CENC.
410   if (decrypt_config->encryption_scheme() == media::EncryptionScheme::kCenc ||
411       subsamples.size() == 1) {
412     std::vector<uint8_t> encrypted_bytes(total_encrypted_size);
413     ExtractSubsampleCypherBytes(subsamples, encrypted->data(),
414                                 encrypted_bytes.data());
415     cros_cdm_remote_->Decrypt(
416         std::move(encrypted_bytes), std::move(cros_decrypt_config),
417         base::BindOnce(&ContentDecryptionModuleAdapter::OnDecrypt,
418                        base::Unretained(this), stream_type, encrypted,
419                        total_encrypted_size));
420     return;
421   }
422 
423   // We need to specify the subsampling and put that in the decrypt config.
424   for (const auto& sample : subsamples) {
425     cros_decrypt_config->subsamples.push_back(cdm::mojom::SubsampleEntry::New(
426         sample.clear_bytes, sample.cypher_bytes));
427   }
428   // TODO(jkardatzke): Evaluate the performance cost here of copying the data
429   // and see if want to use something like MojoDecoderBufferWriter instead.
430   cros_cdm_remote_->Decrypt(
431       std::vector<uint8_t>(encrypted->data(),
432                            encrypted->data() + encrypted->data_size()),
433       std::move(cros_decrypt_config),
434       base::BindOnce(&ContentDecryptionModuleAdapter::OnDecrypt,
435                      base::Unretained(this), stream_type, encrypted,
436                      encrypted->data_size()));
437 }
438 
CancelDecrypt(StreamType stream_type)439 void ContentDecryptionModuleAdapter::CancelDecrypt(StreamType stream_type) {
440   // This can get called from decoder threads or mojo threads, so we may need
441   // to repost the task.
442   if (!mojo_task_runner_->RunsTasksInCurrentSequence()) {
443     mojo_task_runner_->PostTask(
444         FROM_HERE,
445         base::BindOnce(&ContentDecryptionModuleAdapter::CancelDecrypt,
446                        weak_factory_.GetWeakPtr(), stream_type));
447     return;
448   }
449   media::Decryptor::DecryptCB callback =
450       std::move(stream_type == kVideo ? pending_video_decrypt_cb_
451                                       : pending_audio_decrypt_cb_);
452   if (callback)
453     std::move(callback).Run(media::Decryptor::kSuccess, nullptr);
454 }
455 
InitializeAudioDecoder(const media::AudioDecoderConfig & config,DecoderInitCB init_cb)456 void ContentDecryptionModuleAdapter::InitializeAudioDecoder(
457     const media::AudioDecoderConfig& config,
458     DecoderInitCB init_cb) {
459   // ContentDecryptionModuleAdapter does not support audio decoding.
460   std::move(init_cb).Run(false);
461 }
462 
InitializeVideoDecoder(const media::VideoDecoderConfig & config,DecoderInitCB init_cb)463 void ContentDecryptionModuleAdapter::InitializeVideoDecoder(
464     const media::VideoDecoderConfig& config,
465     DecoderInitCB init_cb) {
466   // ContentDecryptionModuleAdapter does not support video decoding.
467   std::move(init_cb).Run(false);
468 }
469 
DecryptAndDecodeAudio(scoped_refptr<media::DecoderBuffer> encrypted,const AudioDecodeCB & audio_decode_cb)470 void ContentDecryptionModuleAdapter::DecryptAndDecodeAudio(
471     scoped_refptr<media::DecoderBuffer> encrypted,
472     const AudioDecodeCB& audio_decode_cb) {
473   NOTREACHED()
474       << "ContentDecryptionModuleAdapter does not support audio decoding";
475 }
476 
DecryptAndDecodeVideo(scoped_refptr<media::DecoderBuffer> encrypted,const VideoDecodeCB & video_decode_cb)477 void ContentDecryptionModuleAdapter::DecryptAndDecodeVideo(
478     scoped_refptr<media::DecoderBuffer> encrypted,
479     const VideoDecodeCB& video_decode_cb) {
480   NOTREACHED()
481       << "ContentDecryptionModuleAdapter does not support video decoding";
482 }
483 
ResetDecoder(StreamType stream_type)484 void ContentDecryptionModuleAdapter::ResetDecoder(StreamType stream_type) {
485   NOTREACHED() << "ContentDecryptionModuleAdapter does not support decoding";
486 }
487 
DeinitializeDecoder(StreamType stream_type)488 void ContentDecryptionModuleAdapter::DeinitializeDecoder(
489     StreamType stream_type) {
490   // We do not support audio/video decoding, but since this can be called any
491   // time after InitializeAudioDecoder/InitializeVideoDecoder, nothing to be
492   // done here.
493 }
494 
CanAlwaysDecrypt()495 bool ContentDecryptionModuleAdapter::CanAlwaysDecrypt() {
496   return false;
497 }
498 
~ContentDecryptionModuleAdapter()499 ContentDecryptionModuleAdapter::~ContentDecryptionModuleAdapter() {
500   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
501   DVLOG(2) << __func__;
502   cdm_session_tracker_.CloseRemainingSessions(session_closed_cb_);
503 }
504 
OnConnectionError()505 void ContentDecryptionModuleAdapter::OnConnectionError() {
506   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
507   DVLOG(1) << __func__;
508   // The mojo connection doesn't manage our lifecycle, that's handled by the
509   // owner of the media::ContentDecryptionModule implementation we provide; so
510   // only drop the bindings and notify the other end about all of the closed
511   // sessions; don't destruct here.
512   cros_client_receiver_.reset();
513   cros_cdm_remote_.reset();
514 
515   // We've lost our communication, so reject all outstanding promises and close
516   // any open sessions.
517   cdm_promise_adapter_.Clear();
518   cdm_session_tracker_.CloseRemainingSessions(session_closed_cb_);
519 }
520 
RejectTrackedPromise(uint32_t promise_id,cdm::mojom::CdmPromiseResultPtr promise_result)521 void ContentDecryptionModuleAdapter::RejectTrackedPromise(
522     uint32_t promise_id,
523     cdm::mojom::CdmPromiseResultPtr promise_result) {
524   cdm_promise_adapter_.RejectPromise(promise_id, promise_result->exception,
525                                      promise_result->system_code,
526                                      promise_result->error_message);
527 }
528 
OnSimplePromiseResult(uint32_t promise_id,cdm::mojom::CdmPromiseResultPtr promise_result)529 void ContentDecryptionModuleAdapter::OnSimplePromiseResult(
530     uint32_t promise_id,
531     cdm::mojom::CdmPromiseResultPtr promise_result) {
532   DVLOG(1) << __func__ << " received result: " << promise_result->success;
533   if (!promise_result->success) {
534     RejectTrackedPromise(promise_id, std::move(promise_result));
535     return;
536   }
537   cdm_promise_adapter_.ResolvePromise(promise_id);
538 }
539 
OnGetStatusForPolicy(uint32_t promise_id,cdm::mojom::CdmPromiseResultPtr promise_result,media::CdmKeyInformation::KeyStatus key_status)540 void ContentDecryptionModuleAdapter::OnGetStatusForPolicy(
541     uint32_t promise_id,
542     cdm::mojom::CdmPromiseResultPtr promise_result,
543     media::CdmKeyInformation::KeyStatus key_status) {
544   if (!promise_result->success) {
545     RejectTrackedPromise(promise_id, std::move(promise_result));
546     return;
547   }
548   cdm_promise_adapter_.ResolvePromise(promise_id, key_status);
549 }
550 
OnSessionPromiseResult(uint32_t promise_id,cdm::mojom::CdmPromiseResultPtr promise_result,const std::string & session_id)551 void ContentDecryptionModuleAdapter::OnSessionPromiseResult(
552     uint32_t promise_id,
553     cdm::mojom::CdmPromiseResultPtr promise_result,
554     const std::string& session_id) {
555   DVLOG(1) << __func__ << " received result: " << promise_result->success
556            << " session: " << session_id;
557   if (!promise_result->success) {
558     RejectTrackedPromise(promise_id, std::move(promise_result));
559     return;
560   }
561   cdm_session_tracker_.AddSession(session_id);
562   cdm_promise_adapter_.ResolvePromise(promise_id, session_id);
563 }
564 
StoreDecryptCallback(StreamType stream_type,DecryptCB decrypt_cb)565 void ContentDecryptionModuleAdapter::StoreDecryptCallback(
566     StreamType stream_type,
567     DecryptCB decrypt_cb) {
568   if (stream_type == kVideo) {
569     DCHECK(!pending_video_decrypt_cb_);
570     pending_video_decrypt_cb_ = std::move(decrypt_cb);
571   } else {
572     DCHECK(!pending_audio_decrypt_cb_);
573     pending_audio_decrypt_cb_ = std::move(decrypt_cb);
574   }
575 }
576 
OnDecrypt(StreamType stream_type,scoped_refptr<media::DecoderBuffer> encrypted,size_t expected_decrypt_size,media::Decryptor::Status status,const std::vector<uint8_t> & decrypted_data)577 void ContentDecryptionModuleAdapter::OnDecrypt(
578     StreamType stream_type,
579     scoped_refptr<media::DecoderBuffer> encrypted,
580     size_t expected_decrypt_size,
581     media::Decryptor::Status status,
582     const std::vector<uint8_t>& decrypted_data) {
583   media::Decryptor::DecryptCB callback =
584       std::move(stream_type == kVideo ? pending_video_decrypt_cb_
585                                       : pending_audio_decrypt_cb_);
586   if (!callback) {
587     // This happens if CancelDecrypt was called.
588     DVLOG(1) << __func__ << " decrypt callback empty";
589     return;
590   }
591   if (status != media::Decryptor::kSuccess) {
592     if (status == media::Decryptor::kNoKey) {
593       DVLOG(1) << "Decryption failed due to no key";
594     } else {
595       LOG(ERROR) << "Failure decrypting data: " << status;
596     }
597     std::move(callback).Run(status, nullptr);
598     return;
599   }
600 
601   if (decrypted_data.size() != expected_decrypt_size) {
602     LOG(ERROR) << "Decrypted data size mismatch got: " << decrypted_data.size()
603                << " expected: " << expected_decrypt_size;
604     std::move(callback).Run(media::Decryptor::kError, nullptr);
605     return;
606   }
607 
608   std::move(callback).Run(
609       media::Decryptor::kSuccess,
610       CopyDecryptedDataToDecoderBuffer(std::move(encrypted), decrypted_data));
611 }
612 
613 }  // namespace chromeos
614