• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_domain_account_manager.h"
17 
18 #include <uv.h>
19 #include <memory>
20 #include "account_log_wrapper.h"
21 #include "domain_account_client.h"
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 #include "napi_account_common.h"
25 #include "napi_account_error.h"
26 #include "napi_common.h"
27 #include "napi_domain_account_common.h"
28 #include "napi_domain_auth_callback.h"
29 
30 namespace OHOS {
31 namespace AccountJsKit {
32 namespace {
33 const size_t ARG_SIZE_ONE = 1;
34 const size_t ARG_SIZE_TWO = 2;
35 const size_t ARG_SIZE_THREE = 3;
36 const size_t PARAM_ONE = 1;
37 const size_t PARAM_ZERO = 0;
38 }
39 
40 using namespace OHOS::AccountSA;
41 
CreatePluginAsyncCallback(napi_env env,napi_callback callback,JsDomainPluginParam * param)42 static napi_value CreatePluginAsyncCallback(napi_env env, napi_callback callback, JsDomainPluginParam *param)
43 {
44     napi_value napiCallback = nullptr;
45     napi_status status = napi_create_function(env, "callback", NAPI_AUTO_LENGTH, callback, param, &napiCallback);
46     if (status != napi_ok) {
47         ACCOUNT_LOGE("failed to create js function");
48         return nullptr;
49     }
50     status = napi_wrap(env, napiCallback, param,
51         [](napi_env env, void *data, void *hint) {
52             ACCOUNT_LOGI("release JsDomainPluginParam");
53             delete reinterpret_cast<JsDomainPluginParam *>(data);
54         }, nullptr, nullptr);
55     if (status != napi_ok) {
56         ACCOUNT_LOGE("failed to wrap callback with JsDomainPluginParam");
57         return nullptr;
58     }
59     return napiCallback;
60 }
61 
GetPluginCallbackCommonParam(napi_env env,napi_callback_info cbInfo,JsDomainPluginParam ** param,BusinessError & error,napi_value * businessData)62 static bool GetPluginCallbackCommonParam(napi_env env, napi_callback_info cbInfo,
63     JsDomainPluginParam **param, BusinessError &error, napi_value *businessData)
64 {
65     size_t argc = ARG_SIZE_TWO;
66     napi_value argv[ARG_SIZE_TWO] = {nullptr};
67     void *data = nullptr;
68     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, &data), false);
69     if (argc < ARG_SIZE_ONE) {
70         ACCOUNT_LOGE("the number of argument should be at least 1");
71         return false;
72     }
73     *param = reinterpret_cast<JsDomainPluginParam *>(data);
74     if ((*param == nullptr) || ((*param)->callback == nullptr)) {
75         ACCOUNT_LOGE("native callback is nullptr");
76         return false;
77     }
78     if (!ParseBusinessError(env, argv[0], error)) {
79         ACCOUNT_LOGE("ParseBussinessError failed");
80         return false;
81     }
82     if (argc == ARG_SIZE_TWO) {
83         *businessData = argv[1];
84     }
85     return true;
86 }
87 
CreateNapiDomainAccountInfo(napi_env env,const DomainAccountInfo & domainAccountInfo)88 static napi_value CreateNapiDomainAccountInfo(napi_env env, const DomainAccountInfo &domainAccountInfo)
89 {
90     napi_value napiInfo = nullptr;
91     NAPI_CALL(env, napi_create_object(env, &napiInfo));
92     napi_value napiName = nullptr;
93     NAPI_CALL(env, napi_create_string_utf8(env, domainAccountInfo.accountName_.c_str(), NAPI_AUTO_LENGTH, &napiName));
94     NAPI_CALL(env, napi_set_named_property(env, napiInfo, "accountName", napiName));
95     napi_value napiDomain = nullptr;
96     NAPI_CALL(env, napi_create_string_utf8(env, domainAccountInfo.domain_.c_str(), NAPI_AUTO_LENGTH, &napiDomain));
97     NAPI_CALL(env, napi_set_named_property(env, napiInfo, "domain", napiDomain));
98     napi_value napiAccountId = nullptr;
99     NAPI_CALL(
100         env, napi_create_string_utf8(env, domainAccountInfo.accountId_.c_str(), NAPI_AUTO_LENGTH, &napiAccountId));
101     NAPI_CALL(env, napi_set_named_property(env, napiInfo, "accountId", napiAccountId));
102     return napiInfo;
103 }
104 
CreateNapiGetAccessTokenOptions(const JsDomainPluginParam * param)105 static napi_value CreateNapiGetAccessTokenOptions(const JsDomainPluginParam *param)
106 {
107     napi_value napiOptions = nullptr;
108     NAPI_CALL(param->env, napi_create_object(param->env, &napiOptions));
109     napi_value napiDomainAccountInfo = CreateNapiDomainAccountInfo(param->env, param->domainAccountInfo);
110     NAPI_CALL(param->env, napi_set_named_property(param->env, napiOptions, "domainAccountInfo", napiDomainAccountInfo));
111     napi_value napiAccountToken = CreateUint8Array(param->env, param->authData.data(), param->authData.size());
112     NAPI_CALL(param->env, napi_set_named_property(param->env, napiOptions, "domainAccountToken", napiAccountToken));
113     napi_value napiParam = AppExecFwk::WrapWantParams(param->env, param->option.getTokenParams_);
114     NAPI_CALL(param->env, napi_set_named_property(param->env, napiOptions, "businessParams", napiParam));
115     napi_value napiUid = nullptr;
116     NAPI_CALL(param->env, napi_create_int32(param->env, param->option.callingUid_, &napiUid));
117     NAPI_CALL(param->env, napi_set_named_property(param->env, napiOptions, "callerUid", napiUid));
118     return napiOptions;
119 }
120 
CreateNapiDomainAuthCallback(napi_env env,const std::shared_ptr<DomainAccountCallback> & nativeCallback)121 static napi_value CreateNapiDomainAuthCallback(
122     napi_env env, const std::shared_ptr<DomainAccountCallback> &nativeCallback)
123 {
124     napi_value napiCallback = nullptr;
125     napi_value global = nullptr;
126     napi_get_global(env, &global);
127     if (global == nullptr) {
128         ACCOUNT_LOGE("failed to get napi global");
129         return napiCallback;
130     }
131     napi_value jsConstructor = nullptr;
132     napi_get_named_property(env, global, "DomainAuthCallback", &jsConstructor);
133     if (jsConstructor == nullptr) {
134         ACCOUNT_LOGE("jsConstructor is nullptr");
135         return napiCallback;
136     }
137     napi_new_instance(env, jsConstructor, 0, nullptr, &napiCallback);
138     auto domainAuthCallback = new (std::nothrow) NapiDomainAuthCallback(nativeCallback);
139     if (domainAuthCallback == nullptr) {
140         ACCOUNT_LOGE("failed to create NapiDomainAuthCallback");
141         return nullptr;
142     }
143     napi_status status = napi_wrap(env, napiCallback, domainAuthCallback,
144         [](napi_env env, void *data, void *hint) {
145             delete (reinterpret_cast<NapiDomainAuthCallback *>(data));
146         }, nullptr, nullptr);
147     if (status != napi_ok) {
148         ACCOUNT_LOGE("wrap js DomainAuthCallback and native callback failed");
149         delete domainAuthCallback;
150         return nullptr;
151     }
152     return napiCallback;
153 }
154 
ParseAuthStatusInfo(napi_env env,napi_value value,AuthStatusInfo & info)155 static bool ParseAuthStatusInfo(napi_env env, napi_value value, AuthStatusInfo &info)
156 {
157     napi_value napiRemainTimes = nullptr;
158     NAPI_CALL_BASE(env, napi_get_named_property(env, value, "remainTimes", &napiRemainTimes), false);
159     if (napiRemainTimes == nullptr) {
160         ACCOUNT_LOGE("remainTimes is undefined");
161         return false;
162     }
163     NAPI_CALL_BASE(env, napi_get_value_int32(env, napiRemainTimes, &info.remainingTimes), false);
164     napi_value napiFreezingTime = nullptr;
165     NAPI_CALL_BASE(env, napi_get_named_property(env, value, "freezingTime", &napiFreezingTime), false);
166     if (napiFreezingTime == nullptr) {
167         ACCOUNT_LOGE("freezingTime is undefined");
168         return false;
169     }
170     NAPI_CALL_BASE(env, napi_get_value_int32(env, napiFreezingTime, &info.freezingTime), false);
171     return true;
172 }
173 
ParseParamForUpdateAccountToken(napi_env env,napi_callback_info cbInfo,UpdateAccountTokenAsyncContext * asyncContext)174 static bool ParseParamForUpdateAccountToken(
175     napi_env env, napi_callback_info cbInfo, UpdateAccountTokenAsyncContext *asyncContext)
176 {
177     size_t argc = ARG_SIZE_THREE;
178     napi_value argv[ARG_SIZE_THREE] = {0};
179     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
180     if (argc < ARG_SIZE_TWO) {
181         ACCOUNT_LOGE("the parameter number for updating account token should be at least two");
182         std::string errMsg = "Parameter error. The number of parameters should be at least 2";
183         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
184         return false;
185     }
186     if (argc == ARG_SIZE_THREE) {
187         if (!GetCallbackProperty(env, argv[argc - 1], asyncContext->callbackRef, 1)) {
188             ACCOUNT_LOGE("failed to get callbackRef for updating account token");
189             std::string errMsg = "Parameter error. The type of \"callback\" must be function";
190             AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
191             return false;
192         }
193     }
194     if (!ParseDomainAccountInfo(env, argv[0], asyncContext->domainInfo)) {
195         ACCOUNT_LOGE("get domainInfo failed");
196         std::string errMsg = "Parameter error. The type of \"domainAccountInfo\" must be DomainAccountInfo";
197         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
198         return false;
199     }
200     if (ParseUint8TypedArrayToVector(env, argv[PARAM_ONE], asyncContext->token) != napi_ok) {
201         ACCOUNT_LOGE("get token failed");
202         std::string errMsg = "Parameter error. The type of \"token\" must be Uint8Array";
203         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
204         return false;
205     }
206     return true;
207 }
208 
ParseParamForIsAuthenticationExpired(napi_env env,napi_callback_info cbInfo,IsAuthenticationExpiredAsyncContext * asyncContext)209 static bool ParseParamForIsAuthenticationExpired(
210     napi_env env, napi_callback_info cbInfo, IsAuthenticationExpiredAsyncContext *asyncContext)
211 {
212     size_t argc = ARG_SIZE_ONE;
213     napi_value argv[ARG_SIZE_ONE] = {0};
214     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
215     if (argc < ARG_SIZE_ONE) {
216         ACCOUNT_LOGE("The number of parameters should be at least 1.");
217         std::string errMsg = "Parameter error. The number of parameters should be at least 1";
218         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
219         return false;
220     }
221     if (!ParseDomainAccountInfo(env, argv[PARAM_ZERO], asyncContext->domainInfo)) {
222         ACCOUNT_LOGE("Get domainInfo failed.");
223         std::string errMsg = "Parameter error. The type of \"domainAccountInfo\" must be DomainAccountInfo";
224         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
225         return false;
226     }
227     return true;
228 }
229 
ParseParamForGetAccessByAccount(napi_env env,const napi_value * argv,size_t argc,GetAccessTokenAsyncContext * asyncContext)230 static bool ParseParamForGetAccessByAccount(
231     napi_env env, const napi_value *argv, size_t argc, GetAccessTokenAsyncContext *asyncContext)
232 {
233     if ((argc == ARG_SIZE_THREE) && (!GetCallbackProperty(env, argv[argc - 1], asyncContext->callbackRef, 1))) {
234         ACCOUNT_LOGE("failed to get callbackRef for getting access token");
235         return false;
236     }
237     if (!AppExecFwk::UnwrapWantParams(env, argv[PARAM_ONE], asyncContext->getTokenParams)) {
238         ACCOUNT_LOGE("unwrapWantParams failed");
239         return false;
240     }
241     return true;
242 }
243 
ParseParamForGetAccessToken(napi_env env,napi_callback_info cbInfo,GetAccessTokenAsyncContext * asyncContext)244 static bool ParseParamForGetAccessToken(
245     napi_env env, napi_callback_info cbInfo, GetAccessTokenAsyncContext *asyncContext)
246 {
247     size_t argc = ARG_SIZE_THREE;
248     napi_value argv[ARG_SIZE_THREE] = {0};
249     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
250     if (argc < ARG_SIZE_ONE) {
251         std::string errMsg = "Parameter error. The number of parameters should be at least 1";
252         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
253         return false;
254     }
255     if (ParseDomainAccountInfo(env, argv[0], asyncContext->domainInfo)) {
256         return ParseParamForGetAccessByAccount(env, argv, argc, asyncContext);
257     }
258     if ((argc == ARG_SIZE_TWO) && (!GetCallbackProperty(env, argv[argc - 1], asyncContext->callbackRef, 1))) {
259         ACCOUNT_LOGE("failed to get callbackRef for getting access token");
260         std::string errMsg = "Parameter error. The type of \"callback\" must be function";
261         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
262         return false;
263     }
264     if (!AppExecFwk::UnwrapWantParams(env, argv[0], asyncContext->getTokenParams)) {
265         ACCOUNT_LOGE("unwrapWantParams failed");
266         std::string errMsg = "Parameter error. The type of \"businessParams\" must be Record";
267         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
268         return false;
269     }
270     return true;
271 }
272 
GetDomainAccountInfoCallback(napi_env env,napi_callback_info cbInfo)273 static napi_value GetDomainAccountInfoCallback(napi_env env, napi_callback_info cbInfo)
274 {
275     ACCOUNT_LOGI("GetDomainAccountInfoCallback enter");
276     JsDomainPluginParam *param = nullptr;
277     BusinessError error;
278     napi_value businessData = nullptr;
279     if (!GetPluginCallbackCommonParam(env, cbInfo, &param, error, &businessData)) {
280         AccountNapiThrow(env, ERR_JS_INVALID_PARAMETER, true);
281         return nullptr;
282     }
283     DomainAccountInfo info;
284     if ((error.code == 0) && (!ParseDomainAccountInfo(env, businessData, info))) {
285         ACCOUNT_LOGE("ParseDomainAccountInfo failed");
286         AccountNapiThrow(env, ERR_JS_INVALID_PARAMETER, true);
287         return nullptr;
288     }
289     AAFwk::WantParams getAccountInfoParams;
290     if (!AppExecFwk::UnwrapWantParams(env, businessData, getAccountInfoParams)) {
291         ACCOUNT_LOGE("unwrapWantParams failed");
292         return nullptr;
293     }
294     Parcel parcel;
295     if (!getAccountInfoParams.Marshalling(parcel)) {
296         ACCOUNT_LOGE("info Marshalling failed");
297         AccountNapiThrow(env, ERR_JS_SYSTEM_SERVICE_EXCEPTION, true);
298         return nullptr;
299     }
300     param->callback->OnResult(error.code, parcel);
301     return nullptr;
302 }
303 
CreatePluginAccountInfoOptions(const JsDomainPluginParam * param)304 static napi_value CreatePluginAccountInfoOptions(const JsDomainPluginParam *param)
305 {
306     napi_value napiOptions = nullptr;
307     NAPI_CALL(param->env, napi_create_object(param->env, &napiOptions));
308     napi_value napiName = nullptr;
309     NAPI_CALL(param->env, napi_create_string_utf8(
310         param->env, param->domainAccountInfo.accountName_.c_str(), NAPI_AUTO_LENGTH, &napiName));
311     NAPI_CALL(param->env, napi_set_named_property(param->env, napiOptions, "accountName", napiName));
312     napi_value napiDomain = nullptr;
313     NAPI_CALL(param->env,
314         napi_create_string_utf8(param->env, param->domainAccountInfo.domain_.c_str(), NAPI_AUTO_LENGTH, &napiDomain));
315     NAPI_CALL(param->env, napi_set_named_property(param->env, napiOptions, "domain", napiDomain));
316     napi_value napiCallingUid = nullptr;
317     NAPI_CALL(param->env, napi_create_int32(param->env, param->callingUid, &napiCallingUid));
318     NAPI_CALL(param->env, napi_set_named_property(param->env, napiOptions, "callerUid", napiCallingUid));
319     return napiOptions;
320 }
321 
GetDomainAccountInfoWork(JsDomainPluginParam * param)322 static std::function<void()> GetDomainAccountInfoWork(JsDomainPluginParam *param)
323 {
324     return [param = std::move(param)] {
325         ACCOUNT_LOGI("Enter GetDomainAccountInfoWork");
326         napi_handle_scope scope = nullptr;
327         napi_open_handle_scope(param->env, &scope);
328         if (scope == nullptr) {
329             ACCOUNT_LOGE("Fail to open scope");
330             delete param;
331             return;
332         }
333         napi_value napiCallback = CreatePluginAsyncCallback(param->env, GetDomainAccountInfoCallback, param);
334         napi_value getDomainAccountInfoPLuginOptions = CreatePluginAccountInfoOptions(param);
335         napi_value argv[] = {getDomainAccountInfoPLuginOptions, napiCallback};
336         NapiCallVoidFunction(param->env, argv, ARG_SIZE_TWO, param->func);
337         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
338         param->lockInfo->count--;
339         param->lockInfo->condition.notify_all();
340         napi_close_handle_scope(param->env, scope);
341         if (napiCallback == nullptr) {
342             delete param;
343         }
344     };
345 }
346 
OnAccountBoundCallback(napi_env env,napi_callback_info cbInfo)347 static napi_value OnAccountBoundCallback(napi_env env, napi_callback_info cbInfo)
348 {
349     ACCOUNT_LOGI("OnAccountBoundCallback enter");
350     JsDomainPluginParam *param = nullptr;
351     BusinessError error;
352     napi_value businessData = nullptr;
353     if (!GetPluginCallbackCommonParam(env, cbInfo, &param, error, &businessData)) {
354         AccountNapiThrow(env, ERR_JS_INVALID_PARAMETER, true);
355         return nullptr;
356     }
357     DomainAccountInfo info;
358     Parcel parcel;
359     if (!info.Marshalling(parcel)) {
360         ACCOUNT_LOGE("info Marshalling failed");
361         AccountNapiThrow(env, ERR_JS_SYSTEM_SERVICE_EXCEPTION, true);
362         return nullptr;
363     }
364     if (error.code != 0) {
365         ACCOUNT_LOGI("bind or unbind error, code: %{public}d", error.code);
366     }
367     param->callback->OnResult(error.code, parcel);
368     return nullptr;
369 }
370 
OnAccountBoundWork(JsDomainPluginParam * param)371 static std::function<void()> OnAccountBoundWork(JsDomainPluginParam *param)
372 {
373     return [param = std::move(param)] {
374         ACCOUNT_LOGI("Enter OnAccountBoundWork");
375         napi_handle_scope scope = nullptr;
376         napi_open_handle_scope(param->env, &scope);
377         if (scope == nullptr) {
378             ACCOUNT_LOGE("Fail to open scope");
379             delete param;
380             return;
381         }
382         napi_value napiLocalId = nullptr;
383         napi_create_int32(param->env, param->userId, &napiLocalId);
384         napi_value napiDomainAccountInfo = CreateNapiDomainAccountInfo(param->env, param->domainAccountInfo);
385         napi_value napiCallback = CreatePluginAsyncCallback(param->env, OnAccountBoundCallback, param);
386         napi_value argv[] = {napiDomainAccountInfo, napiLocalId, napiCallback};
387         NapiCallVoidFunction(param->env, argv, ARG_SIZE_THREE, param->func);
388         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
389         param->lockInfo->count--;
390         param->lockInfo->condition.notify_all();
391         napi_close_handle_scope(param->env, scope);
392         if (napiCallback == nullptr) {
393             delete param;
394         }
395     };
396 }
397 
OnAccountUnBoundWork(JsDomainPluginParam * param)398 static std::function<void()> OnAccountUnBoundWork(JsDomainPluginParam *param)
399 {
400     return [param = std::move(param)] {
401         ACCOUNT_LOGI("Enter OnAccountUnBoundWork");
402         napi_handle_scope scope = nullptr;
403         napi_open_handle_scope(param->env, &scope);
404         if (scope == nullptr) {
405             ACCOUNT_LOGE("Fail to open scope");
406             delete param;
407             return;
408         }
409         napi_value napiDomainAccountInfo = CreateNapiDomainAccountInfo(param->env, param->domainAccountInfo);
410         napi_value napiCallback = CreatePluginAsyncCallback(param->env, OnAccountBoundCallback, param);
411         napi_value argv[] = {napiDomainAccountInfo, napiCallback};
412         NapiCallVoidFunction(param->env, argv, ARG_SIZE_TWO, param->func);
413         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
414         param->lockInfo->count--;
415         param->lockInfo->condition.notify_all();
416         napi_close_handle_scope(param->env, scope);
417         if (napiCallback == nullptr) {
418             delete param;
419         }
420     };
421 }
422 
GetAuthStatusInfoCallback(napi_env env,napi_callback_info cbInfo)423 static napi_value GetAuthStatusInfoCallback(napi_env env, napi_callback_info cbInfo)
424 {
425     ACCOUNT_LOGI("GetAuthStatusInfoCallback enter");
426     JsDomainPluginParam *param = nullptr;
427     BusinessError error;
428     napi_value businessData = nullptr;
429     if (!GetPluginCallbackCommonParam(env, cbInfo, &param, error, &businessData)) {
430         AccountNapiThrow(env, ERR_JS_INVALID_PARAMETER, true);
431         return nullptr;
432     }
433     AuthStatusInfo info;
434     if ((error.code == 0) && (!ParseAuthStatusInfo(env, businessData, info))) {
435         ACCOUNT_LOGE("failed to parse AuthStatusInfo");
436         AccountNapiThrow(env, ERR_JS_INVALID_PARAMETER, true);
437         return nullptr;
438     }
439     Parcel parcel;
440     if (!info.Marshalling(parcel)) {
441         ACCOUNT_LOGE("fail to marshalling AuthStatusInfo");
442         AccountNapiThrow(env, ERR_JS_SYSTEM_SERVICE_EXCEPTION, true);
443         return nullptr;
444     }
445     param->callback->OnResult(error.code, parcel);
446     return nullptr;
447 }
448 
GetAccessTokenCallback(napi_env env,napi_callback_info cbInfo)449 static napi_value GetAccessTokenCallback(napi_env env, napi_callback_info cbInfo)
450 {
451     ACCOUNT_LOGI("GetAccessTokenCallback enter");
452     JsDomainPluginParam *param = nullptr;
453     BusinessError error;
454     napi_value businessData = nullptr;
455     if (!GetPluginCallbackCommonParam(env, cbInfo, &param, error, &businessData)) {
456         AccountNapiThrow(env, ERR_JS_SYSTEM_SERVICE_EXCEPTION, true);
457         return nullptr;
458     }
459     std::vector<uint8_t> accessToken;
460     if ((error.code == 0) && (ParseUint8TypedArrayToVector(env, businessData, accessToken) != napi_ok)) {
461         ACCOUNT_LOGE("Parse access token failed");
462         AccountNapiThrow(env, ERR_JS_SYSTEM_SERVICE_EXCEPTION, true);
463         return nullptr;
464     }
465     Parcel parcel;
466     if (!parcel.WriteUInt8Vector(accessToken)) {
467         ACCOUNT_LOGE("failed to write accessToken");
468         AccountNapiThrow(env, ERR_JS_SYSTEM_SERVICE_EXCEPTION, true);
469         return nullptr;
470     }
471     param->callback->OnResult(error.code, parcel);
472     return nullptr;
473 }
474 
IsUserTokenValidCallback(napi_env env,napi_callback_info cbInfo)475 static napi_value IsUserTokenValidCallback(napi_env env, napi_callback_info cbInfo)
476 {
477     ACCOUNT_LOGI("IsUserTokenValidCallback enter");
478     JsDomainPluginParam *param = nullptr;
479     BusinessError error;
480     napi_value businessData = nullptr;
481     if (!GetPluginCallbackCommonParam(env, cbInfo, &param, error, &businessData)) {
482         AccountNapiThrow(env, ERR_JS_SYSTEM_SERVICE_EXCEPTION, true);
483         return nullptr;
484     }
485     bool isTokenValid = false;
486     if ((error.code == 0) && (!GetBoolProperty(env, businessData, isTokenValid))) {
487         ACCOUNT_LOGE("Parse access token failed");
488         AccountNapiThrow(env, ERR_JS_SYSTEM_SERVICE_EXCEPTION, true);
489         return nullptr;
490     }
491     Parcel parcel;
492     if (!parcel.WriteBool(isTokenValid)) {
493         ACCOUNT_LOGE("failed to write accessToken");
494         AccountNapiThrow(env, ERR_JS_SYSTEM_SERVICE_EXCEPTION, true);
495         return nullptr;
496     }
497     param->callback->OnResult(error.code, parcel);
498     return nullptr;
499 }
500 
GetAccessTokenWork(JsDomainPluginParam * param)501 static std::function<void()> GetAccessTokenWork(JsDomainPluginParam *param)
502 {
503     return [param = std::move(param)] {
504         ACCOUNT_LOGI("Enter GetAccessTokenWork");
505         napi_handle_scope scope = nullptr;
506         napi_open_handle_scope(param->env, &scope);
507         if (scope == nullptr) {
508             ACCOUNT_LOGE("Fail to open scope");
509             delete param;
510             return;
511         }
512         napi_value napiCallback = CreatePluginAsyncCallback(param->env, GetAccessTokenCallback, param);
513         napi_value napiOptions = CreateNapiGetAccessTokenOptions(param);
514         napi_value argv[] = {napiOptions, napiCallback};
515         NapiCallVoidFunction(param->env, argv, ARG_SIZE_TWO, param->func);
516         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
517         param->lockInfo->count--;
518         param->lockInfo->condition.notify_all();
519         napi_close_handle_scope(param->env, scope);
520         if (napiCallback == nullptr) {
521             delete param;
522         }
523     };
524 }
525 
IsUserTokenValidWork(JsDomainPluginParam * param)526 static std::function<void()> IsUserTokenValidWork(JsDomainPluginParam *param)
527 {
528     return [param = std::move(param)] {
529         ACCOUNT_LOGI("Enter IsUserTokenValidWork");
530         napi_handle_scope scope = nullptr;
531         napi_open_handle_scope(param->env, &scope);
532         if (scope == nullptr) {
533             ACCOUNT_LOGE("Fail to open scope");
534             delete param;
535             return;
536         }
537         napi_value napiCallback = CreatePluginAsyncCallback(param->env, IsUserTokenValidCallback, param);
538         napi_value napiDomainAccountInfo = CreateNapiDomainAccountInfo(param->env, param->domainAccountInfo);
539         napi_value napiUserToken = CreateUint8Array(param->env, param->authData.data(), param->authData.size());
540         napi_value argv[] = {napiDomainAccountInfo, napiUserToken, napiCallback};
541         NapiCallVoidFunction(param->env, argv, ARG_SIZE_THREE, param->func);
542         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
543         param->lockInfo->count--;
544         param->lockInfo->condition.notify_all();
545         napi_close_handle_scope(param->env, scope);
546         if (napiCallback == nullptr) {
547             delete param;
548         }
549     };
550 }
551 
GetAuthStatusInfoWork(JsDomainPluginParam * param)552 static std::function<void()> GetAuthStatusInfoWork(JsDomainPluginParam *param)
553 {
554     return [param = std::move(param)] {
555         ACCOUNT_LOGI("Enter GetAuthStatusInfoWork");
556         napi_handle_scope scope = nullptr;
557         napi_open_handle_scope(param->env, &scope);
558         if (scope == nullptr) {
559             ACCOUNT_LOGE("Fail to open scope");
560             delete param;
561             return;
562         }
563         napi_value napiDomainAccountInfo = CreateNapiDomainAccountInfo(param->env, param->domainAccountInfo);
564         napi_value napiCallback = CreatePluginAsyncCallback(param->env, GetAuthStatusInfoCallback, param);
565         napi_value argv[] = { napiDomainAccountInfo, napiCallback };
566         NapiCallVoidFunction(param->env, argv, ARG_SIZE_TWO, param->func);
567         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
568         param->lockInfo->count--;
569         param->lockInfo->condition.notify_all();
570         napi_close_handle_scope(param->env, scope);
571         if (napiCallback == nullptr) {
572             delete param;
573         }
574     };
575 }
576 
NapiDomainAccountPlugin(napi_env env,const JsDomainPlugin & jsPlugin)577 NapiDomainAccountPlugin::NapiDomainAccountPlugin(napi_env env, const JsDomainPlugin &jsPlugin)
578     : env_(env), jsPlugin_(jsPlugin)
579 {}
580 
~NapiDomainAccountPlugin()581 NapiDomainAccountPlugin::~NapiDomainAccountPlugin()
582 {
583     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
584     lockInfo_.condition.wait(lock, [this] { return this->lockInfo_.count == 0; });
585     lockInfo_.count--;
586     if (env_ == nullptr) {
587         return;
588     }
589     ReleaseNapiRefAsync(env_, jsPlugin_.auth);
590     jsPlugin_.auth = nullptr;
591     ReleaseNapiRefAsync(env_, jsPlugin_.authWithPopup);
592     jsPlugin_.authWithPopup = nullptr;
593     ReleaseNapiRefAsync(env_, jsPlugin_.authWithToken);
594     jsPlugin_.authWithToken = nullptr;
595     ReleaseNapiRefAsync(env_, jsPlugin_.getAuthStatusInfo);
596     jsPlugin_.getAuthStatusInfo = nullptr;
597     ReleaseNapiRefAsync(env_, jsPlugin_.getDomainAccountInfo);
598     jsPlugin_.getDomainAccountInfo = nullptr;
599     ReleaseNapiRefAsync(env_, jsPlugin_.onAccountBound);
600     jsPlugin_.onAccountBound = nullptr;
601     ReleaseNapiRefAsync(env_, jsPlugin_.onAccountUnbound);
602     jsPlugin_.onAccountUnbound = nullptr;
603     ReleaseNapiRefAsync(env_, jsPlugin_.isAccountTokenValid);
604     jsPlugin_.isAccountTokenValid = nullptr;
605     ReleaseNapiRefAsync(env_, jsPlugin_.getAccessToken);
606     jsPlugin_.getAccessToken = nullptr;
607 }
608 
AuthCommonWork(JsDomainPluginParam * param)609 static std::function<void()> AuthCommonWork(JsDomainPluginParam *param)
610 {
611     return [param = std::move(param)] {
612         ACCOUNT_LOGI("Enter AuthCommonWork");
613         napi_handle_scope scope = nullptr;
614         napi_open_handle_scope(param->env, &scope);
615         if (scope == nullptr) {
616             ACCOUNT_LOGE("Fail to open scope");
617             delete param;
618             return;
619         }
620         int argc = 0;
621         napi_value argv[ARG_SIZE_THREE] = {0};
622         argv[argc++] = CreateNapiDomainAccountInfo(param->env, param->domainAccountInfo);
623         if (param->authMode != AUTH_WITH_POPUP_MODE) {
624             argv[argc++] = CreateUint8Array(param->env, param->authData.data(), param->authData.size());
625         }
626         argv[argc++] = CreateNapiDomainAuthCallback(param->env, param->callback);
627         NapiCallVoidFunction(param->env, argv, argc, param->func);
628         std::unique_lock<std::mutex> lock(param->lockInfo->mutex);
629         param->lockInfo->count--;
630         param->lockInfo->condition.notify_all();
631         napi_close_handle_scope(param->env, scope);
632         delete param;
633     };
634 }
635 
AuthCommon(AccountSA::AuthMode authMode,const AccountSA::DomainAccountInfo & info,const std::vector<uint8_t> & authData,const std::shared_ptr<AccountSA::DomainAccountCallback> & callback)636 void NapiDomainAccountPlugin::AuthCommon(AccountSA::AuthMode authMode, const AccountSA::DomainAccountInfo &info,
637     const std::vector<uint8_t> &authData, const std::shared_ptr<AccountSA::DomainAccountCallback> &callback)
638 {
639     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
640     if (lockInfo_.count < 0) {
641         ACCOUNT_LOGE("the plugin has been released");
642         return;
643     }
644     JsDomainPluginParam *param = new (std::nothrow) JsDomainPluginParam(env_);
645     if (param == nullptr) {
646         ACCOUNT_LOGE("Failed to create JsDomainPluginParam");
647         return;
648     }
649     switch (authMode) {
650         case AUTH_WITH_CREDENTIAL_MODE:
651             param->func = jsPlugin_.auth;
652             break;
653         case AUTH_WITH_POPUP_MODE:
654             param->func = jsPlugin_.authWithPopup;
655             break;
656         case AUTH_WITH_TOKEN_MODE:
657             param->func = jsPlugin_.authWithToken;
658             break;
659         default:
660             break;
661     }
662     if (param->func == nullptr) {
663         ACCOUNT_LOGE("func is nullptr");
664         delete param;
665         return;
666     }
667     param->lockInfo = &lockInfo_;
668     param->callback = callback;
669     param->domainAccountInfo = info;
670     param->authMode = authMode;
671     param->authData = authData;
672     if (napi_ok != napi_send_event(env_, AuthCommonWork(param), napi_eprio_vip)) {
673         ACCOUNT_LOGE("Post task failed");
674         delete param;
675         return;
676     }
677     lockInfo_.count++;
678     ACCOUNT_LOGI("Post task finish");
679 }
680 
Auth(const DomainAccountInfo & info,const std::vector<uint8_t> & credential,const std::shared_ptr<DomainAccountCallback> & callback)681 void NapiDomainAccountPlugin::Auth(const DomainAccountInfo &info, const std::vector<uint8_t> &credential,
682     const std::shared_ptr<DomainAccountCallback> &callback)
683 {
684     AuthCommon(AUTH_WITH_CREDENTIAL_MODE, info, credential, callback);
685 }
686 
AuthWithPopup(const DomainAccountInfo & info,const std::shared_ptr<DomainAccountCallback> & callback)687 void NapiDomainAccountPlugin::AuthWithPopup(
688     const DomainAccountInfo &info, const std::shared_ptr<DomainAccountCallback> &callback)
689 {
690     AuthCommon(AUTH_WITH_POPUP_MODE, info, {}, callback);
691 }
692 
AuthWithToken(const DomainAccountInfo & info,const std::vector<uint8_t> & token,const std::shared_ptr<DomainAccountCallback> & callback)693 void NapiDomainAccountPlugin::AuthWithToken(const DomainAccountInfo &info, const std::vector<uint8_t> &token,
694     const std::shared_ptr<DomainAccountCallback> &callback)
695 {
696     AuthCommon(AUTH_WITH_TOKEN_MODE, info, token, callback);
697 }
698 
GetAuthStatusInfo(const DomainAccountInfo & info,const std::shared_ptr<DomainAccountCallback> & callback)699 void NapiDomainAccountPlugin::GetAuthStatusInfo(
700     const DomainAccountInfo &info, const std::shared_ptr<DomainAccountCallback> &callback)
701 {
702     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
703     if (lockInfo_.count < 0) {
704         ACCOUNT_LOGE("the plugin has been released");
705         return;
706     }
707     if (jsPlugin_.getAuthStatusInfo == nullptr) {
708         ACCOUNT_LOGE("getAuthStatusInfo function of the js plugin is undefined");
709         return;
710     }
711     JsDomainPluginParam *param = new (std::nothrow) JsDomainPluginParam(env_);
712     if (param == nullptr) {
713         ACCOUNT_LOGE("Failed to create JsDomainPluginParam");
714         return;
715     }
716     param->lockInfo = &lockInfo_;
717     param->func = jsPlugin_.getAuthStatusInfo;
718     param->domainAccountInfo = info;
719     param->callback = callback;
720     if (napi_ok != napi_send_event(env_, GetAuthStatusInfoWork(param), napi_eprio_vip)) {
721         ACCOUNT_LOGE("Post task failed");
722         delete param;
723         return;
724     }
725     lockInfo_.count++;
726     ACCOUNT_LOGI("Post task finish");
727 }
728 
OnAccountBound(const DomainAccountInfo & info,const int32_t localId,const std::shared_ptr<AccountSA::DomainAccountCallback> & callback)729 void NapiDomainAccountPlugin::OnAccountBound(const DomainAccountInfo &info, const int32_t localId,
730     const std::shared_ptr<AccountSA::DomainAccountCallback> &callback)
731 {
732     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
733     if (lockInfo_.count < 0) {
734         ACCOUNT_LOGE("the plugin has been released");
735         return;
736     }
737     if (jsPlugin_.onAccountBound == nullptr) {
738         ACCOUNT_LOGE("OnAccountBound function of the js plugin is undefined");
739         return;
740     }
741     JsDomainPluginParam *param = new (std::nothrow) JsDomainPluginParam(env_);
742     if (param == nullptr) {
743         ACCOUNT_LOGE("Failed to create JsDomainPluginParam");
744         return;
745     }
746     param->lockInfo = &lockInfo_;
747     param->domainAccountInfo = info;
748     param->func = jsPlugin_.onAccountBound;
749     param->callback = callback;
750     param->userId = localId;
751     if (napi_ok != napi_send_event(env_, OnAccountBoundWork(param), napi_eprio_vip)) {
752         ACCOUNT_LOGE("Post task failed");
753         delete param;
754         return;
755     }
756     lockInfo_.count++;
757     ACCOUNT_LOGI("Post task finish");
758 }
759 
OnAccountUnBound(const DomainAccountInfo & info,const std::shared_ptr<AccountSA::DomainAccountCallback> & callback)760 void NapiDomainAccountPlugin::OnAccountUnBound(const DomainAccountInfo &info,
761     const std::shared_ptr<AccountSA::DomainAccountCallback> &callback)
762 {
763     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
764     if (lockInfo_.count < 0) {
765         ACCOUNT_LOGE("the plugin has been released");
766         return;
767     }
768     if (jsPlugin_.onAccountUnbound == nullptr) {
769         ACCOUNT_LOGE("OnAccountUnBound function of the js plugin is undefined");
770         return;
771     }
772     JsDomainPluginParam *param = new (std::nothrow) JsDomainPluginParam(env_);
773     if (param == nullptr) {
774         ACCOUNT_LOGE("Failed to create JsDomainPluginParam");
775         return;
776     }
777     param->lockInfo = &lockInfo_;
778     param->domainAccountInfo = info;
779     param->func = jsPlugin_.onAccountUnbound;
780     param->callback = callback;
781     if (napi_ok != napi_send_event(env_, OnAccountUnBoundWork(param), napi_eprio_vip)) {
782         ACCOUNT_LOGE("Post task failed");
783         delete param;
784         return;
785     }
786     lockInfo_.count++;
787     ACCOUNT_LOGI("Post task finish");
788 }
789 
GetDomainAccountInfo(const GetDomainAccountInfoOptions & options,const std::shared_ptr<AccountSA::DomainAccountCallback> & callback)790 void NapiDomainAccountPlugin::GetDomainAccountInfo(const GetDomainAccountInfoOptions &options,
791     const std::shared_ptr<AccountSA::DomainAccountCallback> &callback)
792 {
793     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
794     if (lockInfo_.count < 0) {
795         ACCOUNT_LOGE("the plugin has been released");
796         return;
797     }
798     if (jsPlugin_.getDomainAccountInfo == nullptr) {
799         ACCOUNT_LOGE("GetDomainAccountInfo function of the js plugin is undefined");
800         return;
801     }
802     JsDomainPluginParam *param = new (std::nothrow) JsDomainPluginParam(env_);
803     if (param == nullptr) {
804         ACCOUNT_LOGE("Failed to create JsDomainPluginParam");
805         return;
806     }
807     param->lockInfo = &lockInfo_;
808     param->domainAccountInfo = options.accountInfo;
809     param->callingUid = options.callingUid;
810     param->callback = callback;
811     param->func = jsPlugin_.getDomainAccountInfo;
812     if (napi_ok != napi_send_event(env_, GetDomainAccountInfoWork(param), napi_eprio_vip)) {
813         ACCOUNT_LOGE("Post task failed");
814         delete param;
815         return;
816     }
817     lockInfo_.count++;
818     ACCOUNT_LOGI("Post task finish");
819 }
820 
IsAccountTokenValid(const DomainAccountInfo & info,const std::vector<uint8_t> & token,const std::shared_ptr<DomainAccountCallback> & callback)821 void NapiDomainAccountPlugin::IsAccountTokenValid(const DomainAccountInfo &info, const std::vector<uint8_t> &token,
822     const std::shared_ptr<DomainAccountCallback> &callback)
823 {
824     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
825     if (lockInfo_.count < 0) {
826         ACCOUNT_LOGE("the plugin has been released");
827         return;
828     }
829     if (jsPlugin_.isAccountTokenValid == nullptr) {
830         ACCOUNT_LOGE("isUserTokenValid function of the js plugin is undefined");
831         return;
832     }
833     JsDomainPluginParam *param = new (std::nothrow) JsDomainPluginParam(env_);
834     if (param == nullptr) {
835         ACCOUNT_LOGE("Failed to create JsDomainPluginParam");
836         return;
837     }
838     param->lockInfo = &lockInfo_;
839     param->callback = callback;
840     param->authData = token;
841     param->domainAccountInfo = info;
842     param->func = jsPlugin_.isAccountTokenValid;
843     if (napi_ok != napi_send_event(env_, IsUserTokenValidWork(param), napi_eprio_vip)) {
844         ACCOUNT_LOGE("Post task failed");
845         delete param;
846         return;
847     }
848     lockInfo_.count++;
849     ACCOUNT_LOGI("Post task finish");
850 }
851 
GetAccessToken(const AccountSA::DomainAccountInfo & domainInfo,const std::vector<uint8_t> & accountToken,const AccountSA::GetAccessTokenOptions & option,const std::shared_ptr<AccountSA::DomainAccountCallback> & callback)852 void NapiDomainAccountPlugin::GetAccessToken(const AccountSA::DomainAccountInfo &domainInfo,
853     const std::vector<uint8_t> &accountToken, const AccountSA::GetAccessTokenOptions &option,
854     const std::shared_ptr<AccountSA::DomainAccountCallback> &callback)
855 {
856     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
857     if (lockInfo_.count < 0) {
858         ACCOUNT_LOGE("the plugin has been released");
859         return;
860     }
861     if (jsPlugin_.getAccessToken == nullptr) {
862         ACCOUNT_LOGE("getAccessToken function of the js plugin is undefined");
863         return;
864     }
865     JsDomainPluginParam *param = new (std::nothrow) JsDomainPluginParam(env_);
866     if (param == nullptr) {
867         ACCOUNT_LOGE("Failed to create JsDomainPluginParam");
868         return;
869     }
870     param->lockInfo = &lockInfo_;
871     param->domainAccountInfo = domainInfo;
872     param->callback = callback;
873     param->authData = accountToken;
874     param->option = option;
875     param->func = jsPlugin_.getAccessToken;
876     if (napi_ok != napi_send_event(env_, GetAccessTokenWork(param), napi_eprio_vip)) {
877         ACCOUNT_LOGE("Post task failed");
878         delete param;
879         return;
880     }
881     lockInfo_.count++;
882     ACCOUNT_LOGI("Post task finish");
883 }
884 
Init(napi_env env,napi_value exports)885 napi_value NapiDomainAccountManager::Init(napi_env env, napi_value exports)
886 {
887     napi_property_descriptor properties[] = {
888         DECLARE_NAPI_STATIC_FUNCTION("registerPlugin", RegisterPlugin),
889         DECLARE_NAPI_STATIC_FUNCTION("unregisterPlugin", UnregisterPlugin),
890         DECLARE_NAPI_STATIC_FUNCTION("auth", Auth),
891         DECLARE_NAPI_STATIC_FUNCTION("authWithPopup", AuthWithPopup),
892         DECLARE_NAPI_STATIC_FUNCTION("hasAccount", HasAccount),
893         DECLARE_NAPI_STATIC_FUNCTION("updateAccountToken", UpdateAccountToken),
894         DECLARE_NAPI_STATIC_FUNCTION("isAuthenticationExpired", IsAuthenticationExpired),
895         DECLARE_NAPI_STATIC_FUNCTION("getAccessToken", GetAccessToken),
896         DECLARE_NAPI_STATIC_FUNCTION("getAccountInfo", GetDomainAccountInfo),
897         DECLARE_NAPI_STATIC_FUNCTION("updateAccountInfo", UpdateAccountInfo),
898         DECLARE_NAPI_FUNCTION("registerPlugin", RegisterPlugin),
899         DECLARE_NAPI_FUNCTION("unregisterPlugin", UnregisterPlugin),
900         DECLARE_NAPI_FUNCTION("hasAccount", HasAccount),
901         DECLARE_NAPI_FUNCTION("updateAccountToken", UpdateAccountToken),
902         DECLARE_NAPI_FUNCTION("getAccessToken", GetAccessToken)
903     };
904     std::string className = "DomainAccountManager";
905     napi_value constructor = nullptr;
906     NAPI_CALL(env, napi_define_class(env, className.c_str(), className.length(), JsConstructor,
907         nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor));
908     NAPI_ASSERT(env, constructor != nullptr, "define js class DomainAccountManager failed");
909     napi_status status = napi_set_named_property(env, exports, className.c_str(), constructor);
910     NAPI_ASSERT(env, status == napi_ok, "set constructor to exports failed");
911     napi_value global = nullptr;
912     status = napi_get_global(env, &global);
913     NAPI_ASSERT(env, status == napi_ok, "get napi global failed");
914     status = napi_set_named_property(env, global, className.c_str(), constructor);
915     NAPI_ASSERT(env, status == napi_ok, "set constructor to global failed");
916     return exports;
917 }
918 
JsConstructor(napi_env env,napi_callback_info cbInfo)919 napi_value NapiDomainAccountManager::JsConstructor(napi_env env, napi_callback_info cbInfo)
920 {
921     napi_value thisVar = nullptr;
922     NAPI_CALL(env, napi_get_cb_info(env, cbInfo, nullptr, nullptr, &thisVar, nullptr));
923     return thisVar;
924 }
925 
ParseContextForRegisterPlugin(napi_env env,napi_callback_info cbInfo,JsDomainPlugin & jsPlugin)926 static bool ParseContextForRegisterPlugin(napi_env env, napi_callback_info cbInfo, JsDomainPlugin &jsPlugin)
927 {
928     size_t argc = ARG_SIZE_ONE;
929     napi_value argv[ARG_SIZE_ONE] = {nullptr};
930     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr), false);
931     if (argc != ARG_SIZE_ONE) {
932         ACCOUNT_LOGE("the number of parameter must be one, but got %{public}zu", argc);
933         return false;
934     }
935     if (!GetNamedJsFunction(env, argv[0], "getAuthStatusInfo", jsPlugin.getAuthStatusInfo)) {
936         ACCOUNT_LOGE("fail to parse getAuthStatusInfo function");
937         return false;
938     }
939     if (!GetNamedJsFunction(env, argv[0], "auth", jsPlugin.auth)) {
940         ACCOUNT_LOGE("fail to parse auth function");
941         return false;
942     }
943     if (!GetNamedJsFunction(env, argv[0], "authWithPopup", jsPlugin.authWithPopup)) {
944         ACCOUNT_LOGE("fail to parse authWithPopup function");
945         return false;
946     }
947     if (!GetNamedJsFunction(env, argv[0], "authWithToken", jsPlugin.authWithToken)) {
948         ACCOUNT_LOGE("fail to parse authWithToken function");
949         return false;
950     }
951     if (!GetNamedJsFunction(env, argv[0], "bindAccount", jsPlugin.onAccountBound)) {
952         ACCOUNT_LOGE("fail to parse onAccountBound function");
953         return false;
954     }
955     if (!GetNamedJsFunction(env, argv[0], "unbindAccount", jsPlugin.onAccountUnbound)) {
956         ACCOUNT_LOGE("fail to parse onAccountUnbound function");
957         return false;
958     }
959     if (!GetNamedJsFunction(env, argv[0], "getAccountInfo", jsPlugin.getDomainAccountInfo)) {
960         ACCOUNT_LOGE("fail to parse getDomainAccountInfo function");
961         return false;
962     }
963     if (!GetNamedJsFunction(env, argv[0], "isAccountTokenValid", jsPlugin.isAccountTokenValid)) {
964         ACCOUNT_LOGE("fail to parse isAccountTokenValid function");
965         return false;
966     }
967     if (!GetNamedJsFunction(env, argv[0], "getAccessToken", jsPlugin.getAccessToken)) {
968         ACCOUNT_LOGE("fail to parse getAccessToken function");
969         return false;
970     }
971     return true;
972 }
973 
RegisterPlugin(napi_env env,napi_callback_info cbInfo)974 napi_value NapiDomainAccountManager::RegisterPlugin(napi_env env, napi_callback_info cbInfo)
975 {
976     JsDomainPlugin jsPlugin;
977     if (!ParseContextForRegisterPlugin(env, cbInfo, jsPlugin)) {
978         std::string errMsg = "Parameter error. The type of \"plugin\" must be DomainPlugin";
979         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
980         return nullptr;
981     }
982     auto plugin = std::make_shared<NapiDomainAccountPlugin>(env, jsPlugin);
983     int32_t errCode = DomainAccountClient::GetInstance().RegisterPlugin(plugin);
984     if (errCode != ERR_OK) {
985         ACCOUNT_LOGE("failed to register plugin, errCode=%{public}d", errCode);
986         AccountNapiThrow(env, errCode, true);
987     }
988     return nullptr;
989 }
990 
ParseParamForHasDomainAccount(napi_env env,napi_callback_info cbInfo,HasDomainAccountAsyncContext * asyncContext)991 static bool ParseParamForHasDomainAccount(
992     napi_env env, napi_callback_info cbInfo, HasDomainAccountAsyncContext *asyncContext)
993 {
994     size_t argc = ARG_SIZE_TWO;
995     napi_value argv[ARG_SIZE_TWO] = {0};
996     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
997     if (argc < ARG_SIZE_ONE) {
998         ACCOUNT_LOGE("paramter number should be at least one");
999         std::string errMsg = "Parameter error. The number of parameters should be at least 1";
1000         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1001         return false;
1002     }
1003     if (argc == ARG_SIZE_TWO) {
1004         if (!GetCallbackProperty(env, argv[argc - 1], asyncContext->callbackRef, 1)) {
1005             ACCOUNT_LOGE("Get callbackRef failed");
1006             std::string errMsg = "Parameter error. The type of \"callback\" must be function";
1007             AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1008             return false;
1009         }
1010     }
1011     if (!ParseDomainAccountInfo(env, argv[0], asyncContext->domainInfo)) {
1012         ACCOUNT_LOGE("get domainInfo failed");
1013         std::string errMsg = "Parameter error. The type of \"domainAccountInfo\" must be DomainAccountInfo";
1014         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1015         return false;
1016     }
1017     return true;
1018 }
1019 
UnregisterPlugin(napi_env env,napi_callback_info cbInfo)1020 napi_value NapiDomainAccountManager::UnregisterPlugin(napi_env env, napi_callback_info cbInfo)
1021 {
1022     int32_t errCode = DomainAccountClient::GetInstance().UnregisterPlugin();
1023     if (errCode != ERR_OK) {
1024         ACCOUNT_LOGE("failed to unregister plugin, errCode=%{public}d", errCode);
1025         AccountNapiThrow(env, errCode, true);
1026     }
1027     return nullptr;
1028 }
1029 
ParseContextForAuth(napi_env env,napi_callback_info cbInfo,JsDomainPluginParam & authContext)1030 static bool ParseContextForAuth(napi_env env, napi_callback_info cbInfo, JsDomainPluginParam &authContext)
1031 {
1032     size_t argc = ARG_SIZE_THREE;
1033     napi_value argv[ARG_SIZE_THREE] = {nullptr};
1034     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr), false);
1035     if (argc != ARG_SIZE_THREE) {
1036         ACCOUNT_LOGE("the number of parameter must be one, but got %{public}zu", argc);
1037         std::string errMsg = "Parameter error. The number of parameters should be at least 3";
1038         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1039         return false;
1040     }
1041     int index = 0;
1042     if (!ParseDomainAccountInfo(env, argv[index++], authContext.domainAccountInfo)) {
1043         ACCOUNT_LOGE("get domainInfo failed");
1044         std::string errMsg = "Parameter error. The type of \"domainAccountInfo\" must be DomainAccountInfo";
1045         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1046         return false;
1047     }
1048     if (ParseUint8TypedArrayToVector(env, argv[index++], authContext.authData) != napi_ok) {
1049         ACCOUNT_LOGE("get credential failed");
1050         std::string errMsg = "Parameter error. The type of \"credential\" must be Uint8Array";
1051         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1052         return false;
1053     }
1054     if (!GetNamedJsFunction(env, argv[index++], "onResult", authContext.callbackRef)) {
1055         ACCOUNT_LOGE("get callback failed");
1056         std::string errMsg = "Parameter error. The type of \"callback\" must be IUserAuthCallback";
1057         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1058         return false;
1059     }
1060     return true;
1061 }
1062 
AuthCompletedCallback(napi_env env,napi_status status,void * data)1063 void AuthCompletedCallback(napi_env env, napi_status status, void *data)
1064 {
1065     delete reinterpret_cast<JsDomainPluginParam *>(data);
1066 }
1067 
Auth(napi_env env,napi_callback_info cbInfo)1068 napi_value NapiDomainAccountManager::Auth(napi_env env, napi_callback_info cbInfo)
1069 {
1070     auto authContext = std::make_unique<JsDomainPluginParam>(env);
1071     if (!ParseContextForAuth(env, cbInfo, *authContext)) {
1072         return nullptr;
1073     }
1074     napi_value resource = nullptr;
1075     NAPI_CALL(env, napi_create_string_utf8(env, "Auth", NAPI_AUTO_LENGTH, &resource));
1076     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1077         [](napi_env env, void *data) {
1078             JsDomainPluginParam *param = reinterpret_cast<JsDomainPluginParam *>(data);
1079             auto jsCallback = std::make_shared<JsDomainAccountAuthCallback>(env, param->callbackRef);
1080             auto callback = std::make_shared<NapiDomainAccountCallback>(env, jsCallback);
1081             param->callbackRef = nullptr;
1082             param->errCode = DomainAccountClient::GetInstance().Auth(
1083                 param->domainAccountInfo, param->authData, callback);
1084             if (param->errCode != ERR_OK) {
1085                 Parcel emptyParcel;
1086                 AccountSA::DomainAuthResult emptyResult;
1087                 if (!emptyResult.Marshalling(emptyParcel)) {
1088                     ACCOUNT_LOGE("authResult Marshalling failed");
1089                     return;
1090                 }
1091                 callback->OnResult(ConvertToJSErrCode(param->errCode), emptyParcel);
1092             }
1093         },
1094         AuthCompletedCallback,
1095         reinterpret_cast<void *>(authContext.get()), &authContext->work));
1096     NAPI_CALL(env, napi_queue_async_work_with_qos(env, authContext->work, napi_qos_user_initiated));
1097     authContext.release();
1098     return nullptr;
1099 }
1100 
ParseContextForAuthWithPopup(napi_env env,napi_callback_info cbInfo,JsDomainPluginParam & authWithPopupContext)1101 static bool ParseContextForAuthWithPopup(
1102     napi_env env, napi_callback_info cbInfo, JsDomainPluginParam &authWithPopupContext)
1103 {
1104     size_t argc = ARG_SIZE_TWO;
1105     napi_value argv[ARG_SIZE_TWO] = {nullptr};
1106     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr), false);
1107     if (argc < ARG_SIZE_ONE) {
1108         ACCOUNT_LOGE("need input at least one parameter, but got %{public}zu", argc);
1109         std::string errMsg = "Parameter error. The number of parameters should be at least 1";
1110         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1111         return false;
1112     }
1113     if (!GetNamedJsFunction(env, argv[argc - 1], "onResult", authWithPopupContext.callbackRef)) {
1114         ACCOUNT_LOGE("get callback failed");
1115         std::string errMsg = "Parameter error. The type of \"callback\" must be function";
1116         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1117         return false;
1118     }
1119     if (argc == ARG_SIZE_TWO) {
1120         napi_valuetype valueType = napi_undefined;
1121         napi_typeof(env, argv[0], &valueType);
1122         if ((valueType == napi_undefined) || (valueType == napi_null)) {
1123             ACCOUNT_LOGI("the userId is undefined or null");
1124         } else {
1125             if (!GetIntProperty(env, argv[0], authWithPopupContext.userId)) {
1126                 std::string errMsg = "Parameter error. The type of \"localId\" must be number";
1127                 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1128                 ACCOUNT_LOGE("get id failed");
1129                 return false;
1130             }
1131         }
1132     }
1133     return true;
1134 }
1135 
GetAccessTokenExecuteCB(napi_env env,void * data)1136 static void GetAccessTokenExecuteCB(napi_env env, void *data)
1137 {
1138     GetAccessTokenAsyncContext *asyncContext = reinterpret_cast<GetAccessTokenAsyncContext *>(data);
1139     auto callback =
1140         std::make_shared<NapiGetAccessTokenCallback>(env, asyncContext->callbackRef, asyncContext->deferred);
1141     asyncContext->errCode = DomainAccountClient::GetInstance().GetAccessToken(
1142         asyncContext->domainInfo, asyncContext->getTokenParams, callback);
1143     if (asyncContext->errCode != ERR_OK) {
1144         std::vector<uint8_t> accessToken;
1145         callback->OnResult(asyncContext->errCode, accessToken);
1146     }
1147     asyncContext->callbackRef = nullptr;
1148 }
1149 
GetAccessTokenCompleteCB(napi_env env,napi_status status,void * data)1150 static void GetAccessTokenCompleteCB(napi_env env, napi_status status, void *data)
1151 {
1152     delete reinterpret_cast<GetAccessTokenAsyncContext *>(data);
1153 }
1154 
GetAccessTokenCompleteWork(GetAccessTokenAsyncContext * param)1155 static std::function<void()> GetAccessTokenCompleteWork(GetAccessTokenAsyncContext *param)
1156 {
1157     return [asyncContext = std::move(param)] {
1158         ACCOUNT_LOGI("Enter GetAccessTokenCompleteWork");
1159         napi_handle_scope scope = nullptr;
1160         napi_open_handle_scope(asyncContext->env, &scope);
1161         if (scope == nullptr) {
1162             ACCOUNT_LOGE("Fail to open scope");
1163             delete asyncContext;
1164             return;
1165         }
1166         napi_value errJs = nullptr;
1167         napi_value dataJs = nullptr;
1168         if (asyncContext->errCode == ERR_OK) {
1169             dataJs =
1170                 CreateUint8Array(asyncContext->env, asyncContext->accessToken.data(), asyncContext->accessToken.size());
1171         } else {
1172             errJs = GenerateBusinessError(asyncContext->env, asyncContext->errCode);
1173         }
1174         ReturnCallbackOrPromise(asyncContext->env, asyncContext, errJs, dataJs);
1175         napi_close_handle_scope(asyncContext->env, scope);
1176         delete asyncContext;
1177     };
1178 }
1179 
AuthWithPopup(napi_env env,napi_callback_info cbInfo)1180 napi_value NapiDomainAccountManager::AuthWithPopup(napi_env env, napi_callback_info cbInfo)
1181 {
1182     auto authWithPopupContext = std::make_unique<JsDomainPluginParam>(env);
1183     if (!ParseContextForAuthWithPopup(env, cbInfo, *authWithPopupContext)) {
1184         return nullptr;
1185     }
1186     napi_value resource = nullptr;
1187     NAPI_CALL(env, napi_create_string_utf8(env, "AuthWithPopup", NAPI_AUTO_LENGTH, &resource));
1188     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1189         [](napi_env env, void *data) {
1190             JsDomainPluginParam *param = reinterpret_cast<JsDomainPluginParam *>(data);
1191             auto jsCallback = std::make_shared<JsDomainAccountAuthCallback>(env, param->callbackRef);
1192             auto callback = std::make_shared<NapiDomainAccountCallback>(env, jsCallback);
1193             param->callbackRef = nullptr;
1194             param->errCode = DomainAccountClient::GetInstance().AuthWithPopup(param->userId, callback);
1195             if (param->errCode != ERR_OK) {
1196                 Parcel emptyParcel;
1197                 AccountSA::DomainAuthResult emptyResult;
1198                 if (!emptyResult.Marshalling(emptyParcel)) {
1199                     ACCOUNT_LOGE("authResult Marshalling failed");
1200                     return;
1201                 }
1202                 callback->OnResult(ConvertToJSErrCode(param->errCode), emptyParcel);
1203             }
1204         },
1205         AuthCompletedCallback,
1206         reinterpret_cast<void *>(authWithPopupContext.get()), &authWithPopupContext->work));
1207     NAPI_CALL(env, napi_queue_async_work_with_qos(env, authWithPopupContext->work, napi_qos_user_initiated));
1208     authWithPopupContext.release();
1209     return nullptr;
1210 }
1211 
HasDomainAccountCompletedWork(HasDomainAccountAsyncContext * param)1212 static std::function<void()> HasDomainAccountCompletedWork(HasDomainAccountAsyncContext *param)
1213 {
1214     return [asyncContext = std::move(param)] {
1215         ACCOUNT_LOGI("Enter HasDomainAccountCompletedWork");
1216         napi_handle_scope scope = nullptr;
1217         napi_open_handle_scope(asyncContext->env, &scope);
1218         if (scope == nullptr) {
1219             ACCOUNT_LOGE("Fail to open scope");
1220             delete asyncContext;
1221             return;
1222         }
1223         napi_value errJs = nullptr;
1224         napi_value dataJs = nullptr;
1225         if (asyncContext->errCode == ERR_OK) {
1226             napi_get_boolean(asyncContext->env, asyncContext->isHasDomainAccount, &dataJs);
1227         } else {
1228             errJs = GenerateBusinessError(asyncContext->env, asyncContext->errCode);
1229         }
1230         ReturnCallbackOrPromise(asyncContext->env, asyncContext, errJs, dataJs);
1231         napi_close_handle_scope(asyncContext->env, scope);
1232         delete asyncContext;
1233     };
1234 }
1235 
NapiHasDomainInfoCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)1236 NapiHasDomainInfoCallback::NapiHasDomainInfoCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
1237     : env_(env), callbackRef_(env, callbackRef), deferred_(deferred)
1238 {}
1239 
OnResult(const int32_t errCode,Parcel & parcel)1240 void NapiHasDomainInfoCallback::OnResult(const int32_t errCode, Parcel &parcel)
1241 {
1242     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
1243     if ((callbackRef_.callbackRef == nullptr) && (deferred_ == nullptr)) {
1244         ACCOUNT_LOGE("js callback is nullptr");
1245         return;
1246     }
1247     auto *asyncContext = new (std::nothrow) HasDomainAccountAsyncContext(env_);
1248     if (asyncContext == nullptr) {
1249         return;
1250     }
1251     if (errCode == ERR_OK) {
1252         parcel.ReadBool(asyncContext->isHasDomainAccount);
1253     }
1254     asyncContext->errCode = errCode;
1255     asyncContext->callbackRef = callbackRef_.callbackRef;
1256     asyncContext->deferred = deferred_;
1257     if (napi_ok != napi_send_event(env_, HasDomainAccountCompletedWork(asyncContext), napi_eprio_vip)) {
1258         ACCOUNT_LOGE("Post task failed");
1259         delete asyncContext;
1260         return;
1261     }
1262     callbackRef_.callbackRef = nullptr;
1263     deferred_ = nullptr;
1264     ACCOUNT_LOGI("Post task finish");
1265 }
1266 
NapiGetAccessTokenCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)1267 NapiGetAccessTokenCallback::NapiGetAccessTokenCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
1268     : env_(env), callbackRef_(env, callbackRef), deferred_(deferred)
1269 {}
1270 
OnResult(const int32_t errCode,const std::vector<uint8_t> & accessToken)1271 void NapiGetAccessTokenCallback::OnResult(const int32_t errCode, const std::vector<uint8_t> &accessToken)
1272 {
1273     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
1274     if ((callbackRef_.callbackRef == nullptr) && (deferred_ == nullptr)) {
1275         ACCOUNT_LOGE("js callback is nullptr");
1276         return;
1277     }
1278     auto *asyncContext = new (std::nothrow) GetAccessTokenAsyncContext(env_);
1279     if (asyncContext == nullptr) {
1280         return;
1281     }
1282     asyncContext->errCode = errCode;
1283     asyncContext->accessToken = accessToken;
1284     asyncContext->callbackRef = callbackRef_.callbackRef;
1285     asyncContext->deferred = deferred_;
1286     if (napi_ok != napi_send_event(env_, GetAccessTokenCompleteWork(asyncContext), napi_eprio_vip)) {
1287         ACCOUNT_LOGE("Post task failed");
1288         delete asyncContext;
1289         return;
1290     }
1291     callbackRef_.callbackRef = nullptr;
1292     deferred_ = nullptr;
1293     ACCOUNT_LOGI("Post task finish");
1294 }
1295 
HasDomainAccountCompleteCB(napi_env env,napi_status status,void * data)1296 static void HasDomainAccountCompleteCB(napi_env env, napi_status status, void *data)
1297 {
1298     delete reinterpret_cast<HasDomainAccountAsyncContext *>(data);
1299 }
1300 
HasDomainAccountExecuteCB(napi_env env,void * data)1301 static void HasDomainAccountExecuteCB(napi_env env, void *data)
1302 {
1303     HasDomainAccountAsyncContext *asyncContext = reinterpret_cast<HasDomainAccountAsyncContext *>(data);
1304     auto callback = std::make_shared<NapiHasDomainInfoCallback>(env, asyncContext->callbackRef, asyncContext->deferred);
1305     asyncContext->errCode = DomainAccountClient::GetInstance().HasAccount(asyncContext->domainInfo, callback);
1306     if (asyncContext->errCode != ERR_OK) {
1307         Parcel emptyParcel;
1308         callback->OnResult(asyncContext->errCode, emptyParcel);
1309     }
1310     asyncContext->callbackRef = nullptr;
1311 }
1312 
UpdateAccountTokenExecuteCB(napi_env env,void * data)1313 static void UpdateAccountTokenExecuteCB(napi_env env, void *data)
1314 {
1315     UpdateAccountTokenAsyncContext *asyncContext = reinterpret_cast<UpdateAccountTokenAsyncContext *>(data);
1316     asyncContext->errCode =
1317         DomainAccountClient::GetInstance().UpdateAccountToken(asyncContext->domainInfo, asyncContext->token);
1318 }
1319 
UpdateAccountTokenCompletedCB(napi_env env,napi_status status,void * data)1320 static void UpdateAccountTokenCompletedCB(napi_env env, napi_status status, void *data)
1321 {
1322     UpdateAccountTokenAsyncContext *asyncContext = reinterpret_cast<UpdateAccountTokenAsyncContext *>(data);
1323     napi_value errJs = nullptr;
1324     napi_value dataJs = nullptr;
1325     if (asyncContext->errCode != ERR_OK) {
1326         errJs = GenerateBusinessError(asyncContext->env, asyncContext->errCode);
1327     } else {
1328         napi_get_null(asyncContext->env, &dataJs);
1329     }
1330     ProcessCallbackOrPromise(env, asyncContext, errJs, dataJs);
1331     delete asyncContext;
1332 }
1333 
UpdateAccountToken(napi_env env,napi_callback_info cbInfo)1334 napi_value NapiDomainAccountManager::UpdateAccountToken(napi_env env, napi_callback_info cbInfo)
1335 {
1336     auto context = std::make_unique<UpdateAccountTokenAsyncContext>(env);
1337     if (!ParseParamForUpdateAccountToken(env, cbInfo, context.get())) {
1338         return nullptr;
1339     }
1340     napi_value result = nullptr;
1341     if (context->callbackRef == nullptr) {
1342         NAPI_CALL(env, napi_create_promise(env, &context->deferred, &result));
1343     }
1344     napi_value resource = nullptr;
1345     NAPI_CALL(env, napi_create_string_utf8(env, "updateAccountToken", NAPI_AUTO_LENGTH, &resource));
1346     NAPI_CALL(env, napi_create_async_work(env,
1347         nullptr,
1348         resource,
1349         UpdateAccountTokenExecuteCB,
1350         UpdateAccountTokenCompletedCB,
1351         reinterpret_cast<void *>(context.get()),
1352         &context->work));
1353     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
1354     context.release();
1355     return result;
1356 }
1357 
IsAuthenticationExpiredExecuteCB(napi_env env,void * data)1358 static void IsAuthenticationExpiredExecuteCB(napi_env env, void *data)
1359 {
1360     IsAuthenticationExpiredAsyncContext *asyncContext = reinterpret_cast<IsAuthenticationExpiredAsyncContext *>(data);
1361     asyncContext->errCode =
1362         DomainAccountClient::GetInstance().IsAuthenticationExpired(asyncContext->domainInfo, asyncContext->isExpired);
1363 }
1364 
IsAuthenticationExpiredCompletedCB(napi_env env,napi_status status,void * data)1365 static void IsAuthenticationExpiredCompletedCB(napi_env env, napi_status status, void *data)
1366 {
1367     IsAuthenticationExpiredAsyncContext *asyncContext = reinterpret_cast<IsAuthenticationExpiredAsyncContext *>(data);
1368     std::unique_ptr<IsAuthenticationExpiredAsyncContext> asyncContextPtr{asyncContext};
1369     napi_value errJs = nullptr;
1370     napi_value dataJs = nullptr;
1371     if (asyncContext->errCode == ERR_OK) {
1372         NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &errJs));
1373         NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, asyncContext->isExpired, &dataJs));
1374     } else {
1375         errJs = GenerateBusinessError(env, asyncContext->errCode);
1376         NAPI_CALL_RETURN_VOID(env, napi_get_null(env, &dataJs));
1377     }
1378     ProcessCallbackOrPromise(env, asyncContext, errJs, dataJs);
1379 }
1380 
IsAuthenticationExpired(napi_env env,napi_callback_info cbInfo)1381 napi_value NapiDomainAccountManager::IsAuthenticationExpired(napi_env env, napi_callback_info cbInfo)
1382 {
1383     auto asyncContextPtr = std::make_unique<IsAuthenticationExpiredAsyncContext>(env);
1384     if (!ParseParamForIsAuthenticationExpired(env, cbInfo, asyncContextPtr.get())) {
1385         return nullptr;
1386     }
1387     napi_value result = nullptr;
1388     NAPI_CALL(env, napi_create_promise(env, &asyncContextPtr->deferred, &result));
1389 
1390     napi_value resource = nullptr;
1391     NAPI_CALL(env, napi_create_string_utf8(env, "IsAuthenticationExpired", NAPI_AUTO_LENGTH, &resource));
1392     NAPI_CALL(env, napi_create_async_work(env,
1393         nullptr,
1394         resource,
1395         IsAuthenticationExpiredExecuteCB,
1396         IsAuthenticationExpiredCompletedCB,
1397         reinterpret_cast<void *>(asyncContextPtr.get()),
1398         &asyncContextPtr->work));
1399     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContextPtr->work, napi_qos_default));
1400     asyncContextPtr.release();
1401     return result;
1402 }
1403 
GetAccessToken(napi_env env,napi_callback_info cbInfo)1404 napi_value NapiDomainAccountManager::GetAccessToken(napi_env env, napi_callback_info cbInfo)
1405 {
1406     auto context = std::make_unique<GetAccessTokenAsyncContext>(env);
1407     if (!ParseParamForGetAccessToken(env, cbInfo, context.get())) {
1408         return nullptr;
1409     }
1410     napi_value result = nullptr;
1411     if (context->callbackRef == nullptr) {
1412         NAPI_CALL(env, napi_create_promise(env, &context->deferred, &result));
1413     }
1414     napi_value resource = nullptr;
1415     NAPI_CALL(env, napi_create_string_utf8(env, "getAccessToken", NAPI_AUTO_LENGTH, &resource));
1416     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1417         GetAccessTokenExecuteCB, GetAccessTokenCompleteCB,
1418         reinterpret_cast<void *>(context.get()), &context->work));
1419     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
1420     context.release();
1421     return result;
1422 }
1423 
HasAccount(napi_env env,napi_callback_info cbInfo)1424 napi_value NapiDomainAccountManager::HasAccount(napi_env env, napi_callback_info cbInfo)
1425 {
1426     auto context = std::make_unique<HasDomainAccountAsyncContext>(env);
1427     if (!ParseParamForHasDomainAccount(env, cbInfo, context.get())) {
1428         return nullptr;
1429     }
1430     napi_value result = nullptr;
1431     if (context->callbackRef == nullptr) {
1432         NAPI_CALL(env, napi_create_promise(env, &context->deferred, &result));
1433     }
1434     napi_value resource = nullptr;
1435     NAPI_CALL(env, napi_create_string_utf8(env, "hasAccount", NAPI_AUTO_LENGTH, &resource));
1436     NAPI_CALL(env, napi_create_async_work(env,
1437         nullptr,
1438         resource,
1439         HasDomainAccountExecuteCB,
1440         HasDomainAccountCompleteCB,
1441         reinterpret_cast<void *>(context.get()),
1442         &context->work));
1443     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
1444     context.release();
1445     return result;
1446 }
1447 
ParseGetDomainAccountInfoOptions(napi_env env,napi_value object,DomainAccountInfo & info)1448 static bool ParseGetDomainAccountInfoOptions(napi_env env, napi_value object, DomainAccountInfo &info)
1449 {
1450     napi_valuetype type = napi_undefined;
1451     napi_typeof(env, object, &type);
1452     if (type != napi_object) {
1453         ACCOUNT_LOGE("Value is not an object.");
1454         return false;
1455     }
1456     if (!GetStringPropertyByKey(env, object, "accountName", info.accountName_)) {
1457         ACCOUNT_LOGE("get domainInfo's accountName failed");
1458         return false;
1459     }
1460     bool hasProp = false;
1461     napi_has_named_property(env, object, "domain", &hasProp);
1462     if (hasProp) {
1463         napi_value value = nullptr;
1464         napi_get_named_property(env, object, "domain", &value);
1465         napi_valuetype valueType = napi_undefined;
1466         napi_typeof(env, value, &valueType);
1467         if ((valueType == napi_undefined) || (valueType == napi_null)) {
1468             ACCOUNT_LOGI("the accountId is undefined or null");
1469         } else if (!GetStringPropertyByKey(env, object, "domain", info.domain_)) {
1470             ACCOUNT_LOGE("get domainInfo's domain failed");
1471             return false;
1472         }
1473     }
1474     return true;
1475 }
1476 
ParseParamForGetAccountInfo(napi_env env,napi_callback_info cbInfo,GetAccountInfoAsyncContext * asyncContext)1477 static bool ParseParamForGetAccountInfo(
1478     napi_env env, napi_callback_info cbInfo, GetAccountInfoAsyncContext *asyncContext)
1479 {
1480     size_t argc = ARG_SIZE_TWO;
1481     napi_value argv[ARG_SIZE_TWO] = {0};
1482     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
1483     if (argc < ARG_SIZE_ONE) {
1484         ACCOUNT_LOGE("the parameter of number should be at least one");
1485         std::string errMsg = "Parameter error. The number of parameters should be at least 1";
1486         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1487         return false;
1488     }
1489     if (argc == ARG_SIZE_TWO) {
1490         if (!GetCallbackProperty(env, argv[argc - 1], asyncContext->callbackRef, 1)) {
1491             ACCOUNT_LOGE("Get callbackRef failed");
1492             std::string errMsg = "Parameter error. The type of \"callback\" must be function";
1493             AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1494             return false;
1495         }
1496     }
1497     if (!ParseGetDomainAccountInfoOptions(env, argv[0], asyncContext->domainInfo)) {
1498         ACCOUNT_LOGE("get domainInfo failed");
1499         std::string errMsg = "Parameter error. The type of \"options\" must be GetDomainAccountInfoOptions";
1500         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1501         return false;
1502     }
1503     return true;
1504 }
1505 
GetAccountInfoCompleteWork(GetAccountInfoAsyncContext * param)1506 static std::function<void()> GetAccountInfoCompleteWork(GetAccountInfoAsyncContext *param)
1507 {
1508     return [asyncContext = std::move(param)] {
1509         napi_handle_scope scope = nullptr;
1510         napi_open_handle_scope(asyncContext->env, &scope);
1511         if (scope == nullptr) {
1512             ACCOUNT_LOGE("Fail to open scope");
1513             if (asyncContext != nullptr) {
1514                 delete asyncContext;
1515             }
1516             return;
1517         }
1518         napi_value errJs = nullptr;
1519         napi_value dataJs = nullptr;
1520         if (asyncContext->errCode == ERR_OK) {
1521             dataJs = AppExecFwk::WrapWantParams(asyncContext->env, asyncContext->getAccountInfoParams);
1522         } else {
1523             errJs = GenerateBusinessError(asyncContext->env, asyncContext->errCode);
1524         }
1525         ReturnCallbackOrPromise(asyncContext->env, asyncContext, errJs, dataJs);
1526         napi_close_handle_scope(asyncContext->env, scope);
1527         delete asyncContext;
1528     };
1529 }
1530 
NapiGetAccountInfoCallback(napi_env env,napi_ref callbackRef,napi_deferred deferred)1531 NapiGetAccountInfoCallback::NapiGetAccountInfoCallback(napi_env env, napi_ref callbackRef, napi_deferred deferred)
1532     : env_(env), callbackRef_(callbackRef), deferred_(deferred)
1533 {}
1534 
OnResult(int32_t errCode,Parcel & parcel)1535 void NapiGetAccountInfoCallback::OnResult(int32_t errCode, Parcel &parcel)
1536 {
1537     std::unique_lock<std::mutex> lock(lockInfo_.mutex);
1538     if ((callbackRef_ == nullptr) && (deferred_ == nullptr)) {
1539         ACCOUNT_LOGE("js callback is nullptr");
1540         return;
1541     }
1542     auto *asyncContext = new (std::nothrow) GetAccountInfoAsyncContext(env_);
1543     if (asyncContext == nullptr) {
1544         return;
1545     }
1546     if (errCode == ERR_OK) {
1547         std::shared_ptr<AAFwk::WantParams> parameters(AAFwk::WantParams::Unmarshalling(parcel));
1548         if (parameters == nullptr) {
1549             ACCOUNT_LOGE("Parameters unmarshalling error");
1550             errCode = ERR_ACCOUNT_COMMON_READ_PARCEL_ERROR;
1551         } else {
1552             asyncContext->getAccountInfoParams = *parameters;
1553         }
1554     }
1555     asyncContext->errCode = errCode;
1556     asyncContext->callbackRef = callbackRef_;
1557     asyncContext->deferred = deferred_;
1558     if (napi_ok !=  napi_send_event(env_, GetAccountInfoCompleteWork(asyncContext), napi_eprio_vip)) {
1559         ACCOUNT_LOGE("Post task failed");
1560         delete asyncContext;
1561         return;
1562     }
1563     callbackRef_ = nullptr;
1564     deferred_ = nullptr;
1565 }
1566 
GetAccountInfoExecuteCB(napi_env env,void * data)1567 static void GetAccountInfoExecuteCB(napi_env env, void *data)
1568 {
1569     GetAccountInfoAsyncContext *asyncContext = reinterpret_cast<GetAccountInfoAsyncContext *>(data);
1570     auto callback =
1571         std::make_shared<NapiGetAccountInfoCallback>(env, asyncContext->callbackRef, asyncContext->deferred);
1572     asyncContext->errCode = DomainAccountClient::GetInstance().GetDomainAccountInfo(asyncContext->domainInfo, callback);
1573     if (asyncContext->errCode != ERR_OK) {
1574         Parcel emptyParcel;
1575         callback->OnResult(asyncContext->errCode, emptyParcel);
1576     }
1577     asyncContext->callbackRef = nullptr;
1578 }
1579 
GetAccountInfoCompleteCB(napi_env env,napi_status status,void * data)1580 static void GetAccountInfoCompleteCB(napi_env env, napi_status status, void *data)
1581 {
1582     delete reinterpret_cast<GetAccountInfoAsyncContext *>(data);
1583 }
1584 
GetDomainAccountInfo(napi_env env,napi_callback_info cbInfo)1585 napi_value NapiDomainAccountManager::GetDomainAccountInfo(napi_env env, napi_callback_info cbInfo)
1586 {
1587     auto context = std::make_unique<GetAccountInfoAsyncContext>(env);
1588     if (!ParseParamForGetAccountInfo(env, cbInfo, context.get())) {
1589         return nullptr;
1590     }
1591     napi_value result = nullptr;
1592     if (context->callbackRef == nullptr) {
1593         NAPI_CALL(env, napi_create_promise(env, &context->deferred, &result));
1594     }
1595     napi_value resource = nullptr;
1596     NAPI_CALL(env, napi_create_string_utf8(env, "getAccountInfo", NAPI_AUTO_LENGTH, &resource));
1597     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1598         GetAccountInfoExecuteCB, GetAccountInfoCompleteCB,
1599         reinterpret_cast<void *>(context.get()), &context->work));
1600     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
1601     context.release();
1602     return result;
1603 }
1604 
ParseParamForUpdateAccountInfo(napi_env env,napi_callback_info cbInfo,UpdateAccountInfoAsyncContext * asyncContext)1605 static bool ParseParamForUpdateAccountInfo(
1606     napi_env env, napi_callback_info cbInfo, UpdateAccountInfoAsyncContext *asyncContext)
1607 {
1608     size_t argc = ARG_SIZE_TWO;
1609     napi_value argv[ARG_SIZE_TWO] = {0};
1610     napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr);
1611     if (argc != ARG_SIZE_TWO) {
1612         ACCOUNT_LOGE("The parameter of number should be two");
1613         std::string errMsg = "Parameter error. The number of parameters should be at least 2";
1614         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1615         return false;
1616     }
1617     if (!ParseDomainAccountInfo(env, argv[0], asyncContext->oldAccountInfo)) {
1618         ACCOUNT_LOGE("Get oldAccountInfo failed");
1619         std::string errMsg = "Parameter error. The type of \"oldAccountInfo\" must be DomainAccountInfo";
1620         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1621         return false;
1622     }
1623     if (!ParseDomainAccountInfo(env, argv[1], asyncContext->newAccountInfo)) {
1624         ACCOUNT_LOGE("Get newAccountInfo failed");
1625         std::string errMsg = "Parameter error. The type of \"newAccountInfo\" must be DomainAccountInfo";
1626         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, true);
1627         return false;
1628     }
1629     return true;
1630 }
1631 
UpdateAccountInfoExecuteCB(napi_env env,void * data)1632 static void UpdateAccountInfoExecuteCB(napi_env env, void *data)
1633 {
1634     UpdateAccountInfoAsyncContext *asyncContext = reinterpret_cast<UpdateAccountInfoAsyncContext *>(data);
1635     asyncContext->errCode = DomainAccountClient::GetInstance().UpdateAccountInfo(
1636         asyncContext->oldAccountInfo, asyncContext->newAccountInfo);
1637 }
1638 
UpdateAccountInfoCompleteCB(napi_env env,napi_status status,void * data)1639 static void UpdateAccountInfoCompleteCB(napi_env env, napi_status status, void *data)
1640 {
1641     UpdateAccountInfoAsyncContext *asyncContext = reinterpret_cast<UpdateAccountInfoAsyncContext *>(data);
1642     napi_value errJs = nullptr;
1643     napi_value dataJs = nullptr;
1644     if (asyncContext->errCode != ERR_OK) {
1645         errJs = GenerateBusinessError(asyncContext->env, asyncContext->errCode);
1646     } else {
1647         napi_get_null(asyncContext->env, &dataJs);
1648     }
1649     ProcessCallbackOrPromise(env, asyncContext, errJs, dataJs);
1650     delete asyncContext;
1651 }
1652 
UpdateAccountInfo(napi_env env,napi_callback_info cbInfo)1653 napi_value NapiDomainAccountManager::UpdateAccountInfo(napi_env env, napi_callback_info cbInfo)
1654 {
1655     auto context = std::make_unique<UpdateAccountInfoAsyncContext>(env);
1656     if (!ParseParamForUpdateAccountInfo(env, cbInfo, context.get())) {
1657         return nullptr;
1658     }
1659     napi_value result = nullptr;
1660     NAPI_CALL(env, napi_create_promise(env, &context->deferred, &result));
1661     napi_value resource = nullptr;
1662     NAPI_CALL(env, napi_create_string_utf8(env, "UpdateAccountInfo", NAPI_AUTO_LENGTH, &resource));
1663     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1664         UpdateAccountInfoExecuteCB, UpdateAccountInfoCompleteCB,
1665         reinterpret_cast<void *>(context.get()), &context->work));
1666     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
1667     context.release();
1668     return result;
1669 }
1670 }  // namespace AccountJsKit
1671 }  // namespace OHOS
1672