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