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 #ifndef CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CONTENT_DECRYPTION_MODULE_ADAPTER_H_
6 #define CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CONTENT_DECRYPTION_MODULE_ADAPTER_H_
7 
8 #include <memory>
9 #include <string>
10 #include <vector>
11 
12 #include "base/memory/weak_ptr.h"
13 #include "base/threading/thread_checker.h"
14 #include "chromeos/components/cdm_factory_daemon/cdm_storage_adapter.h"
15 #include "chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h"
16 #include "chromeos/components/cdm_factory_daemon/mojom/content_decryption_module.mojom.h"
17 #include "media/base/callback_registry.h"
18 #include "media/base/cdm_context.h"
19 #include "media/base/cdm_key_information.h"
20 #include "media/base/cdm_promise_adapter.h"
21 #include "media/base/cdm_session_tracker.h"
22 #include "media/base/content_decryption_module.h"
23 #include "media/base/decrypt_config.h"
24 #include "media/base/decryptor.h"
25 #include "mojo/public/cpp/bindings/associated_receiver.h"
26 #include "mojo/public/cpp/bindings/associated_remote.h"
27 
28 namespace chromeos {
29 
30 // This class adapts the calls between both the media::ContentDecryptionModule
31 // and media::Decryptor interface over to the
32 // chromeos::cdm::mojom::ContentDecryptionModule interface. It also adapts the
33 // chromeos::cdm::mojom::ContentDecryptionModuleClient interface to the
34 // callbacks passed into the constructor which come from
35 // media::CdmFactory::Create. Decryption interface only supports decrypting to
36 // clear and not decoding.
37 //
38 // This implementation runs in the GPU process and expects all calls to be
39 // executed on the mojo thread.  Decrypt, RegisterEventCB and CancelDecrypt
40 // are exceptions, and can be called from any thread.
COMPONENT_EXPORT(CDM_FACTORY_DAEMON)41 class COMPONENT_EXPORT(CDM_FACTORY_DAEMON) ContentDecryptionModuleAdapter
42     : public cdm::mojom::ContentDecryptionModuleClient,
43       public media::ContentDecryptionModule,
44       public media::CdmContext,
45       public chromeos::ChromeOsCdmContext,
46       public media::Decryptor {
47  public:
48   ContentDecryptionModuleAdapter(
49       std::unique_ptr<CdmStorageAdapter> storage,
50       mojo::AssociatedRemote<cdm::mojom::ContentDecryptionModule>
51           cros_cdm_remote,
52       const media::SessionMessageCB& session_message_cb,
53       const media::SessionClosedCB& session_closed_cb,
54       const media::SessionKeysChangeCB& session_keys_change_cb,
55       const media::SessionExpirationUpdateCB& session_expiration_update_cb);
56 
57   ContentDecryptionModuleAdapter(const ContentDecryptionModuleAdapter&) =
58       delete;
59   ContentDecryptionModuleAdapter& operator=(
60       const ContentDecryptionModuleAdapter&) = delete;
61 
62   // This can only be called once after construction.
63   mojo::PendingAssociatedRemote<cdm::mojom::ContentDecryptionModuleClient>
64   GetClientInterface();
65 
66   // media::ContentDecryptionModule:
67   void SetServerCertificate(
68       const std::vector<uint8_t>& certificate_data,
69       std::unique_ptr<media::SimpleCdmPromise> promise) override;
70   void GetStatusForPolicy(
71       media::HdcpVersion min_hdcp_version,
72       std::unique_ptr<media::KeyStatusCdmPromise> promise) override;
73   void CreateSessionAndGenerateRequest(
74       media::CdmSessionType session_type,
75       media::EmeInitDataType init_data_type,
76       const std::vector<uint8_t>& init_data,
77       std::unique_ptr<media::NewSessionCdmPromise> promise) override;
78   void LoadSession(
79       media::CdmSessionType session_type,
80       const std::string& session_id,
81       std::unique_ptr<media::NewSessionCdmPromise> promise) override;
82   void UpdateSession(const std::string& session_id,
83                      const std::vector<uint8_t>& response,
84                      std::unique_ptr<media::SimpleCdmPromise> promise) override;
85   void CloseSession(const std::string& session_id,
86                     std::unique_ptr<media::SimpleCdmPromise> promise) override;
87   void RemoveSession(const std::string& session_id,
88                      std::unique_ptr<media::SimpleCdmPromise> promise) override;
89   media::CdmContext* GetCdmContext() override;
90 
91   // media::CdmContext:
92   std::unique_ptr<media::CallbackRegistration> RegisterEventCB(
93       EventCB event_cb) override;
94   Decryptor* GetDecryptor() override;
95   ChromeOsCdmContext* GetChromeOsCdmContext() override;
96 
97   // chromeos::ChromeOsCdmContext:
98   void GetHwKeyData(const media::DecryptConfig* decrypt_config,
99                     const std::vector<uint8_t>& hw_identifier,
100                     GetHwKeyDataCB callback) override;
101 
102   // cdm::mojom::ContentDecryptionModuleClient:
103   void OnSessionMessage(const std::string& session_id,
104                         media::CdmMessageType message_type,
105                         const std::vector<uint8_t>& message) override;
106   void OnSessionClosed(const std::string& session_id) override;
107   void OnSessionKeysChange(
108       const std::string& session_id,
109       bool has_additional_usable_key,
110       std::vector<std::unique_ptr<media::CdmKeyInformation>> keys_info)
111       override;
112   void OnSessionExpirationUpdate(const std::string& session_id,
113                                  double new_expiry_time_sec) override;
114 
115   // media::Decryptor:
116   void Decrypt(StreamType stream_type,
117                scoped_refptr<media::DecoderBuffer> encrypted,
118                DecryptCB decrypt_cb) override;
119   void CancelDecrypt(StreamType stream_type) override;
120   void InitializeAudioDecoder(const media::AudioDecoderConfig& config,
121                               DecoderInitCB init_cb) override;
122   void InitializeVideoDecoder(const media::VideoDecoderConfig& config,
123                               DecoderInitCB init_cb) override;
124   void DecryptAndDecodeAudio(scoped_refptr<media::DecoderBuffer> encrypted,
125                              const AudioDecodeCB& audio_decode_cb) override;
126   void DecryptAndDecodeVideo(scoped_refptr<media::DecoderBuffer> encrypted,
127                              const VideoDecodeCB& video_decode_cb) override;
128   void ResetDecoder(StreamType stream_type) override;
129   void DeinitializeDecoder(StreamType stream_type) override;
130   bool CanAlwaysDecrypt() override;
131 
132  private:
133   ~ContentDecryptionModuleAdapter() override;
134   void OnConnectionError();
135   void RejectTrackedPromise(uint32_t promise_id,
136                             cdm::mojom::CdmPromiseResultPtr promise_result);
137   void OnSimplePromiseResult(
138       uint32_t promise_id,
139       cdm::mojom::CdmPromiseResultPtr cros_promise_result);
140   void OnGetStatusForPolicy(uint32_t promise_id,
141                             cdm::mojom::CdmPromiseResultPtr cros_promise_result,
142                             media::CdmKeyInformation::KeyStatus key_status);
143   void OnSessionPromiseResult(
144       uint32_t promise_id,
145       cdm::mojom::CdmPromiseResultPtr cros_promise_result,
146       const std::string& session_id);
147   void StoreDecryptCallback(StreamType stream_type, DecryptCB decrypt_cb);
148   void OnDecrypt(StreamType stream_type,
149                  scoped_refptr<media::DecoderBuffer> encrypted,
150                  size_t expected_decrypt_size,
151                  media::Decryptor::Status status,
152                  const std::vector<uint8_t>& decrypted_data);
153 
154   THREAD_CHECKER(thread_checker_);
155 
156   std::unique_ptr<CdmStorageAdapter> storage_;
157 
158   mojo::AssociatedReceiver<cdm::mojom::ContentDecryptionModuleClient>
159       cros_client_receiver_{this};
160   mojo::AssociatedRemote<cdm::mojom::ContentDecryptionModule> cros_cdm_remote_;
161 
162   media::SessionMessageCB session_message_cb_;
163   media::SessionClosedCB session_closed_cb_;
164   media::SessionKeysChangeCB session_keys_change_cb_;
165   media::SessionExpirationUpdateCB session_expiration_update_cb_;
166 
167   media::Decryptor::DecryptCB pending_audio_decrypt_cb_;
168   media::Decryptor::DecryptCB pending_video_decrypt_cb_;
169 
170   scoped_refptr<base::SequencedTaskRunner> mojo_task_runner_;
171 
172   // Track what sessions are open so that if we lose our mojo connection we can
173   // invoke the closed callback on all of them.
174   media::CdmSessionTracker cdm_session_tracker_;
175 
176   // Keep track of outstanding promises.
177   media::CdmPromiseAdapter cdm_promise_adapter_;
178 
179   media::CallbackRegistry<EventCB::RunType> event_callbacks_;
180 
181   // WeakPtrFactory to use for callbacks.
182   base::WeakPtrFactory<ContentDecryptionModuleAdapter> weak_factory_{this};
183 };
184 
185 }  // namespace chromeos
186 
187 #endif  // CHROMEOS_COMPONENTS_CDM_FACTORY_DAEMON_CONTENT_DECRYPTION_MODULE_ADAPTER_H_
188