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