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 "key_session_napi.h"
16 #include "media_key_system_napi.h"
17 #include "napi_param_utils.h"
18 #include "drm_trace.h"
19 #include "drm_error_code.h"
20 #include "drm_api_operation.h"
21 
22 namespace OHOS {
23 namespace DrmStandard {
24 thread_local napi_ref MediaKeySystemNapi::sConstructor_ = nullptr;
25 thread_local sptr<MediaKeySystemImpl> MediaKeySystemNapi::sMediaKeySystemImpl_ = nullptr;
26 
MediaKeySystemNapi()27 MediaKeySystemNapi::MediaKeySystemNapi() : env_(nullptr), wrapper_(nullptr)
28 {
29     DRM_DEBUG_LOG("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
30 }
31 
~MediaKeySystemNapi()32 MediaKeySystemNapi::~MediaKeySystemNapi()
33 {
34     DRM_INFO_LOG("~MediaKeySystemNapi enter.");
35     DRM_DEBUG_LOG("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
36     if (wrapper_ != nullptr) {
37         napi_delete_reference(env_, wrapper_);
38     }
39     if (mediaKeySystemImpl_) {
40         mediaKeySystemImpl_ = nullptr;
41     }
42     if (mediaKeySystemCallbackNapi_) {
43         mediaKeySystemCallbackNapi_ = nullptr;
44     }
45 }
46 
Init(napi_env env,napi_value exports)47 napi_value MediaKeySystemNapi::Init(napi_env env, napi_value exports)
48 {
49     DRM_INFO_LOG("Init enter.");
50     napi_status status;
51     napi_value ctorObj;
52 
53     napi_property_descriptor properties[] = {
54         DECLARE_NAPI_FUNCTION("setConfigurationString", SetConfigurationString),
55         DECLARE_NAPI_FUNCTION("getConfigurationString", GetConfigurationString),
56         DECLARE_NAPI_FUNCTION("setConfigurationByteArray", SetConfigurationByteArray),
57         DECLARE_NAPI_FUNCTION("getConfigurationByteArray", GetConfigurationByteArray),
58         DECLARE_NAPI_FUNCTION("getMaxContentProtectionLevel", GetMaxContentProtectionLevel),
59         DECLARE_NAPI_FUNCTION("generateKeySystemRequest", GenerateKeySystemRequest),
60         DECLARE_NAPI_FUNCTION("processKeySystemResponse", ProcessKeySystemResponse),
61         DECLARE_NAPI_FUNCTION("createMediaKeySession", CreateMediaKeySession),
62         DECLARE_NAPI_FUNCTION("getStatistics", GetStatistics),
63         DECLARE_NAPI_FUNCTION("getCertificateStatus", GetCertificateStatus),
64         DECLARE_NAPI_FUNCTION("getOfflineMediaKeyIds", GetOfflineMediaKeyIds),
65         DECLARE_NAPI_FUNCTION("getOfflineMediaKeyStatus", GetOfflineMediaKeyStatus),
66         DECLARE_NAPI_FUNCTION("clearOfflineMediaKeys", ClearOfflineMediaKeys),
67         DECLARE_NAPI_FUNCTION("destroy", Destroy),
68         DECLARE_NAPI_FUNCTION("on", SetEventCallback),
69         DECLARE_NAPI_FUNCTION("off", UnsetEventCallback),
70     };
71 
72     napi_property_descriptor drm_static_properties[] = {
73         DECLARE_NAPI_STATIC_FUNCTION("createMediaKeySystem", CreateMediaKeySystemInstance),
74         DECLARE_NAPI_STATIC_FUNCTION("isMediaKeySystemSupported", IsMediaKeySystemSupported),
75         DECLARE_NAPI_STATIC_FUNCTION("getMediaKeySystems", GetMediaKeySystems),
76         DECLARE_NAPI_STATIC_FUNCTION("getMediaKeySystemUuid", GetMediaKeySystemUuid)
77     };
78 
79     status = napi_define_class(env, MEDIA_KEY_SYSTEM_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH, MediaKeySystemNapiConstructor,
80         nullptr, sizeof(properties) / sizeof(properties[PARAM0]), properties, &ctorObj);
81     DRM_CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define napi class");
82     status = napi_create_reference(env, ctorObj, 1, &sConstructor_);
83     DRM_CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create napi reference");
84     status = napi_set_named_property(env, exports, MEDIA_KEY_SYSTEM_NAPI_CLASS_NAME, ctorObj);
85     DRM_CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set napi named property");
86     status = napi_define_properties(env, exports, sizeof(drm_static_properties) / sizeof(drm_static_properties[0]),
87         drm_static_properties);
88     DRM_CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static DrmNapi function");
89     return exports;
90 }
91 
MediaKeySystemNapiConstructor(napi_env env,napi_callback_info info)92 napi_value MediaKeySystemNapi::MediaKeySystemNapiConstructor(napi_env env, napi_callback_info info)
93 {
94     DrmTrace trace("MediaKeySystemNapi::MediaKeySystemNapiConstructor");
95     DRM_INFO_LOG("MediaKeySystemNapiConstructor enter.");
96     napi_value result = nullptr;
97     size_t argCount = 0;
98     napi_value jsThis = nullptr;
99 
100     napi_get_undefined(env, &result);
101 
102     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
103     DRM_CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
104 
105     if (status == napi_ok && jsThis != nullptr) {
106         std::unique_ptr<MediaKeySystemNapi> obj = std::make_unique<MediaKeySystemNapi>();
107         obj->env_ = env;
108         if (MediaKeySystemNapi::sMediaKeySystemImpl_ == nullptr) {
109             DRM_ERR_LOG("sMediaKeySystemImpl_ is null");
110             return result;
111         }
112         obj->mediaKeySystemImpl_ = MediaKeySystemNapi::sMediaKeySystemImpl_;
113         obj->mediaKeySystemCallbackNapi_ = new (std::nothrow) MediaKeySystemCallbackNapi(env);
114         obj->mediaKeySystemImpl_->SetCallback(obj->mediaKeySystemCallbackNapi_);
115         status = napi_wrap(env, jsThis, reinterpret_cast<void *>(obj.get()),
116             MediaKeySystemNapi::MediaKeySystemNapiDestructor, nullptr, nullptr);
117         if (status == napi_ok) {
118             ObjectRefMap<MediaKeySystemNapi>::Insert(obj.get());
119             obj.release();
120             return jsThis;
121         } else {
122             ObjectRefMap<MediaKeySystemNapi>::Erase(obj.get());
123             DRM_ERR_LOG("Failure wrapping js to native napi");
124         }
125     }
126 
127     return result;
128 }
129 
CreateMediaKeySystemInstance(napi_env env,napi_callback_info info)130 napi_value MediaKeySystemNapi::CreateMediaKeySystemInstance(napi_env env, napi_callback_info info)
131 {
132     DRM_INFO_LOG("CreateMediaKeySystemInstance enter.");
133     napi_status status;
134     napi_value result = nullptr;
135     napi_value ctor = nullptr;
136     napi_get_undefined(env, &result);
137     status = napi_get_reference_value(env, sConstructor_, &ctor);
138     if (status == napi_ok) {
139         size_t argc = ARGS_ONE;
140         napi_value argv[ARGS_ONE] = {0};
141         napi_value thisVar = nullptr;
142         DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
143         std::string drmSchemaName;
144         char nameBuffer[PATH_MAX] = { 0 };
145         size_t nameBufferLen = 0;
146         status = napi_get_value_string_utf8(env, argv[PARAM0], nameBuffer, PATH_MAX, &nameBufferLen);
147         if (status != napi_ok) {
148             NapiDrmError::ThrowError(env, "The param name is missing or too long.", DRM_INVALID_PARAM);
149             DRM_ERR_LOG("napi_get_value_string_utf8 failed!");
150             return result;
151         }
152         drmSchemaName = std::string(nameBuffer);
153         int32_t ret = MediaKeySystemFactoryImpl::GetInstance()->CreateMediaKeySystem(drmSchemaName,
154             &MediaKeySystemNapi::sMediaKeySystemImpl_);
155         if (ret != DRM_OK) {
156             NapiDrmError::ThrowError(env, "create MediaKeySystem failed.", ret);
157             DRM_ERR_LOG("CreateMediaKeySystem failed!");
158             return result;
159         }
160         status = napi_new_instance(env, ctor, 0, nullptr, &result);
161         MediaKeySystemNapi::sMediaKeySystemImpl_ = nullptr;
162         if (status == napi_ok) {
163             return result;
164         } else {
165             DRM_ERR_LOG("New instance could not be obtained");
166         }
167     }
168     NapiDrmError::ThrowError(env, "create MediaKeySystem failed, unknown error.", DRM_UNKNOWN_ERROR);
169     napi_get_undefined(env, &result);
170     return result;
171 }
172 
MediaKeySystemNapiDestructor(napi_env env,void * nativeObject,void * finalize)173 void MediaKeySystemNapi::MediaKeySystemNapiDestructor(napi_env env, void *nativeObject, void *finalize)
174 {
175     DrmTrace trace("MediaKeySystemNapi::MediaKeySystemNapiDestructor");
176     DRM_INFO_LOG("MediaKeySystemNapiDestructor enter.");
177     MediaKeySystemNapi *mediaKeySystemNapi = reinterpret_cast<MediaKeySystemNapi *>(nativeObject);
178     ObjectRefMap<MediaKeySystemNapi>::DecreaseRef(mediaKeySystemNapi);
179 }
180 
IsMediaKeySystemSupported(napi_env env,napi_callback_info info)181 napi_value MediaKeySystemNapi::IsMediaKeySystemSupported(napi_env env, napi_callback_info info)
182 {
183     DRM_INFO_LOG("IsMediaKeySystemSupported enter.");
184     napi_value result = nullptr;
185     size_t argc = ARGS_THREE;
186     napi_value argv[ARGS_THREE] = {0, 0, 0};
187     napi_value thisVar = nullptr;
188     napi_get_undefined(env, &result);
189     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
190     char buffer[PATH_MAX];
191     size_t length = 0;
192     if (napi_get_value_string_utf8(env, argv[PARAM0], buffer, PATH_MAX, &length) != napi_ok) {
193         DRM_ERR_LOG("Could not able to read drm plugin name argument!");
194         NapiDrmError::ThrowError(env, "Could not able to read drm plugin name argument!", DRM_UNKNOWN_ERROR);
195         return result;
196     }
197     std::string pluginName = std::string(buffer);
198     if (pluginName.length() == 0 || pluginName.length() > MAX_STRING_SIZE) {
199         DRM_ERR_LOG("drm plugin name lenth is not able to zero or more 256!");
200         NapiDrmError::ThrowError(env, "drm plugin name length exceeds reasonable range!", DRM_INVALID_PARAM);
201         return result;
202     }
203     if (MediaKeySystemFactoryImpl::GetInstance() == nullptr) {
204         DRM_ERR_LOG("get instance failed!");
205         NapiDrmError::ThrowError(env, "get instance failed!", DRM_SERVICE_FATAL_ERROR);
206         return result;
207     }
208     if (argc == ARGS_ONE) {
209         bool isSurpportted = MediaKeySystemFactoryImpl::GetInstance()->IsMediaKeySystemSupported(pluginName);
210         napi_get_boolean(env, isSurpportted, &result);
211         return result;
212     }
213     buffer[0] = '\0';
214     if (napi_get_value_string_utf8(env, argv[PARAM1], buffer, PATH_MAX, &length) != napi_ok) {
215         DRM_ERR_LOG("Could not able to read mimeType argument!");
216         NapiDrmError::ThrowError(env, "The param mimeType is missing or too long.", DRM_UNKNOWN_ERROR);
217         return result;
218     }
219     std::string mimeType = std::string(buffer);
220     if (argc == ARGS_TWO && mimeType.length() != 0) {
221         bool isSurpportted = MediaKeySystemFactoryImpl::GetInstance()->IsMediaKeySystemSupported(pluginName, mimeType);
222         napi_get_boolean(env, isSurpportted, &result);
223         return result;
224     }
225     buffer[0] = '\0';
226 
227     int32_t jsContentProtectionLevel = DRM_ERROR;
228     if (napi_get_value_int32(env, argv[PARAM2], &jsContentProtectionLevel) != napi_ok) {
229         DRM_ERR_LOG("Could not able to read securityLevel argument!");
230         NapiDrmError::ThrowError(env, "Could not able to read securityLevel argument.", DRM_UNKNOWN_ERROR);
231         return result;
232     }
233     IMediaKeySessionService::ContentProtectionLevel securityLevel =
234         (IMediaKeySessionService::ContentProtectionLevel)jsContentProtectionLevel;
235     if ((securityLevel <= IMediaKeySessionService::CONTENT_PROTECTION_LEVEL_UNKNOWN) ||
236         (securityLevel >= IMediaKeySessionService::CONTENT_PROTECTION_LEVEL_MAX)) {
237         DRM_ERR_LOG("ContentProtectionLevel is invalid");
238         NapiDrmError::ThrowError(env, "param ContentProtectionLevel exceeds reasonable range!", DRM_INVALID_PARAM);
239         return result;
240     }
241 
242     if (argc == ARGS_THREE) {
243         bool isSurpportted =
244             MediaKeySystemFactoryImpl::GetInstance()->IsMediaKeySystemSupported(pluginName, mimeType, securityLevel);
245         napi_get_boolean(env, isSurpportted, &result);
246         return result;
247     }
248     napi_get_boolean(env, false, &result);
249     return result;
250 }
251 
mapToJsArray(napi_env env,std::map<std::string,std::string> & mediaKeySystemNames)252 static napi_value mapToJsArray(napi_env env, std::map<std::string, std::string> &mediaKeySystemNames)
253 {
254     DRM_INFO_LOG("mapToJsArray enter.");
255     napi_value jsArray;
256     int32_t i = 0;
257     if (napi_create_array_with_length(env, mediaKeySystemNames.size(), &jsArray) != napi_ok) {
258         DRM_ERR_LOG("napi_create_array_with_length failed");
259         NapiDrmError::ThrowError(env, "napi_create_array_with_length failed",
260             DRM_UNKNOWN_ERROR);
261         return nullptr;
262     }
263 
264     for (auto it = mediaKeySystemNames.begin(); it != mediaKeySystemNames.end(); it++) {
265         napi_value jsObject;
266         napi_value jsName;
267         napi_value jsValue;
268         napi_create_object(env, &jsObject);
269         napi_create_string_utf8(env, it->first.c_str(), NAPI_AUTO_LENGTH, &jsName);
270         napi_set_named_property(env, jsObject, "name", jsName);
271         napi_create_string_utf8(env, it->second.c_str(), NAPI_AUTO_LENGTH, &jsValue);
272         napi_set_named_property(env, jsObject, "uuid", jsValue);
273         napi_set_element(env, jsArray, i++, jsObject);
274     }
275     return jsArray;
276 }
277 
GetMediaKeySystems(napi_env env,napi_callback_info info)278 napi_value MediaKeySystemNapi::GetMediaKeySystems(napi_env env, napi_callback_info info)
279 {
280     DRM_INFO_LOG("GetMediaKeySystems enter");
281     napi_value result = nullptr;
282     std::map<std::string, std::string> keySystemNames;
283     napi_get_undefined(env, &result);
284     int32_t ret = MediaKeySystemFactoryImpl::GetInstance()->GetMediaKeySystems(keySystemNames);
285     if (keySystemNames.size() == 0 || ret != DRM_OK) {
286         DRM_ERR_LOG("Plugin not exist.");
287         NapiDrmError::ThrowError(env, "GetMediaKeySystems call Failed!", DRM_SERVICE_FATAL_ERROR);
288         return result;
289     }
290     result = mapToJsArray(env, keySystemNames);
291     return result;
292 }
293 
GetMediaKeySystemUuid(napi_env env,napi_callback_info info)294 napi_value MediaKeySystemNapi::GetMediaKeySystemUuid(napi_env env, napi_callback_info info)
295 {
296     DRM_INFO_LOG("GetMediaKeySystemUuid enter");
297     napi_value result = nullptr;
298     size_t argc = ARGS_ONE;
299     napi_value argv[ARGS_ONE] = {0};
300     napi_value thisVar = nullptr;
301     napi_status status;
302     char nameStr[PATH_MAX];
303     size_t nameStrLength = 0;
304     std::string uuid;
305     napi_get_undefined(env, &result);
306 
307     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
308     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameters maximum");
309 
310     status = napi_get_value_string_utf8(env, argv[PARAM0], nameStr, PATH_MAX, &nameStrLength);
311     if (status != napi_ok) {
312         DRM_ERR_LOG("napi_get_value_string_utf8 failed");
313         NapiDrmError::ThrowError(env, "The param configName is missing or too long.", DRM_INVALID_PARAM);
314         return result;
315     }
316     std::string name = std::string(nameStr);
317     int32_t ret = MediaKeySystemFactoryImpl::GetInstance()->GetMediaKeySystemUuid(name, uuid);
318     if (ret != DRM_OK) {
319         DRM_ERR_LOG("GetMediaKeySystemUuid failed");
320         NapiDrmError::ThrowError(env, "GetMediaKeySystemUuid call failed", DRM_SERVICE_FATAL_ERROR);
321         return result;
322     }
323     status = napi_create_string_utf8(env, uuid.c_str(), NAPI_AUTO_LENGTH, &result);
324     if (status != napi_ok) {
325         DRM_ERR_LOG("napi_create_string_utf8 failed");
326         NapiDrmError::ThrowError(env, "napi_create_string_utf8 failed", DRM_UNKNOWN_ERROR);
327         return result;
328     }
329     return result;
330 }
331 
CreateMediaKeySession(napi_env env,napi_callback_info info)332 napi_value MediaKeySystemNapi::CreateMediaKeySession(napi_env env, napi_callback_info info)
333 {
334     DRM_INFO_LOG("CreateMediaKeySession enter.");
335     DrmTrace trace("MediaKeySystemNapi::CreateMediaKeySession");
336     napi_status status;
337     napi_value result = nullptr;
338     size_t argc = ARGS_ONE;
339     napi_value argv[ARGS_ONE] = {0};
340     napi_value thisVar = nullptr;
341     int32_t jsContentProtectionLevel = 0;
342     IMediaKeySessionService::ContentProtectionLevel securityLevel =
343         IMediaKeySessionService::ContentProtectionLevel::CONTENT_PROTECTION_LEVEL_UNKNOWN;
344     sptr<MediaKeySessionImpl> keySessionImpl = nullptr;
345     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
346     napi_get_undefined(env, &result);
347     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
348     if (argc != ARGS_ZERO) {
349         status = napi_get_value_int32(env, argv[PARAM0], &jsContentProtectionLevel);
350         if (status != napi_ok) {
351             DRM_ERR_LOG("napi_get_value_int32 failed");
352             NapiDrmError::ThrowError(env, "napi_get_value_int32 failed", DRM_UNKNOWN_ERROR);
353             return result;
354         }
355         securityLevel =
356             static_cast<IMediaKeySessionService::ContentProtectionLevel>(jsContentProtectionLevel);
357         if (securityLevel <= IMediaKeySessionService::ContentProtectionLevel::CONTENT_PROTECTION_LEVEL_UNKNOWN ||
358             securityLevel >= IMediaKeySessionService::ContentProtectionLevel::CONTENT_PROTECTION_LEVEL_MAX) {
359             NapiDrmError::ThrowError(env, "The param ContentProtectionLevel exceeds reasonable range.",
360                 DRM_INVALID_PARAM);
361             DRM_ERR_LOG("securityLevel is error!");
362             return result;
363         }
364     }
365     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
366     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
367         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->CreateMediaKeySession(
368             (IMediaKeySessionService::ContentProtectionLevel)securityLevel, &keySessionImpl);
369         if (ret != DRM_OK) {
370             NapiDrmError::ThrowError(env, "CreateMediaKeySession failed.", ret);
371             DRM_ERR_LOG("CreateMediaKeySession get failed!!!");
372             return result;
373         }
374     } else {
375         DRM_ERR_LOG("napi_unwrap call Failed!");
376         NapiDrmError::ThrowError(env, "napi_get_value_int32 failed", DRM_UNKNOWN_ERROR);
377         return result;
378     }
379     result = MediaKeySessionNapi::CreateMediaKeySession(env, keySessionImpl);
380     return result;
381 }
382 
SetConfigurationString(napi_env env,napi_callback_info info)383 napi_value MediaKeySystemNapi::SetConfigurationString(napi_env env, napi_callback_info info)
384 {
385     DRM_INFO_LOG("SetConfiguration enter.");
386     napi_value result = nullptr;
387     size_t argc = ARGS_TWO;
388     napi_value argv[ARGS_TWO] = {0};
389     napi_value thisVar = nullptr;
390     napi_status status;
391     std::string name;
392     std::string value;
393     char nameBuffer[PATH_MAX];
394     size_t nameBufferLen = 0;
395     char valueBuffer[PATH_MAX];
396     size_t valueBufferLen = 0;
397     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
398     napi_get_undefined(env, &result);
399 
400     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
401     NAPI_ASSERT(env, argc <= ARGS_TWO, "Requires 2 parameters maximum");
402 
403     status = napi_get_value_string_utf8(env, argv[PARAM0], nameBuffer, PATH_MAX, &nameBufferLen);
404     if (status != napi_ok) {
405         DRM_ERR_LOG("Could not able to read name argument!");
406         NapiDrmError::ThrowError(env, "The param configName is missing or too long", DRM_INVALID_PARAM);
407         return result;
408     }
409     name = std::string(nameBuffer);
410     status = napi_get_value_string_utf8(env, argv[PARAM1], valueBuffer, PATH_MAX, &valueBufferLen);
411     if (status != napi_ok) {
412         DRM_ERR_LOG("napi_get_value_string_utf8 failed!");
413         NapiDrmError::ThrowError(env, "The param value is missing or too long.", DRM_INVALID_PARAM);
414         return result;
415     }
416     value = std::string(valueBuffer);
417     if (value.length() == 0) {
418         DRM_ERR_LOG("String Parameter length cannot be zero!");
419         NapiDrmError::ThrowError(env, "The param value length is 0.", DRM_INVALID_PARAM);
420         return result;
421     }
422     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
423     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
424         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->SetConfigurationString(name, value);
425         if (ret != napi_ok) {
426             DRM_ERR_LOG("SetConfigurationString failed!");
427             NapiDrmError::ThrowError(env, "SetConfigurationString failed, service error.", DRM_SERVICE_FATAL_ERROR);
428             return result;
429         }
430     } else {
431         DRM_ERR_LOG("SetConfiguration call Failed!");
432         NapiDrmError::ThrowError(env, "SetConfigurationString failed, unknown error.", DRM_UNKNOWN_ERROR);
433         return result;
434     }
435     return result;
436 }
437 
GetConfigurationString(napi_env env,napi_callback_info info)438 napi_value MediaKeySystemNapi::GetConfigurationString(napi_env env, napi_callback_info info)
439 {
440     DRM_INFO_LOG("GetConfiguration enter");
441     napi_value result = nullptr;
442     size_t argc = ARGS_ONE;
443     napi_value argv[ARGS_ONE] = {0};
444     napi_value thisVar = nullptr;
445     napi_status status;
446     char nameStr[PATH_MAX];
447     size_t nameStrLength = 0;
448     std::string value;
449     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
450     napi_get_undefined(env, &result);
451 
452     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
453     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameters maximum");
454 
455     status = napi_get_value_string_utf8(env, argv[PARAM0], nameStr, PATH_MAX, &nameStrLength);
456     if (status != napi_ok) {
457         DRM_ERR_LOG("napi_get_value_string_utf8 failed!");
458         NapiDrmError::ThrowError(env, "The param configName is missing or too long.", DRM_INVALID_PARAM);
459         return result;
460     }
461     std::string name = std::string(nameStr);
462     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
463     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
464         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->GetConfigurationString(name, value);
465         if (ret != napi_ok) {
466             DRM_ERR_LOG("GetConfigurationString failed!");
467             NapiDrmError::ThrowError(env, "GetConfigurationString failed, service error.", DRM_SERVICE_FATAL_ERROR);
468             return result;
469         }
470     } else {
471         DRM_ERR_LOG("napi_unwrap failed!");
472         NapiDrmError::ThrowError(env, "Get configuration failed, unknown error.", DRM_UNKNOWN_ERROR);
473         return result;
474     }
475 
476     napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
477     return result;
478 }
479 
SetConfigurationByteArray(napi_env env,napi_callback_info info)480 napi_value MediaKeySystemNapi::SetConfigurationByteArray(napi_env env, napi_callback_info info)
481 {
482     DRM_INFO_LOG("SetConfigurationByteArray enter.");
483     napi_value result = nullptr;
484     size_t argc = ARGS_TWO;
485     napi_value argv[ARGS_TWO] = {0};
486     napi_value thisVar = nullptr;
487     napi_status status;
488     std::string name;
489     char nameBuffer[PATH_MAX];
490     size_t nameBufferLen = 0;
491     bool isTypeArray;
492     void *valueData = nullptr;
493     size_t valueDataLen;
494     size_t offset;
495     napi_value arraybuffer = nullptr;
496     napi_typedarray_type type;
497     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
498 
499     napi_get_undefined(env, &result);
500     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
501     NAPI_ASSERT(env, argc <= ARGS_TWO, "requires 2 parameters maximum");
502 
503     status = napi_get_value_string_utf8(env, argv[PARAM0], nameBuffer, PATH_MAX, &nameBufferLen);
504     if (status != napi_ok) {
505         DRM_ERR_LOG("Could not able to read name argument!");
506         NapiDrmError::ThrowError(env, "The param configName is missing or too long.", DRM_INVALID_PARAM);
507         return result;
508     }
509     name = std::string(nameBuffer);
510     napi_is_typedarray(env, argv[PARAM1], &isTypeArray);
511     if (!isTypeArray) {
512         DRM_ERR_LOG("Second parame is not array!");
513         NapiDrmError::ThrowError(env, "The param value type is invalid.", DRM_INVALID_PARAM);
514         return result;
515     }
516     napi_get_typedarray_info(env, argv[PARAM1], &type, &valueDataLen, &valueData, &arraybuffer, &offset);
517     if (valueData == nullptr) {
518         DRM_ERR_LOG("napi_get_typedarray_info failed!");
519         NapiDrmError::ThrowError(env, "The param value is missing or too long.", DRM_INVALID_PARAM);
520         return result;
521     }
522     uint8_t *valueDataPtr = reinterpret_cast<uint8_t *>(valueData);
523     std::vector<uint8_t> value(valueDataPtr, valueDataPtr + valueDataLen);
524     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
525     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
526         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->SetConfigurationByteArray(name, value);
527         if (ret != napi_ok) {
528             DRM_ERR_LOG("SetConfigurationByteArray failed!");
529             NapiDrmError::ThrowError(env, "SetConfigurationByteArray failed, service error.", DRM_SERVICE_FATAL_ERROR);
530             return result;
531         }
532     } else {
533         DRM_ERR_LOG("napi_unwrap call Failed!");
534         NapiDrmError::ThrowError(env, "Set configuration failed, unknown error.", DRM_UNKNOWN_ERROR);
535         return result;
536     }
537     return result;
538 }
539 
GetConfigurationByteArray(napi_env env,napi_callback_info info)540 napi_value MediaKeySystemNapi::GetConfigurationByteArray(napi_env env, napi_callback_info info)
541 {
542     DRM_INFO_LOG("GetConfigurationByteArray enter");
543     napi_value result = nullptr;
544     size_t argc = ARGS_TWO;
545     napi_value argv[ARGS_TWO] = {0};
546     napi_value thisVar = nullptr;
547     napi_status status;
548     char nameStr[PATH_MAX];
549     size_t nameStrLength = 0;
550     std::vector<uint8_t> value;
551     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
552     napi_get_undefined(env, &result);
553 
554     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
555     NAPI_ASSERT(env, argc <= ARGS_TWO, "requires 2 parameters maximum");
556 
557     status = napi_get_value_string_utf8(env, argv[PARAM0], nameStr, PATH_MAX, &nameStrLength);
558     if (status != napi_ok) {
559         DRM_ERR_LOG("Could not able to read name argument!");
560         NapiDrmError::ThrowError(env, "The param configName is missing or too long.", DRM_INVALID_PARAM);
561         return result;
562     }
563     std::string name = std::string(nameStr);
564     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
565     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
566         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->GetConfigurationByteArray(name, value);
567         if (ret != napi_ok) {
568             DRM_ERR_LOG("GetConfigurationByteArray failed!");
569             NapiDrmError::ThrowError(env, "GetConfigurationByteArray failed, service error.", DRM_SERVICE_FATAL_ERROR);
570             return result;
571         }
572     } else {
573         DRM_ERR_LOG("napi_unwrap Failed!");
574         NapiDrmError::ThrowError(env, "GetConfigurationByteArray failed.", DRM_UNKNOWN_ERROR);
575         return result;
576     }
577     size_t valueLen = value.size();
578     NAPI_CALL(env, napi_create_array(env, &result));
579     for (size_t i = 0; i < valueLen; i++) {
580         napi_value item;
581         napi_create_int32(env, value[i], &item);
582         napi_set_element(env, result, i, item);
583     }
584     return result;
585 }
586 
GetMaxContentProtectionLevel(napi_env env,napi_callback_info info)587 napi_value MediaKeySystemNapi::GetMaxContentProtectionLevel(napi_env env, napi_callback_info info)
588 {
589     DRM_INFO_LOG("GetMaxContentProtectionLevel enter.");
590     napi_value result = nullptr;
591     size_t argc = ARGS_ONE;
592     napi_value argv[ARGS_ONE] = {0};
593     napi_value thisVar = nullptr;
594     napi_status status;
595     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
596 
597     napi_get_undefined(env, &result);
598     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
599     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires one parameters maximum");
600     IMediaKeySessionService::ContentProtectionLevel level = IMediaKeySessionService::CONTENT_PROTECTION_LEVEL_UNKNOWN;
601     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
602     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
603         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->GetMaxContentProtectionLevel(&level);
604         if (ret != napi_ok) {
605             DRM_ERR_LOG("GetCertificateStatus failed!");
606             NapiDrmError::ThrowError(env, "GetMaxContentProtectionLevel failed, service error.",
607                 DRM_SERVICE_FATAL_ERROR);
608             return result;
609         }
610     } else {
611         DRM_ERR_LOG("napi_unwrap call Failed!");
612         NapiDrmError::ThrowError(env, "GetMaxContentProtectionLevel failed, unknown error.", DRM_UNKNOWN_ERROR);
613         return result;
614     }
615 
616     NAPI_CALL(env, napi_create_int32(env, (int32_t)level, &result));
617     return result;
618 }
619 
CheckMediaKeySystemStatus(MediaKeySystemNapi * napi,std::shared_ptr<MediaKeySystemAsyncContext> context)620 bool MediaKeySystemNapi::CheckMediaKeySystemStatus(MediaKeySystemNapi *napi,
621     std::shared_ptr<MediaKeySystemAsyncContext> context)
622 {
623     DRM_NAPI_CHECK_AND_RETURN_LOG(napi != nullptr, false, "napi object is nullptr.");
624     if (napi->mediaKeySystemImpl_ == nullptr) {
625         context->SignError(DRM_SERVICE_FATAL_ERROR);
626         return false;
627     }
628     return true;
629 }
630 
CheckContextStatus(std::shared_ptr<MediaKeySystemAsyncContext> context)631 bool MediaKeySystemNapi::CheckContextStatus(std::shared_ptr<MediaKeySystemAsyncContext> context)
632 {
633     DRM_NAPI_CHECK_AND_RETURN_LOG(context != nullptr, false, "context object is nullptr.");
634     if (context->native == nullptr) {
635         context->SignError(DRM_SERVICE_FATAL_ERROR);
636         return false;
637     }
638     return true;
639 }
640 
GenerateKeySystemRequest(napi_env env,napi_callback_info info)641 napi_value MediaKeySystemNapi::GenerateKeySystemRequest(napi_env env, napi_callback_info info)
642 {
643     DRM_INFO_LOG("GenerateKeySystemRequest enter");
644     DrmTrace trace("MediaKeySystemNapi::GenerateKeySystemRequest");
645     auto context = std::make_shared<MediaKeySystemAsyncContext>();
646     if (context == nullptr) {
647         DRM_ERR_LOG("GenerateKeySystemRequest failed.");
648         NapiDrmError::ThrowError(env, "make context failed, unknown error.", DRM_UNKNOWN_ERROR);
649         return NapiParamUtils::GetUndefinedValue(env);
650     }
651 
652     context->GetCbInfo(env, info);
653 
654     auto executor = [context]() {
655         DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckContextStatus(context), "context object state is error.");
656         auto obj = reinterpret_cast<MediaKeySystemNapi *>(context->native);
657         ObjectRefMap objectGuard(obj);
658         auto *napiMediaKeySystem = objectGuard.GetPtr();
659         DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckMediaKeySystemStatus(napiMediaKeySystem, context),
660             "context object state is error.");
661         context->intValue = napiMediaKeySystem->mediaKeySystemImpl_->GenerateKeySystemRequest(
662             context->provisionRequest.data, context->provisionRequest.defaultURL);
663         if (context->intValue != 0) {
664             context->SignError(DRM_SERVICE_FATAL_ERROR);
665         }
666     };
667 
668     auto complete = [env, context](napi_value &output) {
669         NapiParamUtils::SetProvisionRequest(env, context->provisionRequest, output);
670     };
671     return NapiAsyncWork::Enqueue(env, context, "GenerateKeySystemRequest", executor, complete);
672 }
673 
ProcessKeySystemResponse(napi_env env,napi_callback_info info)674 napi_value MediaKeySystemNapi::ProcessKeySystemResponse(napi_env env, napi_callback_info info)
675 {
676     DRM_INFO_LOG("ProcessKeySystemResponse enter.");
677     int64_t beginTime = std::chrono::duration_cast<std::chrono::milliseconds>(
678         std::chrono::system_clock::now().time_since_epoch()).count();
679     DrmTrace trace("MediaKeySystemNapi::ProcessKeySystemResponse");
680     auto context = std::make_shared<MediaKeySystemAsyncContext>();
681     if (context == nullptr) {
682         DRM_ERR_LOG("ProcessKeySystemResponse failed.");
683         NapiDrmError::ThrowError(env, "make context failed, unknown error.", DRM_UNKNOWN_ERROR);
684         return NapiParamUtils::GetUndefinedValue(env);
685     }
686 
687     auto inputParser = [env, context](size_t argc, napi_value *argv) {
688         NAPI_CHECK_ARGS_RETURN_VOID(context, argc == ARGS_ONE, "invalid arguments", DRM_INVALID_PARAM);
689         context->status = NapiParamUtils::GetValueUint8Array(env, context->response, argv[PARAM0]);
690         NAPI_CHECK_STATUS_RETURN_VOID(context, "ProcessKeySystemResponse failed.", DRM_INVALID_PARAM);
691     };
692 
693     context->GetCbInfo(env, info, inputParser);
694 
695     auto executor = [context]() {
696         DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckContextStatus(context), "context object state is error.");
697         auto obj = reinterpret_cast<MediaKeySystemNapi *>(context->native);
698         ObjectRefMap objectGuard(obj);
699         auto *napiMediaKeySystem = objectGuard.GetPtr();
700         DRM_NAPI_CHECK_AND_RETURN_VOID_LOG(CheckMediaKeySystemStatus(napiMediaKeySystem, context),
701             "context object state is error.");
702         context->intValue = napiMediaKeySystem->mediaKeySystemImpl_->ProcessKeySystemResponse(context->response);
703         if (context->intValue != DRM_OK) {
704             context->SignError(DRM_SERVICE_FATAL_ERROR);
705         }
706     };
707 
708     auto complete = [env](napi_value &output) { output = NapiParamUtils::GetUndefinedValue(env); };
709     ConfigParser::WriteEndEvent(0, 0, std::string("processKeySystemResponse"), beginTime);
710     return NapiAsyncWork::Enqueue(env, context, "ProcessKeySystemResponse", executor, complete);
711 }
712 
vectorToJsArray(napi_env env,std::vector<IMediaKeySystemService::MetircKeyValue> & metrics)713 static napi_value vectorToJsArray(napi_env env, std::vector<IMediaKeySystemService::MetircKeyValue> &metrics)
714 {
715     DRM_INFO_LOG("vectorToJsArray enter.");
716     napi_value jsArray;
717     napi_create_array_with_length(env, metrics.size(), &jsArray);
718     for (size_t i = 0; i < metrics.size(); i++) {
719         napi_value jsObject;
720         napi_value jsName;
721         napi_value jsValue;
722         napi_create_object(env, &jsObject);
723         napi_create_string_utf8(env, metrics[i].name.c_str(), NAPI_AUTO_LENGTH, &jsName);
724         napi_set_named_property(env, jsObject, "name", jsName);
725         napi_create_string_utf8(env, metrics[i].value.c_str(), NAPI_AUTO_LENGTH, &jsValue);
726         napi_set_named_property(env, jsObject, "value", jsValue);
727 
728         napi_set_element(env, jsArray, i, jsObject);
729     }
730     return jsArray;
731 }
732 
GetStatistics(napi_env env,napi_callback_info info)733 napi_value MediaKeySystemNapi::GetStatistics(napi_env env, napi_callback_info info)
734 {
735     DRM_INFO_LOG("GetStatistics enter.");
736     napi_value result = nullptr;
737     size_t argc = ARGS_ZERO;
738     napi_value argv[ARGS_ZERO];
739     napi_value thisVar = nullptr;
740     napi_status status;
741     std::vector<IMediaKeySystemService::MetircKeyValue> metrics;
742     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
743     napi_get_undefined(env, &result);
744 
745     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
746     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
747     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
748         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->GetStatistics(metrics);
749         if (ret != napi_ok) {
750             DRM_ERR_LOG("GetStatistics failed!");
751             NapiDrmError::ThrowError(env, "Get statistics failed, service error.", DRM_SERVICE_FATAL_ERROR);
752             return result;
753         }
754     } else {
755         DRM_ERR_LOG("napi_unwrap Failed!");
756         NapiDrmError::ThrowError(env, "GetStatistics failed, unknown error.", DRM_UNKNOWN_ERROR);
757         return result;
758     }
759     result = vectorToJsArray(env, metrics);
760     return result;
761 }
762 
GetCertificateStatus(napi_env env,napi_callback_info info)763 napi_value MediaKeySystemNapi::GetCertificateStatus(napi_env env, napi_callback_info info)
764 {
765     DrmTrace trace("MediaKeySystemNapi::GetCertificateStatus");
766     DRM_INFO_LOG("GetCertificateStatus enter.");
767     napi_value result = nullptr;
768     size_t argc = ARGS_ZERO;
769     napi_value argv[ARGS_ZERO];
770     napi_value thisVar = nullptr;
771     napi_status status;
772     IMediaKeySystemService::CertificateStatus certStatus;
773     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
774 
775     napi_get_undefined(env, &result);
776     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
777     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
778     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
779         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->GetCertificateStatus(&certStatus);
780         if (ret != napi_ok) {
781             DRM_ERR_LOG("GetCertificateStatus failed!");
782             NapiDrmError::ThrowError(env, "GetCertificateStatus failed, service error.", DRM_SERVICE_FATAL_ERROR);
783             return result;
784         }
785     } else {
786         DRM_ERR_LOG("napi_unwrap Failed!");
787         NapiDrmError::ThrowError(env, "GetCertificateStatus failed, unknown error.", DRM_UNKNOWN_ERROR);
788         return result;
789     }
790     NAPI_CALL(env, napi_create_int32(env, (int32_t)certStatus, &result));
791     return result;
792 }
793 
vectorToJs2DArray(napi_env env,std::vector<std::vector<uint8_t>> vec,napi_value result)794 static napi_value vectorToJs2DArray(napi_env env, std::vector<std::vector<uint8_t>> vec, napi_value result)
795 {
796     DRM_INFO_LOG("vectorToJs2DArray enter.");
797     napi_value outArray;
798     napi_value inArray;
799     napi_status status = napi_create_array(env, &outArray);
800     if (status != napi_ok) {
801         DRM_ERR_LOG("napi_create_array failed!");
802         NapiDrmError::ThrowError(env, "napi_create_array failed.", DRM_UNKNOWN_ERROR);
803         return result;
804     }
805 
806     for (size_t i = 0; i < vec.size(); i++) {
807         status = napi_create_array(env, &inArray);
808         if (status != napi_ok) {
809             DRM_ERR_LOG("napi_create_array failed!");
810             NapiDrmError::ThrowError(env, "napi_create_array failed.", DRM_UNKNOWN_ERROR);
811             return result;
812         }
813 
814         for (size_t j = 0; j < vec[i].size(); j++) {
815             napi_value elem;
816             status = napi_create_uint32(env, vec[i][j], &elem);
817             if (status != napi_ok) {
818                 DRM_ERR_LOG("napi_create_uint32 failed!");
819                 NapiDrmError::ThrowError(env, "napi_create_uint32 failed.", DRM_UNKNOWN_ERROR);
820                 return result;
821             }
822             status = napi_set_element(env, inArray, j, elem);
823             if (status != napi_ok) {
824                 DRM_ERR_LOG("napi_set_element failed!");
825                 NapiDrmError::ThrowError(env, "napi_set_element failed.", DRM_UNKNOWN_ERROR);
826                 return result;
827             }
828         }
829         status = napi_set_element(env, outArray, i, inArray);
830         if (status != napi_ok) {
831             DRM_ERR_LOG("napi_set_element failed!");
832             NapiDrmError::ThrowError(env, "napi_set_element failed.", DRM_UNKNOWN_ERROR);
833             return result;
834         }
835     }
836     return outArray;
837 }
838 
GetOfflineMediaKeyIds(napi_env env,napi_callback_info info)839 napi_value MediaKeySystemNapi::GetOfflineMediaKeyIds(napi_env env, napi_callback_info info)
840 {
841     DRM_INFO_LOG("GetOfflineMediaKeyIds enter.");
842     napi_value result = nullptr;
843     size_t argc = ARGS_ZERO;
844     napi_value argv[ARGS_ZERO];
845     napi_value thisVar = nullptr;
846     napi_status status;
847     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
848 
849     napi_get_undefined(env, &result);
850     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
851     NAPI_ASSERT(env, argc >= ARGS_ZERO, "requires 0 parameters maximum");
852     std::vector<std::vector<uint8_t>> licenseIds;
853     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
854     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
855         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->GetOfflineMediaKeyIds(licenseIds);
856         if (ret != napi_ok) {
857             DRM_ERR_LOG("napi GetOfflineMediaKeyIds failed!");
858             NapiDrmError::ThrowError(env, "GetOfflineMediaKeyIds failed, service error.", DRM_SERVICE_FATAL_ERROR);
859             return result;
860         }
861     } else {
862         DRM_ERR_LOG("napi_unwrap call Failed!");
863         NapiDrmError::ThrowError(env, "GetOfflineMediaKeyIds failed, unknown error.", DRM_UNKNOWN_ERROR);
864         return result;
865     }
866 
867     result = vectorToJs2DArray(env, licenseIds, result);
868     return result;
869 }
870 
GetOfflineMediaKeyStatus(napi_env env,napi_callback_info info)871 napi_value MediaKeySystemNapi::GetOfflineMediaKeyStatus(napi_env env, napi_callback_info info)
872 {
873     DRM_INFO_LOG("GetOfflineMediaKeyStatus enter");
874     napi_value result = nullptr;
875     size_t argc = ARGS_ONE;
876     napi_value argv[ARGS_ONE] = {0};
877     napi_value thisVar = nullptr;
878     napi_status status;
879     void *licenseId = nullptr;
880     size_t licenseIdLen;
881     size_t offset;
882     napi_value arraybuffer = nullptr;
883     napi_typedarray_type type;
884     bool isTypeArray;
885     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
886 
887     napi_get_undefined(env, &result);
888     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
889     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameters maximum");
890     napi_is_typedarray(env, argv[PARAM0], &isTypeArray);
891     if (!isTypeArray) {
892         DRM_ERR_LOG("First parame is not array!");
893         NapiDrmError::ThrowError(env, "The param mediaKeyId type is not array.", DRM_INVALID_PARAM);
894         return result;
895     }
896     napi_get_typedarray_info(env, argv[PARAM0], &type, &licenseIdLen, &licenseId, &arraybuffer, &offset);
897     if (licenseId == nullptr) {
898         DRM_ERR_LOG("napi_get_typedarray_info failed!");
899         NapiDrmError::ThrowError(env, "The param mediaKeyId is invalid.", DRM_INVALID_PARAM);
900         return result;
901     }
902     uint8_t *licenseIdPtr = reinterpret_cast<uint8_t *>(licenseId);
903     std::vector<uint8_t> licenseIdVec(licenseIdPtr, licenseIdPtr + licenseIdLen);
904     IMediaKeySessionService::OfflineMediaKeyStatus offlineMediaKeyStatus =
905         IMediaKeySessionService::OFFLINELICENSESTATUS_UNKNOWN;
906     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
907     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
908         int32_t ret =
909             mediaKeySystemNapi->mediaKeySystemImpl_->GetOfflineMediaKeyStatus(licenseIdVec, offlineMediaKeyStatus);
910         if (ret != napi_ok) {
911             DRM_ERR_LOG("GetOfflineMediaKeyStatus failed!");
912             NapiDrmError::ThrowError(env, "GetOfflineMediaKeyStatus failed, service error.", DRM_SERVICE_FATAL_ERROR);
913             return result;
914         }
915     } else {
916         DRM_ERR_LOG("napi_unwrap call Failed!");
917         NapiDrmError::ThrowError(env, "GetOfflineMediaKeyStatus failed, unknown error.", DRM_UNKNOWN_ERROR);
918         return result;
919     }
920 
921     NAPI_CALL(env, napi_create_int32(env, (int32_t)offlineMediaKeyStatus, &result));
922     return result;
923 }
924 
ClearOfflineMediaKeys(napi_env env,napi_callback_info info)925 napi_value MediaKeySystemNapi::ClearOfflineMediaKeys(napi_env env, napi_callback_info info)
926 {
927     DRM_INFO_LOG("ClearOfflineMediaKeys enter.");
928     napi_value result = nullptr;
929     size_t argc = ARGS_ONE;
930     napi_value argv[ARGS_ONE] = {0};
931     napi_value thisVar = nullptr;
932     napi_status status;
933     bool isTypeArray;
934     void *licenseId = nullptr;
935     size_t licenseIdLen;
936     size_t offset;
937     napi_value arraybuffer = nullptr;
938     napi_typedarray_type type;
939     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
940 
941     napi_get_undefined(env, &result);
942     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
943     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 2 parameters maximum");
944     napi_is_typedarray(env, argv[PARAM0], &isTypeArray);
945     if (!isTypeArray) {
946         DRM_ERR_LOG("argv[PARAM0] is not array!");
947         NapiDrmError::ThrowError(env, "The param mediaKeyId is not array.", DRM_INVALID_PARAM);
948         return result;
949     }
950     napi_get_typedarray_info(env, argv[PARAM0], &type, &licenseIdLen, &licenseId, &arraybuffer, &offset);
951     if (licenseId == nullptr) {
952         DRM_ERR_LOG("napi_get_typedarray_info failed!");
953         NapiDrmError::ThrowError(env, "ClearOfflineMediaKeys failed, unknown error.", DRM_UNKNOWN_ERROR);
954         return result;
955     }
956     uint8_t *licenseIdPtr = reinterpret_cast<uint8_t *>(licenseId);
957     std::vector<uint8_t> licenseIdVec(licenseIdPtr, licenseIdPtr + licenseIdLen);
958     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
959     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
960         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->ClearOfflineMediaKeys(licenseIdVec);
961         if (ret != napi_ok) {
962             DRM_ERR_LOG("ClearOfflineMediaKeys failed!");
963             NapiDrmError::ThrowError(env, "ClearOfflineMediaKeys failed, service error.", DRM_SERVICE_FATAL_ERROR);
964             return result;
965         }
966     } else {
967         DRM_ERR_LOG("ClearOfflineMediaKeys call Failed!");
968         NapiDrmError::ThrowError(env, "ClearOfflineMediaKeys failed, unknown error.", DRM_UNKNOWN_ERROR);
969         return result;
970     }
971 
972     return result;
973 }
974 
Destroy(napi_env env,napi_callback_info info)975 napi_value MediaKeySystemNapi::Destroy(napi_env env, napi_callback_info info)
976 {
977     DRM_INFO_LOG("Release enter.");
978     int32_t currentPid = IPCSkeleton::GetCallingPid();
979     DRM_DEBUG_LOG("GetCallingPID: %{public}d", currentPid);
980 
981     napi_status status;
982     napi_value result = nullptr;
983     size_t argc = ARGS_ZERO;
984     napi_value argv[ARGS_ZERO];
985     napi_value thisVar = nullptr;
986     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
987 
988     napi_get_undefined(env, &result);
989     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
990     napi_get_undefined(env, &result);
991     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
992     if (status == napi_ok && mediaKeySystemNapi != nullptr && mediaKeySystemNapi->mediaKeySystemImpl_ != nullptr) {
993         int32_t ret = mediaKeySystemNapi->mediaKeySystemImpl_->Release();
994         if (ret != napi_ok) {
995             DRM_ERR_LOG("GetCertificateStatus failed!");
996             NapiDrmError::ThrowError(env, "Destroy failed, service error.", DRM_SERVICE_FATAL_ERROR);
997             return result;
998         }
999     } else {
1000         DRM_ERR_LOG("napi_unwrap Failed!");
1001         NapiDrmError::ThrowError(env, "Destroy failed.", DRM_UNKNOWN_ERROR);
1002         return result;
1003     }
1004     return result;
1005 }
1006 
SaveEventCallbackReferrence(const std::string eventType,std::shared_ptr<AutoRef> callbackPair)1007 void MediaKeySystemNapi::SaveEventCallbackReferrence(const std::string eventType, std::shared_ptr<AutoRef> callbackPair)
1008 {
1009     DRM_INFO_LOG("SaveEventCallbackReferrence");
1010     std::lock_guard<std::mutex> lock(mutex_);
1011     if (mediaKeySystemCallbackNapi_ != nullptr) {
1012         mediaKeySystemCallbackNapi_->SetCallbackReference(eventType, callbackPair);
1013     } else {
1014         DRM_ERR_LOG("SaveEventCallbackReferrence failed.");
1015     }
1016 }
1017 
ClearEventCallbackReferrence(const std::string eventType)1018 void MediaKeySystemNapi::ClearEventCallbackReferrence(const std::string eventType)
1019 {
1020     DRM_INFO_LOG("ClearEventCallbackReference");
1021     if (mediaKeySystemCallbackNapi_ != nullptr) {
1022         mediaKeySystemCallbackNapi_->ClearCallbackReference(eventType);
1023     } else {
1024         DRM_ERR_LOG("ClearEventCallbackReference failed.");
1025     }
1026 }
1027 
SetEventCallback(napi_env env,napi_callback_info info)1028 napi_value MediaKeySystemNapi::SetEventCallback(napi_env env, napi_callback_info info)
1029 {
1030     DRM_INFO_LOG("SetEventCallback");
1031     napi_value result = nullptr;
1032     napi_get_undefined(env, &result);
1033     size_t length = 0;
1034     size_t argc = ARGS_TWO;
1035     napi_value thisVar = nullptr;
1036     napi_value argv[ARGS_TWO] = { nullptr };
1037     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
1038     NAPI_ASSERT(env, argc == ARGS_TWO, "only requires 2 parameters");
1039     if (thisVar == nullptr || argv[PARAM0] == nullptr || argv[PARAM1] == nullptr) {
1040         NapiDrmError::ThrowError(env, "Mandatory parameters are left unspecified.", DRM_INVALID_PARAM);
1041         DRM_ERR_LOG("Failed to retrieve arguments in SetEventCallback!");
1042         return result;
1043     }
1044     napi_valuetype valueType = napi_undefined;
1045     if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string ||
1046         napi_typeof(env, argv[PARAM1], &valueType) != napi_ok || valueType != napi_function) {
1047         NapiDrmError::ThrowError(env, "Mandatory parameter type is invalid.", DRM_INVALID_PARAM);
1048         return result;
1049     }
1050 
1051     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
1052     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
1053     if (status == napi_ok && mediaKeySystemNapi != nullptr) {
1054         char buffer[PATH_MAX];
1055         napi_get_value_string_utf8(env, argv[PARAM0], buffer, PATH_MAX, &length);
1056         std::string eventType = std::string(buffer);
1057         napi_ref callbackRef;
1058         napi_create_reference(env, argv[PARAM1], 1, &callbackRef);
1059         DRM_INFO_LOG("SetEventCallback event is %{public}s", eventType.c_str());
1060 
1061         std::shared_ptr<AutoRef> callbackPair = std::make_shared<AutoRef>(env, callbackRef);
1062         mediaKeySystemNapi->SaveEventCallbackReferrence(eventType, callbackPair);
1063         DRM_INFO_LOG("SetEventCallback out");
1064     } else {
1065         NapiDrmError::ThrowError(env, "SetEventCallback failed, unknown error.", DRM_UNKNOWN_ERROR);
1066         DRM_ERR_LOG("SetEventCallback failed!");
1067     }
1068     return result;
1069 }
1070 
UnsetEventCallback(napi_env env,napi_callback_info info)1071 napi_value MediaKeySystemNapi::UnsetEventCallback(napi_env env, napi_callback_info info)
1072 {
1073     DRM_INFO_LOG("UnsetEventCallback");
1074     napi_value result = nullptr;
1075     napi_get_undefined(env, &result);
1076     napi_value thisVar = nullptr;
1077     napi_value argv[ARGS_ONE] = { nullptr };
1078     size_t argc = 1;
1079     DRM_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
1080     NAPI_ASSERT(env, argc == ARGS_ONE, "only requires 1 parameters");
1081     if (thisVar == nullptr || argv[PARAM0] == nullptr) {
1082         DRM_ERR_LOG("Failed to retrieve arguments in UnsetEventCallback!");
1083         NapiDrmError::ThrowError(env, "The param callback type is missing.", DRM_INVALID_PARAM);
1084         return result;
1085     }
1086     napi_valuetype valueType = napi_undefined;
1087     if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string) {
1088         DRM_ERR_LOG("Failed to retrieve reasonable arguments in UnsetEventCallback!");
1089         NapiDrmError::ThrowError(env, "The param callback type is not string.", DRM_INVALID_PARAM);
1090         return result;
1091     }
1092 
1093     MediaKeySystemNapi *mediaKeySystemNapi = nullptr;
1094     char buffer[PATH_MAX];
1095     size_t length = 0;
1096     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&mediaKeySystemNapi));
1097     if (status == napi_ok && mediaKeySystemNapi != nullptr) {
1098         napi_get_value_string_utf8(env, argv[PARAM0], buffer, PATH_MAX, &length);
1099         std::string eventType = std::string(buffer);
1100         mediaKeySystemNapi->ClearEventCallbackReferrence(eventType);
1101         DRM_INFO_LOG("UnsetEventCallback out");
1102     } else {
1103         NapiDrmError::ThrowError(env, "UnsetEventCallback failed, unknown error.", DRM_UNKNOWN_ERROR);
1104         DRM_ERR_LOG("UnsetEventCallback failed!");
1105     }
1106     return result;
1107 }
1108 } // namespace DrmStandard
1109 } // namespace OHOS