15bbf6e98Sopenharmony_ci/*
25bbf6e98Sopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd.
35bbf6e98Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
45bbf6e98Sopenharmony_ci * you may not use this file except in compliance with the License.
55bbf6e98Sopenharmony_ci * You may obtain a copy of the License at
65bbf6e98Sopenharmony_ci *
75bbf6e98Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
85bbf6e98Sopenharmony_ci *
95bbf6e98Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
105bbf6e98Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
115bbf6e98Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125bbf6e98Sopenharmony_ci * See the License for the specific language governing permissions and
135bbf6e98Sopenharmony_ci * limitations under the License.
145bbf6e98Sopenharmony_ci */
155bbf6e98Sopenharmony_ci
165bbf6e98Sopenharmony_ci#include "devattest_log.h"
175bbf6e98Sopenharmony_ci#include "devattest_errno.h"
185bbf6e98Sopenharmony_ci#include "devattest_client.h"
195bbf6e98Sopenharmony_ci#include "devattest_napi.h"
205bbf6e98Sopenharmony_ci
215bbf6e98Sopenharmony_ciusing namespace std;
225bbf6e98Sopenharmony_ciusing namespace OHOS;
235bbf6e98Sopenharmony_ciusing namespace OHOS::DevAttest;
245bbf6e98Sopenharmony_ci
255bbf6e98Sopenharmony_cistruct DevAttestAsyncContext {
265bbf6e98Sopenharmony_ci    napi_async_work work;
275bbf6e98Sopenharmony_ci    napi_ref callbackRef = nullptr; // 用于callback模式
285bbf6e98Sopenharmony_ci    napi_deferred deferred; // 用于promise模式
295bbf6e98Sopenharmony_ci    AttestResultInfo value; // 返回值
305bbf6e98Sopenharmony_ci    int32_t ret = DEVATTEST_ERR_JS_SYSTEM_SERVICE_EXCEPTION;
315bbf6e98Sopenharmony_ci};
325bbf6e98Sopenharmony_ci
335bbf6e98Sopenharmony_cistatic napi_value GenerateDevAttestHandle(napi_env env, int32_t auth, int32_t software, string ticketStr,
345bbf6e98Sopenharmony_ci    vector<int32_t> &softwareDetail)
355bbf6e98Sopenharmony_ci{
365bbf6e98Sopenharmony_ci    napi_value resultObject;
375bbf6e98Sopenharmony_ci    napi_create_object(env, &resultObject);
385bbf6e98Sopenharmony_ci    napi_value authResult;
395bbf6e98Sopenharmony_ci    napi_value softwareResult;
405bbf6e98Sopenharmony_ci    napi_value ticket;
415bbf6e98Sopenharmony_ci
425bbf6e98Sopenharmony_ci    napi_create_int32(env, auth, &authResult);
435bbf6e98Sopenharmony_ci    napi_create_int32(env, software, &softwareResult);
445bbf6e98Sopenharmony_ci    napi_create_string_utf8(env, ticketStr.c_str(), ticketStr.length(), &ticket);
455bbf6e98Sopenharmony_ci    napi_set_named_property(env, resultObject, "authResult", authResult);
465bbf6e98Sopenharmony_ci    napi_set_named_property(env, resultObject, "softwareResult", softwareResult);
475bbf6e98Sopenharmony_ci    napi_set_named_property(env, resultObject, "ticket", ticket);
485bbf6e98Sopenharmony_ci
495bbf6e98Sopenharmony_ci    napi_value softwareResultDetail;
505bbf6e98Sopenharmony_ci    napi_create_array(env, &softwareResultDetail);
515bbf6e98Sopenharmony_ci    size_t index = 0;
525bbf6e98Sopenharmony_ci    for (auto& vecData : softwareDetail) {
535bbf6e98Sopenharmony_ci        napi_value id;
545bbf6e98Sopenharmony_ci        napi_create_int32(env, vecData, &id);
555bbf6e98Sopenharmony_ci        napi_set_element(env, softwareResultDetail, index, id);
565bbf6e98Sopenharmony_ci        index++;
575bbf6e98Sopenharmony_ci    }
585bbf6e98Sopenharmony_ci    napi_set_named_property(env, resultObject, "softwareResultDetail", softwareResultDetail);
595bbf6e98Sopenharmony_ci    return resultObject;
605bbf6e98Sopenharmony_ci}
615bbf6e98Sopenharmony_ci
625bbf6e98Sopenharmony_cistatic napi_value GenerateBusinessError(napi_env env, int32_t code)
635bbf6e98Sopenharmony_ci{
645bbf6e98Sopenharmony_ci    napi_value result;
655bbf6e98Sopenharmony_ci    int32_t jsErrCode = ConvertToJsErrCode(code);
665bbf6e98Sopenharmony_ci    if (jsErrCode == DEVATTEST_SUCCESS) {
675bbf6e98Sopenharmony_ci        napi_get_undefined(env, &result);
685bbf6e98Sopenharmony_ci    } else {
695bbf6e98Sopenharmony_ci        napi_value errCode = nullptr;
705bbf6e98Sopenharmony_ci        napi_create_int32(env, jsErrCode, &errCode);
715bbf6e98Sopenharmony_ci
725bbf6e98Sopenharmony_ci        string errMsgStr = ConvertToJsErrMsg(jsErrCode);
735bbf6e98Sopenharmony_ci        napi_value errMsg = nullptr;
745bbf6e98Sopenharmony_ci        napi_create_string_utf8(env, errMsgStr.c_str(), NAPI_AUTO_LENGTH, &errMsg);
755bbf6e98Sopenharmony_ci
765bbf6e98Sopenharmony_ci        napi_create_error(env, nullptr, errMsg, &result);
775bbf6e98Sopenharmony_ci        napi_set_named_property(env, result, "code", errCode);
785bbf6e98Sopenharmony_ci    }
795bbf6e98Sopenharmony_ci    return result;
805bbf6e98Sopenharmony_ci}
815bbf6e98Sopenharmony_ci
825bbf6e98Sopenharmony_cistatic napi_value GenerateReturnValue(napi_env env, DevAttestAsyncContext* callback)
835bbf6e98Sopenharmony_ci{
845bbf6e98Sopenharmony_ci    napi_value result;
855bbf6e98Sopenharmony_ci    if (callback->ret == DEVATTEST_SUCCESS) {
865bbf6e98Sopenharmony_ci        result = GenerateDevAttestHandle(env, callback->value.authResult_, callback->value.softwareResult_,
875bbf6e98Sopenharmony_ci            callback->value.ticket_, callback->value.softwareResultDetail_);
885bbf6e98Sopenharmony_ci    } else {
895bbf6e98Sopenharmony_ci        napi_get_undefined(env, &result);
905bbf6e98Sopenharmony_ci    }
915bbf6e98Sopenharmony_ci    return result;
925bbf6e98Sopenharmony_ci}
935bbf6e98Sopenharmony_ci
945bbf6e98Sopenharmony_ci/* 耗时操作 */
955bbf6e98Sopenharmony_cistatic void Execute(napi_env env, void* data)
965bbf6e98Sopenharmony_ci{
975bbf6e98Sopenharmony_ci    if (data == nullptr) {
985bbf6e98Sopenharmony_ci        HILOGE("[Execute] Invalid parameter");
995bbf6e98Sopenharmony_ci        return;
1005bbf6e98Sopenharmony_ci    }
1015bbf6e98Sopenharmony_ci    DevAttestAsyncContext *asyncContext = static_cast<DevAttestAsyncContext*>(data);
1025bbf6e98Sopenharmony_ci    int32_t ret = DevAttestClient::GetInstance().GetAttestStatus(asyncContext->value);
1035bbf6e98Sopenharmony_ci    if (ret == DEVATTEST_FAIL) {
1045bbf6e98Sopenharmony_ci        asyncContext->ret = DEVATTEST_ERR_JS_SYSTEM_SERVICE_EXCEPTION;
1055bbf6e98Sopenharmony_ci    } else {
1065bbf6e98Sopenharmony_ci        asyncContext->ret = ret;
1075bbf6e98Sopenharmony_ci    }
1085bbf6e98Sopenharmony_ci}
1095bbf6e98Sopenharmony_ci
1105bbf6e98Sopenharmony_ci/* 传参,不耗时 */
1115bbf6e98Sopenharmony_cistatic void Complete(napi_env env, napi_status status, void* data)
1125bbf6e98Sopenharmony_ci{
1135bbf6e98Sopenharmony_ci    DevAttestAsyncContext* callback = static_cast<DevAttestAsyncContext*>(data);
1145bbf6e98Sopenharmony_ci
1155bbf6e98Sopenharmony_ci    // 根据Execute函数的结果进行返回值的赋值, result[0]存放error; result[1]存放返回值
1165bbf6e98Sopenharmony_ci    napi_value result[2] = {0};
1175bbf6e98Sopenharmony_ci    result[0] = GenerateBusinessError(env, callback->ret);
1185bbf6e98Sopenharmony_ci    result[1] = GenerateReturnValue(env, callback);
1195bbf6e98Sopenharmony_ci
1205bbf6e98Sopenharmony_ci    if (callback->callbackRef != nullptr) { // callback模式
1215bbf6e98Sopenharmony_ci        // 调用对应的js的callback函数
1225bbf6e98Sopenharmony_ci        napi_value callbackfunc = nullptr;
1235bbf6e98Sopenharmony_ci        napi_get_reference_value(env, callback->callbackRef, &callbackfunc);
1245bbf6e98Sopenharmony_ci        napi_value returnValue;
1255bbf6e98Sopenharmony_ci        // 此函数的最后一个参数不可传nullptr,否则程序会崩溃
1265bbf6e98Sopenharmony_ci        napi_call_function(env, nullptr, callbackfunc, sizeof(result) / sizeof(result[0]), result, &returnValue);
1275bbf6e98Sopenharmony_ci        napi_delete_reference(env, callback->callbackRef);
1285bbf6e98Sopenharmony_ci    } else { // promise模式
1295bbf6e98Sopenharmony_ci        if (callback->ret == DEVATTEST_SUCCESS) {
1305bbf6e98Sopenharmony_ci            napi_resolve_deferred(env, callback->deferred, result[1]);
1315bbf6e98Sopenharmony_ci        } else {
1325bbf6e98Sopenharmony_ci            napi_reject_deferred(env, callback->deferred, result[0]);
1335bbf6e98Sopenharmony_ci        }
1345bbf6e98Sopenharmony_ci    }
1355bbf6e98Sopenharmony_ci    napi_delete_async_work(env, callback->work); // 异步任务完成之后删除任务
1365bbf6e98Sopenharmony_ci    delete callback;
1375bbf6e98Sopenharmony_ci}
1385bbf6e98Sopenharmony_ci
1395bbf6e98Sopenharmony_ci/* [js] getAttestStatus(callback: AsyncCallback<AttestResultInfo>) : void */
1405bbf6e98Sopenharmony_ci/* [js] getAttestStatus() : Promise<AttestResultInfo> */
1415bbf6e98Sopenharmony_cinapi_value DevAttestNapi::GetAttestResultInfo(napi_env env, napi_callback_info info)
1425bbf6e98Sopenharmony_ci{
1435bbf6e98Sopenharmony_ci    // 获取js的入参数据
1445bbf6e98Sopenharmony_ci    size_t argc = PARAM1; // 参数个数
1455bbf6e98Sopenharmony_ci    napi_value argv[1] = {0}; // 参数的值
1465bbf6e98Sopenharmony_ci    napi_value thisVar = nullptr; // js对象的this指针
1475bbf6e98Sopenharmony_ci    void* data = nullptr; // 回调数据指针
1485bbf6e98Sopenharmony_ci    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1495bbf6e98Sopenharmony_ci    if (argc > PARAM1) {
1505bbf6e98Sopenharmony_ci        HILOGE("[GetAttestResultInfo] Input at most 1 paramter");
1515bbf6e98Sopenharmony_ci        napi_throw(env, GenerateBusinessError(env, DEVATTEST_ERR_JS_PARAMETER_ERROR));
1525bbf6e98Sopenharmony_ci    }
1535bbf6e98Sopenharmony_ci
1545bbf6e98Sopenharmony_ci    // 判断入参的类型是否正确
1555bbf6e98Sopenharmony_ci    napi_valuetype type = napi_undefined;
1565bbf6e98Sopenharmony_ci    if (argc == PARAM1) {
1575bbf6e98Sopenharmony_ci        napi_typeof(env, argv[0], &type);
1585bbf6e98Sopenharmony_ci        if (type != napi_function) {
1595bbf6e98Sopenharmony_ci            HILOGE("[GetAttestResultInfo] the type of argv[0] is not function");
1605bbf6e98Sopenharmony_ci            napi_throw(env, GenerateBusinessError(env, DEVATTEST_ERR_JS_PARAMETER_ERROR));
1615bbf6e98Sopenharmony_ci        }
1625bbf6e98Sopenharmony_ci    }
1635bbf6e98Sopenharmony_ci
1645bbf6e98Sopenharmony_ci    std::unique_ptr<DevAttestAsyncContext> callback = std::make_unique<DevAttestAsyncContext>();
1655bbf6e98Sopenharmony_ci
1665bbf6e98Sopenharmony_ci   // 解析入参callback,判断callback
1675bbf6e98Sopenharmony_ci    if (argc == PARAM1) {
1685bbf6e98Sopenharmony_ci        napi_create_reference(env, argv[0], 1, &callback->callbackRef);
1695bbf6e98Sopenharmony_ci    }
1705bbf6e98Sopenharmony_ci
1715bbf6e98Sopenharmony_ci    // 判断模式,callback ref为空,说明是promise模式,反之是callback模式
1725bbf6e98Sopenharmony_ci    napi_value promise = nullptr;
1735bbf6e98Sopenharmony_ci    if (!callback->callbackRef) {
1745bbf6e98Sopenharmony_ci        napi_create_promise(env, &callback->deferred, &promise);
1755bbf6e98Sopenharmony_ci    } else {
1765bbf6e98Sopenharmony_ci        napi_get_undefined(env, &promise);
1775bbf6e98Sopenharmony_ci    }
1785bbf6e98Sopenharmony_ci
1795bbf6e98Sopenharmony_ci    napi_value resource = nullptr;
1805bbf6e98Sopenharmony_ci    napi_create_string_utf8(env, "GetAttestResultInfo", NAPI_AUTO_LENGTH, &resource);
1815bbf6e98Sopenharmony_ci    napi_create_async_work(env, nullptr, resource,
1825bbf6e98Sopenharmony_ci        Execute,
1835bbf6e98Sopenharmony_ci        Complete,
1845bbf6e98Sopenharmony_ci        static_cast<void*>(callback.get()),
1855bbf6e98Sopenharmony_ci        &callback->work);
1865bbf6e98Sopenharmony_ci    napi_queue_async_work(env, callback->work);
1875bbf6e98Sopenharmony_ci    callback.release();
1885bbf6e98Sopenharmony_ci    return promise;
1895bbf6e98Sopenharmony_ci}
1905bbf6e98Sopenharmony_ci
1915bbf6e98Sopenharmony_ci/* [js] getAttestStatusSync() : AttestResultInfo */
1925bbf6e98Sopenharmony_cinapi_value DevAttestNapi::GetAttestResultInfoSync(napi_env env, napi_callback_info info)
1935bbf6e98Sopenharmony_ci{
1945bbf6e98Sopenharmony_ci    AttestResultInfo attestResultInfo;
1955bbf6e98Sopenharmony_ci    int32_t errCode = DevAttestClient::GetInstance().GetAttestStatus(attestResultInfo);
1965bbf6e98Sopenharmony_ci    if (errCode != DEVATTEST_SUCCESS) {
1975bbf6e98Sopenharmony_ci        HILOGE("[GetAttestResultInfoSync] GetAttestStatus failed errCode:%{public}d", errCode);
1985bbf6e98Sopenharmony_ci        napi_throw(env, GenerateBusinessError(env, errCode));
1995bbf6e98Sopenharmony_ci    }
2005bbf6e98Sopenharmony_ci
2015bbf6e98Sopenharmony_ci    return GenerateDevAttestHandle(env, attestResultInfo.authResult_, attestResultInfo.softwareResult_,
2025bbf6e98Sopenharmony_ci        attestResultInfo.ticket_, attestResultInfo.softwareResultDetail_);
2035bbf6e98Sopenharmony_ci}
2045bbf6e98Sopenharmony_ci
2055bbf6e98Sopenharmony_cinapi_value DevAttestNapi::Init(napi_env env, napi_value exports)
2065bbf6e98Sopenharmony_ci{
2075bbf6e98Sopenharmony_ci    napi_property_descriptor desc[] = {
2085bbf6e98Sopenharmony_ci        DECLARE_NAPI_STATIC_FUNCTION("getAttestStatus", GetAttestResultInfo),
2095bbf6e98Sopenharmony_ci        DECLARE_NAPI_STATIC_FUNCTION("getAttestStatusSync", GetAttestResultInfoSync)
2105bbf6e98Sopenharmony_ci    };
2115bbf6e98Sopenharmony_ci    NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
2125bbf6e98Sopenharmony_ci    return exports;
2135bbf6e98Sopenharmony_ci}
2145bbf6e98Sopenharmony_ci
2155bbf6e98Sopenharmony_ciEXTERN_C_START
2165bbf6e98Sopenharmony_cistatic napi_value DevattestInit(napi_env env, napi_value exports)
2175bbf6e98Sopenharmony_ci{
2185bbf6e98Sopenharmony_ci    HILOGI("Initialize the DevAttestNapi module");
2195bbf6e98Sopenharmony_ci    napi_value ret = DevAttestNapi::Init(env, exports);
2205bbf6e98Sopenharmony_ci    HILOGI("The initialization of the DevAttestNapi module is complete");
2215bbf6e98Sopenharmony_ci    return ret;
2225bbf6e98Sopenharmony_ci}
2235bbf6e98Sopenharmony_ciEXTERN_C_END
2245bbf6e98Sopenharmony_ci
2255bbf6e98Sopenharmony_cistatic napi_module _module = {
2265bbf6e98Sopenharmony_ci    .nm_version = 1,
2275bbf6e98Sopenharmony_ci    .nm_flags = 0,
2285bbf6e98Sopenharmony_ci    .nm_filename = nullptr,
2295bbf6e98Sopenharmony_ci    .nm_register_func = DevattestInit,
2305bbf6e98Sopenharmony_ci    .nm_modname = "deviceAttest",
2315bbf6e98Sopenharmony_ci    .nm_priv = ((void *)0),
2325bbf6e98Sopenharmony_ci    .reserved = { 0 }
2335bbf6e98Sopenharmony_ci};
2345bbf6e98Sopenharmony_ci
2355bbf6e98Sopenharmony_ciextern "C" __attribute__((constructor)) void RegisterModule(void)
2365bbf6e98Sopenharmony_ci{
2375bbf6e98Sopenharmony_ci    napi_module_register(&_module);
2385bbf6e98Sopenharmony_ci}
239