1 /*
2 * Copyright (c) 2023 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 #include "ipc_skeleton.h"
16 #include "napi_param_utils.h"
17 #include "key_session_impl.h"
18 #include "media_key_system_impl.h"
19 #include "key_session_napi.h"
20 #include "drm_trace.h"
21 #include "drm_error_code.h"
22 #include "drm_api_operation.h"
23
24 namespace OHOS {
25 namespace DrmStandard {
26 thread_local napi_ref MediaKeySessionNapi::sConstructor_ = nullptr;
27 thread_local sptr<MediaKeySessionImpl> MediaKeySessionNapi::sMediaKeySessionImpl_ = nullptr;
28
MediaKeySessionNapi()29 MediaKeySessionNapi::MediaKeySessionNapi() : env_(nullptr), wrapper_(nullptr)
30 {
31 DRM_INFO_LOG("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
32 }
33
~MediaKeySessionNapi()34 MediaKeySessionNapi::~MediaKeySessionNapi()
35 {
36 DRM_INFO_LOG("~MediaKeySessionNapi Init enter.");
37 DRM_DEBUG_LOG("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
38 if (wrapper_ != nullptr) {
39 napi_delete_reference(env_, wrapper_);
40 }
41 if (keySessionImpl_) {
42 keySessionImpl_ = nullptr;
43 }
44 if (keySessionCallbackNapi_) {
45 keySessionCallbackNapi_ = nullptr;
46 }
47 }
48
Init(napi_env env,napi_value exports)49 napi_value MediaKeySessionNapi::Init(napi_env env, napi_value exports)
50 {
51 DRM_INFO_LOG("MediaKeySessionNapi Init enter.");
52 napi_status status;
53 napi_value ctorObj;
54
55 napi_property_descriptor session_props[] = {
56 DECLARE_NAPI_FUNCTION("generateMediaKeyRequest", GenerateMediaKeyRequest),
57 DECLARE_NAPI_FUNCTION("processMediaKeyResponse", ProcessMediaKeyResponse),
58 DECLARE_NAPI_FUNCTION("generateOfflineReleaseRequest", GenerateOfflineReleaseRequest),
59 DECLARE_NAPI_FUNCTION("processOfflineReleaseResponse", ProcessOfflineReleaseResponse),
60 DECLARE_NAPI_FUNCTION("checkMediaKeyStatus", CheckMediaKeyStatus),
61 DECLARE_NAPI_FUNCTION("restoreOfflineMediaKeys", RestoreOfflineMediaKeys),
62 DECLARE_NAPI_FUNCTION("clearMediaKeys", ClearMediaKeys),
63 DECLARE_NAPI_FUNCTION("getContentProtectionLevel", GetContentProtectionLevel),
64 DECLARE_NAPI_FUNCTION("requireSecureDecoderModule", RequireSecureDecoderModule),
65 DECLARE_NAPI_FUNCTION("destroy", Destroy),
66 DECLARE_NAPI_FUNCTION("on", SetEventCallback),
67 DECLARE_NAPI_FUNCTION("off", UnsetEventCallback),
68 };
69 status = napi_define_class(env, KEY_SESSION_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH, MediaKeySessionNapiConstructor,
70 nullptr, sizeof(session_props) / sizeof(session_props[PARAM0]), session_props, &ctorObj);
71 if (status == napi_ok) {
72 status = napi_create_reference(env, ctorObj, 1, &sConstructor_);
73 if (status == napi_ok) {
74 status = napi_set_named_property(env, exports, KEY_SESSION_NAPI_CLASS_NAME, ctorObj);
75 if (status == napi_ok) {
76 DRM_DEBUG_LOG("MediaKeySessionNapi return exports");
77 return exports;
78 }
79 }
80 }
81 DRM_INFO_LOG("MediaKeySessionNapi Init call Failed!");
82 return nullptr;
83 }
84
MediaKeySessionNapiConstructor(napi_env env,napi_callback_info info)85 napi_value MediaKeySessionNapi::MediaKeySessionNapiConstructor(napi_env env, napi_callback_info info)
86 {
87 DrmTrace trace("MediaKeySessionNapi::MediaKeySessionNapiConstructor");
88 DRM_INFO_LOG("MediaKeySessionNapiConstructor enter.");
89
90 napi_status status;
91 napi_value result = nullptr;
92 napi_value thisVar = nullptr;
93
94 napi_get_undefined(env, &result);
95 DRM_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
96
97 if (status == napi_ok && thisVar != nullptr) {
98 std::unique_ptr<MediaKeySessionNapi> obj = std::make_unique<MediaKeySessionNapi>();
99 if (obj != nullptr) {
100 obj->env_ = env;
101 if (sMediaKeySessionImpl_ == nullptr) {
102 DRM_ERR_LOG("sMediaKeySessionImpl_ is null");
103 return result;
104 }
105 obj->keySessionImpl_ = sMediaKeySessionImpl_;
106 obj->keySessionCallbackNapi_ = new MediaKeySessionCallbackNapi(env);
107 obj->keySessionImpl_->SetCallback(obj->keySessionCallbackNapi_);
108
109 status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()),
110 MediaKeySessionNapi::MediaKeySessionNapiDestructor, nullptr, nullptr);
111 if (status == napi_ok) {
112 ObjectRefMap<MediaKeySessionNapi>::Insert(obj.get());
113 obj.release();
114 const std::string propertyName = "MediaKeySessionNative";
115 SetMediaKeySessionNativeProperty(env, thisVar, propertyName, sMediaKeySessionImpl_);
116 return thisVar;
117 } else {
118 ObjectRefMap<MediaKeySessionNapi>::Erase(obj.get());
119 DRM_ERR_LOG("Failure wrapping js to native napi");
120 }
121 }
122 }
123 return result;
124 }
125
MediaKeySessionNapiDestructor(napi_env env,void * nativeObject,void * finalize)126 void MediaKeySessionNapi::MediaKeySessionNapiDestructor(napi_env env, void *nativeObject, void *finalize)
127 {
128 DrmTrace trace("MediaKeySessionNapiDestructor");
129 DRM_INFO_LOG("MediaKeySessionNapiDestructor enter.");
130 MediaKeySessionNapi *keySessionNapiObj = reinterpret_cast<MediaKeySessionNapi *>(nativeObject);
131 ObjectRefMap<MediaKeySessionNapi>::DecreaseRef(keySessionNapiObj);
132 }
133
SetMediaKeySessionNativeProperty(napi_env env,napi_value obj,const std::string & name,sptr<MediaKeySessionImpl> keySessionImpl)134 bool MediaKeySessionNapi::SetMediaKeySessionNativeProperty(napi_env env, napi_value obj, const std::string &name,
135 sptr<MediaKeySessionImpl> keySessionImpl)
136 {
137 DRM_INFO_LOG("SetMediaKeySessionNativeProperty enter.");
138 DRM_CHECK_AND_RETURN_RET_LOG(obj != nullptr, false, "obj is nullptr");
139
140 napi_value keySessionImplNative = nullptr;
141 int64_t nativePointer = reinterpret_cast<int64_t>(keySessionImpl.GetRefPtr());
142 napi_status status = napi_create_int64(env, nativePointer, &keySessionImplNative);
143 DRM_CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "create int failed.");
144
145 napi_value nameStr = nullptr;
146 status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &nameStr);
147 DRM_CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "create string failed.");
148
149 status = napi_set_property(env, obj, nameStr, keySessionImplNative);
150 DRM_CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "set property failed.");
151
152 return true;
153 }
154
CreateMediaKeySession(napi_env env,sptr<MediaKeySessionImpl> keySessionImpl)155 napi_value MediaKeySessionNapi::CreateMediaKeySession(napi_env env, sptr<MediaKeySessionImpl> keySessionImpl)
156 {
157 DrmTrace trace("MediaKeySessionNapi::CreateMediaKeySession");
158 DRM_INFO_LOG("CreateMediaKeySession enter.");
159 napi_status status;
160 napi_value result = nullptr;
161 napi_value constructor;
162 status = napi_get_reference_value(env, sConstructor_, &constructor);
163 if (status == napi_ok) {
164 sMediaKeySessionImpl_ = keySessionImpl;
165 if (sMediaKeySessionImpl_ == nullptr) {
166 DRM_ERR_LOG("Failed to CreateMediaKeySession instance");
167 napi_get_undefined(env, &result);
168 return result;
169 }
170 status = napi_new_instance(env, constructor, 0, nullptr, &result);
171 sMediaKeySessionImpl_ = nullptr;
172 if (status == napi_ok && result != nullptr) {
173 DRM_INFO_LOG("success to CreateMediaKeySession napi instance");
174 return result;
175 } else {
176 DRM_ERR_LOG("Failed to CreateMediaKeySession napi instance");
177 }
178 }
179 DRM_DEBUG_LOG("Failed to create CreateMediaKeySession napi instance last");
180 napi_get_undefined(env, &result);
181 return result;
182 }
183
Destroy(napi_env env,napi_callback_info info)184 napi_value MediaKeySessionNapi::Destroy(napi_env env, napi_callback_info info)
185 {
186 DrmTrace trace("MediaKeySessionNapi::Destroy");
187 DRM_INFO_LOG("Destroy enter.");
188 int32_t currentPid = IPCSkeleton::GetCallingPid();
189 DRM_DEBUG_LOG("MediaKeySessionNapi GetCallingPID: %{public}d", currentPid);
190
191 napi_status status;
192 napi_value result = nullptr;
193 size_t argc = ARGS_ZERO;
194 napi_value argv[ARGS_ZERO];
195 napi_value thisVar = nullptr;
196 MediaKeySessionNapi *keySessionNapi = nullptr;
197
198 DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
199
200 napi_get_undefined(env, &result);
201 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&keySessionNapi));
202 if (status == napi_ok && keySessionNapi != nullptr && keySessionNapi->keySessionImpl_ != nullptr) {
203 int32_t ret = keySessionNapi->keySessionImpl_->Release();
204 if (ret != DRM_OK) {
205 DRM_ERR_LOG("keySessionImpl_ Release call Failed!");
206 NapiDrmError::ThrowError(env, "Release failed, service error.", DRM_SERVICE_FATAL_ERROR);
207 return result;
208 }
209 } else {
210 DRM_ERR_LOG("Release call Failed!");
211 NapiDrmError::ThrowError(env, "Release failed, unknown error.", DRM_UNKNOWN_ERROR);
212 return result;
213 }
214 return result;
215 }
216
CheckMediaKeySessionStatus(MediaKeySessionNapi * napi,std::shared_ptr<MediaKeySessionAsyncContext> context)217 bool MediaKeySessionNapi::CheckMediaKeySessionStatus(MediaKeySessionNapi *napi,
218 std::shared_ptr<MediaKeySessionAsyncContext> context)
219 {
220 DRM_NAPI_CHECK_AND_RETURN_LOG(napi != nullptr, false, "napi object is nullptr.");
221 if (napi->keySessionImpl_ == nullptr) {
222 context->SignError(DRM_SERVICE_FATAL_ERROR);
223 return false;
224 }
225 return true;
226 }
227
CheckContextStatus(std::shared_ptr<MediaKeySessionAsyncContext> context)228 bool MediaKeySessionNapi::CheckContextStatus(std::shared_ptr<MediaKeySessionAsyncContext> context)
229 {
230 DRM_NAPI_CHECK_AND_RETURN_LOG(context != nullptr, false, "context object is nullptr.");
231 if (context->native == nullptr) {
232 context->SignError(DRM_SERVICE_FATAL_ERROR);
233 return false;
234 }
235 return true;
236 }
237
GenerateMediaKeyRequest(napi_env env,napi_callback_info info)238 napi_value MediaKeySessionNapi::GenerateMediaKeyRequest(napi_env env, napi_callback_info info)
239 {
240 DRM_INFO_LOG("GenerateMediaKeyRequest enter");
241 DrmTrace trace("MediaKeySessionNapi::GenerateMediaKeyRequest");
242 auto context = std::make_shared<MediaKeySessionAsyncContext>();
243 if (context == nullptr) {
244 DRM_ERR_LOG("GenerateMediaKeyRequest failed.");
245 NapiDrmError::ThrowError(env, "make context failed, unknown error.", DRM_UNKNOWN_ERROR);
246 return NapiParamUtils::GetUndefinedValue(env);
247 }
248
249 auto inputParser = [env, context](size_t argc, napi_value *argv) {
250 NAPI_CHECK_ARGS_RETURN_VOID(context, argc == ARGS_THREE || argc == ARGS_FOUR, "invalid arguments",
251 DRM_INVALID_PARAM);
252 context->mediaKeyRequestInfo.mimeType = NapiParamUtils::GetStringArgument(env, argv[PARAM0]);
253 context->status = NapiParamUtils::GetValueUint8Array(env, context->mediaKeyRequestInfo.initData, argv[PARAM1]);
254 NAPI_CHECK_STATUS_RETURN_VOID(context, "generateMediaKeyRequest failed!", DRM_INVALID_PARAM);
255 int32_t mediaKeyType = 0;
256 context->status = NapiParamUtils::GetValueInt32(env, mediaKeyType, argv[PARAM2]);
257 NAPI_CHECK_STATUS_RETURN_VOID(context, "generateMediaKeyRequest failed!", DRM_INVALID_PARAM);
258 context->mediaKeyRequestInfo.mediaKeyType = (IMediaKeySessionService::MediaKeyType)mediaKeyType;
259 if (argc == ARGS_FOUR) {
260 context->status =
261 NapiParamUtils::GetValueOptionsData(env, context->mediaKeyRequestInfo.optionalData, argv[PARAM3]);
262 NAPI_CHECK_STATUS_RETURN_VOID(context, "generateMediaKeyRequest failed!", DRM_INVALID_PARAM);
263 }
264 };
265 context->GetCbInfo(env, info, inputParser);
266
267 auto executor = [context]() {
268 DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckContextStatus(context), "context object state is error.");
269 auto obj = reinterpret_cast<MediaKeySessionNapi *>(context->native);
270 ObjectRefMap objectGuard(obj);
271 auto *napiMediaKeySession = objectGuard.GetPtr();
272 DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckMediaKeySessionStatus(napiMediaKeySession, context),
273 "MediaKeySession state is error.");
274 context->intValue = napiMediaKeySession->keySessionImpl_->GenerateMediaKeyRequest(context->mediaKeyRequestInfo,
275 context->mediaKeyRequest);
276 if (context->intValue != DRM_OK) {
277 context->SignError(DRM_SERVICE_FATAL_ERROR);
278 }
279 };
280
281 auto complete = [env, context](napi_value &output) {
282 NapiParamUtils::SetMediaKeyRequest(env, context->mediaKeyRequest, output);
283 };
284 return NapiAsyncWork::Enqueue(env, context, "GenerateMediaKeyRequest", executor, complete);
285 }
286
ProcessMediaKeyResponse(napi_env env,napi_callback_info info)287 napi_value MediaKeySessionNapi::ProcessMediaKeyResponse(napi_env env, napi_callback_info info)
288 {
289 DRM_INFO_LOG("ProcessMediaKeyResponse enter.");
290 int64_t beginTime = std::chrono::duration_cast<std::chrono::milliseconds>(
291 std::chrono::system_clock::now().time_since_epoch()).count();
292 DrmTrace trace("MediaKeySessionNapi::ProcessMediaKeyResponse");
293 auto context = std::make_shared<MediaKeySessionAsyncContext>();
294 if (context == nullptr) {
295 DRM_ERR_LOG("ProcessMediaKeyResponse failed.");
296 NapiDrmError::ThrowError(env, "make context failed, unknown error.", DRM_UNKNOWN_ERROR);
297 return NapiParamUtils::GetUndefinedValue(env);
298 }
299
300 auto inputParser = [env, context](size_t argc, napi_value *argv) {
301 NAPI_CHECK_ARGS_RETURN_VOID(context, argc == ARGS_ONE, "invalid arguments", DRM_INVALID_PARAM);
302 context->status = NapiParamUtils::GetValueUint8Array(env, context->response, argv[PARAM0]);
303 NAPI_CHECK_STATUS_RETURN_VOID(context, "ProcessMediaKeyResponse failed!", DRM_INVALID_PARAM);
304 };
305 context->GetCbInfo(env, info, inputParser);
306
307 auto executor = [context]() {
308 DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckContextStatus(context), "context object state is error.");
309 auto obj = reinterpret_cast<MediaKeySessionNapi *>(context->native);
310 ObjectRefMap objectGuard(obj);
311 auto *napiMediaKeySession = objectGuard.GetPtr();
312 DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckMediaKeySessionStatus(napiMediaKeySession, context),
313 "MediaKeySession state is error.");
314 context->intValue =
315 napiMediaKeySession->keySessionImpl_->ProcessMediaKeyResponse(context->licenseId, context->response);
316 if (context->intValue != DRM_OK) {
317 context->SignError(DRM_SERVICE_FATAL_ERROR);
318 }
319 };
320
321 auto complete = [env, context](napi_value &output) {
322 NapiParamUtils::SetValueUint8Array(env, context->licenseId, output);
323 };
324 ConfigParser::WriteEndEvent(0, 0, std::string("processMediaKeyResponse"), beginTime);
325 return NapiAsyncWork::Enqueue(env, context, "ProcessMediaKeyResponse", executor, complete);
326 }
327
GenerateOfflineReleaseRequest(napi_env env,napi_callback_info info)328 napi_value MediaKeySessionNapi::GenerateOfflineReleaseRequest(napi_env env, napi_callback_info info)
329 {
330 DRM_INFO_LOG("GenerateOfflineReleaseRequest enter");
331 auto context = std::make_shared<MediaKeySessionAsyncContext>();
332 if (context == nullptr) {
333 DRM_ERR_LOG("GenerateOfflineReleaseRequest failed.");
334 NapiDrmError::ThrowError(env, "make context failed, unknown error.", DRM_UNKNOWN_ERROR);
335 return NapiParamUtils::GetUndefinedValue(env);
336 }
337
338 auto inputParser = [env, context](size_t argc, napi_value *argv) {
339 NAPI_CHECK_ARGS_RETURN_VOID(context, argc == ARGS_ONE, "invalid arguments", DRM_INVALID_PARAM);
340 context->status = NapiParamUtils::GetValueUint8Array(env, context->releaseLicenseId, argv[PARAM0]);
341 NAPI_CHECK_STATUS_RETURN_VOID(context, "GenerateOfflineReleaseRequest failed.", DRM_INVALID_PARAM);
342 };
343 context->GetCbInfo(env, info, inputParser);
344
345 auto executor = [context]() {
346 DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckContextStatus(context), "context object state is error.");
347 auto obj = reinterpret_cast<MediaKeySessionNapi *>(context->native);
348 ObjectRefMap objectGuard(obj);
349 auto *napiMediaKeySession = objectGuard.GetPtr();
350 DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckMediaKeySessionStatus(napiMediaKeySession, context),
351 "MediaKeySession state is error.");
352 context->intValue = napiMediaKeySession->keySessionImpl_->GenerateOfflineReleaseRequest(
353 context->releaseLicenseId, context->releaseRequest);
354 if (context->intValue != DRM_OK) {
355 context->SignError(DRM_SERVICE_FATAL_ERROR);
356 }
357 };
358
359 auto complete = [env, context](napi_value &output) {
360 NapiParamUtils::SetValueUint8Array(env, context->releaseRequest, output);
361 };
362 return NapiAsyncWork::Enqueue(env, context, "GenerateOfflineReleaseRequest", executor, complete);
363 }
364
ProcessOfflineReleaseResponse(napi_env env,napi_callback_info info)365 napi_value MediaKeySessionNapi::ProcessOfflineReleaseResponse(napi_env env, napi_callback_info info)
366 {
367 DRM_INFO_LOG("ProcessOfflineReleaseResponse enter.");
368 auto context = std::make_shared<MediaKeySessionAsyncContext>();
369 if (context == nullptr) {
370 DRM_ERR_LOG("ProcessOfflineReleaseResponse failed.");
371 NapiDrmError::ThrowError(env, "make context failed, unknown error.", DRM_UNKNOWN_ERROR);
372 return NapiParamUtils::GetUndefinedValue(env);
373 }
374
375 auto inputParser = [env, context](size_t argc, napi_value *argv) {
376 NAPI_CHECK_ARGS_RETURN_VOID(context, argc == ARGS_TWO, "invalid arguments", DRM_INVALID_PARAM);
377 context->status = NapiParamUtils::GetValueUint8Array(env, context->releaseResponseLicenseId, argv[PARAM0]);
378 NAPI_CHECK_STATUS_RETURN_VOID(context, "GetValueUint8Array failed.", DRM_INVALID_PARAM);
379 context->status = NapiParamUtils::GetValueUint8Array(env, context->releaseResponse, argv[PARAM1]);
380 NAPI_CHECK_STATUS_RETURN_VOID(context, "ProcessOfflineReleaseResponse failed.", DRM_INVALID_PARAM);
381 };
382 context->GetCbInfo(env, info, inputParser);
383
384 auto executor = [context]() {
385 DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckContextStatus(context), "context object state is error.");
386 auto obj = reinterpret_cast<MediaKeySessionNapi *>(context->native);
387 ObjectRefMap objectGuard(obj);
388 auto *napiMediaKeySession = objectGuard.GetPtr();
389 DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckMediaKeySessionStatus(napiMediaKeySession, context),
390 "MediaKeySession state is error.");
391 context->intValue = napiMediaKeySession->keySessionImpl_->ProcessOfflineReleaseResponse(
392 context->releaseResponseLicenseId, context->releaseResponse);
393 if (context->intValue != DRM_OK) {
394 context->SignError(DRM_SERVICE_FATAL_ERROR);
395 }
396 };
397
398 auto complete = [env, context](napi_value &output) { output = NapiParamUtils::GetUndefinedValue(env); };
399 return NapiAsyncWork::Enqueue(env, context, "ProcessOfflineReleaseResponse", executor, complete);
400 }
401
vectorToJsArray(napi_env env,std::map<std::string,std::string> & licenseStatus)402 static napi_value vectorToJsArray(napi_env env, std::map<std::string, std::string> &licenseStatus)
403 {
404 DRM_INFO_LOG("vectorToJsArray enter.");
405 napi_value jsArray;
406 napi_value jsName;
407 napi_value jsValue;
408 napi_create_array_with_length(env, licenseStatus.size(), &jsArray);
409 size_t index = 0;
410 for (auto it = licenseStatus.begin(); it != licenseStatus.end(); ++it) {
411 napi_value jsObject;
412 napi_create_object(env, &jsObject);
413 std::string name = it->first;
414 std::string status = it->second;
415 napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &jsName);
416 napi_set_named_property(env, jsObject, "name", jsName);
417 napi_create_string_utf8(env, status.c_str(), NAPI_AUTO_LENGTH, &jsValue);
418 napi_set_named_property(env, jsObject, "value", jsValue);
419 napi_set_element(env, jsArray, index++, jsObject);
420 }
421 return jsArray;
422 }
423
CheckMediaKeyStatus(napi_env env,napi_callback_info info)424 napi_value MediaKeySessionNapi::CheckMediaKeyStatus(napi_env env, napi_callback_info info)
425 {
426 DRM_INFO_LOG("CheckMediaKeyStatus enter");
427 napi_value result = nullptr;
428 size_t argc = ARGS_ZERO;
429 napi_value argv[ARGS_ZERO];
430 napi_value thisVar = nullptr;
431 napi_status status;
432 MediaKeySessionNapi *keySessionNapi = nullptr;
433 std::map<std::string, std::string> licenseStatus;
434
435 napi_get_undefined(env, &result);
436 DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
437 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&keySessionNapi));
438 if (status == napi_ok && keySessionNapi != nullptr && keySessionNapi->keySessionImpl_ != nullptr) {
439 int32_t ret = keySessionNapi->keySessionImpl_->CheckMediaKeyStatus(licenseStatus);
440 if (ret != DRM_OK) {
441 DRM_ERR_LOG("CheckMediaKeyStatus failed!");
442 NapiDrmError::ThrowError(env, "CheckMediaKeyStatus failed.", DRM_SERVICE_FATAL_ERROR);
443 return result;
444 }
445 } else {
446 DRM_ERR_LOG("CheckMediaKeyStatus call Failed!");
447 NapiDrmError::ThrowError(env, "CheckMediaKeyStatus call failed.", DRM_UNKNOWN_ERROR);
448 return result;
449 }
450
451 if (licenseStatus.size() == 0) {
452 DRM_ERR_LOG("Licence not exist.");
453 NapiDrmError::ThrowError(env, "CheckMediaKeyStatus call failed, service error.", DRM_SERVICE_FATAL_ERROR);
454 return result;
455 }
456 result = vectorToJsArray(env, licenseStatus);
457 return result;
458 }
459
RestoreOfflineMediaKeys(napi_env env,napi_callback_info info)460 napi_value MediaKeySessionNapi::RestoreOfflineMediaKeys(napi_env env, napi_callback_info info)
461 {
462 DRM_INFO_LOG("RestoreOfflineMediaKeys enter.");
463 int64_t beginTime = std::chrono::duration_cast<std::chrono::milliseconds>(
464 std::chrono::system_clock::now().time_since_epoch()).count();
465 auto context = std::make_shared<MediaKeySessionAsyncContext>();
466 if (context == nullptr) {
467 DRM_ERR_LOG("RestoreOfflineMediaKeys failed.");
468 NapiDrmError::ThrowError(env, "make_shared failed, unknown error.", DRM_UNKNOWN_ERROR);
469 return NapiParamUtils::GetUndefinedValue(env);
470 }
471
472 auto inputParser = [env, context](size_t argc, napi_value *argv) {
473 NAPI_CHECK_ARGS_RETURN_VOID(context, argc == ARGS_ONE, "invalid arguments", DRM_INVALID_PARAM);
474 context->status = NapiParamUtils::GetValueUint8Array(env, context->restoreLicenseId, argv[PARAM0]);
475 NAPI_CHECK_STATUS_RETURN_VOID(context, "RestoreOfflineMediaKeys failed.", DRM_INVALID_PARAM);
476 };
477 context->GetCbInfo(env, info, inputParser);
478
479 auto executor = [context]() {
480 DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckContextStatus(context), "context object state is error.");
481 auto obj = reinterpret_cast<MediaKeySessionNapi *>(context->native);
482 ObjectRefMap objectGuard(obj);
483 auto *napiMediaKeySession = objectGuard.GetPtr();
484 DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckMediaKeySessionStatus(napiMediaKeySession, context),
485 "MediaKeySession state is error.");
486 context->intValue = napiMediaKeySession->keySessionImpl_->RestoreOfflineMediaKeys(context->restoreLicenseId);
487 if (context->intValue != DRM_OK) {
488 context->SignError(DRM_SERVICE_FATAL_ERROR);
489 }
490 };
491
492 auto complete = [env, context](napi_value &output) { output = NapiParamUtils::GetUndefinedValue(env); };
493 ConfigParser::WriteEndEvent(0, 0, std::string("restoreOfflineMediaKeys"), beginTime);
494 return NapiAsyncWork::Enqueue(env, context, "RestoreOfflineMediaKeys", executor, complete);
495 }
496
ClearMediaKeys(napi_env env,napi_callback_info info)497 napi_value MediaKeySessionNapi::ClearMediaKeys(napi_env env, napi_callback_info info)
498 {
499 DRM_INFO_LOG("ClearMediaKeys enter.");
500 napi_value result = nullptr;
501 size_t argc = ARGS_ZERO;
502 napi_value argv[ARGS_ZERO];
503 napi_value thisVar = nullptr;
504 napi_status status;
505
506 napi_get_undefined(env, &result);
507 int32_t currentPid = IPCSkeleton::GetCallingPid();
508 DRM_DEBUG_LOG("MediaKeySessionNapi GetCallingPID: %{public}d", currentPid);
509 DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
510 MediaKeySessionNapi *keySessionNapi = nullptr;
511 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&keySessionNapi));
512 if (status == napi_ok && keySessionNapi != nullptr && keySessionNapi->keySessionImpl_ != nullptr) {
513 int32_t ret = keySessionNapi->keySessionImpl_->ClearMediaKeys();
514 if (ret != DRM_OK) {
515 DRM_ERR_LOG("ClearMediaKeys call Failed!");
516 NapiDrmError::ThrowError(env, "ClearMediaKeys call failed, service error.",
517 DRM_SERVICE_FATAL_ERROR);
518 return result;
519 }
520 } else {
521 DRM_ERR_LOG("napi_unwrap call Failed!");
522 NapiDrmError::ThrowError(env, "napi_unwrap call failed.", DRM_UNKNOWN_ERROR);
523 return result;
524 }
525 return result;
526 }
527
RequireSecureDecoderModule(napi_env env,napi_callback_info info)528 napi_value MediaKeySessionNapi::RequireSecureDecoderModule(napi_env env, napi_callback_info info)
529 {
530 DRM_INFO_LOG("RequireSecureDecoderModule enter.");
531 napi_value result = nullptr;
532 size_t argc = ARGS_ONE;
533 napi_value argv[ARGS_ONE] = {0};
534 napi_value thisVar = nullptr;
535
536 DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
537 napi_get_undefined(env, &result);
538 if (argc != ARGS_ONE) {
539 DRM_ERR_LOG("invalid arguments.");
540 NapiDrmError::ThrowError(env, "Invalid params, only need one param.", DRM_INVALID_PARAM);
541 return result;
542 }
543 char mimeTypeBuf[PATH_MAX];
544 size_t length = 0;
545 if (napi_get_value_string_utf8(env, argv[PARAM0], mimeTypeBuf, PATH_MAX, &length) != napi_ok) {
546 DRM_ERR_LOG("Could not able to read mimetype!");
547 NapiDrmError::ThrowError(env, "Could not able to read mimetype.", DRM_UNKNOWN_ERROR);
548 return result;
549 }
550
551 std::string mimeType = std::string(mimeTypeBuf);
552 bool statusValue = false;
553 MediaKeySessionNapi *keySessionNapi = nullptr;
554 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&keySessionNapi));
555 if (keySessionNapi == nullptr || keySessionNapi->keySessionImpl_ == nullptr) {
556 DRM_ERR_LOG("napi_unwrapcall Failed!");
557 NapiDrmError::ThrowError(env, "napi_unwrapcall failed.", DRM_UNKNOWN_ERROR);
558 return result;
559 }
560 int32_t ret = keySessionNapi->keySessionImpl_->RequireSecureDecoderModule(mimeType, &statusValue);
561 if (ret != DRM_OK) {
562 DRM_ERR_LOG("keySessionImpl_ RequireSecureDecoderModule call Failed!");
563 NapiDrmError::ThrowError(env, "RequireSecureDecoderModule failed, service error.", DRM_SERVICE_FATAL_ERROR);
564 return result;
565 }
566 status = napi_get_boolean(env, statusValue, &result);
567 DRM_INFO_LOG("napi_get_boolean call success!,statusValue:%{public}d.", statusValue);
568 return result;
569 }
570
GetContentProtectionLevel(napi_env env,napi_callback_info info)571 napi_value MediaKeySessionNapi::GetContentProtectionLevel(napi_env env, napi_callback_info info)
572 {
573 DRM_INFO_LOG("GetContentProtectionLevel enter.");
574 napi_value result = nullptr;
575 size_t argc = ARGS_ONE;
576 napi_value argv[ARGS_ONE] = {0};
577 napi_value thisVar = nullptr;
578 MediaKeySessionNapi *keySessionNapi = nullptr;
579
580 napi_get_undefined(env, &result);
581 DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
582 IMediaKeySessionService::ContentProtectionLevel level = (IMediaKeySessionService::ContentProtectionLevel)0;
583 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&keySessionNapi));
584 if (status == napi_ok && keySessionNapi != nullptr && keySessionNapi->keySessionImpl_ != nullptr) {
585 int32_t ret = keySessionNapi->keySessionImpl_->GetContentProtectionLevel(&level);
586 if (ret != DRM_OK) {
587 DRM_ERR_LOG("GetContentProtectionLevel call Failed!");
588 NapiDrmError::ThrowError(env, "GetContentProtectionLevel failed, service error.", DRM_SERVICE_FATAL_ERROR);
589 return result;
590 }
591 } else {
592 DRM_ERR_LOG("napi_unwrap call Failed!");
593 NapiDrmError::ThrowError(env, "napi_unwrap failed.", DRM_UNKNOWN_ERROR);
594 return result;
595 }
596
597 NAPI_CALL(env, napi_create_int32(env, (int32_t)level, &result));
598 return result;
599 }
600
SetEventCallbackReference(const std::string eventType,std::shared_ptr<AutoRef> callbackPair)601 void MediaKeySessionNapi::SetEventCallbackReference(const std::string eventType, std::shared_ptr<AutoRef> callbackPair)
602 {
603 DRM_INFO_LOG("SetEventCallbackReference");
604 std::lock_guard<std::mutex> lock(mutex_);
605 if (keySessionCallbackNapi_ != nullptr) {
606 keySessionCallbackNapi_->SetCallbackReference(eventType, callbackPair);
607 } else {
608 DRM_ERR_LOG("SetEventCallbackReference failed.");
609 }
610 }
611
ClearEventCallbackReference(const std::string eventType)612 void MediaKeySessionNapi::ClearEventCallbackReference(const std::string eventType)
613 {
614 DRM_INFO_LOG("ClearEventCallbackReference");
615 if (keySessionCallbackNapi_ != nullptr) {
616 keySessionCallbackNapi_->ClearCallbackReference(eventType);
617 } else {
618 DRM_ERR_LOG("ClearEventCallbackReference failed.");
619 }
620 }
621
SetEventCallback(napi_env env,napi_callback_info info)622 napi_value MediaKeySessionNapi::SetEventCallback(napi_env env, napi_callback_info info)
623 {
624 DRM_INFO_LOG("SetEventCallback");
625 napi_value result = nullptr;
626 napi_get_undefined(env, &result);
627 size_t length = 0;
628 size_t argc = ARGS_TWO;
629 napi_value thisVar = nullptr;
630 napi_value argv[ARGS_TWO] = { nullptr };
631 DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
632 NAPI_ASSERT(env, argc == ARGS_TWO, "only requires 2 parameters");
633 if (thisVar == nullptr || argv[PARAM0] == nullptr || argv[PARAM1] == nullptr) {
634 DRM_ERR_LOG("Failed to retrieve arguments in SetEventCallback!");
635 NapiDrmError::ThrowError(env, "Mandatory parameters are left unspecified.", DRM_INVALID_PARAM);
636 return result;
637 }
638 napi_valuetype valueType = napi_undefined;
639 if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string ||
640 napi_typeof(env, argv[PARAM1], &valueType) != napi_ok || valueType != napi_function) {
641 NapiDrmError::ThrowError(
642 env, "Incorrect parameter types, check if callback type is a string, and callback is a function.",
643 DRM_INVALID_PARAM);
644 return result;
645 }
646
647 MediaKeySessionNapi *keySessionNapi = nullptr;
648 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&keySessionNapi));
649 if (status == napi_ok && keySessionNapi != nullptr) {
650 char buffer[PATH_MAX];
651 napi_get_value_string_utf8(env, argv[PARAM0], buffer, PATH_MAX, &length);
652 std::string eventType = std::string(buffer);
653 napi_ref callbackRef;
654 napi_create_reference(env, argv[PARAM1], 1, &callbackRef);
655 DRM_DEBUG_LOG("SetEventCallback event is %{public}s", eventType.c_str());
656
657 std::shared_ptr<AutoRef> callbackPair = std::make_shared<AutoRef>(env, callbackRef);
658 keySessionNapi->SetEventCallbackReference(eventType, callbackPair);
659 } else {
660 DRM_ERR_LOG("napi_unwrap failed!");
661 NapiDrmError::ThrowError(env, "napi_unwrap failed!", DRM_UNKNOWN_ERROR);
662 }
663 return result;
664 }
665
UnsetEventCallback(napi_env env,napi_callback_info info)666 napi_value MediaKeySessionNapi::UnsetEventCallback(napi_env env, napi_callback_info info)
667 {
668 DRM_INFO_LOG("UnsetEventCallback");
669 napi_value result = nullptr;
670 napi_get_undefined(env, &result);
671 napi_value thisVar = nullptr;
672 napi_value argv[1] = { nullptr };
673 size_t argc = 1;
674 DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
675 NAPI_ASSERT(env, argc == ARGS_ONE, "only requires 1 parameters");
676 if (thisVar == nullptr || argv[PARAM0] == nullptr) {
677 DRM_ERR_LOG("Failed to retrieve arguments in UnsetEventCallback!");
678 NapiDrmError::ThrowError(env, "Mandatory parameters are left unspecified.", DRM_INVALID_PARAM);
679 return result;
680 }
681 napi_valuetype valueType = napi_undefined;
682 if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
683 DRM_ERR_LOG("Failed to retrieve reasonable arguments in UnsetEventCallback!");
684 NapiDrmError::ThrowError(env, "the param is not a string", DRM_INVALID_PARAM);
685 return result;
686 }
687
688 MediaKeySessionNapi *keySessionNapi = nullptr;
689 size_t length = 0;
690 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&keySessionNapi));
691 if (status == napi_ok && keySessionNapi != nullptr) {
692 char buffer[PATH_MAX];
693 napi_get_value_string_utf8(env, argv[PARAM0], buffer, PATH_MAX, &length);
694 std::string eventType = std::string(buffer);
695 keySessionNapi->ClearEventCallbackReference(eventType);
696 DRM_INFO_LOG("UnsetEventCallback out");
697 } else {
698 DRM_ERR_LOG("UnsetEventCallback failed!");
699 NapiDrmError::ThrowError(env, "UnsetEventCallback failed, unknown error.", DRM_UNKNOWN_ERROR);
700 }
701 return result;
702 }
703 } // DrmStandardr
704 } // OHOS