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