• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "napi_app_account_common.h"
16 #include "account_error_no.h"
17 #include "account_log_wrapper.h"
18 #include "app_account_constants.h"
19 #include "app_account_manager.h"
20 #include "napi_common.h"
21 
22 namespace OHOS {
23 namespace AccountJsKit {
24 using namespace OHOS::AccountSA;
25 static const std::int32_t SUBSCRIBE_MAX_PARA = 3;
26 static const std::int32_t UNSUBSCRIBE_MAX_PARA = 2;
27 
28 static const std::string ErrMsgList[] = {
29     "the name is not a string", // index equals to PropertyType::NAME value
30     "the owner is not a string", // index equals to PropertyType::OWNER value
31     "the authType is not a string", // index equals to PropertyType::AUTH_TYPE value
32     "the bundleName is not a string", // index equals to PropertyType::BUNDLE_NAME value
33     "the sessionId is not a string", // index equals to PropertyType::SESSION_ID value
34     "the isVisible is not a bool value", // index equals to PropertyType::IS_VISIBLE value
35     "the token is not a string", // index equals to PropertyType::TOKEN value
36     "the extraInfo is not a string", // index equals to PropertyType::EXTRA_INFO value
37     "the credentialType is not a string", // index equals to PropertyType::CREDENTIAL_TYPE value
38     "the credential is not a string", // index equals to PropertyType::CREDENTIAL value
39     "the key is not a string", // index equals to PropertyType::KEY value
40     "the value is not a string", // index equals to PropertyType::VALUE value
41     "the isAccessible is not a bool value", // index equals to PropertyType::IS_ACCESSIBLE value
42     "the isEnable is not a bool value", // index equals to PropertyType::IS_ENABLE value
43 };
44 
45 std::mutex g_lockForAppAccountSubscribers;
46 std::map<AppAccountManager *, std::vector<AsyncContextForSubscribe *>> g_AppAccountSubscribers;
47 
SubscriberPtr(const AppAccountSubscribeInfo & subscribeInfo)48 SubscriberPtr::SubscriberPtr(const AppAccountSubscribeInfo &subscribeInfo) : AppAccountSubscriber(subscribeInfo)
49 {}
50 
UvQueueWorkOnAppAccountsChanged(uv_work_t * work,int status)51 void UvQueueWorkOnAppAccountsChanged(uv_work_t *work, int status)
52 {
53     std::unique_ptr<uv_work_t> workPtr(work);
54     napi_handle_scope scope = nullptr;
55     if (!InitUvWorkCallbackEnv(work, scope)) {
56         return;
57     }
58     std::unique_ptr<SubscriberAccountsWorker> data(reinterpret_cast<SubscriberAccountsWorker *>(work->data));
59     bool isFound = false;
60     {
61         std::lock_guard<std::mutex> lock(g_lockForAppAccountSubscribers);
62         SubscriberPtr *subscriber = data->subscriber;
63         for (auto objectInfoTmp : g_AppAccountSubscribers) {
64             isFound = std::any_of(objectInfoTmp.second.begin(), objectInfoTmp.second.end(),
65                 [subscriber](const AsyncContextForSubscribe *item) {
66                     return item->subscriber.get() == subscriber;
67                 });
68             if (isFound) {
69                 ACCOUNT_LOGD("app account subscriber has been found.");
70                 break;
71             }
72         }
73     }
74     if (isFound) {
75         napi_value results[ARGS_SIZE_ONE] = {nullptr};
76         GetAppAccountInfoForResult(data->env, data->accounts, results[0]);
77         NapiCallVoidFunction(data->env, results, ARGS_SIZE_ONE, data->ref);
78     }
79     napi_close_handle_scope(data->env, scope);
80 }
81 
OnAccountsChanged(const std::vector<AppAccountInfo> & accounts_)82 void SubscriberPtr::OnAccountsChanged(const std::vector<AppAccountInfo> &accounts_)
83 {
84     uv_loop_s *loop = nullptr;
85     napi_get_uv_event_loop(env_, &loop);
86     if (loop == nullptr) {
87         ACCOUNT_LOGE("loop instance is nullptr");
88         return;
89     }
90     uv_work_t *work = new (std::nothrow) uv_work_t;
91     if (work == nullptr) {
92         ACCOUNT_LOGE("work is null");
93         return;
94     }
95 
96     SubscriberAccountsWorker *subscriberAccountsWorker = new (std::nothrow) SubscriberAccountsWorker(env_);
97     if (subscriberAccountsWorker == nullptr) {
98         ACCOUNT_LOGE("SubscriberAccountsWorker is null");
99         delete work;
100         return;
101     }
102 
103     subscriberAccountsWorker->accounts = accounts_;
104     subscriberAccountsWorker->ref = ref_;
105     subscriberAccountsWorker->subscriber = this;
106 
107     work->data = reinterpret_cast<void *>(subscriberAccountsWorker);
108 
109     uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, UvQueueWorkOnAppAccountsChanged, uv_qos_default);
110 }
111 
SetEnv(const napi_env & env)112 void SubscriberPtr::SetEnv(const napi_env &env)
113 {
114     env_ = env;
115 }
116 
SetCallbackRef(const napi_ref & ref)117 void SubscriberPtr::SetCallbackRef(const napi_ref &ref)
118 {
119     ref_ = ref;
120 }
121 
CheckAccountLabelsOnResultWork(uv_work_t * work,int status)122 void CheckAccountLabelsOnResultWork(uv_work_t *work, int status)
123 {
124     std::unique_ptr<uv_work_t> workPtr(work);
125     napi_handle_scope scope = nullptr;
126     if (!InitUvWorkCallbackEnv(work, scope)) {
127         return;
128     }
129     std::unique_ptr<AuthenticatorCallbackParam> data(reinterpret_cast<AuthenticatorCallbackParam *>(work->data));
130     napi_value checkResult[RESULT_COUNT] = {NapiGetNull(data->context.env)};
131     if (data->context.errCode == ERR_JS_SUCCESS) {
132         bool hasLabels = data->result.GetBoolParam(Constants::KEY_BOOLEAN_RESULT, false);
133         napi_get_boolean(data->context.env, hasLabels, &checkResult[PARAMONE]);
134     } else {
135         checkResult[PARAMZERO] = GetErrorCodeValue(data->context.env, data->context.errCode);
136     }
137     ProcessCallbackOrPromise(data->context.env, &(data->context), checkResult[PARAMZERO], checkResult[PARAMONE]);
138     napi_close_handle_scope(data->context.env, scope);
139 }
140 
CreateJSAppAccountInfo(napi_env env,const std::string & name,const std::string & owner)141 static napi_value CreateJSAppAccountInfo(napi_env env, const std::string &name, const std::string &owner)
142 {
143     napi_value object = nullptr;
144     NAPI_CALL(env, napi_create_object(env, &object));
145     napi_value value = nullptr;
146     NAPI_CALL(env, napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &value));
147     NAPI_CALL(env, napi_set_named_property(env, object, "name", value));
148     NAPI_CALL(env, napi_create_string_utf8(env, owner.c_str(), NAPI_AUTO_LENGTH, &value));
149     NAPI_CALL(env, napi_set_named_property(env, object, "owner", value));
150     return object;
151 }
152 
SelectAccountsOnResultWork(uv_work_t * work,int status)153 void SelectAccountsOnResultWork(uv_work_t *work, int status)
154 {
155     napi_handle_scope scope = nullptr;
156     std::unique_ptr<uv_work_t> workPtr(work);
157     if (!InitUvWorkCallbackEnv(work, scope)) {
158         return;
159     }
160     std::unique_ptr<AuthenticatorCallbackParam> param(reinterpret_cast<AuthenticatorCallbackParam *>(work->data));
161     std::vector<std::string> names = param->result.GetStringArrayParam(Constants::KEY_ACCOUNT_NAMES);
162     std::vector<std::string> owners = param->result.GetStringArrayParam(Constants::KEY_ACCOUNT_OWNERS);
163     if (names.size() != owners.size()) {
164         param->context.errCode = ERR_JS_ACCOUNT_AUTHENTICATOR_SERVICE_EXCEPTION;
165     }
166     napi_env env = param->context.env;
167     napi_value selectResult[RESULT_COUNT] = {0};
168     if (param->context.errCode == ERR_JS_SUCCESS) {
169         napi_create_array(env, &selectResult[PARAMONE]);
170         for (size_t i = 0; i < names.size(); ++i) {
171             napi_value object = CreateJSAppAccountInfo(env, names[i], owners[i]);
172             napi_set_element(env, selectResult[PARAMONE], i, object);
173         }
174     } else {
175         selectResult[PARAMZERO] = GetErrorCodeValue(env, param->context.errCode);
176     }
177     ProcessCallbackOrPromise(env, &(param->context), selectResult[PARAMZERO], selectResult[PARAMONE]);
178     napi_close_handle_scope(env, scope);
179 }
180 
AuthenticatorAsyncCallback(napi_env env,napi_ref ref,napi_deferred deferred,uv_after_work_cb workCb)181 AuthenticatorAsyncCallback::AuthenticatorAsyncCallback(
182     napi_env env, napi_ref ref, napi_deferred deferred, uv_after_work_cb workCb)
183     : env_(env), callbackRef_(ref), deferred_(deferred), workCb_(workCb)
184 {}
185 
~AuthenticatorAsyncCallback()186 AuthenticatorAsyncCallback::~AuthenticatorAsyncCallback()
187 {}
188 
OnResult(int32_t resultCode,const AAFwk::Want & result)189 void AuthenticatorAsyncCallback::OnResult(int32_t resultCode, const AAFwk::Want &result)
190 {
191     {
192         std::lock_guard<std::mutex> lock(mutex_);
193         if (isDone) {
194             return;
195         }
196         isDone = true;
197     }
198     uv_loop_s *loop = nullptr;
199     uv_work_t *work = nullptr;
200     AuthenticatorCallbackParam *param = nullptr;
201     if (!InitAuthenticatorWorkEnv(env_, &loop, &work, &param)) {
202         ACCOUNT_LOGE("failed to init work environment");
203         return;
204     }
205     param->context.env = env_;
206     param->context.callbackRef = callbackRef_;
207     param->context.deferred = deferred_;
208     param->context.errCode = resultCode;
209     param->result = result;
210     work->data = param;
211     if (uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, workCb_, uv_qos_default) == ERR_OK) {
212         return;
213     }
214     param->context.callbackRef = nullptr;
215     ReleaseNapiRefAsync(env_, callbackRef_);
216     delete param;
217     delete work;
218 }
219 
OnRequestRedirected(AAFwk::Want & request)220 void AuthenticatorAsyncCallback::OnRequestRedirected(AAFwk::Want &request)
221 {}
222 
OnRequestContinued()223 void AuthenticatorAsyncCallback::OnRequestContinued()
224 {}
225 
AppAccountManagerCallback(napi_env env,JSAuthCallback callback)226 AppAccountManagerCallback::AppAccountManagerCallback(napi_env env, JSAuthCallback callback)
227     : env_(env), callback_(callback)
228 {}
229 
~AppAccountManagerCallback()230 AppAccountManagerCallback::~AppAccountManagerCallback()
231 {}
232 
UvQueueWorkOnResult(uv_work_t * work,int status)233 void UvQueueWorkOnResult(uv_work_t *work, int status)
234 {
235     std::unique_ptr<uv_work_t> workPtr(work);
236     napi_handle_scope scope = nullptr;
237     if (!InitUvWorkCallbackEnv(work, scope)) {
238         return;
239     }
240     std::unique_ptr<AuthenticatorCallbackParam> data(reinterpret_cast<AuthenticatorCallbackParam *>(work->data));
241     ProcessOnResultCallback(data->env, data->callback, data->resultCode, data->result.GetParams());
242     napi_close_handle_scope(data->env, scope);
243 }
244 
UvQueueWorkOnRequestRedirected(uv_work_t * work,int status)245 void UvQueueWorkOnRequestRedirected(uv_work_t *work, int status)
246 {
247     std::unique_ptr<uv_work_t> workPtr(work);
248     napi_handle_scope scope = nullptr;
249     if (!InitUvWorkCallbackEnv(work, scope)) {
250         return;
251     }
252     std::unique_ptr<AuthenticatorCallbackParam> data(reinterpret_cast<AuthenticatorCallbackParam *>(work->data));
253     napi_value results[ARGS_SIZE_ONE] = {AppExecFwk::WrapWant(data->env, data->request)};
254     NapiCallVoidFunction(data->env, results, ARGS_SIZE_ONE, data->callback.onRequestRedirected);
255     napi_close_handle_scope(data->env, scope);
256 }
257 
UvQueueWorkOnRequestContinued(uv_work_t * work,int status)258 void UvQueueWorkOnRequestContinued(uv_work_t *work, int status)
259 {
260     std::unique_ptr<uv_work_t> workPtr(work);
261     napi_handle_scope scope = nullptr;
262     if (!InitUvWorkCallbackEnv(work, scope)) {
263         return;
264     }
265     std::unique_ptr<AuthenticatorCallbackParam> data(reinterpret_cast<AuthenticatorCallbackParam *>(work->data));
266     NapiCallVoidFunction(data->env, nullptr, 0, data->callback.onRequestContinued);
267     napi_close_handle_scope(data->env, scope);
268 }
269 
OnResult(int32_t resultCode,const AAFwk::Want & result)270 void AppAccountManagerCallback::OnResult(int32_t resultCode, const AAFwk::Want &result)
271 {
272     {
273         std::lock_guard<std::mutex> lock(mutex_);
274         if (isDone) {
275             return;
276         }
277         isDone = true;
278     }
279     uv_loop_s *loop = nullptr;
280     uv_work_t *work = nullptr;
281     AuthenticatorCallbackParam *param = nullptr;
282     if (!InitAuthenticatorWorkEnv(env_, &loop, &work, &param)) {
283         ACCOUNT_LOGE("failed to init authenticator work environment");
284         return;
285     }
286     param->resultCode = resultCode;
287     param->result = result;
288     param->callback = callback_;
289     work->data = reinterpret_cast<void *>(param);
290     uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, UvQueueWorkOnResult, uv_qos_default);
291 }
292 
OnRequestRedirected(AAFwk::Want & request)293 void AppAccountManagerCallback::OnRequestRedirected(AAFwk::Want &request)
294 {
295     uv_loop_s *loop = nullptr;
296     uv_work_t *work = nullptr;
297     AuthenticatorCallbackParam *param = nullptr;
298     if (!InitAuthenticatorWorkEnv(env_, &loop, &work, &param)) {
299         ACCOUNT_LOGE("failed to init authenticator work environment");
300         return;
301     }
302     param->request = request;
303     param->callback = callback_;
304     work->data = reinterpret_cast<void *>(param);
305     uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, UvQueueWorkOnRequestRedirected, uv_qos_default);
306 }
307 
OnRequestContinued()308 void AppAccountManagerCallback::OnRequestContinued()
309 {
310     uv_loop_s *loop = nullptr;
311     uv_work_t *work = nullptr;
312     AuthenticatorCallbackParam *param = nullptr;
313     if (!InitAuthenticatorWorkEnv(env_, &loop, &work, &param)) {
314         ACCOUNT_LOGE("failed to init authenticator work environment");
315         return;
316     }
317     param->callback = callback_;
318     work->data = reinterpret_cast<void *>(param);
319     uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, UvQueueWorkOnRequestContinued, uv_qos_default);
320 }
321 
InitAuthenticatorWorkEnv(napi_env env,uv_loop_s ** loop,uv_work_t ** work,AuthenticatorCallbackParam ** param)322 bool InitAuthenticatorWorkEnv(napi_env env, uv_loop_s **loop, uv_work_t **work,
323     AuthenticatorCallbackParam **param)
324 {
325     napi_get_uv_event_loop(env, loop);
326     if (*loop == nullptr) {
327         ACCOUNT_LOGE("loop instance is nullptr");
328         return false;
329     }
330     *work = new (std::nothrow) uv_work_t;
331     if (*work == nullptr) {
332         ACCOUNT_LOGE("work is null");
333         return false;
334     }
335     *param = new (std::nothrow) AuthenticatorCallbackParam(env);
336     if (*param == nullptr) {
337         ACCOUNT_LOGE("failed to create AuthenticatorCallbackParam");
338         delete *work;
339         *work = nullptr;
340         *loop = nullptr;
341         return false;
342     }
343     return true;
344 }
345 
NapiGetNull(napi_env env)346 napi_value NapiGetNull(napi_env env)
347 {
348     napi_value result = nullptr;
349     napi_get_null(env, &result);
350 
351     return result;
352 }
353 
GetNamedProperty(napi_env env,napi_value obj)354 std::string GetNamedProperty(napi_env env, napi_value obj)
355 {
356     char propValue[MAX_VALUE_LEN] = {0};
357     size_t propLen;
358     if (napi_get_value_string_utf8(env, obj, propValue, MAX_VALUE_LEN, &propLen) != napi_ok) {
359         ACCOUNT_LOGE("Can not get string param from argv");
360     }
361 
362     return std::string(propValue);
363 }
364 
SetNamedProperty(napi_env env,napi_value dstObj,const char * objName,const char * propName)365 void SetNamedProperty(napi_env env, napi_value dstObj, const char *objName, const char *propName)
366 {
367     napi_value prop = nullptr;
368     napi_create_string_utf8(env, objName, NAPI_AUTO_LENGTH, &prop);
369     napi_set_named_property(env, dstObj, propName, prop);
370 }
371 
SetNamedProperty(napi_env env,napi_value dstObj,const int32_t objValue,const char * propName)372 void SetNamedProperty(napi_env env, napi_value dstObj, const int32_t objValue, const char *propName)
373 {
374     napi_value prop = nullptr;
375     napi_create_int32(env, objValue, &prop);
376     napi_set_named_property(env, dstObj, propName, prop);
377 }
378 
GetErrorCodeValue(napi_env env,int errCode)379 napi_value GetErrorCodeValue(napi_env env, int errCode)
380 {
381     napi_value jsObject = nullptr;
382     napi_value jsValue = nullptr;
383     NAPI_CALL(env, napi_create_int32(env, errCode, &jsValue));
384     NAPI_CALL(env, napi_create_object(env, &jsObject));
385     NAPI_CALL(env, napi_set_named_property(env, jsObject, "code", jsValue));
386     return jsObject;
387 }
388 
GetAppAccountInfoForResult(napi_env env,const std::vector<AppAccountInfo> & info,napi_value & result)389 void GetAppAccountInfoForResult(napi_env env, const std::vector<AppAccountInfo> &info, napi_value &result)
390 {
391     NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &result));
392     uint32_t index = 0;
393     for (auto item : info) {
394         std::string name;
395         item.GetName(name);
396         std::string owner;
397         item.GetOwner(owner);
398         napi_value objAppAccountInfo = CreateJSAppAccountInfo(env, name, owner);
399         NAPI_CALL_RETURN_VOID(env, napi_set_element(env, result, index++, objAppAccountInfo));
400     }
401 }
402 
GetAuthenticatorInfoForResult(napi_env env,const AuthenticatorInfo & info,napi_value & result)403 void GetAuthenticatorInfoForResult(napi_env env, const AuthenticatorInfo &info, napi_value &result)
404 {
405     napi_value nOwner = nullptr;
406     napi_create_string_utf8(env, info.owner.c_str(), NAPI_AUTO_LENGTH, &nOwner);
407     napi_set_named_property(env, result, "owner", nOwner);
408 
409     napi_value nIconId = nullptr;
410     napi_create_int32(env, info.iconId, &nIconId);
411     napi_set_named_property(env, result, "iconId", nIconId);
412 
413     napi_value nLabelId = nullptr;
414     napi_create_int32(env, info.labelId, &nLabelId);
415     napi_set_named_property(env, result, "labelId", nLabelId);
416 }
417 
GetOAuthTokenInfoForResult(napi_env env,const std::vector<OAuthTokenInfo> & info,napi_value result)418 void GetOAuthTokenInfoForResult(napi_env env, const std::vector<OAuthTokenInfo> &info, napi_value result)
419 {
420     int32_t index = 0;
421     for (auto item : info) {
422         napi_value objOAuthTokenInfo = nullptr;
423         napi_create_object(env, &objOAuthTokenInfo);
424 
425         napi_value nToken = nullptr;
426         napi_create_string_utf8(env, item.token.c_str(), NAPI_AUTO_LENGTH, &nToken);
427         napi_set_named_property(env, objOAuthTokenInfo, "token", nToken);
428 
429         napi_value nAuthType = nullptr;
430         napi_create_string_utf8(env, item.authType.c_str(), NAPI_AUTO_LENGTH, &nAuthType);
431         napi_set_named_property(env, objOAuthTokenInfo, "authType", nAuthType);
432 
433         napi_set_element(env, result, index, objOAuthTokenInfo);
434         index++;
435     }
436 }
437 
GetOAuthListForResult(napi_env env,const std::set<std::string> & info,napi_value result)438 void GetOAuthListForResult(napi_env env, const std::set<std::string> &info, napi_value result)
439 {
440     int32_t index = 0;
441     for (auto item : info) {
442         napi_value nBundleName = nullptr;
443         napi_create_string_utf8(env, item.c_str(), NAPI_AUTO_LENGTH, &nBundleName);
444         napi_set_element(env, result, index, nBundleName);
445         index++;
446     }
447 }
448 
GetAuthenticatorCallbackForResult(napi_env env,sptr<IRemoteObject> callback,napi_value * result)449 void GetAuthenticatorCallbackForResult(napi_env env, sptr<IRemoteObject> callback, napi_value *result)
450 {
451     if (callback == nullptr) {
452         napi_get_undefined(env, result);
453         return;
454     }
455     napi_value remote;
456     napi_create_int64(env, reinterpret_cast<int64_t>(callback.GetRefPtr()), &remote);
457     napi_value global = nullptr;
458     napi_get_global(env, &global);
459     if (global == nullptr) {
460         ACCOUNT_LOGE("get napi global failed");
461         return;
462     }
463     napi_value jsAuthCallbackConstructor = nullptr;
464     napi_get_named_property(env, global, "AuthCallbackConstructor_", &jsAuthCallbackConstructor);
465     if (jsAuthCallbackConstructor == nullptr) {
466         ACCOUNT_LOGE("jsAuthCallbackConstructor is null");
467         return;
468     }
469     size_t argc = ARGS_SIZE_ONE;
470     napi_value argv[ARGS_SIZE_ONE] = { remote };
471     napi_new_instance(env, jsAuthCallbackConstructor, argc, argv, result);
472 }
473 
ParseContextWithExInfo(napi_env env,napi_callback_info cbInfo,AppAccountAsyncContext * asyncContext)474 bool ParseContextWithExInfo(napi_env env, napi_callback_info cbInfo, AppAccountAsyncContext *asyncContext)
475 {
476     size_t argc = ARGS_SIZE_THREE;
477     napi_value argv[ARGS_SIZE_THREE] = {0};
478     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
479     if (argc < ARGS_SIZE_ONE) {
480         asyncContext->errMsg = "the number of parameters should be at least 1";
481         return false;
482     }
483     for (size_t i = 0; i < argc; i++) {
484         napi_valuetype valueType = napi_undefined;
485         napi_typeof(env, argv[i], &valueType);
486         if (i == 0 && valueType == napi_string) {
487             GetStringProperty(env, argv[i], asyncContext->name);
488         } else if (i == 1 && valueType == napi_string) {
489             GetStringProperty(env, argv[i], asyncContext->extraInfo);
490         } else if (i == 1 && valueType == napi_function) {
491             napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
492             break;
493         } else if (i == PARAMTWO && valueType == napi_function) {
494             napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef);
495             break;
496         } else {
497             ACCOUNT_LOGE("Type matching failed");
498             asyncContext->errMsg = "the type of param " + std::to_string(i) + " is incorrect";
499             return false;
500         }
501     }
502     return true;
503 }
504 
ParseArguments(napi_env env,napi_value * argv,const napi_valuetype * valueTypes,size_t argc)505 bool ParseArguments(napi_env env, napi_value *argv, const napi_valuetype *valueTypes, size_t argc)
506 {
507     napi_valuetype valuetype = napi_undefined;
508     for (size_t i = 0; i < argc; ++i) {
509         napi_typeof(env, argv[i], &valuetype);
510         if (valuetype != valueTypes[i]) {
511             argv[i] = nullptr;
512             return false;
513         }
514     }
515     return true;
516 }
517 
ParseContextForAuth(napi_env env,napi_callback_info cbInfo,OAuthAsyncContext * context)518 bool ParseContextForAuth(napi_env env, napi_callback_info cbInfo, OAuthAsyncContext *context)
519 {
520     std::string abilityName;
521     GetAbilityName(env, abilityName);
522     context->options.SetParam(Constants::KEY_CALLER_ABILITY_NAME, abilityName);
523     size_t argc = ARGS_SIZE_FIVE;
524     napi_value argv[ARGS_SIZE_FIVE] = {0};
525     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
526     if (argc < ARGS_SIZE_FOUR) {
527         context->errMsg = "the number of parameters should be at least 4";
528         return false;
529     }
530     if (!GetStringProperty(env, argv[0], context->name)) {
531         context->errMsg = "the name is not string";
532         return false;
533     }
534     if (!GetStringProperty(env, argv[1], context->owner)) {
535         context->errMsg = "the owner is not string";
536         return false;
537     }
538     if (!GetStringProperty(env, argv[PARAMTWO], context->authType)) {
539         context->errMsg = "the authType is not string";
540         return false;
541     }
542     AAFwk::WantParams params;
543     if (argc == ARGS_SIZE_FIVE) {
544         napi_valuetype valueType = napi_undefined;
545         napi_typeof(env, argv[PARAMTHREE], &valueType);
546         if ((valueType == napi_undefined) || (valueType == napi_null)) {
547             ACCOUNT_LOGI("the options is undefined or null");
548         } else {
549             if (!AppExecFwk::UnwrapWantParams(env, argv[PARAMTHREE], params)) {
550                 ACCOUNT_LOGE("UnwrapWantParams failed");
551                 context->errMsg = "the type of options is incorrect";
552                 return false;
553             }
554         }
555     }
556     context->options.SetParams(params);
557     context->options.SetParam(Constants::KEY_CALLER_ABILITY_NAME, abilityName);
558     JSAuthCallback callback;
559     if (!ParseJSAuthCallback(env, argv[argc - 1], callback)) {
560         context->errMsg = "the type of authCallback is incorrect";
561         return false;
562     }
563     context->appAccountMgrCb = new (std::nothrow) AppAccountManagerCallback(env, callback);
564     return true;
565 }
566 
ParseContextForAuthenticate(napi_env env,napi_callback_info cbInfo,OAuthAsyncContext * asyncContext,size_t argc)567 void ParseContextForAuthenticate(napi_env env, napi_callback_info cbInfo, OAuthAsyncContext *asyncContext, size_t argc)
568 {
569     napi_value argv[ARGS_SIZE_FIVE] = {0};
570     napi_value thisVar;
571     napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr);
572     napi_valuetype valueTypes[ARGS_SIZE_FIVE] = {napi_string, napi_string, napi_string, napi_object, napi_object};
573     size_t index = 0;
574     if (argc == ARGS_SIZE_FIVE) {
575         ParseArguments(env, argv, valueTypes, argc);
576         asyncContext->name = GetNamedProperty(env, argv[index++]);
577     } else {
578         argc = ARGS_SIZE_FOUR;
579         ParseArguments(env, argv, &valueTypes[1], argc);
580     }
581     asyncContext->owner = GetNamedProperty(env, argv[index++]);
582     asyncContext->authType = GetNamedProperty(env, argv[index++]);
583     AAFwk::WantParams params;
584     if (!AppExecFwk::UnwrapWantParams(env, argv[index++], params)) {
585         ACCOUNT_LOGE("UnwrapWantParams failed");
586     }
587     asyncContext->options.SetParams(params);
588     std::string abilityName;
589     GetAbilityName(env, abilityName);
590     asyncContext->options.SetParam(Constants::KEY_CALLER_ABILITY_NAME, abilityName);
591     JSAuthCallback callback;
592     ParseJSAuthCallback(env, argv[index], callback);
593     asyncContext->appAccountMgrCb = new (std::nothrow) AppAccountManagerCallback(env, callback);
594 }
595 
ParseContextOAuthProperty(napi_env env,napi_value & argv,PropertyType type,OAuthAsyncContext * asyncContext)596 bool ParseContextOAuthProperty(napi_env env, napi_value &argv, PropertyType type, OAuthAsyncContext *asyncContext)
597 {
598     bool result = false;
599     switch (type) {
600         case PropertyType::NAME :
601             result = GetStringProperty(env, argv, asyncContext->name);
602             break;
603         case PropertyType::OWNER :
604             result = GetStringProperty(env, argv, asyncContext->owner);
605             break;
606         case PropertyType::AUTH_TYPE :
607             result = GetStringProperty(env, argv, asyncContext->authType);
608             break;
609         case PropertyType::BUNDLE_NAME :
610             result = GetStringProperty(env, argv, asyncContext->bundleName);
611             break;
612         case PropertyType::SESSION_ID :
613             result = GetStringProperty(env, argv, asyncContext->sessionId);
614             break;
615         case PropertyType::IS_VISIBLE :
616             result = (napi_get_value_bool(env, argv, &asyncContext->isVisible) == napi_ok) ? true : false;
617             break;
618         case PropertyType::TOKEN :
619             result = GetStringProperty(env, argv, asyncContext->token);
620             break;
621         // when new PropertyType is added, new error message need to be added in ErrMsgList.
622         default:
623             break;
624     }
625     if (!result) {
626         asyncContext->errMsg = ErrMsgList[type];
627     }
628     return result;
629 }
630 
ParseContextForOAuth(napi_env env,napi_callback_info cbInfo,OAuthAsyncContext * asyncContext,const std::vector<PropertyType> & propertyList,napi_value * result)631 bool ParseContextForOAuth(napi_env env, napi_callback_info cbInfo,
632     OAuthAsyncContext *asyncContext, const std::vector<PropertyType> &propertyList, napi_value *result)
633 {
634     // the inner caller promise posInfo.argcSize to be at least 1
635     size_t argcSize = propertyList.size() + 1;
636     size_t argc = argcSize;
637     napi_value argv[ARGS_SIZE_MAX] = {0};
638     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
639     if (argc < argcSize - 1) {
640         asyncContext->errMsg = "the number of parameter should be at least " + std::to_string(argcSize - 1);
641         return false;
642     }
643     if ((argc == argcSize) && (!GetCallbackProperty(env, argv[argcSize - 1], asyncContext->callbackRef, 1))) {
644         asyncContext->errMsg = "the callback is not a function";
645         return false;
646     }
647     for (uint32_t i = 0; i < propertyList.size(); i++) {
648         if (!ParseContextOAuthProperty(env, argv[i], propertyList[i], asyncContext)) {
649             return false;
650         }
651     }
652     if (asyncContext->callbackRef == nullptr) {
653         napi_create_promise(env, &asyncContext->deferred, result);
654     } else {
655         napi_get_undefined(env, result);
656     }
657     return true;
658 }
659 
ParseAppAccountProperty(napi_env env,napi_value & argv,PropertyType type,AppAccountAsyncContext * asyncContext)660 bool ParseAppAccountProperty(napi_env env, napi_value &argv, PropertyType type, AppAccountAsyncContext *asyncContext)
661 {
662     bool result = false;
663     switch (type) {
664         case PropertyType::NAME :
665             result = GetStringProperty(env, argv, asyncContext->name);
666             break;
667         case PropertyType::OWNER :
668             result = GetStringProperty(env, argv, asyncContext->owner);
669             break;
670         case PropertyType::EXTRA_INFO :
671             result = GetStringProperty(env, argv, asyncContext->extraInfo);
672             break;
673         case PropertyType::BUNDLE_NAME :
674             result = GetStringProperty(env, argv, asyncContext->bundleName);
675             break;
676         case PropertyType::CREDENTIAL_TYPE :
677             result = GetStringProperty(env, argv, asyncContext->credentialType);
678             break;
679         case PropertyType::CREDENTIAL :
680             result = GetStringProperty(env, argv, asyncContext->credential);
681             break;
682         case PropertyType::KEY :
683             result = GetStringProperty(env, argv, asyncContext->key);
684             break;
685         case PropertyType::VALUE :
686             result = GetStringProperty(env, argv, asyncContext->value);
687             break;
688         case PropertyType::IS_ACCESSIBLE :
689             result = (napi_get_value_bool(env, argv, &asyncContext->isAccessible) == napi_ok) ? true : false;
690             break;
691         case PropertyType::IS_ENABLE :
692             result = (napi_get_value_bool(env, argv, &asyncContext->isEnable) == napi_ok) ? true : false;
693             break;
694         default:
695             break;
696     }
697     return result;
698 }
699 
ParseContextForAppAccount(napi_env env,napi_callback_info cbInfo,AppAccountAsyncContext * context,const std::vector<PropertyType> & propertyList,napi_value * result)700 bool ParseContextForAppAccount(napi_env env, napi_callback_info cbInfo,
701     AppAccountAsyncContext *context, const std::vector<PropertyType> &propertyList, napi_value *result)
702 {
703     size_t argcSize = propertyList.size() + 1;
704     size_t argc = argcSize;
705     napi_value argv[ARGS_SIZE_MAX] = {0};
706     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
707     if (argc < (argcSize - 1)) {
708         context->errMsg = "the number of parameter should be at least " + std::to_string(argcSize - 1);
709         return false;
710     }
711     if ((argc == argcSize) && (!GetCallbackProperty(env, argv[argcSize - 1], context->callbackRef, 1))) {
712         context->errMsg = "the callback is not a function";
713         return false;
714     }
715     for (size_t i = 0; i < propertyList.size(); i++) {
716         if (!ParseAppAccountProperty(env, argv[i], propertyList[i], context)) {
717             context->errMsg = ErrMsgList[propertyList[i]];
718             return false;
719         }
720     }
721     if (context->callbackRef == nullptr) {
722         napi_create_promise(env, &context->deferred, result);
723     } else {
724         napi_get_undefined(env, result);
725     }
726     return true;
727 }
728 
ParseContextCBArray(napi_env env,napi_callback_info cbInfo,GetAccountsAsyncContext * asyncContext)729 bool ParseContextCBArray(napi_env env, napi_callback_info cbInfo, GetAccountsAsyncContext *asyncContext)
730 {
731     size_t argc = ARGS_SIZE_ONE;
732     napi_value argv[ARGS_SIZE_ONE] = {0};
733     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
734     if ((argc == ARGS_SIZE_ONE) && (!GetCallbackProperty(env, argv[0], asyncContext->callbackRef, 1))) {
735         asyncContext->errMsg = "the callback is not a function";
736         return false;
737     }
738     return true;
739 }
740 
ParseContextWithStrCBArray(napi_env env,napi_callback_info cbInfo,GetAccountsAsyncContext * asyncContext)741 bool ParseContextWithStrCBArray(napi_env env, napi_callback_info cbInfo, GetAccountsAsyncContext *asyncContext)
742 {
743     size_t argc = ARGS_SIZE_TWO;
744     napi_value argv[ARGS_SIZE_TWO] = {0};
745     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
746     if (argc < ARGS_SIZE_ONE) {
747         asyncContext->errMsg = "the number of parameter should be at least 2";
748         return false;
749     }
750     if ((argc == ARGS_SIZE_TWO) && (!GetCallbackProperty(env, argv[1], asyncContext->callbackRef, 1))) {
751         asyncContext->errMsg = "the callback is not a function";
752         return false;
753     }
754     if (!GetStringProperty(env, argv[0], asyncContext->owner)) {
755         asyncContext->errMsg = "the owner is not a string";
756         return false;
757     }
758     return true;
759 }
760 
ParseParametersBySubscribe(const napi_env & env,napi_callback_info cbInfo,AsyncContextForSubscribe * context)761 bool ParseParametersBySubscribe(const napi_env &env, napi_callback_info cbInfo, AsyncContextForSubscribe *context)
762 {
763     size_t argc = SUBSCRIBE_MAX_PARA;
764     napi_value argv[SUBSCRIBE_MAX_PARA] = {nullptr};
765     napi_value thisVar = nullptr;
766     napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr);
767     context->errCode = ERR_JS_PARAMETER_ERROR;
768     if (argc != SUBSCRIBE_MAX_PARA) {
769         context->errMsg = "the number of parameters should be 3";
770         return false;
771     }
772     if (!GetStringProperty(env, argv[0], context->type)) {
773         context->errMsg = "the type is not a string";
774         return false;
775     }
776     if ((context->type != "change") && (context->type != "accountChange")) {
777         context->errMsg = "the type is invalid";
778         context->errCode = ERR_JS_INVALID_PARAMETER;
779         return false;
780     }
781     bool isArray = false;
782     napi_is_array(env, argv[1], &isArray);
783     if (!isArray) {
784         context->errMsg = "the owners is not a string array";
785         return false;
786     }
787     uint32_t length = 0;
788     napi_get_array_length(env, argv[1], &length);
789     if (length == 0) {
790         context->errMsg = "the owers should not be empty";
791         context->errCode = ERR_JS_INVALID_PARAMETER;
792         return false;
793     }
794     for (size_t i = 0; i < length; i++) {
795         napi_value ownerStr = nullptr;
796         napi_get_element(env, argv[1], i, &ownerStr);
797         std::string owner;
798         if (!GetStringProperty(env, ownerStr, owner)) {
799             context->errMsg = "the owners is not a string array";
800             return false;
801         }
802         context->owners.emplace_back(owner);
803     }
804     if (!GetCallbackProperty(env, argv[PARAMTWO], context->callbackRef, 1)) {
805         context->errMsg = "the callback is not a function";
806         return false;
807     }
808     napi_unwrap(env, thisVar, reinterpret_cast<void **>(&context->appAccountManager));
809     return true;
810 }
811 
GetSubscriberByUnsubscribe(const napi_env & env,std::vector<std::shared_ptr<SubscriberPtr>> & subscribers,AsyncContextForUnsubscribe * asyncContextForOff,bool & isFind)812 napi_value GetSubscriberByUnsubscribe(const napi_env &env, std::vector<std::shared_ptr<SubscriberPtr>> &subscribers,
813     AsyncContextForUnsubscribe *asyncContextForOff, bool &isFind)
814 {
815     napi_value result;
816 
817     {
818         std::lock_guard<std::mutex> lock(g_lockForAppAccountSubscribers);
819 
820         for (auto subscriberInstance : g_AppAccountSubscribers) {
821             if (subscriberInstance.first == asyncContextForOff->appAccountManager) {
822                 for (auto item : subscriberInstance.second) {
823                     subscribers.emplace_back(item->subscriber);
824                 }
825                 isFind = true;
826                 break;
827             }
828         }
829     }
830 
831     NAPI_CALL(env, napi_get_boolean(env, isFind, &result));
832     return result;
833 }
834 
ParseParametersByUnsubscribe(const napi_env & env,napi_callback_info cbInfo,AsyncContextForUnsubscribe * context)835 bool ParseParametersByUnsubscribe(
836     const napi_env &env, napi_callback_info cbInfo, AsyncContextForUnsubscribe *context)
837 {
838     size_t argc = UNSUBSCRIBE_MAX_PARA;
839     napi_value argv[UNSUBSCRIBE_MAX_PARA] = {nullptr};
840     napi_value thisVar = nullptr;
841     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, NULL), false);
842     if (argc < 1) {
843         context->errMsg = "the number of parameters should be at least 1";
844         context->errCode = ERR_JS_PARAMETER_ERROR;
845         return false;
846     }
847     if (!GetStringProperty(env, argv[0], context->type)) {
848         context->errMsg = "the type is not a string";
849         context->errCode = ERR_JS_PARAMETER_ERROR;
850         return false;
851     }
852     if ((context->type != "change") && (context->type != "accountChange")) {
853         context->errMsg = "the type is invalid";
854         context->errCode = ERR_JS_INVALID_PARAMETER;
855         return false;
856     }
857     if ((argc == UNSUBSCRIBE_MAX_PARA) && (!GetCallbackProperty(env, argv[1], context->callbackRef, 1))) {
858         context->errMsg = "the callback is not a function";
859         context->errCode = ERR_JS_PARAMETER_ERROR;
860         return false;
861     }
862     napi_unwrap(env, thisVar, reinterpret_cast<void **>(&context->appAccountManager));
863     if (context->appAccountManager == nullptr) {
864         ACCOUNT_LOGE("appAccountManager is nullptr");
865         return false;
866     }
867     context->argc = argc;
868     return true;
869 }
870 
UnsubscribeExecuteCB(napi_env env,void * data)871 void UnsubscribeExecuteCB(napi_env env, void *data)
872 {
873     AsyncContextForUnsubscribe *asyncContextForOff = reinterpret_cast<AsyncContextForUnsubscribe *>(data);
874     for (auto offSubscriber : asyncContextForOff->subscribers) {
875         int errCode = AppAccountManager::UnsubscribeAppAccount(offSubscriber);
876         ACCOUNT_LOGD("Unsubscribe errcode parameter is %{public}d", errCode);
877     }
878 }
879 
UnsubscribeCallbackCompletedCB(napi_env env,napi_status status,void * data)880 void UnsubscribeCallbackCompletedCB(napi_env env, napi_status status, void *data)
881 {
882     AsyncContextForUnsubscribe *asyncContextForOff = reinterpret_cast<AsyncContextForUnsubscribe *>(data);
883     if (asyncContextForOff == nullptr) {
884         return;
885     }
886 
887     if (asyncContextForOff->argc >= UNSUBSCRIBE_MAX_PARA) {
888         napi_value result = nullptr;
889         napi_get_null(env, &result);
890         napi_value results[ARGS_SIZE_ONE] = {result};
891         NapiCallVoidFunction(env, results, ARGS_SIZE_ONE, asyncContextForOff->callbackRef);
892     }
893 
894     {
895         std::lock_guard<std::mutex> lock(g_lockForAppAccountSubscribers);
896         ACCOUNT_LOGD("Erase before g_AppAccountSubscribers.size = %{public}zu", g_AppAccountSubscribers.size());
897         // erase the info from map
898         auto subscribe = g_AppAccountSubscribers.find(asyncContextForOff->appAccountManager);
899         if (subscribe != g_AppAccountSubscribers.end()) {
900             for (auto offCBInfo : subscribe->second) {
901                 delete offCBInfo;
902             }
903             g_AppAccountSubscribers.erase(subscribe);
904         }
905         ACCOUNT_LOGD("Erase end g_AppAccountSubscribers.size = %{public}zu", g_AppAccountSubscribers.size());
906     }
907     delete asyncContextForOff;
908 }
909 
ParseVerifyCredentialOptions(napi_env env,napi_value object,VerifyCredentialOptions & options)910 bool ParseVerifyCredentialOptions(napi_env env, napi_value object, VerifyCredentialOptions &options)
911 {
912     napi_valuetype valueType = napi_undefined;
913     napi_typeof(env, object, &valueType);
914     if ((valueType == napi_undefined) || (valueType == napi_null)) {
915         ACCOUNT_LOGI("the VerifyCredentialOptions is undefined or null");
916         return true;
917     }
918     if (valueType != napi_object) {
919         ACCOUNT_LOGE("the type of object is not napi_object");
920         return false;
921     }
922     if (!GetOptionalStringPropertyByKey(env, object, "credential", options.credential)) {
923         ACCOUNT_LOGE("failed to get options's credential property");
924         return false;
925     }
926     if (!GetOptionalStringPropertyByKey(env, object, "credentialType", options.credentialType)) {
927         ACCOUNT_LOGE("failed to get options's credentialType property");
928         return false;
929     }
930     napi_value value = nullptr;
931     bool hasProp = false;
932     napi_has_named_property(env, object, "parameters", &hasProp);
933     if (hasProp) {
934         napi_get_named_property(env, object, "parameters", &value);
935         valueType = napi_undefined;
936         napi_typeof(env, value, &valueType);
937         if ((valueType == napi_undefined) || (valueType == napi_null)) {
938             ACCOUNT_LOGI("the parameters is undefined or null");
939         } else {
940             if (!AppExecFwk::UnwrapWantParams(env, value, options.parameters)) {
941                 return false;
942             }
943         }
944     }
945     return true;
946 }
947 
ParseOptionalStringVectorByKey(napi_env env,napi_value object,const char * key,bool & result,std::vector<std::string> & array)948 static bool ParseOptionalStringVectorByKey(
949     napi_env env, napi_value object, const char* key, bool &result, std::vector<std::string> &array)
950 {
951     napi_has_named_property(env, object, key, &result);
952     if (result) {
953         napi_value value = nullptr;
954         napi_get_named_property(env, object, key, &value);
955         napi_valuetype valueType = napi_undefined;
956         napi_typeof(env, value, &valueType);
957         if ((valueType == napi_undefined) || (valueType == napi_null)) {
958             result = false;
959             ACCOUNT_LOGI("the %{public}s is undefined or null", key);
960             return true;
961         }
962         if (!ParseStringVector(env, value, array)) {
963             return false;
964         }
965     }
966     return true;
967 }
968 
ParseSelectAccountsOptions(napi_env env,napi_value object,SelectAccountsOptions & options)969 bool ParseSelectAccountsOptions(napi_env env, napi_value object, SelectAccountsOptions &options)
970 {
971     napi_valuetype valueType = napi_undefined;
972     napi_typeof(env, object, &valueType);
973     if (valueType != napi_object) {
974         return false;
975     }
976     napi_value value = nullptr;
977     napi_has_named_property(env, object, "allowedAccounts", &options.hasAccounts);
978     if (options.hasAccounts) {
979         napi_get_named_property(env, object, "allowedAccounts", &value);
980         valueType = napi_undefined;
981         napi_typeof(env, value, &valueType);
982         if ((valueType == napi_undefined) || (valueType == napi_null)) {
983             options.hasAccounts = false;
984             ACCOUNT_LOGI("the allowedAccounts is undefined or null");
985         } else {
986             if (!ParseAccountVector(env, value, options.allowedAccounts)) {
987                 return false;
988             }
989         }
990     }
991     if (!ParseOptionalStringVectorByKey(env, object, "allowedOwners", options.hasOwners, options.allowedOwners)) {
992         return false;
993     }
994     if (!ParseOptionalStringVectorByKey(env, object, "requiredLabels", options.hasLabels, options.requiredLabels)) {
995         return false;
996     }
997     return true;
998 }
999 
ParseSetPropertiesOptions(napi_env env,napi_value object,SetPropertiesOptions & options)1000 bool ParseSetPropertiesOptions(napi_env env, napi_value object, SetPropertiesOptions &options)
1001 {
1002     napi_valuetype valueType = napi_undefined;
1003     napi_typeof(env, object, &valueType);
1004     if ((valueType == napi_undefined) || (valueType == napi_null)) {
1005         ACCOUNT_LOGI("the SetPropertiesOptions is undefined or null");
1006         return true;
1007     }
1008     if (valueType != napi_object) {
1009         return false;
1010     }
1011     napi_value value = nullptr;
1012     bool hasProp = false;
1013     napi_has_named_property(env, object, "properties", &hasProp);
1014     if (hasProp) {
1015         napi_get_named_property(env, object, "properties", &value);
1016         valueType = napi_undefined;
1017         napi_typeof(env, value, &valueType);
1018         if ((valueType == napi_undefined) || (valueType == napi_null)) {
1019             ACCOUNT_LOGI("the properties is undefined or null");
1020         } else {
1021             if (!AppExecFwk::UnwrapWantParams(env, value, options.properties)) {
1022                 return false;
1023             }
1024         }
1025     }
1026     hasProp = false;
1027     napi_has_named_property(env, object, "parameters", &hasProp);
1028     if (hasProp) {
1029         napi_get_named_property(env, object, "parameters", &value);
1030         valueType = napi_undefined;
1031         napi_typeof(env, value, &valueType);
1032         if ((valueType == napi_undefined) || (valueType == napi_null)) {
1033             ACCOUNT_LOGI("the parameters is undefined or null");
1034         } else {
1035             if (!AppExecFwk::UnwrapWantParams(env, value, options.parameters)) {
1036                 return false;
1037             }
1038         }
1039     }
1040     return true;
1041 }
1042 
GetNamedFunction(napi_env env,napi_value object,const std::string & name,napi_ref & funcRef)1043 bool GetNamedFunction(napi_env env, napi_value object, const std::string &name, napi_ref &funcRef)
1044 {
1045     napi_value value = nullptr;
1046     napi_get_named_property(env, object, name.c_str(), &value);
1047     return GetCallbackProperty(env, value, funcRef, 1);
1048 }
1049 
ParseJSAuthCallback(napi_env env,napi_value object,JSAuthCallback & callback)1050 bool ParseJSAuthCallback(napi_env env, napi_value object, JSAuthCallback &callback)
1051 {
1052     napi_valuetype valueType = napi_undefined;
1053     napi_typeof(env, object, &valueType);
1054     if (valueType != napi_object) {
1055         ACCOUNT_LOGE("the type of callback is invalid");
1056         return false;
1057     }
1058     bool hasProp = false;
1059     napi_has_named_property(env, object, "onRequestContinued", &hasProp);
1060     if (hasProp) {
1061         napi_value value = nullptr;
1062         napi_get_named_property(env, object, "onRequestContinued", &value);
1063         valueType = napi_undefined;
1064         napi_typeof(env, value, &valueType);
1065         if ((valueType == napi_undefined) || (valueType == napi_null)) {
1066             ACCOUNT_LOGI("the parameters is undefined or null");
1067         } else {
1068             if (!GetNamedFunction(env, object, "onRequestContinued", callback.onRequestContinued)) {
1069                 ACCOUNT_LOGE("the onRequestContinued is invalid");
1070                 return false;
1071             }
1072         }
1073     }
1074     return GetNamedFunction(env, object, "onResult", callback.onResult) ||
1075         GetNamedFunction(env, object, "onRequestRedirected", callback.onRequestRedirected);
1076 }
1077 
ParseContextForVerifyCredential(napi_env env,napi_callback_info info,VerifyCredentialContext * context)1078 bool ParseContextForVerifyCredential(napi_env env, napi_callback_info info, VerifyCredentialContext *context)
1079 {
1080     size_t argc = ARGS_SIZE_FOUR;
1081     napi_value argv[ARGS_SIZE_FOUR] = {0};
1082     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1083     if (argc < ARGS_SIZE_THREE) {
1084         context->errMsg = "the number of parameter shoulde be at least 3";
1085         return false;
1086     }
1087     int32_t index = 0;
1088     if (!GetStringProperty(env, argv[index++], context->name)) {
1089         context->errMsg = "the name is not a string";
1090         return false;
1091     }
1092     if (!GetStringProperty(env, argv[index++], context->owner)) {
1093         context->errMsg = "the owner is not a string";
1094         return false;
1095     }
1096     if ((argc == ARGS_SIZE_FOUR) && (!ParseVerifyCredentialOptions(env, argv[index++], context->options))) {
1097         context->errMsg = "the type of options is not VerifyCredentialOptions";
1098         return false;
1099     }
1100     if (!ParseJSAuthCallback(env, argv[index], context->callback)) {
1101         context->errMsg = "the type of callback is not AuthCallback";
1102         return false;
1103     }
1104     return true;
1105 }
1106 
ParseContextForSetProperties(napi_env env,napi_callback_info info,SetPropertiesContext * context)1107 bool ParseContextForSetProperties(napi_env env, napi_callback_info info, SetPropertiesContext *context)
1108 {
1109     size_t argc = ARGS_SIZE_THREE;
1110     napi_value argv[ARGS_SIZE_THREE] = {0};
1111     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1112     if (argc < ARGS_SIZE_TWO) {
1113         context->errMsg = "the number of parameter shoulde be at least 2";
1114         return false;
1115     }
1116     int32_t index = 0;
1117     if (!GetStringProperty(env, argv[index++], context->owner)) {
1118         context->errMsg = "the owner is not a string";
1119         return false;
1120     }
1121     if (argc == ARGS_SIZE_THREE) {
1122         if (!ParseSetPropertiesOptions(env, argv[index++], context->options)) {
1123             context->errMsg = "the type of options is not SetPropertiesOptions";
1124             return false;
1125         }
1126     }
1127     if (!ParseJSAuthCallback(env, argv[index], context->callback)) {
1128         context->errMsg = "the type of callback is not AuthCallback";
1129         return false;
1130     }
1131     return true;
1132 }
1133 
ParseContextForSelectAccount(napi_env env,napi_callback_info info,SelectAccountsContext * context)1134 bool ParseContextForSelectAccount(napi_env env, napi_callback_info info, SelectAccountsContext *context)
1135 {
1136     size_t argc = ARGS_SIZE_TWO;
1137     napi_value argv[ARGS_SIZE_TWO] = {0};
1138     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1139     if (argc < ARGS_SIZE_ONE) {
1140         context->errMsg = "the number of parameter shoulde be at least 1";
1141         return false;
1142     }
1143     if ((argc == ARGS_SIZE_TWO) && (!GetCallbackProperty(env, argv[PARAMONE], context->callbackRef, PARAMTWO))) {
1144         context->errMsg = "the callback is not a function";
1145         return false;
1146     }
1147     if (!ParseSelectAccountsOptions(env, argv[0], context->options)) {
1148         context->errMsg = "the type of options is not SelectAccountsOptions";
1149         return false;
1150     }
1151     return true;
1152 }
1153 
GetArrayLength(napi_env env,napi_value value,uint32_t & length)1154 bool GetArrayLength(napi_env env, napi_value value, uint32_t &length)
1155 {
1156     bool isArray = false;
1157     napi_is_array(env, value, &isArray);
1158     if (!isArray) {
1159         ACCOUNT_LOGE("wrong argument type, array expected");
1160         return false;
1161     }
1162     napi_get_array_length(env, value, &length);
1163     return true;
1164 }
1165 
ParseAccountVector(napi_env env,napi_value value,std::vector<std::pair<std::string,std::string>> & accountVec)1166 bool ParseAccountVector(napi_env env, napi_value value, std::vector<std::pair<std::string, std::string>> &accountVec)
1167 {
1168     uint32_t length = 0;
1169     if (!GetArrayLength(env, value, length)) {
1170         return false;
1171     }
1172     napi_valuetype valueType = napi_undefined;
1173     for (uint32_t i = 0; i < length; ++i) {
1174         napi_value item = nullptr;
1175         napi_get_element(env, value, i, &item);
1176         NAPI_CALL_BASE(env, napi_typeof(env, item, &valueType), false);
1177         if (valueType != napi_object) {
1178             ACCOUNT_LOGD("Wrong argument type, Object expected");
1179             return false;
1180         }
1181         std::string name;
1182         if (!GetStringPropertyByKey(env, item, "name", name)) {
1183             return false;
1184         }
1185         std::string owner;
1186         if (!GetStringPropertyByKey(env, item, "owner", owner)) {
1187             return false;
1188         }
1189         accountVec.push_back(std::make_pair(owner, name));
1190     }
1191     return true;
1192 }
1193 
ParseStringVector(napi_env env,napi_value value,std::vector<std::string> & strVec)1194 bool ParseStringVector(napi_env env, napi_value value, std::vector<std::string> &strVec)
1195 {
1196     uint32_t length = 0;
1197     if (!GetArrayLength(env, value, length)) {
1198         return false;
1199     }
1200     for (uint32_t i = 0; i < length; ++i) {
1201         napi_value item = nullptr;
1202         napi_get_element(env, value, i, &item);
1203         std::string str;
1204         if (!GetStringProperty(env, item, str)) {
1205             return false;
1206         }
1207         strVec.push_back(str);
1208     }
1209     return true;
1210 }
1211 
ParseContextForCheckAccountLabels(napi_env env,napi_callback_info info,CheckAccountLabelsContext * context)1212 bool ParseContextForCheckAccountLabels(napi_env env, napi_callback_info info, CheckAccountLabelsContext *context)
1213 {
1214     size_t argc = ARGS_SIZE_FOUR;
1215     napi_value argv[ARGS_SIZE_FOUR] = {0};
1216     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
1217     if (argc < ARGS_SIZE_THREE) {
1218         context->errMsg = "the number of parameter should be at least 3";
1219         return false;
1220     }
1221     if ((argc == ARGS_SIZE_FOUR) && (!GetCallbackProperty(env, argv[PARAMTHREE], context->callbackRef, PARAMTWO))) {
1222         context->errMsg = "the callback is not a function";
1223         return false;
1224     }
1225     if (!GetStringProperty(env, argv[0], context->name)) {
1226         context->errMsg = "the name is not a string";
1227         return false;
1228     }
1229     if (!GetStringProperty(env, argv[PARAMONE], context->owner)) {
1230         context->errMsg = "the owner is not a string";
1231         return false;
1232     }
1233     if (!ParseStringVector(env, argv[PARAMTWO], context->labels)) {
1234         context->errMsg = "the labels is not a string vector";
1235         return false;
1236     }
1237     return true;
1238 }
1239 
VerifyCredCompleteCB(napi_env env,napi_status status,void * data)1240 void VerifyCredCompleteCB(napi_env env, napi_status status, void *data)
1241 {
1242     (void) status;
1243     auto context = reinterpret_cast<VerifyCredentialContext *>(data);
1244     if ((context->errCode != ERR_JS_SUCCESS) && (context->appAccountMgrCb != nullptr)) {
1245         AAFwk::Want errResult;
1246         context->appAccountMgrCb->OnResult(context->errCode, errResult);
1247     }
1248     delete context;
1249 }
1250 
ProcessOnResultCallback(napi_env env,JSAuthCallback & callback,int32_t resultCode,const AAFwk::WantParams & result)1251 void ProcessOnResultCallback(
1252     napi_env env, JSAuthCallback &callback, int32_t resultCode, const AAFwk::WantParams &result)
1253 {
1254     napi_value results[ARGS_SIZE_TWO] = {nullptr};
1255     napi_create_int32(env, resultCode, &results[0]);
1256     results[ARGS_SIZE_ONE] = AppExecFwk::WrapWantParams(env, result);
1257     NapiCallVoidFunction(env, results, ARGS_SIZE_TWO, callback.onResult);
1258     if (callback.onResult != nullptr) {
1259         napi_delete_reference(env, callback.onResult);
1260         callback.onResult = nullptr;
1261     }
1262     if (callback.onRequestRedirected != nullptr) {
1263         napi_delete_reference(env, callback.onRequestRedirected);
1264         callback.onRequestRedirected = nullptr;
1265     }
1266     if (callback.onRequestContinued != nullptr) {
1267         napi_delete_reference(env, callback.onRequestContinued);
1268         callback.onRequestContinued = nullptr;
1269     }
1270 }
1271 
ParseCreateAccountOptions(napi_env env,napi_value object,CreateAccountOptions & options)1272 bool ParseCreateAccountOptions(napi_env env, napi_value object, CreateAccountOptions &options)
1273 {
1274     bool hasCustomData = false;
1275     napi_has_named_property(env, object, "customData", &hasCustomData);
1276     if (!hasCustomData) {
1277         return true;
1278     }
1279     napi_value customDataValue = nullptr;
1280     napi_get_named_property(env, object, "customData", &customDataValue);
1281     napi_valuetype valueType = napi_undefined;
1282     napi_typeof(env, customDataValue, &valueType);
1283     if ((valueType == napi_undefined) || (valueType == napi_null)) {
1284         ACCOUNT_LOGI("the customData of CreateAccountOptions is undefined or null");
1285         return true;
1286     }
1287     if (valueType != napi_object) {
1288         ACCOUNT_LOGE("customData type is not object");
1289         return false;
1290     }
1291     napi_value keyArr = nullptr;
1292     napi_get_property_names(env, customDataValue, &keyArr);
1293     uint32_t keyNum = 0;
1294     napi_get_array_length(env, keyArr, &keyNum);
1295     for (uint32_t i = 0; i < keyNum; ++i) {
1296         napi_value item = nullptr;
1297         napi_get_element(env, keyArr, i, &item);
1298         std::string keyStr;
1299         if (!GetStringProperty(env, item, keyStr)) {
1300             ACCOUNT_LOGE("fail to get string");
1301             return false;
1302         }
1303         napi_value val = nullptr;
1304         napi_get_named_property(env, customDataValue, keyStr.c_str(), &val);
1305         std::string valStr;
1306         if (!GetStringProperty(env, val, valStr)) {
1307             ACCOUNT_LOGE("fail to get string");
1308             return false;
1309         }
1310         options.customData.emplace(keyStr, valStr);
1311     }
1312     return true;
1313 }
1314 
ParseCreateAccountImplicitlyOptions(napi_env env,napi_value object,CreateAccountImplicitlyOptions & options)1315 bool ParseCreateAccountImplicitlyOptions(napi_env env, napi_value object, CreateAccountImplicitlyOptions &options)
1316 {
1317     napi_valuetype valueType = napi_undefined;
1318     napi_typeof(env, object, &valueType);
1319     if ((valueType == napi_undefined) || (valueType == napi_null)) {
1320         ACCOUNT_LOGI("the CreateAccountImplicitlyOptions is undefined or null");
1321         return true;
1322     }
1323     if (valueType != napi_object) {
1324         return false;
1325     }
1326     napi_value value = nullptr;
1327     napi_has_named_property(env, object, "requiredLabels", &options.hasRequiredLabels);
1328     if (options.hasRequiredLabels) {
1329         napi_get_named_property(env, object, "requiredLabels", &value);
1330         valueType = napi_undefined;
1331         napi_typeof(env, value, &valueType);
1332         if ((valueType == napi_undefined) || (valueType == napi_null)) {
1333             options.hasRequiredLabels = false;
1334             ACCOUNT_LOGI("the requiredLabels is undefined or null");
1335         } else {
1336             if (!ParseStringVector(env, value, options.requiredLabels)) {
1337                 return false;
1338             }
1339         }
1340     }
1341     if (!GetOptionalStringPropertyByKey(env, object, "authType", options.authType)) {
1342         ACCOUNT_LOGE("failed to get options's authType property");
1343         return false;
1344     }
1345     bool hasParam = false;
1346     napi_has_named_property(env, object, "parameters", &hasParam);
1347     AAFwk::WantParams params;
1348     if (hasParam) {
1349         napi_get_named_property(env, object, "parameters", &value);
1350         valueType = napi_undefined;
1351         napi_typeof(env, value, &valueType);
1352         if ((valueType == napi_undefined) || (valueType == napi_null)) {
1353             ACCOUNT_LOGI("the authType is undefined or null");
1354         } else {
1355             if (!AppExecFwk::UnwrapWantParams(env, value, params)) {
1356                 return false;
1357             }
1358         }
1359     }
1360     options.parameters.SetParams(params);
1361     return true;
1362 }
1363 
ParseContextForCreateAccount(napi_env env,napi_callback_info cbInfo,CreateAccountContext * context)1364 bool ParseContextForCreateAccount(napi_env env, napi_callback_info cbInfo, CreateAccountContext *context)
1365 {
1366     size_t argc = ARGS_SIZE_THREE;
1367     napi_value argv[ARGS_SIZE_THREE] = {0};
1368     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
1369     if (argc < ARGS_SIZE_ONE) {
1370         context->errMsg = "the number of parameters should be at least 1";
1371         return false;
1372     }
1373     if (!GetStringProperty(env, argv[0], context->name)) {
1374         context->errMsg = "the name is not a string";
1375         return false;
1376     }
1377     for (size_t i = 1; i < argc; i++) {
1378         napi_valuetype valueType = napi_undefined;
1379         napi_typeof(env, argv[i], &valueType);
1380         if (i == 1 && valueType == napi_object) {
1381             if (!ParseCreateAccountOptions(env, argv[i], context->options)) {
1382                 context->errMsg = "the type of options is not CreateAccountOptions";
1383                 return false;
1384             }
1385         } else if (i == 1 && valueType == napi_function) {
1386             napi_create_reference(env, argv[i], 1, &context->callbackRef);
1387             break;
1388         } else if ((i == 1) && ((valueType == napi_undefined) || (valueType == napi_null))) {
1389             ACCOUNT_LOGI("the param'1 is undefined or null");
1390             continue;
1391         } else if (i == PARAMTWO && valueType == napi_function) {
1392             napi_create_reference(env, argv[i], 1, &context->callbackRef);
1393             break;
1394         } else if ((i == PARAMTWO) && ((valueType == napi_undefined) || (valueType == napi_null))) {
1395             ACCOUNT_LOGI("the param'2 is undefined or null");
1396             break;
1397         } else {
1398             ACCOUNT_LOGE("Type matching failed");
1399             context->errMsg = "the type of param " + std::to_string(i) + " is incorrect";
1400             return false;
1401         }
1402     }
1403     return true;
1404 }
1405 
ParseContextForCreateAccountImplicitly(napi_env env,napi_callback_info cbInfo,CreateAccountImplicitlyContext * context)1406 bool ParseContextForCreateAccountImplicitly(
1407     napi_env env, napi_callback_info cbInfo, CreateAccountImplicitlyContext *context)
1408 {
1409     size_t argc = ARGS_SIZE_THREE;
1410     napi_value argv[ARGS_SIZE_THREE] = {0};
1411     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
1412     if (argc < ARGS_SIZE_TWO) {
1413         context->errMsg = "the number of parameters should be at least 2";
1414         return false;
1415     }
1416     if (!GetStringProperty(env, argv[0], context->owner)) {
1417         context->errMsg = "the type of owner is not string";
1418         return false;
1419     }
1420     if (argc == ARGS_SIZE_THREE) {
1421         napi_valuetype valueType = napi_undefined;
1422         napi_typeof(env, argv[1], &valueType);
1423         if ((valueType == napi_undefined) || (valueType == napi_null)) {
1424             ACCOUNT_LOGI("the authType is undefined or null");
1425         } else {
1426             if (!ParseCreateAccountImplicitlyOptions(env, argv[1], context->options)) {
1427                 context->errMsg = "the type of options is not CreateAccountImplicitlyOptions";
1428                 return false;
1429             }
1430         }
1431     }
1432     if (!ParseJSAuthCallback(env, argv[argc - 1], context->callback)) {
1433         context->errMsg = "the type of callback is not AuthCallback";
1434         return false;
1435     }
1436     std::string abilityName;
1437     GetAbilityName(env, abilityName);
1438     context->options.parameters.SetParam(Constants::KEY_CALLER_ABILITY_NAME, abilityName);
1439     return true;
1440 }
1441 
GetAbilityName(napi_env env,std::string & abilityName)1442 bool GetAbilityName(napi_env env, std::string &abilityName)
1443 {
1444     napi_value global;
1445     napi_get_global(env, &global);
1446     napi_value abilityObj;
1447     napi_get_named_property(env, global, "ability", &abilityObj);
1448     if (abilityObj == nullptr) {
1449         return false;
1450     }
1451     AppExecFwk::Ability *ability = nullptr;
1452     napi_get_value_external(env, abilityObj, reinterpret_cast<void **>(&ability));
1453     if (ability == nullptr) {
1454         return false;
1455     }
1456     auto abilityInfo = ability->GetAbilityInfo();
1457     if (abilityInfo == nullptr) {
1458         return false;
1459     }
1460     abilityName = abilityInfo->name;
1461     return true;
1462 }
1463 }  // namespace AccountJsKit
1464 }  // namespace OHOS
1465