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