1 /*
2  * Copyright (c) 2022-2024 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 "napi_app_account_authenticator.h"
17 
18 #include <uv.h>
19 
20 #include "account_log_wrapper.h"
21 #include "app_account_constants.h"
22 #include "iapp_account_authenticator_callback.h"
23 #include "ipc_object_stub.h"
24 #include "napi/native_api.h"
25 #include "napi/native_node_api.h"
26 #include "napi_account_common.h"
27 #include "napi_app_account_authenticator_callback.h"
28 #include "napi_app_account_common.h"
29 #include "napi_common.h"
30 #include "napi_remote_object.h"
31 
32 namespace OHOS {
33 namespace AccountJsKit {
34 using namespace OHOS::AccountSA;
35 
OnEnvCleanUp(void * data)36 static void OnEnvCleanUp(void *data)
37 {
38     if (data == nullptr) {
39         ACCOUNT_LOGE("data is nullptr");
40         return;
41     }
42     auto authenticator = reinterpret_cast<NapiAppAccountAuthenticator *>(data);
43     authenticator->SetEnv(nullptr);
44 }
45 
NapiAppAccountAuthenticator(napi_env env,JsAuthenticator & jsAuthenticator)46 NapiAppAccountAuthenticator::NapiAppAccountAuthenticator(napi_env env, JsAuthenticator &jsAuthenticator)
47     : env_(env), jsAuthenticator_(jsAuthenticator)
48 {}
49 
~NapiAppAccountAuthenticator()50 NapiAppAccountAuthenticator::~NapiAppAccountAuthenticator()
51 {
52     std::vector<napi_ref> napiRefVec = {
53         jsAuthenticator_.addAccountImplicitly,
54         jsAuthenticator_.authenticate,
55         jsAuthenticator_.verifyCredential,
56         jsAuthenticator_.checkAccountLabels,
57         jsAuthenticator_.setProperties,
58         jsAuthenticator_.isAccountRemovable,
59         jsAuthenticator_.createAccountImplicitly,
60         jsAuthenticator_.auth
61     };
62     ReleaseNapiRefArray(env_, napiRefVec);
63     jsAuthenticator_.addAccountImplicitly = nullptr;
64     jsAuthenticator_.authenticate = nullptr;
65     jsAuthenticator_.verifyCredential = nullptr;
66     jsAuthenticator_.checkAccountLabels = nullptr;
67     jsAuthenticator_.setProperties = nullptr;
68     jsAuthenticator_.isAccountRemovable = nullptr;
69     jsAuthenticator_.createAccountImplicitly = nullptr;
70     jsAuthenticator_.auth = nullptr;
71     napi_remove_env_cleanup_hook(env_, OnEnvCleanUp, this);
72 }
73 
CheckObjectLegality() const74 bool NapiAppAccountAuthenticator::CheckObjectLegality() const
75 {
76     return true;
77 }
78 
GetObjectType() const79 int NapiAppAccountAuthenticator::GetObjectType() const
80 {
81     return OBJECT_TYPE_NATIVE;
82 }
83 
SetEnv(napi_env env)84 void NapiAppAccountAuthenticator::SetEnv(napi_env env)
85 {
86     env_ = env;
87 }
88 
InitWorkEnv(uv_loop_s ** loop,uv_work_t ** work,JsAuthenticatorParam ** param)89 ErrCode NapiAppAccountAuthenticator::InitWorkEnv(uv_loop_s **loop, uv_work_t **work, JsAuthenticatorParam **param)
90 {
91     napi_get_uv_event_loop(env_, loop);
92     if (*loop == nullptr) {
93         ACCOUNT_LOGE("failed to get uv event loop");
94         return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
95     }
96     *work = new (std::nothrow) uv_work_t;
97     if (*work == nullptr) {
98         ACCOUNT_LOGE("failed to allocate memory");
99         return ERR_ACCOUNT_COMMON_INSUFFICIENT_MEMORY_ERROR;
100     }
101     *param = new (std::nothrow) JsAuthenticatorParam();
102     if (*param == nullptr) {
103         ACCOUNT_LOGE("failed to allocate memory");
104         delete *work;
105         return ERR_ACCOUNT_COMMON_INSUFFICIENT_MEMORY_ERROR;
106     }
107     (*param)->env = env_;
108     (*param)->jsAuthenticator = jsAuthenticator_;
109     return ERR_OK;
110 }
111 
AddAccountImplicitly(const std::string & authType,const std::string & callerBundleName,const AAFwk::WantParams & options,const sptr<IRemoteObject> & callback)112 ErrCode NapiAppAccountAuthenticator::AddAccountImplicitly(
113     const std::string &authType, const std::string &callerBundleName,
114     const AAFwk::WantParams &options, const sptr<IRemoteObject> &callback)
115 {
116     if (jsAuthenticator_.addAccountImplicitly == nullptr) {
117         return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
118     }
119     uv_loop_s *loop = nullptr;
120     uv_work_t *work = nullptr;
121     JsAuthenticatorParam *param = nullptr;
122     ErrCode result = InitWorkEnv(&loop, &work, &param);
123     if (result != ERR_OK) {
124         ACCOUNT_LOGE("failed to InitWorkEnv");
125         return result;
126     }
127     param->authType = authType;
128     param->callerBundleName = callerBundleName;
129     param->options = options;
130     param->callback = callback;
131     work->data = reinterpret_cast<void *>(param);
132     int32_t ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, AddAccountImplicitlyWork, uv_qos_default);
133     if (ret != 0) {
134         ACCOUNT_LOGE("failed to uv_queue_work_with_qos, errCode: %{public}d", ret);
135         delete work;
136         delete param;
137     }
138     return ret;
139 }
140 
Authenticate(const std::string & name,const std::string & authType,const std::string & callerBundleName,const AAFwk::WantParams & options,const sptr<IRemoteObject> & callback)141 ErrCode NapiAppAccountAuthenticator::Authenticate(const std::string &name, const std::string &authType,
142     const std::string &callerBundleName, const AAFwk::WantParams &options, const sptr<IRemoteObject> &callback)
143 {
144     if (jsAuthenticator_.authenticate == nullptr) {
145         return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
146     }
147     uv_loop_s *loop = nullptr;
148     uv_work_t *work = nullptr;
149     JsAuthenticatorParam *param = nullptr;
150     ErrCode result = InitWorkEnv(&loop, &work, &param);
151     if (result != ERR_OK) {
152         return result;
153     }
154     param->authType = authType;
155     param->name = name;
156     param->callerBundleName = callerBundleName;
157     param->options = options;
158     param->callback = callback;
159     work->data = reinterpret_cast<void *>(param);
160     int32_t ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, AuthenticateWork, uv_qos_default);
161     if (ret != 0) {
162         ACCOUNT_LOGE("failed to uv_queue_work_with_qos, errCode: %{public}d", ret);
163         delete work;
164         delete param;
165     }
166     return ret;
167 }
168 
CreateAccountImplicitly(const CreateAccountImplicitlyOptions & options,const sptr<IRemoteObject> & callback)169 ErrCode NapiAppAccountAuthenticator::CreateAccountImplicitly(
170     const CreateAccountImplicitlyOptions &options, const sptr<IRemoteObject> &callback)
171 {
172     if (jsAuthenticator_.createAccountImplicitly == nullptr) {
173         return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
174     }
175     uv_loop_s *loop = nullptr;
176     uv_work_t *work = nullptr;
177     JsAuthenticatorParam *param = nullptr;
178     ErrCode result = InitWorkEnv(&loop, &work, &param);
179     if (result != ERR_OK) {
180         ACCOUNT_LOGE("failed to InitWorkEnv");
181         return result;
182     }
183     param->createOptions = options;
184     param->callback = callback;
185     work->data = reinterpret_cast<void *>(param);
186     int32_t ret =
187         uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, CreateAccountImplicitlyWork, uv_qos_default);
188     if (ret != 0) {
189         ACCOUNT_LOGE("failed to uv_queue_work_with_qos, errCode: %{public}d", ret);
190         delete work;
191         delete param;
192     }
193     return ret;
194 }
195 
Auth(const std::string & name,const std::string & authType,const AAFwk::WantParams & options,const sptr<IRemoteObject> & callback)196 ErrCode NapiAppAccountAuthenticator::Auth(const std::string &name, const std::string &authType,
197     const AAFwk::WantParams &options, const sptr<IRemoteObject> &callback)
198 {
199     if (jsAuthenticator_.auth == nullptr) {
200         return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
201     }
202     uv_loop_s *loop = nullptr;
203     uv_work_t *work = nullptr;
204     JsAuthenticatorParam *param = nullptr;
205     ErrCode result = InitWorkEnv(&loop, &work, &param);
206     if (result != ERR_OK) {
207         return result;
208     }
209     param->authType = authType;
210     param->name = name;
211     param->options = options;
212     param->callback = callback;
213     work->data = reinterpret_cast<void *>(param);
214     int32_t ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, AuthWork, uv_qos_default);
215     if (ret != 0) {
216         ACCOUNT_LOGE("failed to uv_queue_work_with_qos, errCode: %{public}d", ret);
217         delete work;
218         delete param;
219     }
220     return ret;
221 }
222 
VerifyCredential(const std::string & name,const VerifyCredentialOptions & options,const sptr<IRemoteObject> & callback)223 ErrCode NapiAppAccountAuthenticator::VerifyCredential(
224     const std::string &name, const VerifyCredentialOptions &options, const sptr<IRemoteObject> &callback)
225 {
226     if (jsAuthenticator_.verifyCredential == nullptr) {
227         return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
228     }
229     uv_loop_s *loop = nullptr;
230     uv_work_t *work = nullptr;
231     JsAuthenticatorParam *param = nullptr;
232     ErrCode result = InitWorkEnv(&loop, &work, &param);
233     if (result != ERR_OK) {
234         return result;
235     }
236     param->verifyCredOptions = options;
237     param->name = name;
238     param->callback = callback;
239     work->data = reinterpret_cast<void *>(param);
240     int32_t ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, VerifyCredentialWork, uv_qos_default);
241     if (ret != 0) {
242         ACCOUNT_LOGE("failed to uv_queue_work_with_qos, errCode: %{public}d", ret);
243         delete work;
244         delete param;
245     }
246     return ret;
247 }
248 
SetProperties(const SetPropertiesOptions & options,const sptr<IRemoteObject> & callback)249 ErrCode NapiAppAccountAuthenticator::SetProperties(
250     const SetPropertiesOptions &options, const sptr<IRemoteObject> &callback)
251 {
252     if (jsAuthenticator_.setProperties == nullptr) {
253         return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
254     }
255     uv_loop_s *loop = nullptr;
256     uv_work_t *work = nullptr;
257     JsAuthenticatorParam *param = nullptr;
258     ErrCode result = InitWorkEnv(&loop, &work, &param);
259     if (result != ERR_OK) {
260         return result;
261     }
262     param->setPropOptions = options;
263     param->callback = callback;
264     work->data = reinterpret_cast<void *>(param);
265     int32_t ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, SetPropertiesWork, uv_qos_default);
266     if (ret != 0) {
267         ACCOUNT_LOGE("failed to uv_queue_work_with_qos, errCode: %{public}d", ret);
268         delete work;
269         delete param;
270     }
271     return ret;
272 }
273 
CheckAccountLabels(const std::string & name,const std::vector<std::string> & labels,const sptr<IRemoteObject> & callback)274 ErrCode NapiAppAccountAuthenticator::CheckAccountLabels(
275     const std::string &name, const std::vector<std::string> &labels, const sptr<IRemoteObject> &callback)
276 {
277     if (jsAuthenticator_.checkAccountLabels == nullptr) {
278         return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
279     }
280     uv_loop_s *loop = nullptr;
281     uv_work_t *work = nullptr;
282     JsAuthenticatorParam *param = nullptr;
283     ErrCode result = InitWorkEnv(&loop, &work, &param);
284     if (result != ERR_OK) {
285         return result;
286     }
287     param->labels = labels;
288     param->name = name;
289     param->callback = callback;
290     work->data = reinterpret_cast<void *>(param);
291     int32_t ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, CheckAccountLabelsWork, uv_qos_default);
292     if (ret != 0) {
293         ACCOUNT_LOGE("failed to uv_queue_work_with_qos, errCode: %{public}d", ret);
294         delete work;
295         delete param;
296     }
297     return ret;
298 }
299 
IsAccountRemovable(const std::string & name,const sptr<IRemoteObject> & callback)300 ErrCode NapiAppAccountAuthenticator::IsAccountRemovable(const std::string &name, const sptr<IRemoteObject> &callback)
301 {
302     if (jsAuthenticator_.isAccountRemovable == nullptr) {
303         return ERR_APPACCOUNT_SERVICE_OAUTH_SERVICE_EXCEPTION;
304     }
305     uv_loop_s *loop = nullptr;
306     uv_work_t *work = nullptr;
307     JsAuthenticatorParam *param = nullptr;
308     ErrCode result = InitWorkEnv(&loop, &work, &param);
309     if (result != ERR_OK) {
310         return result;
311     }
312     param->name = name;
313     param->callback = callback;
314     work->data = reinterpret_cast<void *>(param);
315     int32_t ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, IsAccountRemovableWork, uv_qos_default);
316     if (ret != 0) {
317         ACCOUNT_LOGE("failed to uv_queue_work_with_qos, errCode: %{public}d", ret);
318         delete work;
319         delete param;
320     }
321     return ret;
322 }
323 
CreateAuthenticatorCallback(napi_env env,sptr<IRemoteObject> nativeCallback)324 napi_value NapiAppAccountAuthenticator::CreateAuthenticatorCallback(
325     napi_env env, sptr<IRemoteObject> nativeCallback)
326 {
327     napi_value global = nullptr;
328     napi_get_global(env, &global);
329     if (global == nullptr) {
330         ACCOUNT_LOGE("failed to get napi global");
331         return nullptr;
332     }
333     napi_value jsAuthCallbackConstructor = nullptr;
334     napi_get_named_property(env, global, "AuthCallbackConstructor_", &jsAuthCallbackConstructor);
335     if (jsAuthCallbackConstructor == nullptr) {
336         ACCOUNT_LOGE("jsAuthCallbackConstructor is null");
337         return nullptr;
338     }
339     napi_value jsCallback = nullptr;
340     NAPI_CALL(env, napi_new_instance(env, jsAuthCallbackConstructor, 0, nullptr, &jsCallback));
341     auto callback = new (std::nothrow) NapiAppAccountAuthenticatorCallback(nativeCallback);
342     if (callback == nullptr) {
343         ACCOUNT_LOGE("failed to create NapiAppAccountAuthenticatorCallback");
344         return nullptr;
345     }
346     napi_status status = napi_wrap(
347         env, jsCallback, callback,
348         [](napi_env env, void *data, void *hint) {
349             ACCOUNT_LOGI("js AuthCallback instance garbage collection");
350             delete (reinterpret_cast<NapiAppAccountAuthenticatorCallback *>(data));
351         },
352         nullptr, nullptr);
353     if (status != napi_ok) {
354         ACCOUNT_LOGE("Wrap js AuthenticatorStub and native callback failed");
355         delete callback;
356         return nullptr;
357     }
358     return jsCallback;
359 }
360 
CreateJsVerifyCredentialOptions(napi_env env,VerifyCredentialOptions & options,napi_value * jsOptions)361 void NapiAppAccountAuthenticator::CreateJsVerifyCredentialOptions(
362     napi_env env, VerifyCredentialOptions &options, napi_value *jsOptions)
363 {
364     NAPI_CALL_RETURN_VOID(env, napi_create_object(env, jsOptions));
365     napi_value strVal;
366     NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, options.credentialType.c_str(), NAPI_AUTO_LENGTH, &strVal));
367     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, *jsOptions, "credentialType", strVal));
368     NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, options.credential.c_str(), NAPI_AUTO_LENGTH, &strVal));
369     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, *jsOptions, "credential", strVal));
370     napi_value jsParam = AppExecFwk::WrapWantParams(env, options.parameters);
371     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, *jsOptions, "parameters", jsParam));
372 }
373 
CreateJsSetPropertiesOptions(napi_env env,SetPropertiesOptions & options,napi_value * jsOptions)374 void NapiAppAccountAuthenticator::CreateJsSetPropertiesOptions(
375     napi_env env, SetPropertiesOptions &options, napi_value *jsOptions)
376 {
377     NAPI_CALL_RETURN_VOID(env, napi_create_object(env, jsOptions));
378     napi_value jsProperties = AppExecFwk::WrapWantParams(env, options.properties);
379     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, *jsOptions, "properties", jsProperties));
380     napi_value jsParam = AppExecFwk::WrapWantParams(env, options.parameters);
381     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, *jsOptions, "parameters", jsParam));
382 }
383 
CallJsFunction(napi_env env,napi_ref funcRef,napi_value * argv,size_t argc)384 void NapiAppAccountAuthenticator::CallJsFunction(
385     napi_env env, napi_ref funcRef, napi_value *argv, size_t argc)
386 {
387     napi_value undefined = nullptr;
388     napi_get_undefined(env, &undefined);
389     napi_value returnVal;
390     napi_value function = nullptr;
391     napi_get_reference_value(env, funcRef, &function);
392     napi_call_function(env, undefined, function, argc, argv, &returnVal);
393 }
394 
AddAccountImplicitlyWork(uv_work_t * work,int status)395 void NapiAppAccountAuthenticator::AddAccountImplicitlyWork(uv_work_t *work, int status)
396 {
397     std::unique_ptr<uv_work_t> workPtr(work);
398     napi_handle_scope scope = nullptr;
399     if (!InitUvWorkCallbackEnv(work, scope)) {
400         return;
401     }
402     std::unique_ptr<JsAuthenticatorParam> param(reinterpret_cast<JsAuthenticatorParam *>(work->data));
403     napi_value jsAuthType;
404     napi_create_string_utf8(param->env, param->authType.c_str(), NAPI_AUTO_LENGTH, &jsAuthType);
405     napi_value jsCallerBundleName;
406     napi_create_string_utf8(param->env, param->callerBundleName.c_str(), NAPI_AUTO_LENGTH, &jsCallerBundleName);
407     napi_value jsOptions = AppExecFwk::WrapWantParams(param->env, param->options);
408     napi_value jsCallback = CreateAuthenticatorCallback(param->env, param->callback);
409     napi_value argv[] = { jsAuthType, jsCallerBundleName, jsOptions, jsCallback};
410     CallJsFunction(param->env, param->jsAuthenticator.addAccountImplicitly, argv, ARGS_SIZE_FOUR);
411     napi_close_handle_scope(param->env, scope);
412 }
413 
AuthenticateWork(uv_work_t * work,int status)414 void NapiAppAccountAuthenticator::AuthenticateWork(uv_work_t *work, int status)
415 {
416     std::unique_ptr<uv_work_t> workPtr(work);
417     napi_handle_scope scope = nullptr;
418     if (!InitUvWorkCallbackEnv(work, scope)) {
419         return;
420     }
421     std::unique_ptr<JsAuthenticatorParam> param(reinterpret_cast<JsAuthenticatorParam *>(work->data));
422     napi_value jsName;
423     napi_create_string_utf8(param->env, param->name.c_str(), NAPI_AUTO_LENGTH, &jsName);
424     napi_value jsAuthType;
425     napi_create_string_utf8(param->env, param->authType.c_str(), NAPI_AUTO_LENGTH, &jsAuthType);
426     napi_value jsCallerBundleName;
427     napi_create_string_utf8(param->env, param->callerBundleName.c_str(), NAPI_AUTO_LENGTH, &jsCallerBundleName);
428     napi_value jsOptions = AppExecFwk::WrapWantParams(param->env, param->options);
429     napi_value jsCallback = CreateAuthenticatorCallback(param->env, param->callback);
430     napi_value argv[] = { jsName, jsAuthType, jsCallerBundleName, jsOptions, jsCallback};
431     CallJsFunction(param->env, param->jsAuthenticator.authenticate, argv, ARGS_SIZE_FIVE);
432     napi_close_handle_scope(param->env, scope);
433 }
434 
CreateAccountImplicitlyWork(uv_work_t * work,int status)435 void NapiAppAccountAuthenticator::CreateAccountImplicitlyWork(uv_work_t *work, int status)
436 {
437     std::unique_ptr<uv_work_t> workPtr(work);
438     napi_handle_scope scope = nullptr;
439     if (!InitUvWorkCallbackEnv(work, scope)) {
440         return;
441     }
442     std::unique_ptr<JsAuthenticatorParam> param(reinterpret_cast<JsAuthenticatorParam *>(work->data));
443     napi_value jsObject = nullptr;
444     napi_create_object(param->env, &jsObject);
445     if (param->createOptions.hasAuthType) {
446         napi_value jsAuthType;
447         napi_create_string_utf8(param->env, param->createOptions.authType.c_str(), NAPI_AUTO_LENGTH, &jsAuthType);
448         napi_set_named_property(param->env, jsObject, "authType", jsAuthType);
449     }
450     if (param->createOptions.hasRequiredLabels) {
451         napi_value jsRequiredLabels = CreateStringArray(param->env, param->createOptions.requiredLabels);
452         napi_set_named_property(param->env, jsObject, "requiredLabels", jsRequiredLabels);
453     }
454     napi_value jsParams = AppExecFwk::WrapWantParams(param->env, param->createOptions.parameters.GetParams());
455     napi_set_named_property(param->env, jsObject, "parameters", jsParams);
456     napi_value jsCallback = CreateAuthenticatorCallback(param->env, param->callback);
457     napi_value argv[] = {jsObject, jsCallback};
458     CallJsFunction(param->env, param->jsAuthenticator.createAccountImplicitly, argv, ARGS_SIZE_TWO);
459     napi_close_handle_scope(param->env, scope);
460 }
461 
AuthWork(uv_work_t * work,int status)462 void NapiAppAccountAuthenticator::AuthWork(uv_work_t *work, int status)
463 {
464     std::unique_ptr<uv_work_t> workPtr(work);
465     napi_handle_scope scope = nullptr;
466     if (!InitUvWorkCallbackEnv(work, scope)) {
467         return;
468     }
469     std::unique_ptr<JsAuthenticatorParam> param(reinterpret_cast<JsAuthenticatorParam *>(work->data));
470     napi_value jsName;
471     napi_create_string_utf8(param->env, param->name.c_str(), NAPI_AUTO_LENGTH, &jsName);
472     napi_value jsAuthType;
473     napi_create_string_utf8(param->env, param->authType.c_str(), NAPI_AUTO_LENGTH, &jsAuthType);
474     napi_value jsOptions = AppExecFwk::WrapWantParams(param->env, param->options);
475     napi_value jsCallback = CreateAuthenticatorCallback(param->env, param->callback);
476     napi_value argv[] = { jsName, jsAuthType, jsOptions, jsCallback};
477     CallJsFunction(param->env, param->jsAuthenticator.auth, argv, ARGS_SIZE_FOUR);
478     napi_close_handle_scope(param->env, scope);
479 }
480 
VerifyCredentialWork(uv_work_t * work,int status)481 void NapiAppAccountAuthenticator::VerifyCredentialWork(uv_work_t *work, int status)
482 {
483     std::unique_ptr<uv_work_t> workPtr(work);
484     napi_handle_scope scope = nullptr;
485     if (!InitUvWorkCallbackEnv(work, scope)) {
486         return;
487     }
488     std::unique_ptr<JsAuthenticatorParam> param(reinterpret_cast<JsAuthenticatorParam *>(work->data));
489     napi_value jsName;
490     napi_create_string_utf8(param->env, param->name.c_str(), NAPI_AUTO_LENGTH, &jsName);
491     napi_value jsOptions;
492     CreateJsVerifyCredentialOptions(param->env, param->verifyCredOptions, &jsOptions);
493     napi_value jsCallback = CreateAuthenticatorCallback(param->env, param->callback);
494     napi_value argv[] = { jsName, jsOptions, jsCallback};
495     CallJsFunction(param->env, param->jsAuthenticator.verifyCredential, argv, ARGS_SIZE_THREE);
496     napi_close_handle_scope(param->env, scope);
497 }
498 
SetPropertiesWork(uv_work_t * work,int status)499 void NapiAppAccountAuthenticator::SetPropertiesWork(uv_work_t *work, int status)
500 {
501     std::unique_ptr<uv_work_t> workPtr(work);
502     napi_handle_scope scope = nullptr;
503     if (!InitUvWorkCallbackEnv(work, scope)) {
504         return;
505     }
506     std::unique_ptr<JsAuthenticatorParam> param(reinterpret_cast<JsAuthenticatorParam *>(work->data));
507     napi_value jsOptions;
508     CreateJsSetPropertiesOptions(param->env, param->setPropOptions, &jsOptions);
509     napi_value jsCallback = CreateAuthenticatorCallback(param->env, param->callback);
510     napi_value argv[] = {jsOptions, jsCallback};
511     CallJsFunction(param->env, param->jsAuthenticator.setProperties, argv, ARGS_SIZE_TWO);
512     napi_close_handle_scope(param->env, scope);
513 }
514 
CheckAccountLabelsWork(uv_work_t * work,int status)515 void NapiAppAccountAuthenticator::CheckAccountLabelsWork(uv_work_t *work, int status)
516 {
517     std::unique_ptr<uv_work_t> workPtr(work);
518     napi_handle_scope scope = nullptr;
519     if (!InitUvWorkCallbackEnv(work, scope)) {
520         return;
521     }
522     std::unique_ptr<JsAuthenticatorParam> param(reinterpret_cast<JsAuthenticatorParam *>(work->data));
523     napi_value jsName;
524     napi_create_string_utf8(param->env, param->name.c_str(), NAPI_AUTO_LENGTH, &jsName);
525     napi_value jsLabels = nullptr;
526     napi_create_array(param->env, &jsLabels);
527     for (size_t i = 0; i < param->labels.size(); ++i) {
528         napi_value value = nullptr;
529         napi_create_string_utf8(param->env, param->labels[i].c_str(), NAPI_AUTO_LENGTH, &value);
530         napi_set_element(param->env, jsLabels, i, value);
531     }
532     napi_value jsCallback = CreateAuthenticatorCallback(param->env, param->callback);
533     napi_value argv[] = {jsName, jsLabels, jsCallback};
534     CallJsFunction(param->env, param->jsAuthenticator.checkAccountLabels, argv, ARGS_SIZE_THREE);
535     napi_close_handle_scope(param->env, scope);
536 }
537 
IsAccountRemovableWork(uv_work_t * work,int status)538 void NapiAppAccountAuthenticator::IsAccountRemovableWork(uv_work_t *work, int status)
539 {
540     std::unique_ptr<uv_work_t> workPtr(work);
541     napi_handle_scope scope = nullptr;
542     if (!InitUvWorkCallbackEnv(work, scope)) {
543         return;
544     }
545     std::unique_ptr<JsAuthenticatorParam> param(reinterpret_cast<JsAuthenticatorParam *>(work->data));
546     napi_value jsName;
547     napi_create_string_utf8(param->env, param->name.c_str(), NAPI_AUTO_LENGTH, &jsName);
548     napi_value jsCallback = CreateAuthenticatorCallback(param->env, param->callback);
549     napi_value argv[] = {jsName, jsCallback};
550     CallJsFunction(param->env, param->jsAuthenticator.isAccountRemovable, argv, ARGS_SIZE_TWO);
551     napi_close_handle_scope(param->env, scope);
552 }
553 
GetJsRemoteObject()554 napi_value NapiAppAccountAuthenticator::GetJsRemoteObject()
555 {
556     return remoteObject_;
557 }
558 
SetJsRemoteObject(napi_value remoteObject)559 void NapiAppAccountAuthenticator::SetJsRemoteObject(napi_value remoteObject)
560 {
561     remoteObject_ = remoteObject;
562 }
563 
GetRemoteObject(napi_env env,napi_callback_info cbInfo)564 napi_value NapiAppAccountAuthenticator::GetRemoteObject(napi_env env, napi_callback_info cbInfo)
565 {
566     napi_value thisVar = nullptr;
567     napi_get_cb_info(env, cbInfo, nullptr, nullptr, &thisVar, nullptr);
568     return thisVar;
569 }
570 
Init(napi_env env,napi_value exports)571 napi_value NapiAppAccountAuthenticator::Init(napi_env env, napi_value exports)
572 {
573     const std::string className = "Authenticator";
574     napi_value constructor = nullptr;
575     napi_define_class(env, className.c_str(), className.length(), JsConstructor, nullptr,
576         0, nullptr, &constructor);
577     NAPI_ASSERT(env, constructor != nullptr, "define js class Authenticator failed");
578     napi_status status = napi_set_named_property(env, exports, className.c_str(), constructor);
579     NAPI_ASSERT(env, status == napi_ok, "set property Authenticator to exports failed");
580     return exports;
581 }
582 
GetNamedFunction(napi_env env,napi_value value,const std::string & name,napi_ref * result)583 napi_status NapiAppAccountAuthenticator::GetNamedFunction(
584     napi_env env, napi_value value, const std::string &name, napi_ref *result)
585 {
586     napi_value jsFunc = nullptr;
587     napi_get_named_property(env, value, name.c_str(), &jsFunc);
588     return napi_create_reference(env, jsFunc, 1, result);
589 }
590 
JsConstructor(napi_env env,napi_callback_info info)591 napi_value NapiAppAccountAuthenticator::JsConstructor(napi_env env, napi_callback_info info)
592 {
593     napi_value thisVar = nullptr;
594     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
595     NAPI_ASSERT(env, status == napi_ok, "get callback info failed");
596     JsAuthenticator jsAuthenticator;
597     GetNamedFunction(env, thisVar, "addAccountImplicitly", &jsAuthenticator.addAccountImplicitly);
598     GetNamedFunction(env, thisVar, "authenticate", &jsAuthenticator.authenticate);
599     GetNamedFunction(env, thisVar, "verifyCredential", &jsAuthenticator.verifyCredential);
600     GetNamedFunction(env, thisVar, "checkAccountLabels", &jsAuthenticator.checkAccountLabels);
601     GetNamedFunction(env, thisVar, "isAccountRemovable", &jsAuthenticator.isAccountRemovable);
602     GetNamedFunction(env, thisVar, "checkAccountRemovable", &jsAuthenticator.isAccountRemovable);
603     GetNamedFunction(env, thisVar, "setProperties", &jsAuthenticator.setProperties);
604     GetNamedFunction(env, thisVar, "createAccountImplicitly", &jsAuthenticator.createAccountImplicitly);
605     GetNamedFunction(env, thisVar, "auth", &jsAuthenticator.auth);
606     napi_value object = nullptr;
607     napi_create_object(env, &object);
608     NAPIRemoteObjectExport(env, object);
609     sptr<NapiAppAccountAuthenticator> authenticator =
610         new (std::nothrow) NapiAppAccountAuthenticator(env, jsAuthenticator);
611     if (authenticator == nullptr) {
612         ACCOUNT_LOGE("failed to construct NapiAppAccountAuthenticator");
613         return nullptr;
614     }
615     napi_value napiRemoteObj = NAPI_ohos_rpc_CreateJsRemoteObject(env, authenticator->AsObject());
616     napi_value func = nullptr;
617     napi_create_function(env, "getRemoteObject", 0, GetRemoteObject, nullptr, &func);
618     NAPI_ASSERT(env, func != nullptr, "create function getRemoteObject failed");
619     status = napi_set_named_property(env, napiRemoteObj, "getRemoteObject", func);
620     NAPI_ASSERT(env, status == napi_ok, "set property getRemoteObject failed");
621     status = napi_add_env_cleanup_hook(env, OnEnvCleanUp, authenticator.GetRefPtr());
622     NAPI_ASSERT(env, status == napi_ok, "add cleanup hook failed");
623     return napiRemoteObj;
624 }
625 }  // namespace AccountJsKit
626 }  // namespace OHOS