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, ¶m, 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, ¶m, 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, ¶m, 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, ¶m, 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, ¶m, 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