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