• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef DRM_ADAPTER_IMPL_H
17 #define DRM_ADAPTER_IMPL_H
18 
19 #include <mutex>
20 #include <pthread.h>
21 #include <securec.h>
22 
23 #include "drm_adapter.h"
24 #include "native_drm_common.h"
25 #include "native_drm_err.h"
26 #include "nweb_log.h"
27 
28 namespace OHOS::NWeb {
29 
30 const std::string SECURITY_LEVEL = "securityLevel";
31 const std::string SERVER_CERTIFICATE = "serviceCertificate";
32 const std::string ORIGIN = "origin";
33 const std::string PRIVACY_MODE = "privacyMode";
34 const std::string SESSION_SHARING = "sessionSharing";
35 const std::string ENABLE = "enable";
36 const std::string WIDEVINE_NAME = "com.widevine.alpha";
37 const std::string WISEPLAY_NAME = "com.wiseplay.drm";
38 
39 constexpr int32_t SECURITY_LEVEL_1 = 1;
40 constexpr int32_t SECURITY_LEVEL_3 = 3;
41 constexpr int32_t SECURITY_LEVEL_UNKNOWN = 0;
42 constexpr int32_t INFO_SIZE = 8;
43 constexpr int32_t MAX_URL_LENGTH = 2048;
44 constexpr int32_t MAX_REQUEST_LENGTH = 12288;
45 constexpr int32_t HEX_OFFSET = 4;
46 constexpr int32_t MAX_KEY_SET_ID_LEN = 128;
47 constexpr uint64_t MILLISECOND_IN_SECOND = 1000;
48 constexpr int32_t MILLISECOND_DIGITS = 3;
49 constexpr int32_t EXPIRATION_INFO_MAX_LEN = 16;
50 constexpr int32_t EXPIRATION_INFO_BASE = 10;
51 
52 enum class MediaKeyType : int32_t {
53     MEDIA_KEY_TYPE_OFFLINE = 0,
54     MEDIA_KEY_TYPE_ONLINE,
55     MEDIA_KEY_TYPE_RELEASE,
56 };
57 
58 enum class ClearInfoType : int32_t {
59     KEY_RELEASE = 0,
60     LOAD_FAIL,
61 };
62 
63 enum class KeyStatus : uint32_t {
64     KEY_STATUS_USABLE = 0,
65     KEY_STATUS_EXPIRED = 1,
66     KEY_STATUS_OUTPUT_NOT_ALLOWED = 2,
67     KEY_STATUS_PENDING = 3,
68     KEY_STATUS_INTERNAL_ERROR = 4,
69     KEY_STATUS_USABLE_IN_FUTURE = 5,
70 };
71 
72 enum class DrmResult : int32_t {
73     DRM_RESULT_ERROR = -1,
74     DRM_RESULT_OK = 0,
75 };
76 
77 enum class KeySystemType : int32_t {
78     NONE = 0,
79     WIDEVINE,
80     WISEPLAY
81 };
82 
83 class SessionId {
84 public:
CreateSessionId(const std::string & emeId)85     static std::shared_ptr<SessionId> CreateSessionId(const std::string& emeId)
86     {
87         return std::make_shared<SessionId>(emeId, nullptr, 0);
88     }
89 
SessionId(std::string emeId,const uint8_t * keySetId,int32_t keySetIdLen)90     SessionId(std::string emeId, const uint8_t* keySetId, int32_t keySetIdLen)
91         : emeId_(emeId), keySetIdLen_(keySetIdLen)
92     {
93         (void)memset_s(keySetId_, sizeof(keySetId_), 0, sizeof(keySetId_));
94         if (keySetId != nullptr && keySetIdLen > 0 && keySetIdLen <= MAX_KEY_SET_ID_LEN) {
95             if (memcpy_s(keySetId_, sizeof(keySetId_), keySetId, keySetIdLen) != 0) {
96                 WVLOG_E("memcpy_s failed!");
97             }
98         }
99     }
100 
EmeId()101     std::string EmeId()
102     {
103         return emeId_;
104     }
105 
KeySetId()106     uint8_t* KeySetId()
107     {
108         return keySetId_;
109     }
110 
KeySetIdLen()111     int32_t KeySetIdLen()
112     {
113         return keySetIdLen_;
114     }
115 
SetKeySetId(uint8_t * keySetId,int32_t keySetIdLen)116     void SetKeySetId(uint8_t* keySetId, int32_t keySetIdLen)
117     {
118         if (keySetIdLen > MAX_KEY_SET_ID_LEN) {
119             WVLOG_E("keySetIdLen error!");
120             return;
121         }
122         if (keySetId == nullptr || keySetIdLen <= 0) {
123             (void)memset_s(keySetId_, sizeof(keySetId_), 0, sizeof(keySetId_));
124         } else {
125             if (memcpy_s(keySetId_, sizeof(keySetId_), keySetId, keySetIdLen) != 0) {
126                 WVLOG_E("memcpy_s failed!");
127             }
128         }
129         keySetIdLen_ = keySetIdLen;
130     }
131 
132 private:
133     std::string emeId_;
134     uint8_t keySetId_[MAX_KEY_SET_ID_LEN];
135     int32_t keySetIdLen_;
136 };
137 
138 class SessionInfo {
139 public:
SessionInfo(std::shared_ptr<SessionId> sessionId,std::string mimeType,int32_t keyType)140     SessionInfo(std::shared_ptr<SessionId> sessionId, std::string mimeType, int32_t keyType)
141         : sessionId_(sessionId), mimeType_(mimeType), keyType_(keyType)
142     {}
143 
MimeType()144     std::string MimeType()
145     {
146         return mimeType_;
147     }
148 
KeyType()149     int32_t KeyType()
150     {
151         return keyType_;
152     }
153 
IsRelease()154     bool IsRelease()
155     {
156         return (keyType_ == static_cast<int32_t>(MediaKeyType::MEDIA_KEY_TYPE_RELEASE));
157     }
158 
SetKeyType(int32_t keyType)159     void SetKeyType(int32_t keyType)
160     {
161         keyType_ = keyType;
162     }
163 
GetSessionId()164     std::shared_ptr<SessionId> GetSessionId()
165     {
166         return sessionId_;
167     }
168 
169 private:
170     std::shared_ptr<SessionId> sessionId_;
171     std::string mimeType_;
172     int32_t keyType_;
173 };
174 
175 class DrmCallbackImpl {
176 public:
177     DrmCallbackImpl(std::shared_ptr<DrmCallbackAdapter> callbackAdapter);
178     ~DrmCallbackImpl() = default;
179 
180     void OnSessionMessage(const std::string& sessionId, int32_t& type, const std::vector<uint8_t>& message);
181     void OnProvisionRequest(const std::string& defaultUrl, const std::string& requestData);
182     void OnProvisioningComplete(bool success);
183     void OnMediaKeySessionReady(void* session);
184     void OnPromiseRejected(uint32_t promiseId, const std::string& errorMessage);
185     void OnPromiseResolved(uint32_t promiseId);
186     void OnPromiseResolvedWithSession(uint32_t promiseId, const std::string& sessionId);
187     void OnSessionClosed(const std::string& sessionId);
188     void OnSessionKeysChange(const std::string& sessionId, const std::vector<std::string>& keyIdArray,
189         const std::vector<uint32_t>& statusArray, bool hasAdditionalUsableKey, bool isKeyRelease);
190     void OnSessionExpirationUpdate(const std::string& sessionId, uint64_t expirationTime);
191     void OnStorageProvisioned();
192     void OnStorageSaveInfo(const std::vector<uint8_t>& ketSetId, const std::string& mimeType,
193         const std::string& sessionId, int32_t keyType);
194     void OnStorageLoadInfo(const std::string& sessionId);
195     void OnStorageClearInfoForKeyRelease(const std::string& sessionId);
196     void OnStorageClearInfoForLoadFail(const std::string& sessionId);
197     void OnMediaLicenseReady(bool success);
198 
199     void UpdateMediaKeySessionInfoMap(MediaKeySession* keySession, std::shared_ptr<SessionInfo> sessionInfo);
200     std::shared_ptr<SessionInfo> GetMediaKeySessionInfo(MediaKeySession* keySession);
201     void RemoveMediaKeySessionInfo(MediaKeySession* keySession);
202     void ClearMediaKeySessionInfo();
203 
204 private:
205     std::shared_ptr<DrmCallbackAdapter> callbackAdapter_;
206     std::unordered_map<MediaKeySession*, std::shared_ptr<SessionInfo>> mediaKeySessionInfoMap_;
207     std::mutex mediaKeySessionInfoMutex_;
208 };
209 
210 class DrmAdapterImpl : public DrmAdapter {
211 public:
212     DrmAdapterImpl() = default;
213     ~DrmAdapterImpl() override;
214 
215     static Drm_ErrCode SystemCallBackWithObj(
216         MediaKeySystem* mediaKeySystem, DRM_EventType eventType, uint8_t* info, int32_t infoLen, char* extra);
217     static Drm_ErrCode SessionEventCallBackWithObj(
218         MediaKeySession* mediaKeySession, DRM_EventType eventType, uint8_t* info, int32_t infoLen, char* extra);
219     static Drm_ErrCode SessionKeyChangeCallBackWithObj(
220         MediaKeySession* mediaKeySession, DRM_KeysInfo* keysInfo, bool newKeysAvailable);
221 
222     bool IsSupported(const std::string& name) override;
223     bool IsSupported2(const std::string& name, const std::string& mimeType) override;
224     bool IsSupported3(const std::string& name, const std::string& mimeType, int32_t level) override;
225     std::vector<uint8_t> GetUUID(const std::string& name) override;
226     void StorageProvisionedResult(bool result) override;
227     void StorageSaveInfoResult(bool result, int32_t type) override;
228     void StorageLoadInfoResult(const std::string& sessionId, const std::vector<uint8_t>& keySetId,
229         const std::string& mimeType, uint32_t keyType) override;
230     void StorageClearInfoResult(bool result, int32_t type) override;
231 
232     int32_t CreateKeySystem(const std::string& name, const std::string& origin, int32_t securityLevel) override;
233     int32_t ProcessKeySystemResponse(const std::string& response, bool isResponseReceived) override;
234     int32_t GenerateMediaKeyRequest(const std::string& sessionId, int32_t type, int32_t initDataLen,
235         const std::vector<uint8_t>& initData, const std::string& mimeType, uint32_t promiseId) override;
236     int32_t UpdateSession(uint32_t promiseId, const std::string& sessionId, std::vector<uint8_t> response) override;
237     int32_t CloseSession(uint32_t promiseId, const std::string& sessionId) override;
238     int32_t RemoveSession(uint32_t promiseId, const std::string& sessionId) override;
239     int32_t LoadSession(uint32_t promiseId, const std::string& sessionId) override;
240     int32_t ReleaseMediaKeySystem() override;
241     int32_t ReleaseMediaKeySession() override;
242 
243     int32_t SetConfigurationString(const std::string& configName, const std::string& value) override;
244     int32_t GetConfigurationString(const std::string& configName, char* value, int32_t valueLen) override;
245     int32_t SetConfigurationByteArray(const std::string& configName, const uint8_t* value, int32_t valueLen) override;
246     int32_t GetConfigurationByteArray(const std::string& configName, uint8_t* value, int32_t* valueLen) override;
247     int32_t GetMaxContentProtectionLevel(int32_t& level) override;
248     int32_t GetCertificateStatus(int32_t& certStatus) override;
249     int32_t RegistDrmCallback(std::shared_ptr<DrmCallbackAdapter> callbackAdapter) override;
250     int32_t ClearMediaKeys() override;
251     int32_t GetSecurityLevel() override;
252     int32_t RequireSecureDecoderModule(const std::string& mimeType, bool& status) override;
253 
254 private:
255     int32_t CreateMediaKeySession(std::string emeId = "");
256     int32_t ReleaseMediaKeySession(MediaKeySession* drmKeySession);
257     MediaKeySession* GetMediaKeySession(std::string emeId);
258 
259     void PutSessionInfo(std::shared_ptr<SessionId> sessionId, const std::string& mimeType, int32_t type);
260     std::shared_ptr<SessionInfo> GetSessionInfo(std::shared_ptr<SessionId> sessionId);
261     void RemoveSessionInfo(std::shared_ptr<SessionId> sessionId);
262     void LoadSessionInfo(const std::string& emeId);
263     void LoadSessionWithLoadedStorage(std::shared_ptr<SessionId> sessionId, uint32_t promiseId);
264     void UpdateSessionResult(
265         bool isKeyRelease, std::shared_ptr<SessionId> sessionId, uint8_t* mediaKeyId, int32_t mediaKeyIdLen);
266 
267     void SetKeyType(std::shared_ptr<SessionId> sessionId, int32_t keyType);
268     void SetKeySetId(std::shared_ptr<SessionId> sessionId, uint8_t* mediaKeyId, int32_t mediaKeyIdLen);
269 
270     std::shared_ptr<SessionId> GetSessionIdByEmeId(const std::string& emeId);
271 
272     void ClearPersistentSessionInfoFroKeyRelease(std::shared_ptr<SessionId> sessionId);
273     void ClearPersistentSessionInfoForLoadFail(std::shared_ptr<SessionId> sessionId);
274 
275     void HandleKeyUpdatedCallback(uint32_t promiseId, bool result);
276 
277     static void OnSessionExpirationUpdate(MediaKeySession* drmKeySession, uint8_t* info, int32_t infoLen);
278     static void GetKeyRequest(MediaKeySession* drmKeySession, uint8_t* info, int32_t infoLen);
279 
280 private:
281     static std::unordered_map<MediaKeySystem*, std::shared_ptr<DrmCallbackImpl>> mediaKeySystemCallbackMap_;
282     static std::unordered_map<MediaKeySession*, std::shared_ptr<DrmCallbackImpl>> mediaKeySessionCallbackMap_;
283     static std::mutex mediaKeySystemCallbackMapMutex_;
284     static std::mutex mediaKeySessionCallbackMutex_;
285 
286     MediaKeySystem* drmKeySystem_ = nullptr;
287     MediaKeySession* drmKeySession_ = nullptr;
288     DRM_ContentProtectionLevel contentProtectionLevel_ = CONTENT_PROTECTION_LEVEL_UNKNOWN;
289     std::shared_ptr<DrmCallbackImpl> callback_ = nullptr;
290 
291     std::unordered_map<std::string, std::shared_ptr<SessionInfo>> emeSessionInfoMap_;
292     std::unordered_map<std::string, MediaKeySession*> emeMediaKeySessionMap_;
293     std::mutex mediaKeySessionMutex_;
294 
295     uint32_t removeSessionPromiseId_ = 0;
296     uint32_t updateSessionPromiseId_ = 0;
297     uint32_t loadSessionPromiseId_ = 0;
298     std::string releaseEmeId_ = "";
299     KeySystemType keySystemType_ = KeySystemType::NONE;
300 };
301 } // namespace OHOS::NWeb
302 #endif // DRM_ADAPTER_IMPL_H