• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string>
16 #include "devattest_log.h"
17 #include "devattest_errno.h"
18 #include "devattest_client.h"
19 #include "attest_result_info.h"
20 #include "devattest_napi.h"
21 
22 using namespace std;
23 using namespace OHOS;
24 using namespace OHOS::DevAttest;
25 
26 struct DevAttestAsyncContext {
27     napi_async_work work;
28     napi_ref callbackRef = nullptr; // 用于callback模式
29     napi_deferred deferred; // 用于promise模式
30     AttestResultInfo value; // 返回值
31     int32_t ret = DEVATTEST_ERR_JS_SYSTEM_SERVICE_EXCEPTION;
32 };
33 
GenerateDevAttestHandle(napi_env env,int32_t auth,int32_t software,string ticketStr,vector<int32_t> & softwareDetail)34 static napi_value GenerateDevAttestHandle(napi_env env, int32_t auth, int32_t software, string ticketStr,
35     vector<int32_t> &softwareDetail)
36 {
37     napi_value resultObject;
38     napi_create_object(env, &resultObject);
39     napi_value authResult;
40     napi_value softwareResult;
41     napi_value ticket;
42 
43     napi_create_int32(env, auth, &authResult);
44     napi_create_int32(env, software, &softwareResult);
45     napi_create_string_utf8(env, ticketStr.c_str(), ticketStr.length(), &ticket);
46     napi_set_named_property(env, resultObject, "authResult", authResult);
47     napi_set_named_property(env, resultObject, "softwareResult", softwareResult);
48     napi_set_named_property(env, resultObject, "ticket", ticket);
49 
50     napi_value softwareResultDetail;
51     napi_create_array(env, &softwareResultDetail);
52     size_t index = 0;
53     for (auto& vecData : softwareDetail) {
54         napi_value id;
55         napi_create_int32(env, vecData, &id);
56         napi_set_element(env, softwareResultDetail, index, id);
57         index++;
58     }
59     napi_set_named_property(env, resultObject, "softwareResultDetail", softwareResultDetail);
60     return resultObject;
61 }
62 
GenerateBusinessError(napi_env env,int32_t code)63 static napi_value GenerateBusinessError(napi_env env, int32_t code)
64 {
65     napi_value result;
66     int32_t jsErrCode = ConvertToJsErrCode(code);
67     HILOGI("[GenerateBusinessError] jsErrCode:%{public}d", jsErrCode);
68     if (jsErrCode == DEVATTEST_SUCCESS) {
69         napi_get_undefined(env, &result);
70     } else {
71         napi_value errCode = nullptr;
72         napi_create_int32(env, jsErrCode, &errCode);
73 
74         string errMsgStr = ConvertToJsErrMsg(jsErrCode);
75         napi_value errMsg = nullptr;
76         napi_create_string_utf8(env, errMsgStr.c_str(), NAPI_AUTO_LENGTH, &errMsg);
77 
78         napi_create_error(env, nullptr, errMsg, &result);
79         napi_set_named_property(env, result, "code", errCode);
80     }
81     return result;
82 }
83 
GenerateReturnValue(napi_env env,DevAttestAsyncContext * callback)84 static napi_value GenerateReturnValue(napi_env env, DevAttestAsyncContext* callback)
85 {
86     napi_value result;
87     if (callback->ret == DEVATTEST_SUCCESS) {
88         result = GenerateDevAttestHandle(env, callback->value.authResult_, callback->value.softwareResult_,
89             callback->value.ticket_, callback->value.softwareResultDetail_);
90     } else {
91         napi_get_undefined(env, &result);
92     }
93     return result;
94 }
95 
96 /* 耗时操作 */
Execute(napi_env env,void * data)97 static void Execute(napi_env env, void* data)
98 {
99     if (data == nullptr) {
100         HILOGI("[Execute] Invalid parameter");
101         return;
102     }
103     DevAttestAsyncContext *asyncContext = static_cast<DevAttestAsyncContext*>(data);
104     int32_t ret = DelayedSingleton<DevAttestClient>::GetInstance()->GetAttestStatus(asyncContext->value);
105     if (ret == DEVATTEST_FAIL) {
106         asyncContext->ret = DEVATTEST_ERR_JS_SYSTEM_SERVICE_EXCEPTION;
107     } else {
108         asyncContext->ret = ret;
109     }
110 }
111 
112 /* 传参,不耗时 */
Complete(napi_env env,napi_status status,void * data)113 static void Complete(napi_env env, napi_status status, void* data)
114 {
115     DevAttestAsyncContext* callback = static_cast<DevAttestAsyncContext*>(data);
116 
117     // 根据Execute函数的结果进行返回值的赋值, result[0]存放error; result[1]存放返回值
118     napi_value result[2] = {0};
119     result[0] = GenerateBusinessError(env, callback->ret);
120     result[1] = GenerateReturnValue(env, callback);
121 
122     if (callback->callbackRef != nullptr) { // callback模式
123         // 调用对应的js的callback函数
124         napi_value callbackfunc = nullptr;
125         napi_get_reference_value(env, callback->callbackRef, &callbackfunc);
126         napi_value returnValue;
127         // 此函数的最后一个参数不可传nullptr,否则程序会崩溃
128         napi_call_function(env, nullptr, callbackfunc, sizeof(result) / sizeof(result[0]), result, &returnValue);
129         napi_delete_reference(env, callback->callbackRef);
130     } else { // promise模式
131         if (callback->ret == DEVATTEST_SUCCESS) {
132             napi_resolve_deferred(env, callback->deferred, result[1]);
133         } else {
134             napi_reject_deferred(env, callback->deferred, result[0]);
135         }
136     }
137     napi_delete_async_work(env, callback->work); // 异步任务完成之后删除任务
138     delete callback;
139 }
140 
141 /* [js] getAttestStatus(callback: AsyncCallback<AttestResultInfo>) : void */
142 /* [js] getAttestStatus() : Promise<AttestResultInfo> */
GetAttestResultInfo(napi_env env,napi_callback_info info)143 napi_value DevAttestNapi::GetAttestResultInfo(napi_env env, napi_callback_info info)
144 {
145     // 获取js的入参数据
146     size_t argc = PARAM1; // 参数个数
147     napi_value argv[1] = {0}; // 参数的值
148     napi_value thisVar = nullptr; // js对象的this指针
149     void* data = nullptr; // 回调数据指针
150     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
151     if (argc > PARAM1) {
152         HILOGE("[GetAttestResultInfo] Input at most 1 paramter");
153         napi_throw(env, GenerateBusinessError(env, DEVATTEST_ERR_JS_PARAMETER_ERROR));
154     }
155 
156     // 判断入参的类型是否正确
157     napi_valuetype type = napi_undefined;
158     if (argc == PARAM1) {
159         napi_typeof(env, argv[0], &type);
160         if (type != napi_function) {
161             HILOGE("[GetAttestResultInfo] the type of argv[0] is not function");
162             napi_throw(env, GenerateBusinessError(env, DEVATTEST_ERR_JS_PARAMETER_ERROR));
163         }
164     }
165 
166     std::unique_ptr<DevAttestAsyncContext> callback = std::make_unique<DevAttestAsyncContext>();
167 
168    // 解析入参callback,判断callback
169     if (argc == PARAM1) {
170         napi_create_reference(env, argv[0], 1, &callback->callbackRef);
171     }
172 
173     // 判断模式,callback ref为空,说明是promise模式,反之是callback模式
174     napi_value promise = nullptr;
175     if (!callback->callbackRef) {
176         napi_create_promise(env, &callback->deferred, &promise);
177     } else {
178         napi_get_undefined(env, &promise);
179     }
180 
181     napi_value resource = nullptr;
182     napi_create_string_utf8(env, "GetAttestResultInfo", NAPI_AUTO_LENGTH, &resource);
183     napi_create_async_work(env, nullptr, resource,
184         Execute,
185         Complete,
186         static_cast<void*>(callback.get()),
187         &callback->work);
188     napi_queue_async_work(env, callback->work);
189     callback.release();
190     return promise;
191 }
192 
193 /* [js] getAttestStatusSync() : AttestResultInfo */
GetAttestResultInfoSync(napi_env env,napi_callback_info info)194 napi_value DevAttestNapi::GetAttestResultInfoSync(napi_env env, napi_callback_info info)
195 {
196     AttestResultInfo attestResultInfo;
197     int32_t errCode = DelayedSingleton<DevAttestClient>::GetInstance()->GetAttestStatus(attestResultInfo);
198     if (errCode != DEVATTEST_SUCCESS) {
199         HILOGE("[GetAttestResultInfoSync] GetAttestStatus failed errCode:%{public}d", errCode);
200         napi_throw(env, GenerateBusinessError(env, errCode));
201     }
202 
203     return GenerateDevAttestHandle(env, attestResultInfo.authResult_, attestResultInfo.softwareResult_,
204         attestResultInfo.ticket_, attestResultInfo.softwareResultDetail_);
205 }
206 
Init(napi_env env,napi_value exports)207 napi_value DevAttestNapi::Init(napi_env env, napi_value exports)
208 {
209     napi_property_descriptor desc[] = {
210         DECLARE_NAPI_STATIC_FUNCTION("getAttestStatus", GetAttestResultInfo),
211         DECLARE_NAPI_STATIC_FUNCTION("getAttestStatusSync", GetAttestResultInfoSync)
212     };
213     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
214     return exports;
215 }
216 
217 EXTERN_C_START
DevattestInit(napi_env env,napi_value exports)218 static napi_value DevattestInit(napi_env env, napi_value exports)
219 {
220     HILOGI("Initialize the DevAttestNapi module");
221     napi_value ret = DevAttestNapi::Init(env, exports);
222     HILOGI("The initialization of the DevAttestNapi module is complete");
223     return ret;
224 }
225 EXTERN_C_END
226 
227 static napi_module _module = {
228     .nm_version = 1,
229     .nm_flags = 0,
230     .nm_filename = nullptr,
231     .nm_register_func = DevattestInit,
232     .nm_modname = "deviceAttest",
233     .nm_priv = ((void *)0),
234     .reserved = { 0 }
235 };
236 
RegisterModule(void)237 extern "C" __attribute__((constructor)) void RegisterModule(void)
238 {
239     napi_module_register(&_module);
240 }
241