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