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