1 /*
2  * Copyright (c) 2022 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 <cstdint>
17 #include <sstream>
18 #include <string>
19 
20 #include "napi/native_common.h"
21 #include "node_api.h"
22 
23 #include "surface.h"
24 #include "surface_utils.h"
25 
26 #include "iam_logger.h"
27 
28 #include "face_auth_client.h"
29 #include "face_auth_defines.h"
30 
31 #define LOG_TAG "FACE_AUTH_NAPI"
32 
33 using namespace std;
34 
35 namespace OHOS {
36 namespace UserIam {
37 namespace FaceAuth {
38 namespace {
39 enum ResultCode : int32_t {
40     OHOS_CHECK_PERMISSION_FAILED = 201,
41     OHOS_CHECK_SYSTEM_PERMISSION_FAILED = 202,
42     RESULT_CODE_FAIL = 12700001,
43 };
44 
45 const std::map<int32_t, std::string> g_result2Str = {
46     { OHOS_CHECK_PERMISSION_FAILED, "Permission verification failed." },
47     { OHOS_CHECK_SYSTEM_PERMISSION_FAILED, "The caller is not a system application." },
48     { RESULT_CODE_FAIL, "The operation is failed." },
49 };
50 
FaceAuthManagerConstructor(napi_env env,napi_callback_info info)51 napi_value FaceAuthManagerConstructor(napi_env env, napi_callback_info info)
52 {
53     IAM_LOGI("start");
54     napi_value thisVar = nullptr;
55     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
56     return thisVar;
57 }
58 
GenerateBusinessError(napi_env env,int32_t result)59 napi_value GenerateBusinessError(napi_env env, int32_t result)
60 {
61     napi_value code;
62     std::string msgStr;
63     auto res = g_result2Str.find(result);
64     if (res == g_result2Str.end()) {
65         IAM_LOGE("result %{public}d not found", result);
66         msgStr = g_result2Str.at(RESULT_CODE_FAIL);
67         NAPI_CALL(env, napi_create_int32(env, RESULT_CODE_FAIL, &code));
68     } else {
69         msgStr = res->second;
70         NAPI_CALL(env, napi_create_int32(env, result, &code));
71     }
72     IAM_LOGI("get msg %{public}s", msgStr.c_str());
73 
74     napi_value msg;
75     NAPI_CALL(env, napi_create_string_utf8(env, msgStr.c_str(), NAPI_AUTO_LENGTH, &msg));
76 
77     napi_value businessError;
78     NAPI_CALL(env, napi_create_error(env, nullptr, msg, &businessError));
79     NAPI_CALL(env, napi_set_named_property(env, businessError, "code", code));
80 
81     return businessError;
82 }
83 
GetBufferProducerBySurfaceId(uint64_t surfaceId,sptr<IBufferProducer> & bufferProducer)84 bool GetBufferProducerBySurfaceId(uint64_t surfaceId, sptr<IBufferProducer> &bufferProducer)
85 {
86     if (surfaceId == 0) {
87         IAM_LOGI("surface id is 0, get buffer producer null");
88         bufferProducer = nullptr;
89         return true;
90     }
91 
92     auto surfaceUtils = SurfaceUtils::GetInstance();
93     if (surfaceUtils == nullptr) {
94         IAM_LOGE("Get SurfaceUtils failed!");
95         return false;
96     }
97 
98     sptr<Surface> previewSurface = surfaceUtils->GetSurface(surfaceId);
99     if (previewSurface == nullptr) {
100         IAM_LOGE("GetSurface failed!");
101         return false;
102     }
103 
104     bufferProducer = previewSurface->GetProducer();
105     if (bufferProducer == nullptr) {
106         IAM_LOGE("GetProducer Failed!");
107         return false;
108     }
109 
110     IAM_LOGI("get buffer producer success");
111     return true;
112 }
113 
SetSurfaceId(napi_env env,napi_callback_info info)114 napi_value SetSurfaceId(napi_env env, napi_callback_info info)
115 {
116     static constexpr size_t argsOne = 1;
117     size_t argc = argsOne;
118     napi_value argv;
119     napi_status ret = napi_get_cb_info(env, info, &argc, &argv, nullptr, nullptr);
120     if (ret != napi_ok || argc != argsOne) {
121         IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
122         napi_throw(env, GenerateBusinessError(env, RESULT_CODE_FAIL));
123         return nullptr;
124     }
125     static constexpr int maxLen = 25;
126     char buf[maxLen] = { '\0' };
127     size_t len;
128     ret = napi_get_value_string_utf8(env, argv, buf, maxLen, &len);
129     if (ret != napi_ok) {
130         IAM_LOGE("napi_get_value_string_utf8 fail:%{public}d", ret);
131         napi_throw(env, GenerateBusinessError(env, RESULT_CODE_FAIL));
132         return nullptr;
133     }
134     buf[maxLen - 1] = '\0';
135     std::string strSurfaceId = buf;
136     std::istringstream surfaceIdStream(strSurfaceId);
137     uint64_t surfaceId;
138     surfaceIdStream >> surfaceId;
139 
140     sptr<IBufferProducer> bufferProducer(nullptr);
141     if (!GetBufferProducerBySurfaceId(surfaceId, bufferProducer)) {
142         IAM_LOGE("GetBufferProducerBySurfaceId fail");
143         napi_throw(env, GenerateBusinessError(env, RESULT_CODE_FAIL));
144         return nullptr;
145     }
146     int32_t result = FaceAuthClient::GetInstance().SetBufferProducer(bufferProducer);
147     if (result != FACE_AUTH_SUCCESS) {
148         IAM_LOGE("SetBufferProducer fail");
149         napi_throw(env, GenerateBusinessError(env, result));
150         return nullptr;
151     }
152     return nullptr;
153 }
154 
GetFaceAuthManagerConstructor(napi_env env)155 napi_value GetFaceAuthManagerConstructor(napi_env env)
156 {
157     IAM_LOGI("start");
158     napi_property_descriptor methods[] = { DECLARE_NAPI_FUNCTION("setSurfaceId", SetSurfaceId) };
159     napi_value result = nullptr;
160     NAPI_CALL(env,
161         napi_define_class(env, "FaceAuth", NAPI_AUTO_LENGTH, FaceAuthManagerConstructor, nullptr,
162             sizeof(methods) / sizeof(napi_property_descriptor), methods, &result));
163     return result;
164 }
165 
GetResultCodeConstructor(napi_env env)166 napi_value GetResultCodeConstructor(napi_env env)
167 {
168     IAM_LOGI("start");
169     napi_value resultCode = nullptr;
170     NAPI_CALL(env, napi_create_object(env, &resultCode));
171     napi_value fail = nullptr;
172     NAPI_CALL(env, napi_create_int32(env, RESULT_CODE_FAIL, &fail));
173     NAPI_CALL(env, napi_set_named_property(env, resultCode, "FAIL", fail));
174     return resultCode;
175 }
176 
ModuleInit(napi_env env,napi_value exports)177 napi_value ModuleInit(napi_env env, napi_value exports)
178 {
179     IAM_LOGI("start");
180     NAPI_CALL(env, napi_set_named_property(env, exports, "FaceAuthManager", GetFaceAuthManagerConstructor(env)));
181 
182     napi_property_descriptor enums[] = {
183         DECLARE_NAPI_PROPERTY("ResultCode", GetResultCodeConstructor(env)),
184     };
185     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(enums) / sizeof(napi_property_descriptor), enums));
186 
187     return exports;
188 }
189 } // namespace
190 
RegisterModule(void)191 extern "C" __attribute__((constructor)) void RegisterModule(void)
192 {
193     napi_module module = { .nm_version = 1,
194         .nm_flags = 0,
195         .nm_filename = nullptr,
196         .nm_register_func = ModuleInit,
197         .nm_modname = "userIAM.faceAuth",
198         .nm_priv = nullptr,
199         .reserved = {} };
200     napi_module_register(&module);
201 }
202 } // namespace FaceAuth
203 } // namespace UserIam
204 } // namespace OHOS