1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_distributed_account.h"
17 #include <map>
18 #include <string>
19 #include <unistd.h>
20 #include "account_log_wrapper.h"
21 #include "account_permission_manager.h"
22 #include "js_native_api.h"
23 #include "js_native_api_types.h"
24 #include "napi_account_common.h"
25 #include "napi/native_api.h"
26 #include "napi/native_common.h"
27 #include "napi/native_node_api.h"
28 #include "node_api.h"
29 #include "ohos_account_kits.h"
30 #include "napi_account_error.h"
31 #include "napi_common.h"
32 
33 using namespace OHOS::AccountSA;
34 
35 namespace OHOS {
36 namespace AccountJsKit {
37 constexpr std::int32_t PARAM_ZERO = 0;
38 constexpr std::int32_t PARAM_ONE = 1;
39 constexpr std::int32_t PARAM_TWO = 2;
40 constexpr std::int32_t ARGS_SIZE_ONE = 1;
41 constexpr std::int32_t ARGS_SIZE_TWO = 2;
42 constexpr std::int32_t ARGS_SIZE_THREE = 3;
43 constexpr int RESULT_COUNT = 2;
44 const std::string DISTRIBUTED_ACCOUNT_CLASS_NAME = "DistributedAccountAbility";
45 const std::string PROPERTY_KEY_NAME = "name";
46 const std::string PROPERTY_KEY_ID = "id";
47 const std::string PROPERTY_KEY_EVENT = "event";
48 const std::string PROPERTY_KEY_NICKNAME = "nickname";
49 const std::string PROPERTY_KEY_AVATAR = "avatar";
50 const std::string PROPERTY_KEY_SCALABLE = "scalableData";
51 const std::string PROPERTY_KEY_STATUS = "status";
52 
53 static thread_local napi_ref distributedAccountRef_ = nullptr;
54 
DistributedAccountAsyncContext(napi_env napiEnv)55 DistributedAccountAsyncContext::DistributedAccountAsyncContext(napi_env napiEnv) : env(napiEnv)
56 {}
57 
~DistributedAccountAsyncContext()58 DistributedAccountAsyncContext::~DistributedAccountAsyncContext()
59 {
60     if (callbackRef != nullptr) {
61         NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, callbackRef));
62         callbackRef = nullptr;
63     }
64 }
65 
DistributedAccountStatusConstructor(napi_env env)66 napi_value DistributedAccountStatusConstructor(napi_env env)
67 {
68     napi_value distributedAccountStatus = nullptr;
69     napi_value status1 = nullptr;
70     napi_value status2 = nullptr;
71     NAPI_CALL(env, napi_create_object(env, &distributedAccountStatus));
72     NAPI_CALL(env, napi_create_int32(env, static_cast<int32_t>(OHOS_ACCOUNT_STATE::ACCOUNT_STATE_UNBOUND), &status1));
73     NAPI_CALL(env, napi_create_int32(env, static_cast<int32_t>(OHOS_ACCOUNT_STATE::ACCOUNT_STATE_LOGIN), &status2));
74     NAPI_CALL(env, napi_set_named_property(env, distributedAccountStatus, "NOT_LOGGED_IN", status1));
75     NAPI_CALL(env, napi_set_named_property(env, distributedAccountStatus, "LOGGED_IN", status2));
76     return distributedAccountStatus;
77 }
78 
ParseQueryOhosAccountInfoAsyncContext(napi_env env,napi_callback_info cbInfo,DistributedAccountAsyncContext * asyncContext)79 bool ParseQueryOhosAccountInfoAsyncContext(
80     napi_env env, napi_callback_info cbInfo, DistributedAccountAsyncContext *asyncContext)
81 {
82     size_t argc = ARGS_SIZE_ONE;
83     napi_value argv[ARGS_SIZE_ONE] = {nullptr};
84     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr), false);
85     if (argc >= ARGS_SIZE_ONE) {
86         if (!GetCallbackProperty(env, argv[PARAM_ZERO], asyncContext->callbackRef, 1)) {
87             ACCOUNT_LOGE("Get callbackRef failed.");
88             std::string errMsg = "Parameter error. The type of \"callback\" must be function";
89             AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
90             return false;
91         }
92     }
93     return true;
94 }
95 
GetAccountInfo(napi_env env,napi_value object,DistributedAccountAsyncContext * asyncContext)96 static bool GetAccountInfo(napi_env env, napi_value object, DistributedAccountAsyncContext *asyncContext)
97 {
98     if (!GetStringPropertyByKey(env, object, PROPERTY_KEY_NAME, asyncContext->ohosAccountInfo.name_)) {
99         ACCOUNT_LOGE("Failed to get DistributedInfo's %{public}s property", PROPERTY_KEY_NAME.c_str());
100         std::string errMsg = "Parameter error. The type of " + PROPERTY_KEY_NAME + " must be string";
101         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
102         return false;
103     }
104     if (!GetStringPropertyByKey(env, object, PROPERTY_KEY_ID, asyncContext->ohosAccountInfo.uid_)) {
105         ACCOUNT_LOGE("Failed to get DistributedInfo's %{public}s property", PROPERTY_KEY_ID.c_str());
106         std::string errMsg = "Parameter error. The type of " + PROPERTY_KEY_ID + " must be string";
107         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
108         return false;
109     }
110     if (!GetOptionalStringPropertyByKey(env, object, PROPERTY_KEY_NICKNAME, asyncContext->ohosAccountInfo.nickname_)) {
111         ACCOUNT_LOGE("Failed to get DistributedInfo's %{public}s property", PROPERTY_KEY_NICKNAME.c_str());
112         std::string errMsg = "Parameter error. The type of " + PROPERTY_KEY_NICKNAME + " must be string";
113         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
114         return false;
115     }
116     if (!GetOptionalStringPropertyByKey(env, object, PROPERTY_KEY_AVATAR, asyncContext->ohosAccountInfo.avatar_)) {
117         ACCOUNT_LOGE("Failed to get DistributedInfo's %{public}s property", PROPERTY_KEY_AVATAR.c_str());
118         std::string errMsg = "Parameter error. The type of " + PROPERTY_KEY_AVATAR + " must be string";
119         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
120         return false;
121     }
122     bool hasProp = false;
123     napi_has_named_property(env, object, "scalableData", &hasProp);
124     AAFwk::WantParams params;
125     if (hasProp) {
126         napi_value value = nullptr;
127         napi_get_named_property(env, object, "scalableData", &value);
128         napi_valuetype valuetype = napi_undefined;
129         NAPI_CALL_BASE(env, napi_typeof(env, value, &valuetype), false);
130         if ((valuetype == napi_undefined) || (valuetype == napi_null)) {
131             ACCOUNT_LOGI("the scalableData is undefined or null");
132         } else {
133             if (!AppExecFwk::UnwrapWantParams(env, value, params)) {
134                 ACCOUNT_LOGE("Failed to get DistributedInfo's %{public}s property", PROPERTY_KEY_SCALABLE.c_str());
135                 std::string errMsg = "Parameter error. The type of " + PROPERTY_KEY_SCALABLE + " must be object";
136                 AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
137                 return false;
138             }
139         }
140     }
141     asyncContext->ohosAccountInfo.scalableData_.SetParams(params);
142     return true;
143 }
144 
ParseInfoAndEvent(napi_env env,napi_value argv,DistributedAccountAsyncContext * asyncContext)145 static bool ParseInfoAndEvent(napi_env env, napi_value argv, DistributedAccountAsyncContext *asyncContext)
146 {
147     napi_valuetype valueType = napi_undefined;
148     NAPI_CALL_BASE(env, napi_typeof(env, argv, &valueType), false);
149     if (valueType != napi_object) {
150         ACCOUNT_LOGE("DistributedInfo is not an object.");
151         std::string errMsg = "Parameter error. The type of \"accountInfo\" must be DistributedInfo";
152         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
153         return false;
154     }
155     if (!GetAccountInfo(env, argv, asyncContext)) {
156         return false;
157     }
158     if (!GetStringPropertyByKey(env, argv, PROPERTY_KEY_EVENT, asyncContext->event)) {
159         ACCOUNT_LOGE("Failed to get DistributedInfo's %{public}s property", PROPERTY_KEY_EVENT.c_str());
160         std::string errMsg = "Parameter error. The type of " + PROPERTY_KEY_EVENT + " must be string";
161         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
162         return false;
163     }
164     return true;
165 }
166 
ParseUpdateOhosAccountInfoAsyncContext(napi_env env,napi_callback_info cbInfo,DistributedAccountAsyncContext * asyncContext)167 bool ParseUpdateOhosAccountInfoAsyncContext(
168     napi_env env, napi_callback_info cbInfo, DistributedAccountAsyncContext *asyncContext)
169 {
170     size_t argc = ARGS_SIZE_TWO;
171     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
172     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr), false);
173     if (argc < ARGS_SIZE_ONE) {
174         ACCOUNT_LOGE("The number of parameters should be at least 1.");
175         std::string errMsg = "Parameter error. The number of parameters should be at least 1";
176         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
177         return false;
178     }
179     if (argc >= ARGS_SIZE_TWO) {
180         if (!GetCallbackProperty(env, argv[PARAM_ONE], asyncContext->callbackRef, 1)) {
181             ACCOUNT_LOGE("Get callbackRef failed.");
182             std::string errMsg = "Parameter error. The type of \"callback\" must be function";
183             AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
184             return false;
185         }
186     }
187     return ParseInfoAndEvent(env, argv[PARAM_ZERO], asyncContext);
188 }
189 
ProcessCallbackOrPromise(napi_env env,const DistributedAccountAsyncContext * asyncContext,napi_value err,napi_value data)190 void ProcessCallbackOrPromise(
191     napi_env env, const DistributedAccountAsyncContext *asyncContext, napi_value err, napi_value data)
192 {
193     if (asyncContext->deferred != nullptr) {
194         if (asyncContext->errCode == ERR_OK) {
195             napi_resolve_deferred(env, asyncContext->deferred, data);
196         } else {
197             napi_reject_deferred(env, asyncContext->deferred, err);
198         }
199     } else {
200         napi_value args[RESULT_COUNT] = { err, data };
201         napi_value callback = nullptr;
202         napi_get_reference_value(env, asyncContext->callbackRef, &callback);
203         napi_value returnVal = nullptr;
204         napi_call_function(env, nullptr, callback, RESULT_COUNT, args, &returnVal);
205     }
206 }
207 
ProcessSetNamedProperty(napi_env env,const DistributedAccountAsyncContext * asyncContext)208 void ProcessSetNamedProperty(napi_env env, const DistributedAccountAsyncContext *asyncContext)
209 {
210     napi_value result[RESULT_COUNT] = {0};
211     if (asyncContext->errCode == ERR_OK) {
212         if (asyncContext->throwErr) {
213             napi_get_null(env, &result[0]);
214         } else {
215             napi_get_undefined(env, &result[0]);
216         }
217         napi_create_object(env, &result[1]);
218         napi_value value = nullptr;
219         napi_create_string_utf8(env, asyncContext->ohosAccountInfo.name_.c_str(),
220                                 asyncContext->ohosAccountInfo.name_.size(), &value);
221         napi_set_named_property(env, result[1], PROPERTY_KEY_NAME.c_str(), value);
222         napi_create_string_utf8(env, asyncContext->ohosAccountInfo.uid_.c_str(),
223                                 asyncContext->ohosAccountInfo.uid_.size(), &value);
224         napi_set_named_property(env, result[1], PROPERTY_KEY_ID.c_str(), value);
225         napi_create_string_utf8(env, asyncContext->event.c_str(), asyncContext->event.size(), &value);
226         napi_set_named_property(env, result[1], PROPERTY_KEY_EVENT.c_str(), value);
227         napi_create_string_utf8(env, asyncContext->ohosAccountInfo.nickname_.c_str(),
228                                 asyncContext->ohosAccountInfo.nickname_.size(), &value);
229         napi_set_named_property(env, result[1], PROPERTY_KEY_NICKNAME.c_str(), value);
230         napi_create_string_utf8(env, asyncContext->ohosAccountInfo.avatar_.c_str(),
231                                 asyncContext->ohosAccountInfo.avatar_.size(), &value);
232         napi_set_named_property(env, result[1], PROPERTY_KEY_AVATAR.c_str(), value);
233         napi_create_int32(env, asyncContext->ohosAccountInfo.status_, &value);
234         napi_set_named_property(env, result[1], PROPERTY_KEY_STATUS.c_str(), value);
235         napi_value scalable = nullptr;
236         napi_create_object(env, &scalable);
237         scalable = AppExecFwk::WrapWantParams(env, (asyncContext->ohosAccountInfo.scalableData_).GetParams());
238         napi_set_named_property(env, result[1], PROPERTY_KEY_SCALABLE.c_str(), scalable);
239     } else {
240         if (asyncContext->throwErr) {
241             result[0] = GenerateBusinessError(env, asyncContext->errCode);
242             napi_get_null(env, &result[1]);
243         } else {
244             napi_value message = nullptr;
245             napi_create_string_utf8(env, "query ohos account info failed", NAPI_AUTO_LENGTH, &message);
246             napi_create_error(env, nullptr, message, &result[0]);
247             napi_get_undefined(env, &result[1]);
248         }
249     }
250     ProcessCallbackOrPromise(env, asyncContext, result[0], result[1]);
251 }
252 
Init(napi_env env,napi_value exports)253 napi_value NapiDistributedAccount::Init(napi_env env, napi_value exports)
254 {
255     napi_property_descriptor descriptor[] = {
256         DECLARE_NAPI_FUNCTION("getDistributedAccountAbility", GetDistributedAccountAbility),
257         DECLARE_NAPI_PROPERTY("DistributedAccountStatus", DistributedAccountStatusConstructor(env)),
258     };
259     napi_define_properties(env, exports, sizeof(descriptor) / sizeof(napi_property_descriptor), descriptor);
260 
261     napi_property_descriptor properties[] = {
262         DECLARE_NAPI_FUNCTION("queryOsAccountDistributedInfo", QueryOsAccountDistributedInfo),
263         DECLARE_NAPI_FUNCTION("getOsAccountDistributedInfo", GetOsAccountDistributedInfo),
264         DECLARE_NAPI_FUNCTION("updateOsAccountDistributedInfo", UpdateOsAccountDistributedInfo),
265         DECLARE_NAPI_FUNCTION("setOsAccountDistributedInfo", SetOsAccountDistributedInfo),
266         DECLARE_NAPI_FUNCTION("getOsAccountDistributedInfoByLocalId", GetOsAccountDistributedInfoByLocalId),
267         DECLARE_NAPI_FUNCTION("setOsAccountDistributedInfoByLocalId", SetOsAccountDistributedInfoByLocalId),
268         DECLARE_NAPI_FUNCTION("setCurrentOsAccountDistributedInfo", SetCurrentOsAccountDistributedInfo),
269     };
270     napi_value cons = nullptr;
271     napi_define_class(env, DISTRIBUTED_ACCOUNT_CLASS_NAME.c_str(), DISTRIBUTED_ACCOUNT_CLASS_NAME.size(),
272         JsConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &cons);
273     napi_create_reference(env, cons, 1, &distributedAccountRef_);
274     napi_set_named_property(env, exports, DISTRIBUTED_ACCOUNT_CLASS_NAME.c_str(), cons);
275 
276     return exports;
277 }
278 
JsConstructor(napi_env env,napi_callback_info cbinfo)279 napi_value NapiDistributedAccount::JsConstructor(napi_env env, napi_callback_info cbinfo)
280 {
281     napi_value thisVar = nullptr;
282     napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr);
283     return thisVar;
284 }
285 
GetDistributedAccountAbility(napi_env env,napi_callback_info cbInfo)286 napi_value NapiDistributedAccount::GetDistributedAccountAbility(napi_env env, napi_callback_info cbInfo)
287 {
288     napi_value instance = nullptr;
289     napi_value cons = nullptr;
290     if (napi_get_reference_value(env, distributedAccountRef_, &cons) != napi_ok) {
291         return nullptr;
292     }
293 
294     if (napi_new_instance(env, cons, 0, nullptr, &instance) != napi_ok) {
295         return nullptr;
296     }
297 
298     return instance;
299 }
300 
QueryOsAccountDistributedInfo(napi_env env,napi_callback_info cbInfo)301 napi_value NapiDistributedAccount::QueryOsAccountDistributedInfo(napi_env env, napi_callback_info cbInfo)
302 {
303     return QueryOhosAccountInfo(env, cbInfo, false);
304 }
305 
GetOsAccountDistributedInfo(napi_env env,napi_callback_info cbInfo)306 napi_value NapiDistributedAccount::GetOsAccountDistributedInfo(napi_env env, napi_callback_info cbInfo)
307 {
308     return QueryOhosAccountInfo(env, cbInfo, true);
309 }
310 
QueryOhosAccountInfoExecuteCB(napi_env env,void * data)311 static void QueryOhosAccountInfoExecuteCB(napi_env env, void *data)
312 {
313     DistributedAccountAsyncContext *asyncContext = reinterpret_cast<DistributedAccountAsyncContext *>(data);
314     if (!asyncContext->throwErr) {
315         std::pair<bool, OhosAccountInfo> accountInfo = OhosAccountKits::GetInstance().QueryOhosAccountInfo();
316         if (accountInfo.first) {
317             asyncContext->ohosAccountInfo.name_ = accountInfo.second.name_;
318             asyncContext->ohosAccountInfo.uid_ = accountInfo.second.uid_;
319             asyncContext->ohosAccountInfo.status_ = accountInfo.second.status_;
320             asyncContext->errCode = napi_ok;
321         } else {
322             asyncContext->errCode = napi_generic_failure;
323         }
324     } else if (!asyncContext->withLocalId) {
325         asyncContext->errCode = OhosAccountKits::GetInstance().GetOhosAccountInfo(asyncContext->ohosAccountInfo);
326     } else {
327         asyncContext->errCode = OhosAccountKits::GetInstance().GetOhosAccountInfoByUserId(
328             asyncContext->localId, asyncContext->ohosAccountInfo);
329     }
330 }
331 
QueryOhosAccountInfoCompletedCB(napi_env env,napi_status status,void * data)332 static void QueryOhosAccountInfoCompletedCB(napi_env env, napi_status status, void *data)
333 {
334     DistributedAccountAsyncContext *asyncContext = reinterpret_cast<DistributedAccountAsyncContext *>(data);
335     ProcessSetNamedProperty(env, asyncContext);
336     napi_delete_async_work(env, asyncContext->work);
337     delete asyncContext;
338 }
339 
QueryOhosAccountInfo(napi_env env,napi_callback_info cbInfo,bool throwErr)340 napi_value NapiDistributedAccount::QueryOhosAccountInfo(napi_env env, napi_callback_info cbInfo, bool throwErr)
341 {
342     auto *asyncContext = new (std::nothrow) DistributedAccountAsyncContext(env);
343     if (asyncContext == nullptr) {
344         ACCOUNT_LOGE("insufficient memory for asyncContext!");
345         return nullptr;
346     }
347     std::unique_ptr<DistributedAccountAsyncContext> contextPtr(asyncContext);
348     asyncContext->throwErr = throwErr;
349     asyncContext->withLocalId = false;
350     if (!ParseQueryOhosAccountInfoAsyncContext(env, cbInfo, asyncContext) && throwErr) {
351         return nullptr;
352     }
353     napi_value result = nullptr;
354     if (asyncContext->callbackRef == nullptr) {
355         NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &result));
356     }
357     napi_value resource = nullptr;
358     NAPI_CALL(env, napi_create_string_utf8(env, "QueryOhosAccountInfo", NAPI_AUTO_LENGTH, &resource));
359     NAPI_CALL(env, napi_create_async_work(env,
360         nullptr,
361         resource,
362         QueryOhosAccountInfoExecuteCB,
363         QueryOhosAccountInfoCompletedCB,
364         reinterpret_cast<void *>(asyncContext), &asyncContext->work));
365     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
366     contextPtr.release();
367     return result;
368 }
369 
UpdateOsAccountDistributedInfo(napi_env env,napi_callback_info cbInfo)370 napi_value NapiDistributedAccount::UpdateOsAccountDistributedInfo(napi_env env, napi_callback_info cbInfo)
371 {
372     return UpdateOhosAccountInfo(env, cbInfo, false);
373 }
374 
SetOsAccountDistributedInfo(napi_env env,napi_callback_info cbInfo)375 napi_value NapiDistributedAccount::SetOsAccountDistributedInfo(napi_env env, napi_callback_info cbInfo)
376 {
377     return UpdateOhosAccountInfo(env, cbInfo, true);
378 }
379 
SetCurrentOsAccountDistributedInfo(napi_env env,napi_callback_info cbInfo)380 napi_value NapiDistributedAccount::SetCurrentOsAccountDistributedInfo(napi_env env, napi_callback_info cbInfo)
381 {
382     if (AccountPermissionManager::CheckSystemApp(false) != ERR_OK) {
383         AccountNapiThrow(env, ERR_JS_IS_NOT_SYSTEM_APP);
384         return nullptr;
385     }
386     return UpdateOhosAccountInfo(env, cbInfo, true);
387 }
388 
UpdateOhosAccountInfoExecuteCB(napi_env env,void * data)389 static void UpdateOhosAccountInfoExecuteCB(napi_env env, void *data)
390 {
391     DistributedAccountAsyncContext *context = reinterpret_cast<DistributedAccountAsyncContext *>(data);
392     if (!context->throwErr) {
393         context->errCode = OhosAccountKits::GetInstance().UpdateOhosAccountInfo(context->ohosAccountInfo.name_,
394             context->ohosAccountInfo.uid_, context->event) ? napi_ok: napi_generic_failure;
395     } else if (context->withLocalId) {
396         context->errCode = OhosAccountKits::GetInstance().SetOhosAccountInfoByUserId(
397             context->localId, context->ohosAccountInfo, context->event);
398     } else {
399         context->errCode = OhosAccountKits::GetInstance().SetOhosAccountInfo(context->ohosAccountInfo, context->event);
400     }
401 }
402 
UpdateOhosAccountInfoCompletedCB(napi_env env,napi_status status,void * data)403 static void UpdateOhosAccountInfoCompletedCB(napi_env env, napi_status status, void *data)
404 {
405     DistributedAccountAsyncContext *asyncContext = reinterpret_cast<DistributedAccountAsyncContext *>(data);
406     napi_value result[RESULT_COUNT] = {0};
407     if (asyncContext->errCode == ERR_OK) {
408         if (asyncContext->throwErr) {
409             napi_get_null(env, &result[0]);
410             napi_get_null(env, &result[1]);
411         } else {
412             napi_get_undefined(env, &result[1]);
413         }
414     } else if (asyncContext->throwErr) {
415         result[0] = GenerateBusinessError(env, asyncContext->errCode);
416     } else {
417         napi_value message = nullptr;
418         napi_create_string_utf8(env, "Update distributed account info failed", NAPI_AUTO_LENGTH, &message);
419         napi_create_error(env, nullptr, message, &result[0]);
420     }
421     ProcessCallbackOrPromise(env, asyncContext, result[0], result[1]);
422     napi_delete_async_work(env, asyncContext->work);
423     delete asyncContext;
424 }
425 
ParseSetOsAccountDistributedInfoByLocalId(napi_env env,napi_callback_info cbInfo,DistributedAccountAsyncContext * asyncContext)426 static bool ParseSetOsAccountDistributedInfoByLocalId(napi_env env, napi_callback_info cbInfo,
427     DistributedAccountAsyncContext *asyncContext)
428 {
429     size_t argc = ARGS_SIZE_THREE;
430     napi_value argv[ARGS_SIZE_THREE] = {nullptr};
431     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr), false);
432     if (argc < ARGS_SIZE_TWO) {
433         ACCOUNT_LOGE("The number of parameters should be at least 2.");
434         std::string errMsg = "Parameter error. The number of parameters should be at least 2";
435         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
436         return false;
437     }
438     if (argc >= ARGS_SIZE_THREE) {
439         if (!GetCallbackProperty(env, argv[PARAM_TWO], asyncContext->callbackRef, 1)) {
440             ACCOUNT_LOGE("Get callbackRef failed.");
441             std::string errMsg = "Parameter error. The type of \"callback\" must be function";
442             AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
443             return false;
444         }
445     }
446     if (!GetIntProperty(env, argv[PARAM_ZERO], asyncContext->localId)) {
447         ACCOUNT_LOGE("Get localId failed.");
448         std::string errMsg = "Parameter error. The type of \"localId\" must be number";
449         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
450         return false;
451     }
452     return ParseInfoAndEvent(env, argv[PARAM_ONE], asyncContext);
453 }
454 
SetOsAccountDistributedInfoByLocalId(napi_env env,napi_callback_info cbInfo)455 napi_value NapiDistributedAccount::SetOsAccountDistributedInfoByLocalId(napi_env env, napi_callback_info cbInfo)
456 {
457     auto *asyncContext = new (std::nothrow) DistributedAccountAsyncContext(env);
458     if (asyncContext == nullptr) {
459         ACCOUNT_LOGE("Insufficient memory for asyncContext!");
460         return nullptr;
461     }
462     std::unique_ptr<DistributedAccountAsyncContext> contextPtr(asyncContext);
463     asyncContext->throwErr = true;
464     asyncContext->withLocalId = true;
465     if (!ParseSetOsAccountDistributedInfoByLocalId(env, cbInfo, asyncContext)) {
466         return nullptr;
467     }
468     napi_value result = nullptr;
469     if (asyncContext->callbackRef == nullptr) {
470         NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &result));
471     }
472     napi_value resource = nullptr;
473     NAPI_CALL(env, napi_create_string_utf8(env, "SetOsAccountDistributedInfoByLocalId", NAPI_AUTO_LENGTH, &resource));
474     NAPI_CALL(env, napi_create_async_work(env,
475         nullptr,
476         resource,
477         UpdateOhosAccountInfoExecuteCB,
478         UpdateOhosAccountInfoCompletedCB,
479         reinterpret_cast<void *>(asyncContext), &asyncContext->work));
480     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
481     contextPtr.release();
482     return result;
483 }
484 
ParseGetOsAccountDistributedInfoByLocalId(napi_env env,napi_callback_info cbInfo,DistributedAccountAsyncContext * asyncContext)485 static bool ParseGetOsAccountDistributedInfoByLocalId(napi_env env, napi_callback_info cbInfo,
486     DistributedAccountAsyncContext *asyncContext)
487 {
488     size_t argc = ARGS_SIZE_TWO;
489     napi_value argv[ARGS_SIZE_TWO] = {nullptr};
490     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, nullptr, nullptr), false);
491     if (argc < ARGS_SIZE_ONE) {
492         ACCOUNT_LOGE("The number of parameters should be at least 1.");
493         std::string errMsg = "Parameter error. The number of parameters should be at least 1";
494         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
495         return false;
496     }
497     if (argc >= ARGS_SIZE_TWO) {
498         if (!GetCallbackProperty(env, argv[PARAM_ONE], asyncContext->callbackRef, 1)) {
499             ACCOUNT_LOGE("Get callbackRef failed.");
500             std::string errMsg = "Parameter error. The type of \"callback\" must be function";
501             AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
502             return false;
503         }
504     }
505     if (!GetIntProperty(env, argv[PARAM_ZERO], asyncContext->localId)) {
506         ACCOUNT_LOGE("Get localId failed.");
507         std::string errMsg = "Parameter error. The type of \"localId\" must be number";
508         AccountNapiThrow(env, ERR_JS_PARAMETER_ERROR, errMsg, asyncContext->throwErr);
509         return false;
510     }
511     return true;
512 }
513 
GetOsAccountDistributedInfoByLocalId(napi_env env,napi_callback_info cbInfo)514 napi_value NapiDistributedAccount::GetOsAccountDistributedInfoByLocalId(napi_env env, napi_callback_info cbInfo)
515 {
516     auto *asyncContext = new (std::nothrow) DistributedAccountAsyncContext(env);
517     if (asyncContext == nullptr) {
518         ACCOUNT_LOGE("Insufficient memory for asyncContext.");
519         return nullptr;
520     }
521     std::unique_ptr<DistributedAccountAsyncContext> contextPtr(asyncContext);
522     asyncContext->throwErr = true;
523     asyncContext->withLocalId = true;
524     if (!ParseGetOsAccountDistributedInfoByLocalId(env, cbInfo, asyncContext)) {
525         return nullptr;
526     }
527     napi_value result = nullptr;
528     if (asyncContext->callbackRef == nullptr) {
529         NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &result));
530     }
531     napi_value resource = nullptr;
532     NAPI_CALL(env, napi_create_string_utf8(env, "GetOsAccountDistributedInfoByLocalId", NAPI_AUTO_LENGTH, &resource));
533     NAPI_CALL(env, napi_create_async_work(env,
534         nullptr,
535         resource,
536         QueryOhosAccountInfoExecuteCB,
537         QueryOhosAccountInfoCompletedCB,
538         reinterpret_cast<void *>(asyncContext), &asyncContext->work));
539     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
540     contextPtr.release();
541     return result;
542 }
543 
UpdateOhosAccountInfo(napi_env env,napi_callback_info cbInfo,bool throwErr)544 napi_value NapiDistributedAccount::UpdateOhosAccountInfo(napi_env env, napi_callback_info cbInfo, bool throwErr)
545 {
546     auto *asyncContext = new (std::nothrow) DistributedAccountAsyncContext(env);
547     if (asyncContext == nullptr) {
548         ACCOUNT_LOGE("insufficient memory for asyncContext!");
549         return nullptr;
550     }
551     asyncContext->throwErr = throwErr;
552     std::unique_ptr<DistributedAccountAsyncContext> contextPtr(asyncContext);
553     if (!ParseUpdateOhosAccountInfoAsyncContext(env, cbInfo, asyncContext) && throwErr) {
554         return nullptr;
555     }
556     napi_value result = nullptr;
557     if (asyncContext->callbackRef == nullptr) {
558         NAPI_CALL(env, napi_create_promise(env, &asyncContext->deferred, &result));
559     }
560     napi_value resource = nullptr;
561     NAPI_CALL(env, napi_create_string_utf8(env, "UpdateOhosAccountInfo", NAPI_AUTO_LENGTH, &resource));
562     NAPI_CALL(env, napi_create_async_work(env,
563         nullptr,
564         resource,
565         UpdateOhosAccountInfoExecuteCB,
566         UpdateOhosAccountInfoCompletedCB,
567         reinterpret_cast<void *>(asyncContext), &asyncContext->work));
568     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
569     contextPtr.release();
570     return result;
571 }
572 } // namespace AccountJsKit
573 } // namespace OHOS
574 
575 EXTERN_C_START
576 /*
577  * function for module exports
578  */
Init(napi_env env,napi_value exports)579 static napi_value Init(napi_env env, napi_value exports)
580 {
581     return OHOS::AccountJsKit::NapiDistributedAccount::Init(env, exports);
582 }
583 EXTERN_C_END
584 
585 /*
586  * module define
587  */
588 static napi_module _module = {
589     .nm_version = 1,
590     .nm_flags = 0,
591     .nm_filename = nullptr,
592     .nm_register_func = Init,
593     .nm_modname = "account.distributedAccount",
594     .nm_priv = ((void*)0),
595     .reserved = {0}
596 };
597 /*
598  * module register
599  */
Register()600 extern "C" __attribute__((constructor)) void Register()
601 {
602     napi_module_register(&_module);
603 }
604