1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_app_account.h"
17 
18 #include <string>
19 #include <cstring>
20 #include <vector>
21 #include "account_log_wrapper.h"
22 #include "app_account_common.h"
23 #include "app_account_manager.h"
24 #include "napi/native_api.h"
25 #include "napi/native_node_api.h"
26 #include "napi_account_common.h"
27 #include "napi_account_error.h"
28 #include "napi_app_account_common.h"
29 
30 using namespace OHOS::AccountSA;
31 namespace OHOS {
32 namespace AccountJsKit {
33 const std::string APP_ACCOUNT_CLASS_NAME = "AppAccountManager";
34 const std::string TYPE_CHANGE = "change";
35 static thread_local napi_ref appAccountRef_ = nullptr;
36 napi_property_descriptor NapiAppAccount::appAccountProperties[] = {
37     DECLARE_NAPI_FUNCTION("addAccount", AddAccount),
38     DECLARE_NAPI_FUNCTION("addAccountImplicitly", AddAccountImplicitly),
39     DECLARE_NAPI_FUNCTION("deleteAccount", DeleteAccount),
40     DECLARE_NAPI_FUNCTION("disableAppAccess", DisableAppAccess),
41     DECLARE_NAPI_FUNCTION("enableAppAccess", EnableAppAccess),
42     DECLARE_NAPI_FUNCTION("checkAppAccountSyncEnable", CheckAppAccountSyncEnable),
43     DECLARE_NAPI_FUNCTION("setAccountCredential", SetAccountCredential),
44     DECLARE_NAPI_FUNCTION("setAccountExtraInfo", SetAccountExtraInfo),
45     DECLARE_NAPI_FUNCTION("setAppAccountSyncEnable", SetAppAccountSyncEnable),
46     DECLARE_NAPI_FUNCTION("setAssociatedData", SetAssociatedData),
47     DECLARE_NAPI_FUNCTION("authenticate", Authenticate),
48     DECLARE_NAPI_FUNCTION("getAllAccessibleAccounts", GetAllAccessibleAccounts),
49     DECLARE_NAPI_FUNCTION("getAllAccounts", GetAllAccounts),
50     DECLARE_NAPI_FUNCTION("getAccountCredential", GetAccountCredential),
51     DECLARE_NAPI_FUNCTION("getAccountExtraInfo", GetAccountExtraInfo),
52     DECLARE_NAPI_FUNCTION("getAssociatedData", GetAssociatedData),
53     DECLARE_NAPI_FUNCTION("getAssociatedDataSync", GetAssociatedDataSync),
54     DECLARE_NAPI_FUNCTION("getOAuthToken", GetOAuthToken),
55     DECLARE_NAPI_FUNCTION("setOAuthToken", SetOAuthToken),
56     DECLARE_NAPI_FUNCTION("deleteOAuthToken", DeleteOAuthToken),
57     DECLARE_NAPI_FUNCTION("getAuthenticatorInfo", GetAuthenticatorInfo),
58     DECLARE_NAPI_FUNCTION("getAllOAuthTokens", GetAllOAuthTokens),
59     DECLARE_NAPI_FUNCTION("getOAuthList", GetOAuthList),
60     DECLARE_NAPI_FUNCTION("setOAuthTokenVisibility", SetOAuthTokenVisibility),
61     DECLARE_NAPI_FUNCTION("checkOAuthTokenVisibility", CheckOAuthTokenVisibility),
62     DECLARE_NAPI_FUNCTION("getAuthenticatorCallback", GetAuthenticatorCallback),
63     DECLARE_NAPI_FUNCTION("on", Subscribe),
64     DECLARE_NAPI_FUNCTION("off", Unsubscribe),
65     DECLARE_NAPI_FUNCTION("checkAppAccess", CheckAppAccess),
66     DECLARE_NAPI_FUNCTION("checkAccountLabels", CheckAccountLabels),
67     DECLARE_NAPI_FUNCTION("setAuthenticatorProperties", SetAuthenticatorProperties),
68     DECLARE_NAPI_FUNCTION("verifyCredential", VerifyCredential),
69     DECLARE_NAPI_FUNCTION("selectAccountsByOptions", SelectAccountsByOptions),
70     DECLARE_NAPI_FUNCTION("deleteAccountCredential", DeleteAccountCredential),
71     // new api
72     DECLARE_NAPI_FUNCTION("createAccount", CreateAccount),
73     DECLARE_NAPI_FUNCTION("createAccountImplicitly", CreateAccountImplicitly),
74     DECLARE_NAPI_FUNCTION("auth", Auth),
75     DECLARE_NAPI_FUNCTION("removeAccount", RemoveAccount),
76     DECLARE_NAPI_FUNCTION("setAppAccess", SetAppAccess),
77     DECLARE_NAPI_FUNCTION("setCredential", SetCredential),
78     DECLARE_NAPI_FUNCTION("getCredential", GetCredential),
79     DECLARE_NAPI_FUNCTION("deleteCredential", DeleteCredential),
80     DECLARE_NAPI_FUNCTION("setDataSyncEnabled", SetDataSyncEnabled),
81     DECLARE_NAPI_FUNCTION("checkDataSyncEnabled", CheckDataSyncEnabled),
82     DECLARE_NAPI_FUNCTION("setCustomData", SetCustomData),
83     DECLARE_NAPI_FUNCTION("getCustomData", GetCustomData),
84     DECLARE_NAPI_FUNCTION("getCustomDataSync", GetAssociatedDataSync),
85     DECLARE_NAPI_FUNCTION("getAccountsByOwner", GetAccountsByOwner),
86     DECLARE_NAPI_FUNCTION("getAuthToken", GetAuthToken),
87     DECLARE_NAPI_FUNCTION("setAuthToken", SetAuthToken),
88     DECLARE_NAPI_FUNCTION("deleteAuthToken", DeleteAuthToken),
89     DECLARE_NAPI_FUNCTION("getAllAuthTokens", GetAllAuthTokens),
90     DECLARE_NAPI_FUNCTION("getAuthList", GetAuthList),
91     DECLARE_NAPI_FUNCTION("setAuthTokenVisibility", SetAuthTokenVisibility),
92     DECLARE_NAPI_FUNCTION("checkAuthTokenVisibility", CheckAuthTokenVisibility),
93     DECLARE_NAPI_FUNCTION("getAuthCallback", GetAuthCallback),
94     DECLARE_NAPI_FUNCTION("queryAuthenticatorInfo", QueryAuthenticatorInfo)
95 };
96 
CheckSpecialCharacters(const std::string & name)97 static bool CheckSpecialCharacters(const std::string &name)
98 {
99     for (const auto &specialCharacter : Constants::SPECIAL_CHARACTERS) {
100         std::size_t index = name.find(specialCharacter);
101         if (index != std::string::npos) {
102             ACCOUNT_LOGE("found a special character, specialCharacter = %{public}c", specialCharacter);
103             return false;
104         }
105     }
106     return true;
107 }
108 
Init(napi_env env,napi_value exports)109 napi_value NapiAppAccount::Init(napi_env env, napi_value exports)
110 {
111     napi_property_descriptor descriptor[] = {
112         DECLARE_NAPI_FUNCTION("createAppAccountManager", CreateAppAccountManager),
113     };
114     NAPI_CALL(
115         env, napi_define_properties(env, exports, sizeof(descriptor) / sizeof(napi_property_descriptor), descriptor));
116 
117     napi_value cons = nullptr;
118     NAPI_CALL(env,
119         napi_define_class(env, APP_ACCOUNT_CLASS_NAME.c_str(), APP_ACCOUNT_CLASS_NAME.size(), JsConstructor, nullptr,
120             sizeof(appAccountProperties) / sizeof(napi_property_descriptor), appAccountProperties, &cons));
121     NAPI_CALL(env, napi_create_reference(env, cons, 1, &appAccountRef_));
122     NAPI_CALL(env, napi_set_named_property(env, exports, APP_ACCOUNT_CLASS_NAME.c_str(), cons));
123     return exports;
124 }
125 
JsConstructor(napi_env env,napi_callback_info cbInfo)126 napi_value NapiAppAccount::JsConstructor(napi_env env, napi_callback_info cbInfo)
127 {
128     napi_value thisVar = nullptr;
129     NAPI_CALL(env, napi_get_cb_info(env, cbInfo, nullptr, nullptr, &thisVar, nullptr));
130     return thisVar;
131 }
132 
CreateAppAccountManager(napi_env env,napi_callback_info cbInfo)133 napi_value NapiAppAccount::CreateAppAccountManager(napi_env env, napi_callback_info cbInfo)
134 {
135     napi_value instance = nullptr;
136     napi_value cons = nullptr;
137     if (napi_get_reference_value(env, appAccountRef_, &cons) != napi_ok) {
138         return nullptr;
139     }
140 
141     if (napi_new_instance(env, cons, 0, nullptr, &instance) != napi_ok) {
142         return nullptr;
143     }
144 
145     AppAccountManager *objectInfo = new (std::nothrow) AppAccountManager();
146     if (objectInfo == nullptr) {
147         ACCOUNT_LOGE("failed to create AppAccountManager for insufficient memory");
148         return nullptr;
149     }
150     napi_status status = napi_wrap(env, instance, objectInfo,
151         [](napi_env env, void *data, void *hint) {
152             ACCOUNT_LOGI("js AppAccountManager instance garbage collection");
153             delete reinterpret_cast<AppAccountManager *>(data);
154         }, nullptr, nullptr);
155     if (status != napi_ok) {
156         ACCOUNT_LOGE("failed to wrap js instance with native object");
157         delete objectInfo;
158         return nullptr;
159     }
160     return instance;
161 }
162 
AddAccount(napi_env env,napi_callback_info cbInfo)163 napi_value NapiAppAccount::AddAccount(napi_env env, napi_callback_info cbInfo)
164 {
165     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env);
166     ParseContextWithExInfo(env, cbInfo, asyncContext.get());
167     napi_value result = nullptr;
168     if (asyncContext->callbackRef == nullptr) {
169         napi_create_promise(env, &asyncContext->deferred, &result);
170     } else {
171         napi_get_undefined(env, &result);
172     }
173     napi_value resource = nullptr;
174     napi_create_string_utf8(env, "AddAccountInternal", NAPI_AUTO_LENGTH, &resource);
175     napi_create_async_work(env,
176         nullptr,
177         resource,
178         [](napi_env env, void *data) {
179             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
180             asyncContext->errCode = AppAccountManager::AddAccount(asyncContext->name, asyncContext->extraInfo);
181         },
182         [](napi_env env, napi_status status, void *data) {
183             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
184             ProcessCallbackOrPromise(env, asyncContext,
185                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode)), NapiGetNull(env));
186             delete asyncContext;
187         },
188         reinterpret_cast<void *>(asyncContext.get()),
189         &asyncContext->work);
190     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
191     asyncContext.release();
192     return result;
193 }
194 
CreateAccount(napi_env env,napi_callback_info cbInfo)195 napi_value NapiAppAccount::CreateAccount(napi_env env, napi_callback_info cbInfo)
196 {
197     auto context = std::make_unique<CreateAccountContext>(env);
198     if (!ParseContextForCreateAccount(env, cbInfo, context.get())) {
199         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, context->errMsg));
200         return NapiGetNull(env);
201     }
202     napi_value result = nullptr;
203     if (context->callbackRef == nullptr) {
204         napi_create_promise(env, &context->deferred, &result);
205     } else {
206         napi_get_undefined(env, &result);
207     }
208     napi_value resource = nullptr;
209     napi_create_string_utf8(env, "CreateAccount", NAPI_AUTO_LENGTH, &resource);
210     napi_create_async_work(env, nullptr, resource,
211         [](napi_env env, void *data) {
212             CreateAccountContext *context = reinterpret_cast<CreateAccountContext *>(data);
213             context->errCode = AppAccountManager::CreateAccount(context->name, context->options);
214         },
215         [](napi_env env, napi_status status, void *data) {
216             CreateAccountContext *context = reinterpret_cast<CreateAccountContext *>(data);
217             ProcessCallbackOrPromise(env, context,
218                 GenerateBusinessError(env, context->errCode), NapiGetNull(env));
219             delete context;
220         }, reinterpret_cast<void *>(context.get()), &context->work);
221     napi_queue_async_work_with_qos(env, context->work, napi_qos_default);
222     context.release();
223     return result;
224 }
225 
CreateAccountImplicitly(napi_env env,napi_callback_info cbInfo)226 napi_value NapiAppAccount::CreateAccountImplicitly(napi_env env, napi_callback_info cbInfo)
227 {
228     auto context = std::make_unique<CreateAccountImplicitlyContext>(env);
229     if (!ParseContextForCreateAccountImplicitly(env, cbInfo, context.get())) {
230         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, context->errMsg));
231         return NapiGetNull(env);
232     }
233     context->appAccountMgrCb = new (std::nothrow) AppAccountManagerCallback(env, context->callback);
234     if (context->appAccountMgrCb == nullptr) {
235         ACCOUNT_LOGE("insufficient memory for AppAccountManagerCallback!");
236         return NapiGetNull(env);
237     }
238     napi_value resourceName = nullptr;
239     napi_create_string_latin1(env, "CreateAccountImplicitly", NAPI_AUTO_LENGTH, &resourceName);
240     napi_create_async_work(env, nullptr, resourceName,
241         [](napi_env env, void *data) {
242             auto context = reinterpret_cast<CreateAccountImplicitlyContext *>(data);
243             ErrCode errCode = AppAccountManager::CreateAccountImplicitly(context->owner,
244                 context->options, context->appAccountMgrCb);
245             context->errCode = ConvertToJSErrCode(errCode);
246         },
247         [](napi_env env, napi_status status, void *data) {
248             auto context = reinterpret_cast<CreateAccountImplicitlyContext *>(data);
249             AAFwk::Want errResult;
250             if ((context->errCode != 0) && (context->appAccountMgrCb != nullptr)) {
251                 context->appAccountMgrCb->OnResult(context->errCode, errResult);
252             }
253             delete context;
254         }, reinterpret_cast<void *>(context.get()), &context->work);
255     napi_queue_async_work_with_qos(env, context->work, napi_qos_default);
256     context.release();
257     return NapiGetNull(env);
258 }
259 
AddAccountImplicitly(napi_env env,napi_callback_info cbInfo)260 napi_value NapiAppAccount::AddAccountImplicitly(napi_env env, napi_callback_info cbInfo)
261 {
262     auto asyncContext = std::make_unique<OAuthAsyncContext>(env);
263     ParseContextForAuthenticate(env, cbInfo, asyncContext.get(), ARGS_SIZE_FOUR);
264     if (asyncContext->appAccountMgrCb == nullptr) {
265         ACCOUNT_LOGE("insufficient memory for AppAccountManagerCallback!");
266         return NapiGetNull(env);
267     }
268     napi_value resourceName = nullptr;
269     NAPI_CALL(env, napi_create_string_latin1(env, "AddAccountImplicitly", NAPI_AUTO_LENGTH, &resourceName));
270     NAPI_CALL(env,
271         napi_create_async_work(env,
272             nullptr,
273             resourceName,
274             [](napi_env env, void *data) {
275                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
276                 ErrCode errCode = AppAccountManager::AddAccountImplicitly(asyncContext->owner,
277                     asyncContext->authType, asyncContext->options, asyncContext->appAccountMgrCb);
278                 asyncContext->errCode = ConvertToJSErrCodeV8(errCode);
279             },
280             [](napi_env env, napi_status status, void *data) {
281                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
282                 AAFwk::Want errResult;
283                 if ((asyncContext->errCode != 0) && (asyncContext->appAccountMgrCb != nullptr)) {
284                     asyncContext->appAccountMgrCb->OnResult(asyncContext->errCode, errResult);
285                 }
286                 delete asyncContext;
287             },
288             reinterpret_cast<void *>(asyncContext.get()), &asyncContext->work));
289     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
290     asyncContext.release();
291     return NapiGetNull(env);
292 }
293 
DeleteAccount(napi_env env,napi_callback_info cbInfo)294 napi_value NapiAppAccount::DeleteAccount(napi_env env, napi_callback_info cbInfo)
295 {
296     return RemoveAccountInternal(env, cbInfo, false);
297 }
298 
RemoveAccount(napi_env env,napi_callback_info cbInfo)299 napi_value NapiAppAccount::RemoveAccount(napi_env env, napi_callback_info cbInfo)
300 {
301     return RemoveAccountInternal(env, cbInfo, true);
302 }
303 
RemoveAccountInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)304 napi_value NapiAppAccount::RemoveAccountInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
305 {
306     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env, isThrowable);
307     std::vector<PropertyType> propertyList = { PropertyType::NAME };
308     napi_value result = nullptr;
309     if ((!ParseContextForAppAccount(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
310         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
311         return NapiGetNull(env);
312     }
313     napi_value resource = nullptr;
314     napi_create_string_utf8(env, "DeleteAccount", NAPI_AUTO_LENGTH, &resource);
315 
316     napi_create_async_work(env,
317         nullptr,
318         resource,
319         [](napi_env env, void *data) {
320             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
321             asyncContext->errCode = AppAccountManager::DeleteAccount(asyncContext->name);
322         },
323         [](napi_env env, napi_status status, void *data) {
324             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
325             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
326                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
327             ProcessCallbackOrPromise(env, asyncContext, err, NapiGetNull(env));
328             delete asyncContext;
329         },
330         reinterpret_cast<void *>(asyncContext.get()),
331         &asyncContext->work);
332     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
333     asyncContext.release();
334     return result;
335 }
336 
DisableAppAccess(napi_env env,napi_callback_info cbInfo)337 napi_value NapiAppAccount::DisableAppAccess(napi_env env, napi_callback_info cbInfo)
338 {
339     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env);
340     std::vector<PropertyType> propertyList = {PropertyType::NAME, PropertyType::BUNDLE_NAME};
341     napi_value result = nullptr;
342     ParseContextForAppAccount(env, cbInfo, asyncContext.get(), propertyList, &result);
343 
344     napi_value resource = nullptr;
345     napi_create_string_utf8(env, "DisableAppAccess", NAPI_AUTO_LENGTH, &resource);
346     napi_create_async_work(env,
347         nullptr,
348         resource,
349         [](napi_env env, void *data) {
350             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
351             asyncContext->errCode = AppAccountManager::DisableAppAccess(asyncContext->name, asyncContext->bundleName);
352         },
353         [](napi_env env, napi_status status, void *data) {
354             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
355             ProcessCallbackOrPromise(env, asyncContext,
356                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode)), NapiGetNull(env));
357             delete asyncContext;
358         },
359         reinterpret_cast<void *>(asyncContext.get()),
360         &asyncContext->work);
361     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
362     asyncContext.release();
363     return result;
364 }
365 
EnableAppAccess(napi_env env,napi_callback_info cbInfo)366 napi_value NapiAppAccount::EnableAppAccess(napi_env env, napi_callback_info cbInfo)
367 {
368     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env);
369     std::vector<PropertyType> propertyList = {PropertyType::NAME, PropertyType::BUNDLE_NAME};
370     napi_value result = nullptr;
371     ParseContextForAppAccount(env, cbInfo, asyncContext.get(), propertyList, &result);
372 
373     napi_value resource = nullptr;
374     napi_create_string_utf8(env, "EnableAppAccess", NAPI_AUTO_LENGTH, &resource);
375     napi_create_async_work(env,
376         nullptr,
377         resource,
378         [](napi_env env, void *data) {
379             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
380             ErrCode errCode = AppAccountManager::EnableAppAccess(asyncContext->name, asyncContext->bundleName);
381             asyncContext->errCode = ConvertToJSErrCode(errCode);
382         },
383         [](napi_env env, napi_status status, void *data) {
384             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
385             ProcessCallbackOrPromise(env, asyncContext,
386                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode)), NapiGetNull(env));
387             delete asyncContext;
388         },
389         reinterpret_cast<void *>(asyncContext.get()),
390         &asyncContext->work);
391     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
392     asyncContext.release();
393     return result;
394 }
395 
SetAppAccess(napi_env env,napi_callback_info cbInfo)396 napi_value NapiAppAccount::SetAppAccess(napi_env env, napi_callback_info cbInfo)
397 {
398     auto context = std::make_unique<AppAccountAsyncContext>(env);
399     std::vector<PropertyType> propertyList = {
400         PropertyType::NAME, PropertyType::BUNDLE_NAME, PropertyType::IS_ACCESSIBLE};
401     napi_value result = nullptr;
402     if (!ParseContextForAppAccount(env, cbInfo, context.get(), propertyList, &result)) {
403         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, context->errMsg));
404         return NapiGetNull(env);
405     }
406 
407     napi_value resource = nullptr;
408     napi_create_string_utf8(env, "SetAppAccess", NAPI_AUTO_LENGTH, &resource);
409     napi_create_async_work(env, nullptr, resource,
410         [](napi_env env, void *data) {
411             AppAccountAsyncContext *context = reinterpret_cast<AppAccountAsyncContext *>(data);
412             context->errCode =
413                 AppAccountManager::SetAppAccess(context->name, context->bundleName, context->isAccessible);
414         },
415         [](napi_env env, napi_status status, void *data) {
416             AppAccountAsyncContext *context = reinterpret_cast<AppAccountAsyncContext *>(data);
417             ProcessCallbackOrPromise(env, context,
418                 GenerateBusinessError(env, context->errCode), NapiGetNull(env));
419             delete context;
420         }, reinterpret_cast<void *>(context.get()), &context->work);
421     napi_queue_async_work_with_qos(env, context->work, napi_qos_default);
422     context.release();
423     return result;
424 }
425 
CheckAppAccountSyncEnable(napi_env env,napi_callback_info cbInfo)426 napi_value NapiAppAccount::CheckAppAccountSyncEnable(napi_env env, napi_callback_info cbInfo)
427 {
428     return CheckDataSyncEnabledInternal(env, cbInfo, false);
429 }
430 
CheckDataSyncEnabled(napi_env env,napi_callback_info cbInfo)431 napi_value NapiAppAccount::CheckDataSyncEnabled(napi_env env, napi_callback_info cbInfo)
432 {
433     return CheckDataSyncEnabledInternal(env, cbInfo, true);
434 }
435 
CheckDataSyncEnabledInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)436 napi_value NapiAppAccount::CheckDataSyncEnabledInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
437 {
438     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env, isThrowable);
439     std::vector<PropertyType> propertyList = { PropertyType::NAME };
440     napi_value result = nullptr;
441     if ((!ParseContextForAppAccount(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
442         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
443         return NapiGetNull(env);
444     }
445 
446     napi_value resource = nullptr;
447     napi_create_string_utf8(env, "CheckAppAccountSyncEnable", NAPI_AUTO_LENGTH, &resource);
448 
449     napi_create_async_work(env,
450         nullptr,
451         resource,
452         [](napi_env env, void *data) {
453             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
454             asyncContext->errCode =
455                 AppAccountManager::CheckAppAccountSyncEnable(asyncContext->name, asyncContext->result);
456         },
457         [](napi_env env, napi_status status, void *data) {
458             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
459             napi_value boolVal = nullptr;
460             napi_get_boolean(env, asyncContext->result, &boolVal);
461             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
462                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
463             ProcessCallbackOrPromise(env, asyncContext, err, boolVal);
464             delete asyncContext;
465         },
466         reinterpret_cast<void *>(asyncContext.get()),
467         &asyncContext->work);
468     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
469     asyncContext.release();
470     return result;
471 }
472 
SetAccountCredential(napi_env env,napi_callback_info cbInfo)473 napi_value NapiAppAccount::SetAccountCredential(napi_env env, napi_callback_info cbInfo)
474 {
475     return SetCredentialInternal(env, cbInfo, false);
476 }
477 
SetCredential(napi_env env,napi_callback_info cbInfo)478 napi_value NapiAppAccount::SetCredential(napi_env env, napi_callback_info cbInfo)
479 {
480     return SetCredentialInternal(env, cbInfo, true);
481 }
482 
SetCredentialInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)483 napi_value NapiAppAccount::SetCredentialInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
484 {
485     auto context = std::make_unique<AppAccountAsyncContext>(env, isThrowable);
486     std::vector<PropertyType> propertyList = {
487         PropertyType::NAME, PropertyType::CREDENTIAL_TYPE, PropertyType::CREDENTIAL };
488     napi_value result = nullptr;
489     if ((!ParseContextForAppAccount(env, cbInfo, context.get(), propertyList, &result)) && isThrowable) {
490         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, context->errMsg));
491         return NapiGetNull(env);
492     }
493 
494     napi_value resource = nullptr;
495     NAPI_CALL(env, napi_create_string_utf8(env, "SetAccountCredential", NAPI_AUTO_LENGTH, &resource));
496     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
497         [](napi_env env, void *data) {
498             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
499             if ((!asyncContext->throwErr) && (!CheckSpecialCharacters(asyncContext->name))) {
500                 asyncContext->errCode = ERR_ACCOUNT_COMMON_INVALID_PARAMETER;
501                 return;
502             }
503             asyncContext->errCode = AppAccountManager::SetAccountCredential(
504                 asyncContext->name, asyncContext->credentialType, asyncContext->credential);
505         },
506         [](napi_env env, napi_status status, void *data) {
507             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
508             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
509                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
510             ProcessCallbackOrPromise(env, asyncContext, err, NapiGetNull(env));
511             delete asyncContext;
512         },
513         reinterpret_cast<void *>(context.get()), &context->work));
514     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
515     context.release();
516     return result;
517 }
518 
SetAccountExtraInfo(napi_env env,napi_callback_info cbInfo)519 napi_value NapiAppAccount::SetAccountExtraInfo(napi_env env, napi_callback_info cbInfo)
520 {
521     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env);
522     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::EXTRA_INFO };
523     napi_value result = nullptr;
524     ParseContextForAppAccount(env, cbInfo, asyncContext.get(), propertyList, &result);
525     napi_value resource = nullptr;
526     NAPI_CALL(env, napi_create_string_utf8(env, "SetAccountExtraInfo", NAPI_AUTO_LENGTH, &resource));
527     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
528         [](napi_env env, void *data) {
529             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
530             asyncContext->errCode = AppAccountManager::SetAccountExtraInfo(
531                 asyncContext->name, asyncContext->extraInfo);
532         },
533         [](napi_env env, napi_status status, void *data) {
534             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
535             ProcessCallbackOrPromise(env, asyncContext,
536                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode)), NapiGetNull(env));
537             delete asyncContext;
538         },
539         reinterpret_cast<void *>(asyncContext.get()), &asyncContext->work));
540     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
541     asyncContext.release();
542     return result;
543 }
544 
SetAppAccountSyncEnable(napi_env env,napi_callback_info cbInfo)545 napi_value NapiAppAccount::SetAppAccountSyncEnable(napi_env env, napi_callback_info cbInfo)
546 {
547     return SetDataSyncEnabledInternal(env, cbInfo, false);
548 }
549 
SetDataSyncEnabled(napi_env env,napi_callback_info cbInfo)550 napi_value NapiAppAccount::SetDataSyncEnabled(napi_env env, napi_callback_info cbInfo)
551 {
552     return SetDataSyncEnabledInternal(env, cbInfo, true);
553 }
554 
SetDataSyncEnabledInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)555 napi_value NapiAppAccount::SetDataSyncEnabledInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
556 {
557     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env, isThrowable);
558     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::IS_ENABLE };
559     napi_value result = nullptr;
560     if ((!ParseContextForAppAccount(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
561         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
562         return NapiGetNull(env);
563     }
564 
565     napi_value resource = nullptr;
566     napi_create_string_utf8(env, "SetAppAccountSyncEnable", NAPI_AUTO_LENGTH, &resource);
567 
568     napi_create_async_work(env, nullptr, resource,
569         [](napi_env env, void *data) {
570             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
571             if ((!asyncContext->throwErr) && (!CheckSpecialCharacters(asyncContext->name))) {
572                 asyncContext->errCode = ERR_ACCOUNT_COMMON_INVALID_PARAMETER;
573                 return;
574             }
575             asyncContext->errCode =
576                 AppAccountManager::SetAppAccountSyncEnable(asyncContext->name, asyncContext->isEnable);
577         },
578         [](napi_env env, napi_status status, void *data) {
579             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
580             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
581                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
582             ProcessCallbackOrPromise(env, asyncContext, err, NapiGetNull(env));
583             delete asyncContext;
584         },
585         reinterpret_cast<void *>(asyncContext.get()), &asyncContext->work);
586     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
587     asyncContext.release();
588     return result;
589 }
590 
SetAssociatedData(napi_env env,napi_callback_info cbInfo)591 napi_value NapiAppAccount::SetAssociatedData(napi_env env, napi_callback_info cbInfo)
592 {
593     return SetCustomDataInternal(env, cbInfo, false);
594 }
595 
SetCustomData(napi_env env,napi_callback_info cbInfo)596 napi_value NapiAppAccount::SetCustomData(napi_env env, napi_callback_info cbInfo)
597 {
598     return SetCustomDataInternal(env, cbInfo, true);
599 }
600 
SetCustomDataInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)601 napi_value NapiAppAccount::SetCustomDataInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
602 {
603     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env, isThrowable);
604     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::KEY, PropertyType::VALUE };
605     napi_value result = nullptr;
606     if ((!ParseContextForAppAccount(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
607         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
608         return NapiGetNull(env);
609     }
610 
611     napi_value resource = nullptr;
612     napi_create_string_utf8(env, "SetAssociatedData", NAPI_AUTO_LENGTH, &resource);
613 
614     napi_create_async_work(env, nullptr, resource,
615         [](napi_env env, void *data) {
616             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
617             if ((!asyncContext->throwErr) && (!CheckSpecialCharacters(asyncContext->name))) {
618                 asyncContext->errCode = ERR_ACCOUNT_COMMON_INVALID_PARAMETER;
619                 return;
620             }
621             asyncContext->errCode =
622                 AppAccountManager::SetAssociatedData(asyncContext->name, asyncContext->key, asyncContext->value);
623         },
624         [](napi_env env, napi_status status, void *data) {
625             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
626             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
627                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
628             ProcessCallbackOrPromise(env, asyncContext, err, NapiGetNull(env));
629             delete asyncContext;
630         }, reinterpret_cast<void *>(asyncContext.get()), &asyncContext->work);
631     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
632     asyncContext.release();
633     return result;
634 }
635 
GetAllAccessibleAccounts(napi_env env,napi_callback_info cbInfo)636 napi_value NapiAppAccount::GetAllAccessibleAccounts(napi_env env, napi_callback_info cbInfo)
637 {
638     return GetAllAccessibleAccountsInternal(env, cbInfo, false);
639 }
640 
GetAllAccessibleAccountsInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)641 napi_value NapiAppAccount::GetAllAccessibleAccountsInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
642 {
643     auto asyncContext = std::make_unique<GetAccountsAsyncContext>(env, isThrowable);
644     if ((!ParseContextCBArray(env, cbInfo, asyncContext.get())) && isThrowable) {
645         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
646         return NapiGetNull(env);
647     }
648 
649     napi_value result = nullptr;
650     if (asyncContext->callbackRef == nullptr) {
651         napi_create_promise(env, &asyncContext->deferred, &result);
652     } else {
653         napi_get_undefined(env, &result);
654     }
655 
656     napi_value resource = nullptr;
657     napi_create_string_utf8(env, "GetAllAccessibleAccounts", NAPI_AUTO_LENGTH, &resource);
658 
659     napi_create_async_work(env, nullptr, resource,
660         [](napi_env env, void *data) {
661             GetAccountsAsyncContext *asyncContext = reinterpret_cast<GetAccountsAsyncContext *>(data);
662             if (asyncContext->throwErr) {
663                 asyncContext->errCode =
664                     AppAccountManager::QueryAllAccessibleAccounts(asyncContext->owner, asyncContext->appAccounts);
665             } else {
666                 asyncContext->errCode =
667                     AppAccountManager::GetAllAccessibleAccounts(asyncContext->appAccounts);
668             }
669         },
670         [](napi_env env, napi_status status, void *data) {
671             GetAccountsAsyncContext *asyncContext = reinterpret_cast<GetAccountsAsyncContext *>(data);
672             napi_value arrVal = nullptr;
673             GetAppAccountInfoForResult(env, asyncContext->appAccounts, arrVal);
674             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
675                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
676             ProcessCallbackOrPromise(env, asyncContext, err, arrVal);
677             delete asyncContext;
678         },
679         reinterpret_cast<void *>(asyncContext.get()),
680         &asyncContext->work);
681     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
682     asyncContext.release();
683     return result;
684 }
685 
GetAllAccounts(napi_env env,napi_callback_info cbInfo)686 napi_value NapiAppAccount::GetAllAccounts(napi_env env, napi_callback_info cbInfo)
687 {
688     size_t argc = ARGS_SIZE_TWO;
689     napi_value argv[ARGS_SIZE_TWO] = {0};
690     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
691     if (argc == 0) {
692         return GetAllAccessibleAccountsInternal(env, cbInfo, true);
693     }
694     napi_valuetype valueType = napi_undefined;
695     napi_typeof(env, argv[0], &valueType);
696     if (valueType == napi_function) {
697         return GetAllAccessibleAccountsInternal(env, cbInfo, true);
698     }
699     return GetAccountsByOwnerInternal(env, cbInfo, false);
700 }
701 
GetAccountsByOwner(napi_env env,napi_callback_info cbInfo)702 napi_value NapiAppAccount::GetAccountsByOwner(napi_env env, napi_callback_info cbInfo)
703 {
704     return GetAccountsByOwnerInternal(env, cbInfo, true);
705 }
706 
GetAccountsByOwnerInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)707 napi_value NapiAppAccount::GetAccountsByOwnerInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
708 {
709     auto asyncContext = std::make_unique<GetAccountsAsyncContext>(env, isThrowable);
710     if ((!ParseContextWithStrCBArray(env, cbInfo, asyncContext.get())) && isThrowable) {
711         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
712         return NapiGetNull(env);
713     }
714 
715     napi_value result = nullptr;
716     if (asyncContext->callbackRef == nullptr) {
717         napi_create_promise(env, &asyncContext->deferred, &result);
718     } else {
719         napi_get_undefined(env, &result);
720     }
721 
722     napi_value resource = nullptr;
723     napi_create_string_utf8(env, "GetAllAccounts", NAPI_AUTO_LENGTH, &resource);
724 
725     napi_create_async_work(env, nullptr, resource,
726         [](napi_env env, void *data) {
727             GetAccountsAsyncContext *asyncContext = reinterpret_cast<GetAccountsAsyncContext *>(data);
728             if (!asyncContext->throwErr) {
729                 asyncContext->errCode =
730                     AppAccountManager::GetAllAccounts(asyncContext->owner, asyncContext->appAccounts);
731             } else if (asyncContext->owner.empty()) {
732                 asyncContext->errCode = ERR_ACCOUNT_COMMON_INVALID_PARAMETER;
733             } else {
734                 asyncContext->errCode =
735                     AppAccountManager::QueryAllAccessibleAccounts(asyncContext->owner, asyncContext->appAccounts);
736             }
737         },
738         [](napi_env env, napi_status status, void *data) {
739             GetAccountsAsyncContext *asyncContext = reinterpret_cast<GetAccountsAsyncContext *>(data);
740             napi_value arrVal = nullptr;
741             GetAppAccountInfoForResult(env, asyncContext->appAccounts, arrVal);
742             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
743                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
744             ProcessCallbackOrPromise(env, asyncContext, err, arrVal);
745             delete asyncContext;
746         }, reinterpret_cast<void *>(asyncContext.get()), &asyncContext->work);
747     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
748     asyncContext.release();
749     return result;
750 }
751 
GetAccountCredential(napi_env env,napi_callback_info cbInfo)752 napi_value NapiAppAccount::GetAccountCredential(napi_env env, napi_callback_info cbInfo)
753 {
754     return GetCredentialInternal(env, cbInfo, false);
755 }
756 
GetCredential(napi_env env,napi_callback_info cbInfo)757 napi_value NapiAppAccount::GetCredential(napi_env env, napi_callback_info cbInfo)
758 {
759     return GetCredentialInternal(env, cbInfo, true);
760 }
761 
GetCredentialInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)762 napi_value NapiAppAccount::GetCredentialInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
763 {
764     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env, isThrowable);
765     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::CREDENTIAL_TYPE };
766     napi_value result = nullptr;
767     if ((!ParseContextForAppAccount(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
768         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
769         return NapiGetNull(env);
770     }
771 
772     napi_value resource = nullptr;
773     napi_create_string_utf8(env, "GetAccountCredential", NAPI_AUTO_LENGTH, &resource);
774 
775     napi_create_async_work(env, nullptr, resource,
776         [](napi_env env, void *data) {
777             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
778             asyncContext->errCode = AppAccountManager::GetAccountCredential(
779                 asyncContext->name, asyncContext->credentialType, asyncContext->credential);
780         },
781         [](napi_env env, napi_status status, void *data) {
782             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
783             napi_value strVal = nullptr;
784             napi_create_string_utf8(env, asyncContext->credential.c_str(), NAPI_AUTO_LENGTH, &strVal);
785             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
786                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
787             ProcessCallbackOrPromise(env, asyncContext, err, strVal);
788             delete asyncContext;
789         },
790         reinterpret_cast<void *>(asyncContext.get()), &asyncContext->work);
791     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
792     asyncContext.release();
793     return result;
794 }
795 
GetAccountExtraInfo(napi_env env,napi_callback_info cbInfo)796 napi_value NapiAppAccount::GetAccountExtraInfo(napi_env env, napi_callback_info cbInfo)
797 {
798     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env);
799     std::vector<PropertyType> propertyList = { PropertyType::NAME };
800     napi_value result = nullptr;
801     ParseContextForAppAccount(env, cbInfo, asyncContext.get(), propertyList, &result);
802 
803     napi_value resource = nullptr;
804     napi_create_string_utf8(env, "GetAccountExtraInfo", NAPI_AUTO_LENGTH, &resource);
805 
806     napi_create_async_work(env,
807         nullptr,
808         resource,
809         [](napi_env env, void *data) {
810             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
811             asyncContext->errCode = AppAccountManager::GetAccountExtraInfo(
812                 asyncContext->name, asyncContext->extraInfo);
813         },
814         [](napi_env env, napi_status status, void *data) {
815             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
816             napi_value strVal = nullptr;
817             napi_create_string_utf8(env, asyncContext->extraInfo.c_str(), NAPI_AUTO_LENGTH, &strVal);
818             ProcessCallbackOrPromise(env, asyncContext,
819                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode)), strVal);
820             delete asyncContext;
821         },
822         reinterpret_cast<void *>(asyncContext.get()),
823         &asyncContext->work);
824     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
825     asyncContext.release();
826     return result;
827 }
828 
GetAssociatedData(napi_env env,napi_callback_info cbInfo)829 napi_value NapiAppAccount::GetAssociatedData(napi_env env, napi_callback_info cbInfo)
830 {
831     return GetCustomDataInternal(env, cbInfo, false);
832 }
833 
GetCustomData(napi_env env,napi_callback_info cbInfo)834 napi_value NapiAppAccount::GetCustomData(napi_env env, napi_callback_info cbInfo)
835 {
836     return GetCustomDataInternal(env, cbInfo, true);
837 }
838 
GetCustomDataInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)839 napi_value NapiAppAccount::GetCustomDataInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
840 {
841     auto asyncContext = std::make_unique<AppAccountAsyncContext>(env, isThrowable);
842     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::KEY };
843     napi_value result = nullptr;
844     if ((!ParseContextForAppAccount(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
845         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
846         return NapiGetNull(env);
847     }
848 
849     napi_value resource = nullptr;
850     napi_create_string_utf8(env, "GetAssociatedData", NAPI_AUTO_LENGTH, &resource);
851     napi_create_async_work(env,
852         nullptr,
853         resource,
854         [](napi_env env, void *data) {
855             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
856             asyncContext->errCode =
857                 AppAccountManager::GetAssociatedData(asyncContext->name, asyncContext->key, asyncContext->value);
858         },
859         [](napi_env env, napi_status status, void *data) {
860             AppAccountAsyncContext *asyncContext = reinterpret_cast<AppAccountAsyncContext *>(data);
861             napi_value strVal = NapiGetNull(env);
862             napi_create_string_utf8(env, asyncContext->value.c_str(), NAPI_AUTO_LENGTH, &strVal);
863             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
864                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
865             ProcessCallbackOrPromise(env, asyncContext, err, strVal);
866             delete asyncContext;
867         },
868         reinterpret_cast<void *>(asyncContext.get()),
869         &asyncContext->work);
870     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
871     asyncContext.release();
872     return result;
873 }
874 
GetAssociatedDataSync(napi_env env,napi_callback_info cbInfo)875 napi_value NapiAppAccount::GetAssociatedDataSync(napi_env env, napi_callback_info cbInfo)
876 {
877     size_t argc = ARGS_SIZE_TWO;
878     napi_value argv[ARGS_SIZE_TWO] = {0};
879     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
880     std::string name;
881     std::string key;
882     if ((argc < ARGS_SIZE_TWO) || (!GetStringProperty(env, argv[0], name)) ||
883         (!GetStringProperty(env, argv[1], key))) {
884         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR));
885         return nullptr;
886     }
887     std::string value;
888     ErrCode errCode = AppAccountManager::GetAssociatedData(name, key, value);
889     napi_value result = nullptr;
890     if (errCode == ERR_OK) {
891         NAPI_CALL(env, napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result));
892     } else {
893         napi_throw(env, GenerateBusinessError(env, errCode));
894     }
895     return result;
896 }
897 
Authenticate(napi_env env,napi_callback_info cbInfo)898 napi_value NapiAppAccount::Authenticate(napi_env env, napi_callback_info cbInfo)
899 {
900     return AuthInternal(env, cbInfo, false);
901 }
902 
Auth(napi_env env,napi_callback_info cbInfo)903 napi_value NapiAppAccount::Auth(napi_env env, napi_callback_info cbInfo)
904 {
905     return AuthInternal(env, cbInfo, true);
906 }
907 
AuthInternalExecuteCB(napi_env env,void * data)908 void AuthInternalExecuteCB(napi_env env, void *data)
909 {
910     auto asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
911     if ((!asyncContext->throwErr) && (!CheckSpecialCharacters(asyncContext->name))) {
912         asyncContext->errCode = ConvertToJSErrCodeV8(ERR_ACCOUNT_COMMON_INVALID_PARAMETER);
913         return;
914     }
915     ErrCode errCode = AppAccountManager::Authenticate(asyncContext->name, asyncContext->owner,
916         asyncContext->authType, asyncContext->options, asyncContext->appAccountMgrCb);
917     asyncContext->errCode =
918         asyncContext->throwErr ? ConvertToJSErrCode(errCode) : ConvertToJSErrCodeV8(errCode);
919 }
920 
AuthInternalCompletedCB(napi_env env,napi_status status,void * data)921 void AuthInternalCompletedCB(napi_env env, napi_status status, void *data)
922 {
923     OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
924     AAFwk::Want errResult;
925     if ((asyncContext->errCode != 0) && (asyncContext->appAccountMgrCb != nullptr)) {
926         asyncContext->appAccountMgrCb->OnResult(asyncContext->errCode, errResult);
927     }
928     delete asyncContext;
929 }
930 
AuthInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)931 napi_value NapiAppAccount::AuthInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
932 {
933     auto asyncContext = std::make_unique<OAuthAsyncContext>(env, isThrowable);
934     if (isThrowable) {
935         if (!ParseContextForAuth(env, cbInfo, asyncContext.get())) {
936             napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
937             return NapiGetNull(env);
938         }
939         asyncContext->options.SetParam(Constants::API_V9, true);
940     } else {
941         ParseContextForAuthenticate(env, cbInfo, asyncContext.get(), ARGS_SIZE_FIVE);
942     }
943     napi_value result = nullptr;
944     if (asyncContext->appAccountMgrCb == nullptr) {
945         NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &result));
946     } else {
947         NAPI_CALL(env, napi_get_undefined(env, &result));
948     }
949     napi_value resourceName = nullptr;
950     NAPI_CALL(env, napi_create_string_latin1(env, "Authenticate", NAPI_AUTO_LENGTH, &resourceName));
951     NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName,
952         AuthInternalExecuteCB,
953         AuthInternalCompletedCB,
954         reinterpret_cast<void *>(asyncContext.get()),
955         &asyncContext->work));
956     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated));
957     asyncContext.release();
958     return NapiGetNull(env);
959 }
960 
GetOAuthToken(napi_env env,napi_callback_info cbInfo)961 napi_value NapiAppAccount::GetOAuthToken(napi_env env, napi_callback_info cbInfo)
962 {
963     return GetAuthTokenInternal(env, cbInfo, false);
964 }
965 
GetAuthToken(napi_env env,napi_callback_info cbInfo)966 napi_value NapiAppAccount::GetAuthToken(napi_env env, napi_callback_info cbInfo)
967 {
968     return GetAuthTokenInternal(env, cbInfo, true);
969 }
970 
GetAuthTokenInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)971 napi_value NapiAppAccount::GetAuthTokenInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
972 {
973     auto asyncContext = std::make_unique<OAuthAsyncContext>(env, isThrowable);
974     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::OWNER, PropertyType::AUTH_TYPE };
975     napi_value result = nullptr;
976     if ((!ParseContextForOAuth(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
977         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
978         return NapiGetNull(env);
979     }
980 
981     napi_value resource = nullptr;
982     napi_create_string_utf8(env, "GetOAuthToken", NAPI_AUTO_LENGTH, &resource);
983     napi_create_async_work(env, nullptr, resource,
984         [](napi_env env, void *data) {
985             auto asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
986             if (asyncContext->throwErr) {
987                 asyncContext->errCode = AppAccountManager::GetAuthToken(
988                     asyncContext->name, asyncContext->owner, asyncContext->authType, asyncContext->token);
989             } else {
990                 asyncContext->errCode = AppAccountManager::GetOAuthToken(
991                     asyncContext->name, asyncContext->owner, asyncContext->authType, asyncContext->token);
992             }
993         },
994         [](napi_env env, napi_status status, void *data) {
995             OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
996             napi_value strVal = nullptr;
997             napi_create_string_utf8(env, asyncContext->token.c_str(), NAPI_AUTO_LENGTH, &strVal);
998             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
999                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
1000             ProcessCallbackOrPromise(env, asyncContext, err, strVal);
1001             delete asyncContext;
1002         },
1003         reinterpret_cast<void *>(asyncContext.get()),
1004         &asyncContext->work);
1005     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
1006     asyncContext.release();
1007     return result;
1008 }
1009 
SetOAuthToken(napi_env env,napi_callback_info cbInfo)1010 napi_value NapiAppAccount::SetOAuthToken(napi_env env, napi_callback_info cbInfo)
1011 {
1012     return SetAuthTokenInternal(env, cbInfo, false);
1013 }
1014 
SetAuthToken(napi_env env,napi_callback_info cbInfo)1015 napi_value NapiAppAccount::SetAuthToken(napi_env env, napi_callback_info cbInfo)
1016 {
1017     return SetAuthTokenInternal(env, cbInfo, true);
1018 }
1019 
SetAuthTokenInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)1020 napi_value NapiAppAccount::SetAuthTokenInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
1021 {
1022     auto asyncContext = std::make_unique<OAuthAsyncContext>(env, isThrowable);
1023     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::AUTH_TYPE, PropertyType::TOKEN };
1024     napi_value result = nullptr;
1025     if ((!ParseContextForOAuth(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
1026         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
1027         return NapiGetNull(env);
1028     }
1029     napi_value resource = nullptr;
1030     napi_create_string_utf8(env, "SetOAuthToken", NAPI_AUTO_LENGTH, &resource);
1031     napi_create_async_work(env, nullptr, resource,
1032         [](napi_env env, void *data) {
1033             OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1034             if ((!asyncContext->throwErr) && (!CheckSpecialCharacters(asyncContext->name))) {
1035                 asyncContext->errCode = ERR_ACCOUNT_COMMON_INVALID_PARAMETER;
1036                 return;
1037             }
1038             asyncContext->errCode = AppAccountManager::SetOAuthToken(
1039                 asyncContext->name, asyncContext->authType, asyncContext->token);
1040         },
1041         [](napi_env env, napi_status status, void *data) {
1042             OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1043             napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
1044                 GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
1045             ProcessCallbackOrPromise(env, asyncContext, err, NapiGetNull(env));
1046             delete asyncContext;
1047         },
1048         reinterpret_cast<void *>(asyncContext.get()),
1049         &asyncContext->work);
1050     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
1051     asyncContext.release();
1052     return result;
1053 }
1054 
DeleteOAuthToken(napi_env env,napi_callback_info cbInfo)1055 napi_value NapiAppAccount::DeleteOAuthToken(napi_env env, napi_callback_info cbInfo)
1056 {
1057     return DeleteAuthTokenInternal(env, cbInfo, false);
1058 }
1059 
DeleteAuthToken(napi_env env,napi_callback_info cbInfo)1060 napi_value NapiAppAccount::DeleteAuthToken(napi_env env, napi_callback_info cbInfo)
1061 {
1062     return DeleteAuthTokenInternal(env, cbInfo, true);
1063 }
1064 
DeleteAuthTokenInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)1065 napi_value NapiAppAccount::DeleteAuthTokenInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
1066 {
1067     auto asyncContext = std::make_unique<OAuthAsyncContext>(env, isThrowable);
1068     std::vector<PropertyType> propertyList = {
1069         PropertyType::NAME, PropertyType::OWNER, PropertyType::AUTH_TYPE, PropertyType::TOKEN };
1070     napi_value result = nullptr;
1071     if ((!ParseContextForOAuth(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
1072         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
1073         return NapiGetNull(env);
1074     }
1075     napi_value resource = nullptr;
1076     NAPI_CALL(env, napi_create_string_utf8(env, "DeleteOAuthToken", NAPI_AUTO_LENGTH, &resource));
1077     NAPI_CALL(env,
1078         napi_create_async_work(env, nullptr, resource,
1079             [](napi_env env, void *data) {
1080                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1081                 if (asyncContext->throwErr) {
1082                     asyncContext->errCode = AppAccountManager::DeleteAuthToken(
1083                         asyncContext->name, asyncContext->owner, asyncContext->authType, asyncContext->token);
1084                 } else {
1085                     asyncContext->errCode = AppAccountManager::DeleteOAuthToken(
1086                         asyncContext->name, asyncContext->owner, asyncContext->authType, asyncContext->token);
1087                 }
1088             },
1089             [](napi_env env, napi_status status, void *data) {
1090                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1091                 napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
1092                     GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
1093                 ProcessCallbackOrPromise(env, asyncContext, err, NapiGetNull(env));
1094                 delete asyncContext;
1095             },
1096             reinterpret_cast<void *>(asyncContext.get()), &asyncContext->work));
1097     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
1098     asyncContext.release();
1099     return result;
1100 }
1101 
SetOAuthTokenVisibility(napi_env env,napi_callback_info cbInfo)1102 napi_value NapiAppAccount::SetOAuthTokenVisibility(napi_env env, napi_callback_info cbInfo)
1103 {
1104     return SetAuthTokenVisibilityInternal(env, cbInfo, false);
1105 }
1106 
SetAuthTokenVisibility(napi_env env,napi_callback_info cbInfo)1107 napi_value NapiAppAccount::SetAuthTokenVisibility(napi_env env, napi_callback_info cbInfo)
1108 {
1109     return SetAuthTokenVisibilityInternal(env, cbInfo, true);
1110 }
1111 
SetAuthTokenVisibilityInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)1112 napi_value NapiAppAccount::SetAuthTokenVisibilityInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
1113 {
1114     auto asyncContext = std::make_unique<OAuthAsyncContext>(env, isThrowable);
1115     std::vector<PropertyType> propertyList = {
1116         PropertyType::NAME, PropertyType::AUTH_TYPE, PropertyType::BUNDLE_NAME, PropertyType::IS_VISIBLE };
1117     napi_value result = nullptr;
1118     if ((!ParseContextForOAuth(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
1119         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
1120         return NapiGetNull(env);
1121     }
1122     napi_value resource = nullptr;
1123     NAPI_CALL(env, napi_create_string_utf8(env, "SetOAuthTokenVisibility", NAPI_AUTO_LENGTH, &resource));
1124     NAPI_CALL(env,
1125         napi_create_async_work(env,
1126             nullptr,
1127             resource,
1128             [](napi_env env, void *data) {
1129                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1130                 if (asyncContext->throwErr) {
1131                     asyncContext->errCode = AppAccountManager::SetAuthTokenVisibility(
1132                         asyncContext->name, asyncContext->authType, asyncContext->bundleName, asyncContext->isVisible);
1133                 } else {
1134                     asyncContext->errCode = AppAccountManager::SetOAuthTokenVisibility(
1135                         asyncContext->name, asyncContext->authType, asyncContext->bundleName, asyncContext->isVisible);
1136                 }
1137             },
1138             [](napi_env env, napi_status status, void *data) {
1139                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1140                 napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
1141                     GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
1142                 ProcessCallbackOrPromise(env, asyncContext, err, NapiGetNull(env));
1143                 delete asyncContext;
1144             },
1145             reinterpret_cast<void *>(asyncContext.get()),
1146             &asyncContext->work));
1147     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
1148     asyncContext.release();
1149     return result;
1150 }
1151 
CheckOAuthTokenVisibility(napi_env env,napi_callback_info cbInfo)1152 napi_value NapiAppAccount::CheckOAuthTokenVisibility(napi_env env, napi_callback_info cbInfo)
1153 {
1154     return CheckAuthTokenVisibilityInternal(env, cbInfo, false);
1155 }
1156 
CheckAuthTokenVisibility(napi_env env,napi_callback_info cbInfo)1157 napi_value NapiAppAccount::CheckAuthTokenVisibility(napi_env env, napi_callback_info cbInfo)
1158 {
1159     return CheckAuthTokenVisibilityInternal(env, cbInfo, true);
1160 }
1161 
CheckAuthTokenVisibilityExecuteCB(napi_env env,void * data)1162 static void CheckAuthTokenVisibilityExecuteCB(napi_env env, void *data)
1163 {
1164     OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1165     if (asyncContext->throwErr) {
1166         asyncContext->errCode = AppAccountManager::CheckAuthTokenVisibility(
1167             asyncContext->name, asyncContext->authType, asyncContext->bundleName, asyncContext->isVisible);
1168     } else {
1169         asyncContext->errCode = AppAccountManager::CheckOAuthTokenVisibility(
1170             asyncContext->name, asyncContext->authType, asyncContext->bundleName, asyncContext->isVisible);
1171     }
1172 }
1173 
CheckAuthTokenVisibilityCompleteCB(napi_env env,napi_status status,void * data)1174 static void CheckAuthTokenVisibilityCompleteCB(napi_env env, napi_status status, void *data)
1175 {
1176     OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1177     napi_value boolVal = nullptr;
1178     napi_get_boolean(env, asyncContext->isVisible, &boolVal);
1179     napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
1180         GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
1181     ProcessCallbackOrPromise(env, asyncContext, err, boolVal);
1182     delete asyncContext;
1183 }
1184 
CheckAuthTokenVisibilityInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)1185 napi_value NapiAppAccount::CheckAuthTokenVisibilityInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
1186 {
1187     auto asyncContext = std::make_unique<OAuthAsyncContext>(env, isThrowable);
1188     std::vector<PropertyType> propertyList = {
1189         PropertyType::NAME, PropertyType::AUTH_TYPE, PropertyType::BUNDLE_NAME };
1190     napi_value result = nullptr;
1191     if ((!ParseContextForOAuth(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
1192         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
1193         return NapiGetNull(env);
1194     }
1195     napi_value resource = nullptr;
1196     NAPI_CALL(env, napi_create_string_utf8(env, "CheckOAuthTokenVisibility", NAPI_AUTO_LENGTH, &resource));
1197     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1198         CheckAuthTokenVisibilityExecuteCB, CheckAuthTokenVisibilityCompleteCB,
1199         reinterpret_cast<void *>(asyncContext.get()), &asyncContext->work));
1200     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
1201     asyncContext.release();
1202     return result;
1203 }
1204 
GetAuthenticatorInfo(napi_env env,napi_callback_info cbInfo)1205 napi_value NapiAppAccount::GetAuthenticatorInfo(napi_env env, napi_callback_info cbInfo)
1206 {
1207     return QueryAuthenticatorInfoInternal(env, cbInfo, false);
1208 }
1209 
QueryAuthenticatorInfo(napi_env env,napi_callback_info cbInfo)1210 napi_value NapiAppAccount::QueryAuthenticatorInfo(napi_env env, napi_callback_info cbInfo)
1211 {
1212     return QueryAuthenticatorInfoInternal(env, cbInfo, true);
1213 }
1214 
QueryAuthenticatorInfoInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)1215 napi_value NapiAppAccount::QueryAuthenticatorInfoInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
1216 {
1217     auto asyncContext = std::make_unique<OAuthAsyncContext>(env, isThrowable);
1218     std::vector<PropertyType> propertyList = { PropertyType::OWNER };
1219     napi_value result = nullptr;
1220     if ((!ParseContextForOAuth(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
1221         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
1222         return NapiGetNull(env);
1223     }
1224 
1225     napi_value resource = nullptr;
1226     NAPI_CALL(env, napi_create_string_utf8(env, "GetAuthenticatorInfo", NAPI_AUTO_LENGTH, &resource));
1227     NAPI_CALL(env,
1228         napi_create_async_work(env,
1229             nullptr,
1230             resource,
1231             [](napi_env env, void *data) {
1232                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1233                 asyncContext->errCode = AppAccountManager::GetAuthenticatorInfo(
1234                     asyncContext->owner, asyncContext->authenticatorInfo);
1235             },
1236             [](napi_env env, napi_status status, void *data) {
1237                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1238                 napi_value result = nullptr;
1239                 napi_create_object(env, &result);
1240                 GetAuthenticatorInfoForResult(env, asyncContext->authenticatorInfo, result);
1241                 napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
1242                     GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
1243                 ProcessCallbackOrPromise(env, asyncContext, err, result);
1244                 delete asyncContext;
1245             },
1246             reinterpret_cast<void *>(asyncContext.get()),
1247             &asyncContext->work));
1248     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
1249     asyncContext.release();
1250     return result;
1251 }
1252 
GetAllOAuthTokens(napi_env env,napi_callback_info cbInfo)1253 napi_value NapiAppAccount::GetAllOAuthTokens(napi_env env, napi_callback_info cbInfo)
1254 {
1255     return GetAllAuthTokensInternal(env, cbInfo, false);
1256 }
1257 
GetAllAuthTokens(napi_env env,napi_callback_info cbInfo)1258 napi_value NapiAppAccount::GetAllAuthTokens(napi_env env, napi_callback_info cbInfo)
1259 {
1260     return GetAllAuthTokensInternal(env, cbInfo, true);
1261 }
1262 
GetAllAuthTokensInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)1263 napi_value NapiAppAccount::GetAllAuthTokensInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
1264 {
1265     auto asyncContext = std::make_unique<OAuthAsyncContext>(env, isThrowable);
1266     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::OWNER };
1267     napi_value result = nullptr;
1268     if ((!ParseContextForOAuth(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
1269         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
1270         return NapiGetNull(env);
1271     }
1272 
1273     napi_value resource = nullptr;
1274     NAPI_CALL(env, napi_create_string_utf8(env, "GetAllOAuthTokens", NAPI_AUTO_LENGTH, &resource));
1275     NAPI_CALL(env,
1276         napi_create_async_work(env,
1277             nullptr,
1278             resource,
1279             [](napi_env env, void *data) {
1280                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1281                 asyncContext->errCode = AppAccountManager::GetAllOAuthTokens(
1282                     asyncContext->name, asyncContext->owner, asyncContext->oauthTokenInfos);
1283             },
1284             [](napi_env env, napi_status status, void *data) {
1285                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1286                 napi_value arrVal = nullptr;
1287                 napi_create_array(env, &arrVal);
1288                 GetOAuthTokenInfoForResult(env, asyncContext->oauthTokenInfos, arrVal);
1289                 napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
1290                     GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
1291                 ProcessCallbackOrPromise(env, asyncContext, err, arrVal);
1292                 delete asyncContext;
1293             },
1294             reinterpret_cast<void *>(asyncContext.get()),
1295             &asyncContext->work));
1296     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
1297     asyncContext.release();
1298     return result;
1299 }
1300 
GetOAuthList(napi_env env,napi_callback_info cbInfo)1301 napi_value NapiAppAccount::GetOAuthList(napi_env env, napi_callback_info cbInfo)
1302 {
1303     return GetAuthListInternal(env, cbInfo, false);
1304 }
1305 
GetAuthList(napi_env env,napi_callback_info cbInfo)1306 napi_value NapiAppAccount::GetAuthList(napi_env env, napi_callback_info cbInfo)
1307 {
1308     return GetAuthListInternal(env, cbInfo, true);
1309 }
1310 
GetAuthListInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)1311 napi_value NapiAppAccount::GetAuthListInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
1312 {
1313     auto asyncContext = std::make_unique<OAuthAsyncContext>(env, isThrowable);
1314     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::AUTH_TYPE };
1315     napi_value result = nullptr;
1316     if ((!ParseContextForOAuth(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
1317         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
1318         return NapiGetNull(env);
1319     }
1320 
1321     napi_value resource = nullptr;
1322     NAPI_CALL(env, napi_create_string_utf8(env, "GetOAuthList", NAPI_AUTO_LENGTH, &resource));
1323     NAPI_CALL(env,
1324         napi_create_async_work(env, nullptr, resource,
1325             [](napi_env env, void *data) {
1326                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1327                 if (asyncContext->throwErr) {
1328                     asyncContext->errCode = AppAccountManager::GetAuthList(
1329                         asyncContext->name, asyncContext->authType, asyncContext->authList);
1330                 } else {
1331                     asyncContext->errCode = AppAccountManager::GetOAuthList(
1332                         asyncContext->name, asyncContext->authType, asyncContext->authList);
1333                 }
1334             },
1335             [](napi_env env, napi_status status, void *data) {
1336                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1337                 napi_value arrVal = nullptr;
1338                 napi_create_array(env, &arrVal);
1339                 GetOAuthListForResult(env, asyncContext->authList, arrVal);
1340                 napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
1341                     GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
1342                 ProcessCallbackOrPromise(env, asyncContext, err, arrVal);
1343                 delete asyncContext;
1344             },
1345             reinterpret_cast<void *>(asyncContext.get()),
1346             &asyncContext->work));
1347     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
1348     asyncContext.release();
1349     return result;
1350 }
1351 
GetAuthenticatorCallback(napi_env env,napi_callback_info cbInfo)1352 napi_value NapiAppAccount::GetAuthenticatorCallback(napi_env env, napi_callback_info cbInfo)
1353 {
1354     return GetAuthCallbackInternal(env, cbInfo, false);
1355 }
1356 
GetAuthCallback(napi_env env,napi_callback_info cbInfo)1357 napi_value NapiAppAccount::GetAuthCallback(napi_env env, napi_callback_info cbInfo)
1358 {
1359     return GetAuthCallbackInternal(env, cbInfo, true);
1360 }
1361 
GetAuthCallbackInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)1362 napi_value NapiAppAccount::GetAuthCallbackInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
1363 {
1364     auto asyncContext = std::make_unique<OAuthAsyncContext>(env, isThrowable);
1365     std::vector<PropertyType> propertyList = { PropertyType::SESSION_ID };
1366     napi_value result = nullptr;
1367     if ((!ParseContextForOAuth(env, cbInfo, asyncContext.get(), propertyList, &result)) && isThrowable) {
1368         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, asyncContext->errMsg));
1369         return NapiGetNull(env);
1370     }
1371 
1372     napi_value resource = nullptr;
1373     NAPI_CALL(env, napi_create_string_utf8(env, "GetAuthenticatorCallback", NAPI_AUTO_LENGTH, &resource));
1374     NAPI_CALL(env,
1375         napi_create_async_work(env,
1376             nullptr,
1377             resource,
1378             [](napi_env env, void *data) {
1379                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1380                 asyncContext->errCode = AppAccountManager::GetAuthenticatorCallback(
1381                     asyncContext->sessionId, asyncContext->authenticatorCb);
1382             },
1383             [](napi_env env, napi_status status, void *data) {
1384                 OAuthAsyncContext *asyncContext = reinterpret_cast<OAuthAsyncContext *>(data);
1385                 napi_value result = nullptr;
1386                 GetAuthenticatorCallbackForResult(env, asyncContext->authenticatorCb, &result);
1387                 napi_value err = asyncContext->throwErr ? GenerateBusinessError(env, asyncContext->errCode) :
1388                     GetErrorCodeValue(env, ConvertToJSErrCodeV8(asyncContext->errCode));
1389                 ProcessCallbackOrPromise(env, asyncContext, err, result);
1390                 delete asyncContext;
1391             },
1392             reinterpret_cast<void *>(asyncContext.get()),
1393             &asyncContext->work));
1394     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
1395     asyncContext.release();
1396     return result;
1397 }
1398 
CheckAppAccess(napi_env env,napi_callback_info cbInfo)1399 napi_value NapiAppAccount::CheckAppAccess(napi_env env, napi_callback_info cbInfo)
1400 {
1401     auto context = std::make_unique<AppAccountAsyncContext>(env);
1402     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::BUNDLE_NAME };
1403     napi_value result = nullptr;
1404     if (!ParseContextForAppAccount(env, cbInfo, context.get(), propertyList, &result)) {
1405         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, context->errMsg));
1406         return NapiGetNull(env);
1407     }
1408 
1409     napi_value resource = nullptr;
1410     NAPI_CALL(env, napi_create_string_utf8(env, "CheckAppAccess", NAPI_AUTO_LENGTH, &resource));
1411     NAPI_CALL(env, napi_create_async_work(env,
1412         nullptr,
1413         resource,
1414         [](napi_env env, void *data) {
1415             auto context = reinterpret_cast<AppAccountAsyncContext *>(data);
1416             context->errCode = AppAccountManager::CheckAppAccess(
1417                 context->name, context->bundleName, context->isAccessible);
1418         },
1419         [](napi_env env, napi_status status, void *data) {
1420             auto context = reinterpret_cast<AppAccountAsyncContext *>(data);
1421             napi_value boolVal = nullptr;
1422             napi_get_boolean(env, context->isAccessible, &boolVal);
1423             ProcessCallbackOrPromise(env, context, GenerateBusinessError(env, context->errCode), boolVal);
1424             delete context;
1425         },
1426         reinterpret_cast<void *>(context.get()),
1427         &context->work));
1428     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
1429     context.release();
1430     return result;
1431 }
1432 
DeleteAccountCredential(napi_env env,napi_callback_info cbInfo)1433 napi_value NapiAppAccount::DeleteAccountCredential(napi_env env, napi_callback_info cbInfo)
1434 {
1435     return DeleteCredentialInternal(env, cbInfo, false);
1436 }
1437 
DeleteCredential(napi_env env,napi_callback_info cbInfo)1438 napi_value NapiAppAccount::DeleteCredential(napi_env env, napi_callback_info cbInfo)
1439 {
1440     return DeleteCredentialInternal(env, cbInfo, true);
1441 }
1442 
DeleteCredentialInternal(napi_env env,napi_callback_info cbInfo,bool isThrowable)1443 napi_value NapiAppAccount::DeleteCredentialInternal(napi_env env, napi_callback_info cbInfo, bool isThrowable)
1444 {
1445     auto context = std::make_unique<AppAccountAsyncContext>(env, isThrowable);
1446     std::vector<PropertyType> propertyList = { PropertyType::NAME, PropertyType::CREDENTIAL_TYPE };
1447     napi_value result = nullptr;
1448     if ((!ParseContextForAppAccount(env, cbInfo, context.get(), propertyList, &result)) && isThrowable) {
1449         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, context->errMsg));
1450         return NapiGetNull(env);
1451     }
1452 
1453     napi_value resource = nullptr;
1454     napi_create_string_utf8(env, "DeleteAccountCredential", NAPI_AUTO_LENGTH, &resource);
1455     napi_create_async_work(env, nullptr, resource,
1456         [](napi_env env, void *data) {
1457             auto context = reinterpret_cast<AppAccountAsyncContext *>(data);
1458             context->errCode = AppAccountManager::DeleteAccountCredential(
1459                 context->name, context->credentialType);
1460         },
1461         [](napi_env env, napi_status status, void *data) {
1462             auto context = reinterpret_cast<AppAccountAsyncContext *>(data);
1463             if (context->throwErr) {
1464                 ProcessCallbackOrPromise(env, context, GenerateBusinessError(env, context->errCode), NapiGetNull(env));
1465             } else {
1466                 napi_value ret = nullptr;
1467                 napi_get_undefined(env, &ret);
1468                 ProcessCallbackOrPromise(env, context, GenerateBusinessError(env, context->errCode), ret);
1469             }
1470             delete context;
1471         }, reinterpret_cast<void *>(context.get()), &context->work);
1472     napi_queue_async_work_with_qos(env, context->work, napi_qos_default);
1473     context.release();
1474     return result;
1475 }
1476 
CheckAccountLabels(napi_env env,napi_callback_info cbInfo)1477 napi_value NapiAppAccount::CheckAccountLabels(napi_env env, napi_callback_info cbInfo)
1478 {
1479     auto context = std::make_unique<CheckAccountLabelsContext>(env);
1480     if (!ParseContextForCheckAccountLabels(env, cbInfo, context.get())) {
1481         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, context->errMsg));
1482         return NapiGetNull(env);
1483     }
1484     napi_value result = nullptr;
1485     if (context->callbackRef == nullptr) {
1486         NAPI_CALL(env, napi_create_promise(env, &context->deferred, &result));
1487     } else {
1488         NAPI_CALL(env, napi_get_undefined(env, &result));
1489     }
1490     napi_value resource = nullptr;
1491     NAPI_CALL(env, napi_create_string_utf8(env, "CheckAccountLabels", NAPI_AUTO_LENGTH, &resource));
1492     NAPI_CALL(env, napi_create_async_work(env,
1493         nullptr,
1494         resource,
1495         [](napi_env env, void *data) {
1496             auto context = reinterpret_cast<CheckAccountLabelsContext *>(data);
1497             sptr<AuthenticatorAsyncCallback> callback = new (std::nothrow) AuthenticatorAsyncCallback(
1498                 context->env, context->callbackRef, context->deferred, CheckAccountLabelsOnResultWork);
1499             if (callback == nullptr) {
1500                 ACCOUNT_LOGE("failed to create AuthenticatorAsyncCallback for insufficient memory");
1501                 context->errCode = ERR_ACCOUNT_COMMON_INSUFFICIENT_MEMORY_ERROR;
1502                 return;
1503             }
1504             context->errCode = AppAccountManager::CheckAccountLabels(
1505                 context->name, context->owner, context->labels, callback);
1506         },
1507         [](napi_env env, napi_status status, void *data) {
1508             auto context = reinterpret_cast<CheckAccountLabelsContext *>(data);
1509             if (context->errCode != ERR_OK) {
1510                 ProcessCallbackOrPromise(env, context, GenerateBusinessError(env, context->errCode), NapiGetNull(env));
1511             } else {
1512                 context->callbackRef = nullptr;
1513             }
1514             delete context;
1515         },
1516         reinterpret_cast<void *>(context.get()), &context->work));
1517     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
1518     context.release();
1519     return result;
1520 }
1521 
SelectAccountsByOptions(napi_env env,napi_callback_info cbInfo)1522 napi_value NapiAppAccount::SelectAccountsByOptions(napi_env env, napi_callback_info cbInfo)
1523 {
1524     auto context = std::make_unique<SelectAccountsContext>(env);
1525     if (!ParseContextForSelectAccount(env, cbInfo, context.get())) {
1526         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, context->errMsg));
1527         return NapiGetNull(env);
1528     }
1529     napi_value result = nullptr;
1530     if (context->callbackRef == nullptr) {
1531         NAPI_CALL(env, napi_create_promise(env, &context->deferred, &result));
1532     } else {
1533         NAPI_CALL(env, napi_get_undefined(env, &result));
1534     }
1535     napi_value resource = nullptr;
1536     NAPI_CALL(env, napi_create_string_utf8(env, "SelectAccountsByOptions", NAPI_AUTO_LENGTH, &resource));
1537     NAPI_CALL(env, napi_create_async_work(env,
1538         nullptr,
1539         resource,
1540         [](napi_env env, void *data) {
1541             auto context = reinterpret_cast<SelectAccountsContext *>(data);
1542             sptr<AuthenticatorAsyncCallback> callback = new (std::nothrow) AuthenticatorAsyncCallback(
1543                 context->env, context->callbackRef, context->deferred, SelectAccountsOnResultWork);
1544             if (callback == nullptr) {
1545                 ACCOUNT_LOGD("failed to create AuthenticatorAsyncCallback for insufficient memory");
1546                 context->errCode = ERR_ACCOUNT_COMMON_INSUFFICIENT_MEMORY_ERROR;
1547                 return;
1548             }
1549             context->errCode =
1550                 AppAccountManager::SelectAccountsByOptions(context->options, callback);
1551         },
1552         [](napi_env env, napi_status status, void *data) {
1553             auto context = reinterpret_cast<SelectAccountsContext *>(data);
1554             if (context->errCode != ERR_OK) {
1555                 ProcessCallbackOrPromise(env, context, GenerateBusinessError(env, context->errCode), NapiGetNull(env));
1556             } else {
1557                 context->callbackRef = nullptr;
1558             }
1559             delete context;
1560         },
1561         reinterpret_cast<void *>(context.get()), &context->work));
1562     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
1563     context.release();
1564     return result;
1565 }
1566 
VerifyCredential(napi_env env,napi_callback_info cbInfo)1567 napi_value NapiAppAccount::VerifyCredential(napi_env env, napi_callback_info cbInfo)
1568 {
1569     auto context = std::make_unique<VerifyCredentialContext>(env);
1570     if (!ParseContextForVerifyCredential(env, cbInfo, context.get())) {
1571         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, context->errMsg));
1572         return NapiGetNull(env);
1573     }
1574     context->appAccountMgrCb = new (std::nothrow) AppAccountManagerCallback(env, context->callback);
1575     if (context->appAccountMgrCb == nullptr) {
1576         ACCOUNT_LOGD("failed to create AppAccountManagerCallback for insufficient memory");
1577         AAFwk::WantParams result;
1578         ProcessOnResultCallback(env, context->callback, ERR_JS_SYSTEM_SERVICE_EXCEPTION, result);
1579         return NapiGetNull(env);
1580     }
1581     napi_value resource = nullptr;
1582     NAPI_CALL(env, napi_create_string_utf8(env, "VerifyCredential", NAPI_AUTO_LENGTH, &resource));
1583     NAPI_CALL(env, napi_create_async_work(env,
1584         nullptr,
1585         resource,
1586         [](napi_env env, void *data) {
1587             auto context = reinterpret_cast<VerifyCredentialContext *>(data);
1588             ErrCode errCode = AppAccountManager::VerifyCredential(
1589                 context->name, context->owner, context->options, context->appAccountMgrCb);
1590             context->errCode = ConvertToJSErrCode(errCode);
1591         },
1592         VerifyCredCompleteCB, reinterpret_cast<void *>(context.get()), &context->work));
1593     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
1594     context.release();
1595     return NapiGetNull(env);
1596 }
1597 
SetAuthenticatorProperties(napi_env env,napi_callback_info cbInfo)1598 napi_value NapiAppAccount::SetAuthenticatorProperties(napi_env env, napi_callback_info cbInfo)
1599 {
1600     auto context = std::make_unique<SetPropertiesContext>(env);
1601     if (!ParseContextForSetProperties(env, cbInfo, context.get())) {
1602         napi_throw(env, GenerateBusinessError(env, ERR_JS_PARAMETER_ERROR, context->errMsg));
1603         return NapiGetNull(env);
1604     }
1605     context->appAccountMgrCb = new (std::nothrow) AppAccountManagerCallback(env, context->callback);
1606     if (context->appAccountMgrCb == nullptr) {
1607         ACCOUNT_LOGD("failed to create AppAccountManagerCallback for insufficient memory");
1608         AAFwk::WantParams result;
1609         ProcessOnResultCallback(env, context->callback, ERR_JS_SYSTEM_SERVICE_EXCEPTION, result);
1610         return NapiGetNull(env);
1611     }
1612     napi_value resource = nullptr;
1613     NAPI_CALL(env, napi_create_string_utf8(env, "SetAuthenticatorProperties", NAPI_AUTO_LENGTH, &resource));
1614     NAPI_CALL(env, napi_create_async_work(env,
1615         nullptr,
1616         resource,
1617         [](napi_env env, void *data) {
1618             auto context = reinterpret_cast<SetPropertiesContext *>(data);
1619             ErrCode errCode = AppAccountManager::SetAuthenticatorProperties(
1620                 context->owner, context->options, context->appAccountMgrCb);
1621             context->errCode = ConvertToJSErrCode(errCode);
1622         },
1623         [](napi_env env, napi_status status, void *data) {
1624             auto context = reinterpret_cast<SetPropertiesContext *>(data);
1625             if ((context->errCode != ERR_JS_SUCCESS) && (context->appAccountMgrCb != nullptr)) {
1626                 AAFwk::Want errResult;
1627                 context->appAccountMgrCb->OnResult(context->errCode, errResult);
1628             }
1629             delete context;
1630         },
1631         reinterpret_cast<void *>(context.get()),
1632         &context->work));
1633     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
1634     context.release();
1635     return NapiGetNull(env);
1636 }
1637 
IsExitSubscribe(napi_env env,AsyncContextForSubscribe * context)1638 static bool IsExitSubscribe(napi_env env, AsyncContextForSubscribe *context)
1639 {
1640     auto subscribe = g_AppAccountSubscribers.find(context->appAccountManager);
1641     if (subscribe == g_AppAccountSubscribers.end()) {
1642         return false;
1643     }
1644     for (size_t index = 0; index < subscribe->second.size(); index++) {
1645         if (CompareOnAndOffRef(env, subscribe->second[index]->callbackRef, context->callbackRef)) {
1646             return true;
1647         }
1648     }
1649     return false;
1650 }
1651 
Subscribe(napi_env env,napi_callback_info cbInfo)1652 napi_value NapiAppAccount::Subscribe(napi_env env, napi_callback_info cbInfo)
1653 {
1654     auto context = std::make_unique<AsyncContextForSubscribe>(env);
1655     if (!ParseParametersBySubscribe(env, cbInfo, context.get())) {
1656         if (context->type != TYPE_CHANGE) {
1657             napi_throw(env, GenerateBusinessError(env, context->errCode, context->errMsg));
1658         }
1659         return NapiGetNull(env);
1660     }
1661     if (context->appAccountManager == nullptr) {
1662         if (context->type != TYPE_CHANGE) {
1663             napi_throw(env, GenerateBusinessError(env, ERR_JS_SYSTEM_SERVICE_EXCEPTION,
1664                 std::string("system service exception")));
1665         }
1666         return NapiGetNull(env);
1667     }
1668     AppAccountSubscribeInfo subscribeInfo(context->owners);
1669     context->subscriber = std::make_shared<SubscriberPtr>(subscribeInfo);
1670     if (context->subscriber == nullptr) {
1671         ACCOUNT_LOGE("fail to create subscriber");
1672         return NapiGetNull(env);
1673     }
1674     context->subscriber->SetEnv(env);
1675     context->subscriber->SetCallbackRef(context->callbackRef);
1676     std::lock_guard<std::mutex> lock(g_lockForAppAccountSubscribers);
1677     if (IsExitSubscribe(env, context.get())) {
1678         return NapiGetNull(env);
1679     }
1680     ErrCode errCode = AppAccountManager::SubscribeAppAccount(context->subscriber);
1681     if ((errCode != ERR_OK) && (context->type != TYPE_CHANGE)) {
1682         napi_throw(env, GenerateBusinessError(env, errCode));
1683         return NapiGetNull(env);
1684     }
1685     g_AppAccountSubscribers[context->appAccountManager].emplace_back(context.get());
1686     context.release();
1687     return NapiGetNull(env);
1688 }
1689 
UnsubscribeSync(napi_env env,const AsyncContextForUnsubscribe * context)1690 static void UnsubscribeSync(napi_env env, const AsyncContextForUnsubscribe *context)
1691 {
1692     std::lock_guard<std::mutex> lock(g_lockForAppAccountSubscribers);
1693     auto subscribe = g_AppAccountSubscribers.find(context->appAccountManager);
1694     if (subscribe == g_AppAccountSubscribers.end()) {
1695         return;
1696     }
1697     for (size_t index = 0; index < subscribe->second.size(); ++index) {
1698         if ((context->callbackRef != nullptr) &&
1699             (!CompareOnAndOffRef(env, subscribe->second[index]->callbackRef, context->callbackRef))) {
1700             continue;
1701         }
1702         int errCode = AppAccountManager::UnsubscribeAppAccount(subscribe->second[index]->subscriber);
1703         if (errCode != ERR_OK) {
1704             napi_throw(env, GenerateBusinessError(env, errCode));
1705             return;
1706         }
1707         delete subscribe->second[index];
1708         if (context->callbackRef != nullptr) {
1709             subscribe->second.erase(subscribe->second.begin() + index);
1710             break;
1711         }
1712     }
1713     if ((context->callbackRef == nullptr) || (subscribe->second.empty())) {
1714         g_AppAccountSubscribers.erase(subscribe);
1715     }
1716 }
1717 
Unsubscribe(napi_env env,napi_callback_info cbInfo)1718 napi_value NapiAppAccount::Unsubscribe(napi_env env, napi_callback_info cbInfo)
1719 {
1720     AsyncContextForUnsubscribe *context = new (std::nothrow) AsyncContextForUnsubscribe(env);
1721     if (context == nullptr) {
1722         ACCOUNT_LOGE("asyncContextForOff is null");
1723         return NapiGetNull(env);
1724     }
1725     if (!ParseParametersByUnsubscribe(env, cbInfo, context)) {
1726         if (context->type != TYPE_CHANGE) {
1727             napi_throw(env, GenerateBusinessError(env, context->errCode, context->errMsg));
1728         }
1729         delete context;
1730         return NapiGetNull(env);
1731     };
1732     if (context->type == TYPE_CHANGE) {
1733         bool isFind = false;
1734         std::vector<std::shared_ptr<SubscriberPtr>> subscribers = {nullptr};
1735         napi_value result = GetSubscriberByUnsubscribe(env, subscribers, context, isFind);
1736         if (!result) {
1737             ACCOUNT_LOGE("Unsubscribe failed. The current subscriber does not exist");
1738             delete context;
1739             return NapiGetNull(env);
1740         }
1741         context->subscribers = subscribers;
1742 
1743         napi_value resourceName = nullptr;
1744         napi_create_string_latin1(env, "Unsubscribe", NAPI_AUTO_LENGTH, &resourceName);
1745 
1746         napi_create_async_work(env, nullptr, resourceName, UnsubscribeExecuteCB, UnsubscribeCallbackCompletedCB,
1747             reinterpret_cast<void *>(context), &context->work);
1748         napi_queue_async_work_with_qos(env, context->work, napi_qos_default);
1749     } else {
1750         UnsubscribeSync(env, context);
1751         delete context;
1752     }
1753     return NapiGetNull(env);
1754 }
1755 }  // namespace AccountJsKit
1756 }  // namespace OHOS
1757