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