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