1 /*
2  * Copyright (c) 2021-2024 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 #include "napi_atmanager.h"
16 
17 #include "access_token.h"
18 #include "napi_request_global_switch_on_setting.h"
19 #include "napi_request_permission.h"
20 #include "napi_request_permission_on_setting.h"
21 #include "parameter.h"
22 #include "token_setproc.h"
23 #include "want.h"
24 
25 namespace OHOS {
26 namespace Security {
27 namespace AccessToken {
28 std::mutex g_lockForPermStateChangeRegisters;
29 std::vector<RegisterPermStateChangeInfo*> g_permStateChangeRegisters;
30 std::mutex g_lockCache;
31 std::map<std::string, PermissionStatusCache> g_cache;
32 static PermissionParamCache g_paramCache;
33 namespace {
34 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
35     LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AccessTokenAbilityAccessCtrl"
36 };
37 static const char* PERMISSION_STATUS_CHANGE_KEY = "accesstoken.permission.change";
ReturnPromiseResult(napi_env env,int32_t contextResult,napi_deferred deferred,napi_value result)38 static void ReturnPromiseResult(napi_env env, int32_t contextResult, napi_deferred deferred, napi_value result)
39 {
40     if (contextResult != RET_SUCCESS) {
41         int32_t jsCode = NapiContextCommon::GetJsErrorCode(contextResult);
42         napi_value businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
43         NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, deferred, businessError));
44     } else {
45         NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, deferred, result));
46     }
47 }
48 
ReturnCallbackResult(napi_env env,int32_t contextResult,napi_ref & callbackRef,napi_value result)49 static void ReturnCallbackResult(napi_env env, int32_t contextResult, napi_ref &callbackRef, napi_value result)
50 {
51     napi_value businessError = GetNapiNull(env);
52     if (contextResult != RET_SUCCESS) {
53         int32_t jsCode = NapiContextCommon::GetJsErrorCode(contextResult);
54         businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
55     }
56     napi_value results[ASYNC_CALL_BACK_VALUES_NUM] = { businessError, result };
57 
58     napi_value callback = nullptr;
59     napi_value thisValue = nullptr;
60     napi_value thatValue = nullptr;
61     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &thisValue));
62     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, 0, &thatValue));
63     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callbackRef, &callback));
64     NAPI_CALL_RETURN_VOID(env,
65         napi_call_function(env, thisValue, callback, ASYNC_CALL_BACK_VALUES_NUM, results, &thatValue));
66 }
67 
ConvertPermStateChangeInfo(napi_env env,napi_value value,const PermStateChangeInfo & result)68 static bool ConvertPermStateChangeInfo(napi_env env, napi_value value, const PermStateChangeInfo& result)
69 {
70     napi_value element;
71     NAPI_CALL_BASE(env, napi_create_int32(env, result.permStateChangeType, &element), false);
72     NAPI_CALL_BASE(env, napi_set_named_property(env, value, "change", element), false);
73     element = nullptr;
74     NAPI_CALL_BASE(env, napi_create_int32(env, result.tokenID, &element), false);
75     NAPI_CALL_BASE(env, napi_set_named_property(env, value, "tokenID", element), false);
76     element = nullptr;
77     NAPI_CALL_BASE(env, napi_create_string_utf8(env, result.permissionName.c_str(),
78         NAPI_AUTO_LENGTH, &element), false);
79     NAPI_CALL_BASE(env, napi_set_named_property(env, value, "permissionName", element), false);
80     return true;
81 };
82 
NotifyPermStateChanged(RegisterPermStateChangeWorker * registerPermStateChangeData)83 static void NotifyPermStateChanged(RegisterPermStateChangeWorker* registerPermStateChangeData)
84 {
85     napi_value result = {nullptr};
86     NAPI_CALL_RETURN_VOID(registerPermStateChangeData->env,
87         napi_create_object(registerPermStateChangeData->env, &result));
88     if (!ConvertPermStateChangeInfo(registerPermStateChangeData->env,
89         result, registerPermStateChangeData->result)) {
90         ACCESSTOKEN_LOG_ERROR(LABEL, "ConvertPermStateChangeInfo failed");
91         return;
92     }
93 
94     napi_value undefined = nullptr;
95     napi_value callback = nullptr;
96     napi_value resultOut = nullptr;
97     NAPI_CALL_RETURN_VOID(registerPermStateChangeData->env,
98         napi_get_undefined(registerPermStateChangeData->env, &undefined));
99     NAPI_CALL_RETURN_VOID(registerPermStateChangeData->env,
100         napi_get_reference_value(registerPermStateChangeData->env, registerPermStateChangeData->ref, &callback));
101     NAPI_CALL_RETURN_VOID(registerPermStateChangeData->env,
102         napi_call_function(registerPermStateChangeData->env, undefined, callback, 1, &result, &resultOut));
103 }
104 
UvQueueWorkPermStateChanged(uv_work_t * work,int status)105 static void UvQueueWorkPermStateChanged(uv_work_t* work, int status)
106 {
107     if (work == nullptr || work->data == nullptr) {
108         ACCESSTOKEN_LOG_ERROR(LABEL, "Work == nullptr || work->data == nullptr");
109         return;
110     }
111     std::unique_ptr<uv_work_t> uvWorkPtr {work};
112     RegisterPermStateChangeWorker* registerPermStateChangeData =
113         reinterpret_cast<RegisterPermStateChangeWorker*>(work->data);
114     std::unique_ptr<RegisterPermStateChangeWorker> workPtr {registerPermStateChangeData};
115 
116     napi_handle_scope scope = nullptr;
117     napi_open_handle_scope(registerPermStateChangeData->env, &scope);
118     if (scope == nullptr) {
119         ACCESSTOKEN_LOG_ERROR(LABEL, "Fail to open scope");
120         return;
121     }
122     NotifyPermStateChanged(registerPermStateChangeData);
123     napi_close_handle_scope(registerPermStateChangeData->env, scope);
124     ACCESSTOKEN_LOG_DEBUG(LABEL, "UvQueueWorkPermStateChanged end");
125 };
126 
IsPermissionFlagValid(uint32_t flag)127 static bool IsPermissionFlagValid(uint32_t flag)
128 {
129     ACCESSTOKEN_LOG_DEBUG(LABEL, "Permission flag is %{public}d", flag);
130     return (flag == PermissionFlag::PERMISSION_USER_SET) || (flag == PermissionFlag::PERMISSION_USER_FIXED) ||
131         (flag == PermissionFlag::PERMISSION_ALLOW_THIS_TIME);
132 };
133 } // namespace
134 
RegisterPermStateChangeScopePtr(const PermStateChangeScope & subscribeInfo)135 RegisterPermStateChangeScopePtr::RegisterPermStateChangeScopePtr(const PermStateChangeScope& subscribeInfo)
136     : PermStateChangeCallbackCustomize(subscribeInfo)
137 {}
138 
~RegisterPermStateChangeScopePtr()139 RegisterPermStateChangeScopePtr::~RegisterPermStateChangeScopePtr()
140 {
141     if (ref_ == nullptr) {
142         return;
143     }
144     DeleteNapiRef();
145 }
146 
PermStateChangeCallback(PermStateChangeInfo & result)147 void RegisterPermStateChangeScopePtr::PermStateChangeCallback(PermStateChangeInfo& result)
148 {
149     std::lock_guard<std::mutex> lock(validMutex_);
150     if (!valid_) {
151         ACCESSTOKEN_LOG_ERROR(LABEL, "Object is invalid.");
152         return;
153     }
154     uv_loop_s* loop = nullptr;
155     NAPI_CALL_RETURN_VOID(env_, napi_get_uv_event_loop(env_, &loop));
156     if (loop == nullptr) {
157         ACCESSTOKEN_LOG_ERROR(LABEL, "Loop instance is nullptr");
158         return;
159     }
160     uv_work_t* work = new (std::nothrow) uv_work_t;
161     if (work == nullptr) {
162         ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for work!");
163         return;
164     }
165     std::unique_ptr<uv_work_t> uvWorkPtr {work};
166     RegisterPermStateChangeWorker* registerPermStateChangeWorker =
167         new (std::nothrow) RegisterPermStateChangeWorker();
168     if (registerPermStateChangeWorker == nullptr) {
169         ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for RegisterPermStateChangeWorker!");
170         return;
171     }
172     std::unique_ptr<RegisterPermStateChangeWorker> workPtr {registerPermStateChangeWorker};
173     registerPermStateChangeWorker->env = env_;
174     registerPermStateChangeWorker->ref = ref_;
175     registerPermStateChangeWorker->result = result;
176     ACCESSTOKEN_LOG_DEBUG(LABEL,
177         "result permStateChangeType = %{public}d, tokenID = %{public}d, permissionName = %{public}s",
178         result.permStateChangeType, result.tokenID, result.permissionName.c_str());
179     registerPermStateChangeWorker->subscriber = shared_from_this();
180     work->data = reinterpret_cast<void *>(registerPermStateChangeWorker);
181     NAPI_CALL_RETURN_VOID(env_,
182         uv_queue_work_with_qos(loop, work, [](uv_work_t* work) {}, UvQueueWorkPermStateChanged, uv_qos_default));
183     uvWorkPtr.release();
184     workPtr.release();
185 }
186 
SetEnv(const napi_env & env)187 void RegisterPermStateChangeScopePtr::SetEnv(const napi_env& env)
188 {
189     env_ = env;
190 }
191 
SetCallbackRef(const napi_ref & ref)192 void RegisterPermStateChangeScopePtr::SetCallbackRef(const napi_ref& ref)
193 {
194     ref_ = ref;
195 }
196 
SetValid(bool valid)197 void RegisterPermStateChangeScopePtr::SetValid(bool valid)
198 {
199     std::lock_guard<std::mutex> lock(validMutex_);
200     valid_ = valid;
201 }
202 
~PermStateChangeContext()203 PermStateChangeContext::~PermStateChangeContext()
204 {}
205 
UvQueueWorkDeleteRef(uv_work_t * work,int32_t status)206 void UvQueueWorkDeleteRef(uv_work_t *work, int32_t status)
207 {
208     if (work == nullptr) {
209         ACCESSTOKEN_LOG_ERROR(LABEL, "Work == nullptr : %{public}d", work == nullptr);
210         return;
211     } else if (work->data == nullptr) {
212         ACCESSTOKEN_LOG_ERROR(LABEL, "Work->data == nullptr : %{public}d", work->data == nullptr);
213         return;
214     }
215     RegisterPermStateChangeWorker* registerPermStateChangeWorker =
216         reinterpret_cast<RegisterPermStateChangeWorker*>(work->data);
217     if (registerPermStateChangeWorker == nullptr) {
218         delete work;
219         return;
220     }
221     napi_delete_reference(registerPermStateChangeWorker->env, registerPermStateChangeWorker->ref);
222     delete registerPermStateChangeWorker;
223     registerPermStateChangeWorker = nullptr;
224     delete work;
225     ACCESSTOKEN_LOG_DEBUG(LABEL, "UvQueueWorkDeleteRef end");
226 }
227 
DeleteNapiRef()228 void RegisterPermStateChangeScopePtr::DeleteNapiRef()
229 {
230     uv_loop_s* loop = nullptr;
231     NAPI_CALL_RETURN_VOID(env_, napi_get_uv_event_loop(env_, &loop));
232     if (loop == nullptr) {
233         ACCESSTOKEN_LOG_ERROR(LABEL, "Loop instance is nullptr");
234         return;
235     }
236     uv_work_t* work = new (std::nothrow) uv_work_t;
237     if (work == nullptr) {
238         ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for work!");
239         return;
240     }
241 
242     std::unique_ptr<uv_work_t> uvWorkPtr {work};
243     RegisterPermStateChangeWorker* registerPermStateChangeWorker =
244         new (std::nothrow) RegisterPermStateChangeWorker();
245     if (registerPermStateChangeWorker == nullptr) {
246         ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for RegisterPermStateChangeWorker!");
247         return;
248     }
249     std::unique_ptr<RegisterPermStateChangeWorker> workPtr {registerPermStateChangeWorker};
250     registerPermStateChangeWorker->env = env_;
251     registerPermStateChangeWorker->ref = ref_;
252 
253     work->data = reinterpret_cast<void *>(registerPermStateChangeWorker);
254     NAPI_CALL_RETURN_VOID(env_,
255         uv_queue_work_with_qos(loop, work, [](uv_work_t* work) {}, UvQueueWorkDeleteRef, uv_qos_default));
256     ACCESSTOKEN_LOG_DEBUG(LABEL, "DeleteNapiRef");
257     uvWorkPtr.release();
258     workPtr.release();
259 }
260 
SetNamedProperty(napi_env env,napi_value dstObj,const int32_t objValue,const char * propName)261 void NapiAtManager::SetNamedProperty(napi_env env, napi_value dstObj, const int32_t objValue, const char *propName)
262 {
263     napi_value prop = nullptr;
264     napi_create_int32(env, objValue, &prop);
265     napi_set_named_property(env, dstObj, propName, prop);
266 }
267 
Init(napi_env env,napi_value exports)268 napi_value NapiAtManager::Init(napi_env env, napi_value exports)
269 {
270     ACCESSTOKEN_LOG_DEBUG(LABEL, "Enter init.");
271 
272     napi_property_descriptor descriptor[] = { DECLARE_NAPI_FUNCTION("createAtManager", CreateAtManager) };
273 
274     NAPI_CALL(env, napi_define_properties(env,
275         exports, sizeof(descriptor) / sizeof(napi_property_descriptor), descriptor));
276 
277     napi_property_descriptor properties[] = {
278         DECLARE_NAPI_FUNCTION("verifyAccessToken", VerifyAccessToken),
279         DECLARE_NAPI_FUNCTION("verifyAccessTokenSync", VerifyAccessTokenSync),
280         DECLARE_NAPI_FUNCTION("grantUserGrantedPermission", GrantUserGrantedPermission),
281         DECLARE_NAPI_FUNCTION("revokeUserGrantedPermission", RevokeUserGrantedPermission),
282         DECLARE_NAPI_FUNCTION("checkAccessToken", CheckAccessToken),
283         DECLARE_NAPI_FUNCTION("checkAccessTokenSync", VerifyAccessTokenSync),
284         DECLARE_NAPI_FUNCTION("getPermissionFlags", GetPermissionFlags),
285         DECLARE_NAPI_FUNCTION("on", RegisterPermStateChangeCallback),
286         DECLARE_NAPI_FUNCTION("off", UnregisterPermStateChangeCallback),
287         DECLARE_NAPI_FUNCTION("getVersion", GetVersion),
288         DECLARE_NAPI_FUNCTION("setPermissionRequestToggleStatus", SetPermissionRequestToggleStatus),
289         DECLARE_NAPI_FUNCTION("getPermissionRequestToggleStatus", GetPermissionRequestToggleStatus),
290         DECLARE_NAPI_FUNCTION("requestPermissionsFromUser", NapiRequestPermission::RequestPermissionsFromUser),
291         DECLARE_NAPI_FUNCTION("getPermissionsStatus", NapiRequestPermission::GetPermissionsStatus),
292         DECLARE_NAPI_FUNCTION("requestPermissionOnSetting", NapiRequestPermissionOnSetting::RequestPermissionOnSetting),
293         DECLARE_NAPI_FUNCTION("requestGlobalSwitch", NapiRequestGlobalSwitch::RequestGlobalSwitch),
294     };
295 
296     napi_value cons = nullptr;
297     NAPI_CALL(env, napi_define_class(env, ATMANAGER_CLASS_NAME.c_str(), ATMANAGER_CLASS_NAME.size(),
298         JsConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &cons));
299 
300     NAPI_CALL(env, napi_create_reference(env, cons, 1, &g_atManagerRef_));
301     NAPI_CALL(env, napi_set_named_property(env, exports, ATMANAGER_CLASS_NAME.c_str(), cons));
302 
303     CreateObjects(env, exports);
304 
305     return exports;
306 }
307 
CreateObjects(napi_env env,napi_value exports)308 void NapiAtManager::CreateObjects(napi_env env, napi_value exports)
309 {
310     napi_value grantStatus = nullptr;
311     napi_create_object(env, &grantStatus);
312     SetNamedProperty(env, grantStatus, PERMISSION_DENIED, "PERMISSION_DENIED");
313     SetNamedProperty(env, grantStatus, PERMISSION_GRANTED, "PERMISSION_GRANTED");
314 
315     napi_value permStateChangeType = nullptr;
316     napi_create_object(env, &permStateChangeType);
317     SetNamedProperty(env, permStateChangeType, PERMISSION_REVOKED_OPER, "PERMISSION_REVOKED_OPER");
318     SetNamedProperty(env, permStateChangeType, PERMISSION_GRANTED_OPER, "PERMISSION_GRANTED_OPER");
319 
320     napi_value permissionStatus = nullptr;
321     napi_create_object(env, &permissionStatus);
322     SetNamedProperty(env, permissionStatus, SETTING_OPER, "DENIED");
323     SetNamedProperty(env, permissionStatus, PASS_OPER, "GRANTED");
324     SetNamedProperty(env, permissionStatus, DYNAMIC_OPER, "NOT_DETERMINED");
325     SetNamedProperty(env, permissionStatus, INVALID_OPER, "INVALID");
326     SetNamedProperty(env, permissionStatus, FORBIDDEN_OPER, "RESTRICTED");
327 
328     napi_value permissionRequestToggleStatus = nullptr;
329     napi_create_object(env, &permissionRequestToggleStatus);
330     SetNamedProperty(env, permissionRequestToggleStatus, CLOSED, "CLOSED");
331     SetNamedProperty(env, permissionRequestToggleStatus, OPEN, "OPEN");
332 
333     napi_value globalSwitchType = nullptr;
334     napi_create_object(env, &globalSwitchType);
335     SetNamedProperty(env, globalSwitchType, CAMERA, "CAMERA");
336     SetNamedProperty(env, globalSwitchType, MICROPHONE, "MICROPHONE");
337     SetNamedProperty(env, globalSwitchType, LOCATION, "LOCATION");
338 
339     napi_property_descriptor exportFuncs[] = {
340         DECLARE_NAPI_PROPERTY("GrantStatus", grantStatus),
341         DECLARE_NAPI_PROPERTY("PermissionStateChangeType", permStateChangeType),
342         DECLARE_NAPI_PROPERTY("PermissionStatus", permissionStatus),
343         DECLARE_NAPI_PROPERTY("PermissionRequestToggleStatus", permissionRequestToggleStatus),
344         DECLARE_NAPI_PROPERTY("SwitchType", globalSwitchType),
345     };
346     napi_define_properties(env, exports, sizeof(exportFuncs) / sizeof(*exportFuncs), exportFuncs);
347 }
348 
JsConstructor(napi_env env,napi_callback_info cbinfo)349 napi_value NapiAtManager::JsConstructor(napi_env env, napi_callback_info cbinfo)
350 {
351     ACCESSTOKEN_LOG_DEBUG(LABEL, "Enter JsConstructor");
352 
353     napi_value thisVar = nullptr;
354     NAPI_CALL(env, napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr));
355     return thisVar;
356 }
357 
CreateAtManager(napi_env env,napi_callback_info cbInfo)358 napi_value NapiAtManager::CreateAtManager(napi_env env, napi_callback_info cbInfo)
359 {
360     ACCESSTOKEN_LOG_DEBUG(LABEL, "Enter CreateAtManager");
361 
362     napi_value instance = nullptr;
363     napi_value cons = nullptr;
364 
365     NAPI_CALL(env, napi_get_reference_value(env, g_atManagerRef_, &cons));
366     ACCESSTOKEN_LOG_DEBUG(LABEL, "Get a reference to the global variable g_atManagerRef_ complete");
367 
368     NAPI_CALL(env, napi_new_instance(env, cons, 0, nullptr, &instance));
369 
370     ACCESSTOKEN_LOG_DEBUG(LABEL, "New the js instance complete");
371 
372     return instance;
373 }
374 
ParseInputVerifyPermissionOrGetFlag(const napi_env env,const napi_callback_info info,AtManagerAsyncContext & asyncContext)375 bool NapiAtManager::ParseInputVerifyPermissionOrGetFlag(const napi_env env, const napi_callback_info info,
376     AtManagerAsyncContext& asyncContext)
377 {
378     size_t argc = NapiContextCommon::MAX_PARAMS_TWO;
379 
380     napi_value argv[NapiContextCommon::MAX_PARAMS_TWO] = { nullptr };
381     napi_value thisVar = nullptr;
382     std::string errMsg;
383     void *data = nullptr;
384     NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data), false);
385     if (argc < NapiContextCommon::MAX_PARAMS_TWO) {
386         NAPI_CALL_BASE(env, napi_throw(env, GenerateBusinessError(env,
387             JsErrorCode::JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
388         return false;
389     }
390     asyncContext.env = env;
391     // 0: the first parameter of argv
392     if (!ParseUint32(env, argv[0], asyncContext.tokenId)) {
393         errMsg = GetParamErrorMsg("tokenId", "number");
394         NAPI_CALL_BASE(env,
395             napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
396         return false;
397     }
398 
399     // 1: the second parameter of argv
400     if (!ParseString(env, argv[1], asyncContext.permissionName)) {
401         errMsg = GetParamErrorMsg("permissionName", "string");
402         NAPI_CALL_BASE(env,
403             napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
404         return false;
405     }
406 
407     ACCESSTOKEN_LOG_DEBUG(LABEL, "TokenID = %{public}d, permissionName = %{public}s", asyncContext.tokenId,
408         asyncContext.permissionName.c_str());
409     return true;
410 }
411 
VerifyAccessTokenExecute(napi_env env,void * data)412 void NapiAtManager::VerifyAccessTokenExecute(napi_env env, void *data)
413 {
414     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext *>(data);
415     if (asyncContext == nullptr) {
416         return;
417     }
418     asyncContext->result = AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName);
419 }
420 
VerifyAccessTokenComplete(napi_env env,napi_status status,void * data)421 void NapiAtManager::VerifyAccessTokenComplete(napi_env env, napi_status status, void *data)
422 {
423     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext *>(data);
424     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
425     napi_value result;
426 
427     ACCESSTOKEN_LOG_DEBUG(LABEL, "TokenId = %{public}d, permissionName = %{public}s, verify result = %{public}d.",
428         asyncContext->tokenId, asyncContext->permissionName.c_str(), asyncContext->result);
429 
430     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, asyncContext->result, &result)); // verify result
431     NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncContext->deferred, result));
432 }
433 
VerifyAccessToken(napi_env env,napi_callback_info info)434 napi_value NapiAtManager::VerifyAccessToken(napi_env env, napi_callback_info info)
435 {
436     ACCESSTOKEN_LOG_DEBUG(LABEL, "VerifyAccessToken begin.");
437 
438     auto* asyncContext = new (std::nothrow) AtManagerAsyncContext(env);
439     if (asyncContext == nullptr) {
440         ACCESSTOKEN_LOG_ERROR(LABEL, "New struct failed.");
441         return nullptr;
442     }
443 
444     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
445     if (!ParseInputVerifyPermissionOrGetFlag(env, info, *asyncContext)) {
446         return nullptr;
447     }
448 
449     napi_value result = nullptr;
450     NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
451 
452     napi_value resources = nullptr;
453     NAPI_CALL(env, napi_create_string_utf8(env, "VerifyAccessToken", NAPI_AUTO_LENGTH, &resources));
454 
455     NAPI_CALL(env, napi_create_async_work(
456         env, nullptr, resources,
457         VerifyAccessTokenExecute, VerifyAccessTokenComplete,
458         reinterpret_cast<void *>(asyncContext), &(asyncContext->work)));
459     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
460 
461     ACCESSTOKEN_LOG_DEBUG(LABEL, "VerifyAccessToken end.");
462     context.release();
463     return result;
464 }
465 
CheckAccessTokenExecute(napi_env env,void * data)466 void NapiAtManager::CheckAccessTokenExecute(napi_env env, void *data)
467 {
468     if (data == nullptr) {
469         return;
470     }
471     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext *>(data);
472     if (asyncContext == nullptr) {
473         return;
474     }
475     if (asyncContext->tokenId == 0) {
476         asyncContext->errorCode = JS_ERROR_PARAM_INVALID;
477         return;
478     }
479     if ((asyncContext->permissionName.empty()) ||
480         ((asyncContext->permissionName.length() > NapiContextCommon::MAX_LENGTH))) {
481         asyncContext->errorCode = JS_ERROR_PARAM_INVALID;
482         return;
483     }
484 
485     asyncContext->result = AccessTokenKit::VerifyAccessToken(asyncContext->tokenId,
486         asyncContext->permissionName);
487 }
488 
CheckAccessTokenComplete(napi_env env,napi_status status,void * data)489 void NapiAtManager::CheckAccessTokenComplete(napi_env env, napi_status status, void *data)
490     __attribute__((no_sanitize("cfi")))
491 {
492     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext *>(data);
493     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
494 
495     napi_value result = nullptr;
496     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, asyncContext->result, &result));
497     ReturnPromiseResult(env, asyncContext->errorCode, asyncContext->deferred, result);
498 }
499 
CheckAccessToken(napi_env env,napi_callback_info info)500 napi_value NapiAtManager::CheckAccessToken(napi_env env, napi_callback_info info)
501 {
502     ACCESSTOKEN_LOG_DEBUG(LABEL, "CheckAccessToken begin.");
503 
504     auto* asyncContext = new (std::nothrow) AtManagerAsyncContext(env);
505     if (asyncContext == nullptr) {
506         ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
507         return nullptr;
508     }
509 
510     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
511     if (!ParseInputVerifyPermissionOrGetFlag(env, info, *asyncContext)) {
512         return nullptr;
513     }
514 
515     napi_value result = nullptr;
516     NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
517 
518     napi_value resource = nullptr;
519     NAPI_CALL(env, napi_create_string_utf8(env, "CheckAccessToken", NAPI_AUTO_LENGTH, &resource));
520 
521     NAPI_CALL(env, napi_create_async_work(
522         env, nullptr, resource,
523         CheckAccessTokenExecute, CheckAccessTokenComplete,
524         reinterpret_cast<void *>(asyncContext), &(asyncContext->work)));
525     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
526 
527     ACCESSTOKEN_LOG_DEBUG(LABEL, "CheckAccessToken end.");
528     context.release();
529     return result;
530 }
531 
GetPermParamValue()532 std::string NapiAtManager::GetPermParamValue()
533 {
534     long long sysCommitId = GetSystemCommitId();
535     if (sysCommitId == g_paramCache.sysCommitIdCache) {
536         ACCESSTOKEN_LOG_DEBUG(LABEL, "SysCommitId = %{public}lld", sysCommitId);
537         return g_paramCache.sysParamCache;
538     }
539     g_paramCache.sysCommitIdCache = sysCommitId;
540     if (g_paramCache.handle == PARAM_DEFAULT_VALUE) {
541         int32_t handle = static_cast<int32_t>(FindParameter(PERMISSION_STATUS_CHANGE_KEY));
542         if (handle == PARAM_DEFAULT_VALUE) {
543             ACCESSTOKEN_LOG_ERROR(LABEL, "FindParameter failed");
544             return "-1";
545         }
546         g_paramCache.handle = handle;
547     }
548 
549     int32_t currCommitId = static_cast<int32_t>(GetParameterCommitId(g_paramCache.handle));
550     if (currCommitId != g_paramCache.commitIdCache) {
551         char value[NapiContextCommon::VALUE_MAX_LEN] = {0};
552         auto ret = GetParameterValue(g_paramCache.handle, value, NapiContextCommon::VALUE_MAX_LEN - 1);
553         if (ret < 0) {
554             ACCESSTOKEN_LOG_ERROR(LABEL, "Return default value, ret=%{public}d", ret);
555             return "-1";
556         }
557         std::string resStr(value);
558         g_paramCache.sysParamCache = resStr;
559         g_paramCache.commitIdCache = currCommitId;
560     }
561     return g_paramCache.sysParamCache;
562 }
563 
UpdatePermissionCache(AtManagerAsyncContext * asyncContext)564 void NapiAtManager::UpdatePermissionCache(AtManagerAsyncContext* asyncContext)
565 {
566     std::lock_guard<std::mutex> lock(g_lockCache);
567     auto iter = g_cache.find(asyncContext->permissionName);
568     if (iter != g_cache.end()) {
569         std::string currPara = GetPermParamValue();
570         if (currPara != iter->second.paramValue) {
571             asyncContext->result = AccessTokenKit::VerifyAccessToken(
572                 asyncContext->tokenId, asyncContext->permissionName);
573             iter->second.status = asyncContext->result;
574             iter->second.paramValue = currPara;
575             ACCESSTOKEN_LOG_DEBUG(LABEL, "Param changed currPara %{public}s", currPara.c_str());
576         } else {
577             asyncContext->result = iter->second.status;
578         }
579     } else {
580         asyncContext->result = AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName);
581         g_cache[asyncContext->permissionName].status = asyncContext->result;
582         g_cache[asyncContext->permissionName].paramValue = GetPermParamValue();
583         ACCESSTOKEN_LOG_DEBUG(LABEL, "G_cacheParam set %{public}s",
584             g_cache[asyncContext->permissionName].paramValue.c_str());
585     }
586 }
587 
VerifyAccessTokenSync(napi_env env,napi_callback_info info)588 napi_value NapiAtManager::VerifyAccessTokenSync(napi_env env, napi_callback_info info)
589 {
590     static uint64_t selfTokenId = GetSelfTokenID();
591     auto* asyncContext = new (std::nothrow) AtManagerAsyncContext(env);
592     if (asyncContext == nullptr) {
593         ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
594         return nullptr;
595     }
596 
597     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
598     if (!ParseInputVerifyPermissionOrGetFlag(env, info, *asyncContext)) {
599         return nullptr;
600     }
601     if (asyncContext->tokenId == 0) {
602         std::string errMsg = GetParamErrorMsg("tokenID", "number");
603         NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_INVALID, errMsg)));
604         return nullptr;
605     }
606     if ((asyncContext->permissionName.empty()) ||
607         ((asyncContext->permissionName.length() > NapiContextCommon::MAX_LENGTH))) {
608         std::string errMsg = GetParamErrorMsg("permissionName", "string");
609         NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, JS_ERROR_PARAM_INVALID, errMsg)));
610         return nullptr;
611     }
612     if (asyncContext->tokenId != static_cast<AccessTokenID>(selfTokenId)) {
613         asyncContext->result = AccessTokenKit::VerifyAccessToken(asyncContext->tokenId, asyncContext->permissionName);
614         napi_value result = nullptr;
615         NAPI_CALL(env, napi_create_int32(env, asyncContext->result, &result));
616         ACCESSTOKEN_LOG_DEBUG(LABEL, "VerifyAccessTokenSync end.");
617         return result;
618     }
619 
620     UpdatePermissionCache(asyncContext);
621     napi_value result = nullptr;
622     NAPI_CALL(env, napi_create_int32(env, asyncContext->result, &result));
623     return result;
624 }
625 
ParseInputGrantOrRevokePermission(const napi_env env,const napi_callback_info info,AtManagerAsyncContext & asyncContext)626 bool NapiAtManager::ParseInputGrantOrRevokePermission(const napi_env env, const napi_callback_info info,
627     AtManagerAsyncContext& asyncContext)
628 {
629     size_t argc = NapiContextCommon::MAX_PARAMS_FOUR;
630     napi_value argv[NapiContextCommon::MAX_PARAMS_FOUR] = {nullptr};
631     napi_value thatVar = nullptr;
632 
633     void *data = nullptr;
634     NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thatVar, &data), false);
635     // 1: grant and revoke required minnum argc
636     if (argc < NapiContextCommon::MAX_PARAMS_FOUR - 1) {
637         NAPI_CALL_BASE(env, napi_throw(env,
638             GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
639         return false;
640     }
641     asyncContext.env = env;
642     std::string errMsg;
643     // 0: the first parameter of argv
644     if (!ParseUint32(env, argv[0], asyncContext.tokenId)) {
645         errMsg = GetParamErrorMsg("tokenId", "number");
646         NAPI_CALL_BASE(
647             env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
648         return false;
649     }
650 
651     // 1: the second parameter of argv
652     if (!ParseString(env, argv[1], asyncContext.permissionName)) {
653         errMsg = GetParamErrorMsg("permissionName", "string");
654         NAPI_CALL_BASE(env,
655             napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
656         return false;
657     }
658 
659     // 2: the third parameter of argv
660     if (!ParseUint32(env, argv[2], asyncContext.flag)) {
661         errMsg = GetParamErrorMsg("flag", "number");
662         NAPI_CALL_BASE(env,
663             napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
664         return false;
665     }
666 
667     if (argc == NapiContextCommon::MAX_PARAMS_FOUR) {
668         // 3: the fourth parameter of argv
669         if ((!IsUndefinedOrNull(env, argv[3])) && (!ParseCallback(env, argv[3], asyncContext.callbackRef))) {
670             NAPI_CALL_BASE(env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL,
671                                 GetErrorMessage(JsErrorCode::JS_ERROR_PARAM_ILLEGAL))), false);
672             return false;
673         }
674     }
675 
676     ACCESSTOKEN_LOG_DEBUG(LABEL, "TokenID = %{public}d, permissionName = %{public}s, flag = %{public}d",
677         asyncContext.tokenId, asyncContext.permissionName.c_str(), asyncContext.flag);
678     return true;
679 }
680 
GrantUserGrantedPermissionExecute(napi_env env,void * data)681 void NapiAtManager::GrantUserGrantedPermissionExecute(napi_env env, void *data)
682 {
683     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext *>(data);
684     if (asyncContext == nullptr) {
685         return;
686     }
687     PermissionDef permissionDef;
688 
689     permissionDef.grantMode = 0;
690     permissionDef.availableLevel = APL_NORMAL;
691     permissionDef.provisionEnable = false;
692     permissionDef.distributedSceneEnable = false;
693     permissionDef.labelId = 0;
694     permissionDef.descriptionId = 0;
695 
696     int32_t result = AccessTokenKit::GetDefPermission(asyncContext->permissionName, permissionDef);
697     if (result != RET_SUCCESS) {
698         asyncContext->result = result;
699         return;
700     }
701 
702     ACCESSTOKEN_LOG_DEBUG(LABEL, "PermissionName = %{public}s, grantmode = %{public}d.",
703         asyncContext->permissionName.c_str(), permissionDef.grantMode);
704 
705     if (!IsPermissionFlagValid(asyncContext->flag)) {
706         asyncContext->result = ERR_PARAM_INVALID;
707     }
708     // only user_grant permission can use innerkit class method to grant permission, system_grant return failed
709     if (permissionDef.grantMode == USER_GRANT) {
710         asyncContext->result = AccessTokenKit::GrantPermission(asyncContext->tokenId, asyncContext->permissionName,
711             asyncContext->flag);
712     } else {
713         asyncContext->result = ERR_PERMISSION_NOT_EXIST;
714     }
715     ACCESSTOKEN_LOG_DEBUG(LABEL,
716         "tokenId = %{public}d, permissionName = %{public}s, flag = %{public}d, grant result = %{public}d.",
717         asyncContext->tokenId, asyncContext->permissionName.c_str(), asyncContext->flag, asyncContext->result);
718 }
719 
GrantUserGrantedPermissionComplete(napi_env env,napi_status status,void * data)720 void NapiAtManager::GrantUserGrantedPermissionComplete(napi_env env, napi_status status, void *data)
721 {
722     AtManagerAsyncContext* context = reinterpret_cast<AtManagerAsyncContext*>(data);
723     std::unique_ptr<AtManagerAsyncContext> callbackPtr {context};
724     napi_value result = GetNapiNull(env);
725 
726     if (context->deferred != nullptr) {
727         ReturnPromiseResult(env, context->result, context->deferred, result);
728     } else {
729         ReturnCallbackResult(env, context->result, context->callbackRef, result);
730     }
731 }
732 
GetVersion(napi_env env,napi_callback_info info)733 napi_value NapiAtManager::GetVersion(napi_env env, napi_callback_info info)
734 {
735     ACCESSTOKEN_LOG_DEBUG(LABEL, "GetVersion begin.");
736 
737     auto* asyncContext = new (std::nothrow) AtManagerAsyncContext(env);
738     if (asyncContext == nullptr) {
739         ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
740         return nullptr;
741     }
742     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
743 
744     napi_value result = nullptr;
745     NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
746 
747     napi_value resource = nullptr;
748     NAPI_CALL(env, napi_create_string_utf8(env, "GetVersion", NAPI_AUTO_LENGTH, &resource));
749 
750     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, GetVersionExecute, GetVersionComplete,
751         reinterpret_cast<void *>(asyncContext), &(asyncContext->work)));
752     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
753 
754     context.release();
755     ACCESSTOKEN_LOG_DEBUG(LABEL, "GetVersion end.");
756     return result;
757 }
758 
GetVersionExecute(napi_env env,void * data)759 void NapiAtManager::GetVersionExecute(napi_env env, void *data)
760 {
761     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext *>(data);
762     if (asyncContext == nullptr) {
763         return;
764     }
765     uint32_t version;
766     int32_t result = AccessTokenKit::GetVersion(version);
767     if (result != RET_SUCCESS) {
768         asyncContext->errorCode = result;
769         return;
770     }
771     asyncContext->result = static_cast<int32_t>(version);
772     ACCESSTOKEN_LOG_DEBUG(LABEL, "Version result = %{public}d.", asyncContext->result);
773 }
774 
GetVersionComplete(napi_env env,napi_status status,void * data)775 void NapiAtManager::GetVersionComplete(napi_env env, napi_status status, void *data)
776 {
777     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext *>(data);
778     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
779     napi_value result = nullptr;
780     ACCESSTOKEN_LOG_DEBUG(LABEL, "Version result = %{public}d.", asyncContext->result);
781 
782     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, asyncContext->result, &result));
783     ReturnPromiseResult(env, asyncContext->errorCode, asyncContext->deferred, result);
784 }
785 
GrantUserGrantedPermission(napi_env env,napi_callback_info info)786 napi_value NapiAtManager::GrantUserGrantedPermission(napi_env env, napi_callback_info info)
787 {
788     ACCESSTOKEN_LOG_DEBUG(LABEL, "GrantUserGrantedPermission begin.");
789 
790     auto* context = new (std::nothrow) AtManagerAsyncContext(env); // for async work deliver data
791     if (context == nullptr) {
792         ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
793         return nullptr;
794     }
795 
796     std::unique_ptr<AtManagerAsyncContext> contextPtr {context};
797     if (!ParseInputGrantOrRevokePermission(env, info, *context)) {
798         return nullptr;
799     }
800 
801     napi_value result = nullptr;
802 
803     if (context->callbackRef == nullptr) {
804         NAPI_CALL(env, napi_create_promise(env, &(context->deferred), &result));
805     } else {
806         NAPI_CALL(env, napi_get_undefined(env, &result));
807     }
808 
809     napi_value resource = nullptr;
810     NAPI_CALL(env, napi_create_string_utf8(env, "GrantUserGrantedPermission", NAPI_AUTO_LENGTH, &resource));
811 
812     NAPI_CALL(env, napi_create_async_work(
813         env, nullptr, resource,
814         GrantUserGrantedPermissionExecute, GrantUserGrantedPermissionComplete,
815         reinterpret_cast<void *>(context), &(context->work)));
816 
817     NAPI_CALL(env, napi_queue_async_work_with_qos(env, context->work, napi_qos_default));
818 
819     ACCESSTOKEN_LOG_DEBUG(LABEL, "GrantUserGrantedPermission end.");
820     contextPtr.release();
821     return result;
822 }
823 
RevokeUserGrantedPermissionExecute(napi_env env,void * data)824 void NapiAtManager::RevokeUserGrantedPermissionExecute(napi_env env, void *data)
825 {
826     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext *>(data);
827     if (asyncContext == nullptr) {
828         return;
829     }
830     PermissionDef permissionDef;
831 
832     permissionDef.grantMode = 0;
833     permissionDef.availableLevel = APL_NORMAL;
834     permissionDef.provisionEnable = false;
835     permissionDef.distributedSceneEnable = false;
836     permissionDef.labelId = 0;
837     permissionDef.descriptionId = 0;
838 
839     int32_t result = AccessTokenKit::GetDefPermission(asyncContext->permissionName, permissionDef);
840     if (result != RET_SUCCESS) {
841         asyncContext->result = result;
842         return;
843     }
844 
845     ACCESSTOKEN_LOG_DEBUG(LABEL, "PermissionName = %{public}s, grantmode = %{public}d.",
846         asyncContext->permissionName.c_str(), permissionDef.grantMode);
847 
848     if (!IsPermissionFlagValid(asyncContext->flag)) {
849         asyncContext->result = ERR_PARAM_INVALID;
850     }
851     // only user_grant permission can use innerkit class method to grant permission, system_grant return failed
852     if (permissionDef.grantMode == USER_GRANT) {
853         asyncContext->result = AccessTokenKit::RevokePermission(asyncContext->tokenId, asyncContext->permissionName,
854             asyncContext->flag);
855     } else {
856         asyncContext->result = ERR_PERMISSION_NOT_EXIST;
857     }
858     ACCESSTOKEN_LOG_DEBUG(LABEL,
859         "tokenId = %{public}d, permissionName = %{public}s, flag = %{public}d, revoke result = %{public}d.",
860         asyncContext->tokenId, asyncContext->permissionName.c_str(), asyncContext->flag, asyncContext->result);
861 }
862 
RevokeUserGrantedPermissionComplete(napi_env env,napi_status status,void * data)863 void NapiAtManager::RevokeUserGrantedPermissionComplete(napi_env env, napi_status status, void *data)
864 {
865     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext*>(data);
866     std::unique_ptr<AtManagerAsyncContext> callbackPtr {asyncContext};
867 
868     napi_value result = GetNapiNull(env);
869     if (asyncContext->deferred != nullptr) {
870         ReturnPromiseResult(env, asyncContext->result, asyncContext->deferred, result);
871     } else {
872         ReturnCallbackResult(env, asyncContext->result, asyncContext->callbackRef, result);
873     }
874 }
875 
RevokeUserGrantedPermission(napi_env env,napi_callback_info info)876 napi_value NapiAtManager::RevokeUserGrantedPermission(napi_env env, napi_callback_info info)
877 {
878     ACCESSTOKEN_LOG_DEBUG(LABEL, "RevokeUserGrantedPermission begin.");
879 
880     auto* asyncContext = new (std::nothrow) AtManagerAsyncContext(env); // for async work deliver data
881     if (asyncContext == nullptr) {
882         ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
883         return nullptr;
884     }
885 
886     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
887     if (!ParseInputGrantOrRevokePermission(env, info, *asyncContext)) {
888         return nullptr;
889     }
890 
891     napi_value result = nullptr;
892     if (asyncContext->callbackRef == nullptr) {
893         NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result));
894     } else {
895         NAPI_CALL(env, napi_get_undefined(env, &result));
896     }
897 
898     napi_value resource = nullptr;
899     NAPI_CALL(env, napi_create_string_utf8(env, "RevokeUserGrantedPermission", NAPI_AUTO_LENGTH, &resource));
900 
901     NAPI_CALL(env, napi_create_async_work(
902         env, nullptr, resource,
903         RevokeUserGrantedPermissionExecute, RevokeUserGrantedPermissionComplete,
904         reinterpret_cast<void *>(asyncContext), &(asyncContext->work)));
905 
906     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
907     ACCESSTOKEN_LOG_DEBUG(LABEL, "RevokeUserGrantedPermission end.");
908     context.release();
909     return result;
910 }
911 
GetPermissionFlagsExecute(napi_env env,void * data)912 void NapiAtManager::GetPermissionFlagsExecute(napi_env env, void *data)
913 {
914     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext*>(data);
915 
916     asyncContext->result = AccessTokenKit::GetPermissionFlag(asyncContext->tokenId,
917         asyncContext->permissionName, asyncContext->flag);
918 }
919 
GetPermissionFlagsComplete(napi_env env,napi_status status,void * data)920 void NapiAtManager::GetPermissionFlagsComplete(napi_env env, napi_status status, void *data)
921 {
922     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext*>(data);
923     std::unique_ptr<AtManagerAsyncContext> callbackPtr {asyncContext};
924 
925     napi_value result = nullptr;
926     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, asyncContext->flag, &result));
927 
928     ReturnPromiseResult(env, asyncContext->result, asyncContext->deferred, result);
929 }
930 
GetPermissionFlags(napi_env env,napi_callback_info info)931 napi_value NapiAtManager::GetPermissionFlags(napi_env env, napi_callback_info info)
932 {
933     ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionFlags begin.");
934 
935     auto* asyncContext = new (std::nothrow) AtManagerAsyncContext(env);
936     if (asyncContext == nullptr) {
937         ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
938         return nullptr;
939     }
940 
941     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
942     if (!ParseInputVerifyPermissionOrGetFlag(env, info, *asyncContext)) {
943         return nullptr;
944     }
945 
946     napi_value result = nullptr;
947     napi_create_promise(env, &(asyncContext->deferred), &result); // create delay promise object
948 
949     napi_value resource = nullptr; // resource name
950     napi_create_string_utf8(env, "GetPermissionFlags", NAPI_AUTO_LENGTH, &resource);
951     // define work
952     napi_create_async_work(
953         env, nullptr, resource, GetPermissionFlagsExecute, GetPermissionFlagsComplete,
954         reinterpret_cast<void *>(asyncContext), &(asyncContext->work));
955     // add async work handle to the napi queue and wait for result
956     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
957 
958     ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionFlags end.");
959     context.release();
960     return result;
961 }
962 
ParseInputSetToggleStatus(const napi_env env,const napi_callback_info info,AtManagerAsyncContext & asyncContext)963 bool NapiAtManager::ParseInputSetToggleStatus(const napi_env env, const napi_callback_info info,
964     AtManagerAsyncContext& asyncContext)
965 {
966     size_t argc = NapiContextCommon::MAX_PARAMS_TWO;
967     napi_value argv[NapiContextCommon::MAX_PARAMS_TWO] = { nullptr };
968     napi_value thisVar = nullptr;
969     void *data = nullptr;
970     std::string errMsg;
971 
972     NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data), false);
973     if (argc < NapiContextCommon::MAX_PARAMS_TWO) {
974         NAPI_CALL_BASE(env, napi_throw(env, GenerateBusinessError(env,
975             JsErrorCode::JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
976         return false;
977     }
978     asyncContext.env = env;
979     // 0: the first parameter of argv
980     if (!ParseString(env, argv[0], asyncContext.permissionName)) {
981         errMsg = GetParamErrorMsg("permissionName", "string");
982         NAPI_CALL_BASE(env,
983             napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
984         return false;
985     }
986 
987     // 1: the second parameter of argv
988     if (!ParseUint32(env, argv[1], asyncContext.status)) {
989         errMsg = GetParamErrorMsg("status", "number");
990         NAPI_CALL_BASE(env,
991             napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
992         return false;
993     }
994 
995     return true;
996 }
997 
ParseInputGetToggleStatus(const napi_env env,const napi_callback_info info,AtManagerAsyncContext & asyncContext)998 bool NapiAtManager::ParseInputGetToggleStatus(const napi_env env, const napi_callback_info info,
999     AtManagerAsyncContext& asyncContext)
1000 {
1001     size_t argc = NapiContextCommon::MAX_PARAMS_ONE;
1002 
1003     napi_value argv[NapiContextCommon::MAX_PARAMS_ONE] = { nullptr };
1004     napi_value thisVar = nullptr;
1005     std::string errMsg;
1006     void *data = nullptr;
1007     NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data), false);
1008     if (argc < NapiContextCommon::MAX_PARAMS_ONE) {
1009         NAPI_CALL_BASE(env, napi_throw(env, GenerateBusinessError(env,
1010             JsErrorCode::JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
1011         return false;
1012     }
1013     asyncContext.env = env;
1014     // 0: the first parameter of argv
1015     if (!ParseString(env, argv[0], asyncContext.permissionName)) {
1016         errMsg = GetParamErrorMsg("permissionName", "string");
1017         NAPI_CALL_BASE(env,
1018             napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
1019         return false;
1020     }
1021 
1022     return true;
1023 }
1024 
SetPermissionRequestToggleStatusExecute(napi_env env,void * data)1025 void NapiAtManager::SetPermissionRequestToggleStatusExecute(napi_env env, void *data)
1026 {
1027     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext*>(data);
1028 
1029     asyncContext->result = AccessTokenKit::SetPermissionRequestToggleStatus(asyncContext->permissionName,
1030         asyncContext->status, 0);
1031 }
1032 
SetPermissionRequestToggleStatusComplete(napi_env env,napi_status status,void * data)1033 void NapiAtManager::SetPermissionRequestToggleStatusComplete(napi_env env, napi_status status, void *data)
1034 {
1035     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext*>(data);
1036     std::unique_ptr<AtManagerAsyncContext> callbackPtr {asyncContext};
1037 
1038     napi_value result = nullptr;
1039     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, asyncContext->result, &result));
1040 
1041     ReturnPromiseResult(env, asyncContext->result, asyncContext->deferred, result);
1042 }
1043 
GetPermissionRequestToggleStatusExecute(napi_env env,void * data)1044 void NapiAtManager::GetPermissionRequestToggleStatusExecute(napi_env env, void *data)
1045 {
1046     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext*>(data);
1047 
1048     asyncContext->result = AccessTokenKit::GetPermissionRequestToggleStatus(asyncContext->permissionName,
1049         asyncContext->status, 0);
1050 }
1051 
GetPermissionRequestToggleStatusComplete(napi_env env,napi_status status,void * data)1052 void NapiAtManager::GetPermissionRequestToggleStatusComplete(napi_env env, napi_status status, void *data)
1053 {
1054     AtManagerAsyncContext* asyncContext = reinterpret_cast<AtManagerAsyncContext*>(data);
1055     std::unique_ptr<AtManagerAsyncContext> callbackPtr {asyncContext};
1056 
1057     napi_value result = nullptr;
1058     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, asyncContext->status, &result));
1059 
1060     ReturnPromiseResult(env, asyncContext->result, asyncContext->deferred, result);
1061 }
1062 
SetPermissionRequestToggleStatus(napi_env env,napi_callback_info info)1063 napi_value NapiAtManager::SetPermissionRequestToggleStatus(napi_env env, napi_callback_info info)
1064 {
1065     ACCESSTOKEN_LOG_DEBUG(LABEL, "SetPermissionRequestToggleStatus begin.");
1066 
1067     auto* asyncContext = new (std::nothrow) AtManagerAsyncContext(env);
1068     if (asyncContext == nullptr) {
1069         ACCESSTOKEN_LOG_ERROR(LABEL, "New asyncContext failed.");
1070         return nullptr;
1071     }
1072 
1073     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
1074     if (!ParseInputSetToggleStatus(env, info, *asyncContext)) {
1075         return nullptr;
1076     }
1077 
1078     napi_value result = nullptr;
1079     NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result)); // create delay promise object
1080 
1081     napi_value resource = nullptr; // resource name
1082     NAPI_CALL(env, napi_create_string_utf8(env, "SetPermissionRequestToggleStatus", NAPI_AUTO_LENGTH, &resource));
1083 
1084     NAPI_CALL(env, napi_create_async_work(
1085         env, nullptr, resource, SetPermissionRequestToggleStatusExecute, SetPermissionRequestToggleStatusComplete,
1086         reinterpret_cast<void *>(asyncContext), &(asyncContext->work)));
1087     // add async work handle to the napi queue and wait for result
1088     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
1089 
1090     ACCESSTOKEN_LOG_DEBUG(LABEL, "SetPermissionRequestToggleStatus end.");
1091     context.release();
1092     return result;
1093 }
1094 
GetPermissionRequestToggleStatus(napi_env env,napi_callback_info info)1095 napi_value NapiAtManager::GetPermissionRequestToggleStatus(napi_env env, napi_callback_info info)
1096 {
1097     ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionRequestToggleStatus begin.");
1098 
1099     auto* asyncContext = new (std::nothrow) AtManagerAsyncContext(env);
1100     if (asyncContext == nullptr) {
1101         ACCESSTOKEN_LOG_ERROR(LABEL, "New asyncContext failed.");
1102         return nullptr;
1103     }
1104 
1105     std::unique_ptr<AtManagerAsyncContext> context {asyncContext};
1106     if (!ParseInputGetToggleStatus(env, info, *asyncContext)) {
1107         return nullptr;
1108     }
1109 
1110     napi_value result = nullptr;
1111     NAPI_CALL(env, napi_create_promise(env, &(asyncContext->deferred), &result)); // create delay promise object
1112 
1113     napi_value resource = nullptr; // resource name
1114     NAPI_CALL(env, napi_create_string_utf8(env, "GetPermissionRequestToggleStatus", NAPI_AUTO_LENGTH, &resource));
1115 
1116     NAPI_CALL(env, napi_create_async_work(
1117         env, nullptr, resource, GetPermissionRequestToggleStatusExecute, GetPermissionRequestToggleStatusComplete,
1118         reinterpret_cast<void *>(asyncContext), &(asyncContext->work)));
1119     // add async work handle to the napi queue and wait for result
1120     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default));
1121 
1122     ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionRequestToggleStatus end.");
1123     context.release();
1124     return result;
1125 }
1126 
FillPermStateChangeInfo(const napi_env env,const napi_value * argv,const std::string & type,const napi_value thisVar,RegisterPermStateChangeInfo & registerPermStateChangeInfo)1127 bool NapiAtManager::FillPermStateChangeInfo(const napi_env env, const napi_value* argv, const std::string& type,
1128     const napi_value thisVar, RegisterPermStateChangeInfo& registerPermStateChangeInfo)
1129 {
1130     PermStateChangeScope scopeInfo;
1131     std::string errMsg;
1132     napi_ref callback = nullptr;
1133 
1134     // 1: the second parameter of argv
1135     if (!ParseAccessTokenIDArray(env, argv[1], scopeInfo.tokenIDs)) {
1136         errMsg = GetParamErrorMsg("tokenIDList", "Array<number>");
1137         napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg));
1138         return false;
1139     }
1140     // 2: the third parameter of argv
1141     if (!ParseStringArray(env, argv[2], scopeInfo.permList)) {
1142         errMsg = GetParamErrorMsg("tokenIDList", "Array<string>");
1143         napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg));
1144         return false;
1145     }
1146     // 3: the fourth parameter of argv
1147     if (!ParseCallback(env, argv[3], callback)) {
1148         errMsg = GetParamErrorMsg("tokenIDList", "Callback<PermissionStateChangeInfo>");
1149         napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg));
1150         return false;
1151     }
1152     std::sort(scopeInfo.tokenIDs.begin(), scopeInfo.tokenIDs.end());
1153     std::sort(scopeInfo.permList.begin(), scopeInfo.permList.end());
1154     registerPermStateChangeInfo.env = env;
1155     registerPermStateChangeInfo.callbackRef = callback;
1156     registerPermStateChangeInfo.permStateChangeType = type;
1157     registerPermStateChangeInfo.subscriber = std::make_shared<RegisterPermStateChangeScopePtr>(scopeInfo);
1158     registerPermStateChangeInfo.subscriber->SetEnv(env);
1159     registerPermStateChangeInfo.subscriber->SetCallbackRef(callback);
1160     registerPermStateChangeInfo.threadId_ = std::this_thread::get_id();
1161     std::shared_ptr<RegisterPermStateChangeScopePtr> *subscriber =
1162         new (std::nothrow) std::shared_ptr<RegisterPermStateChangeScopePtr>(
1163             registerPermStateChangeInfo.subscriber);
1164     if (subscriber == nullptr) {
1165         ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create subscriber");
1166         return false;
1167     }
1168     napi_wrap(env, thisVar, reinterpret_cast<void*>(subscriber), [](napi_env nev, void *data, void *hint) {
1169         ACCESSTOKEN_LOG_DEBUG(LABEL, "RegisterPermStateChangeScopePtr delete");
1170         std::shared_ptr<RegisterPermStateChangeScopePtr>* subscriber =
1171             static_cast<std::shared_ptr<RegisterPermStateChangeScopePtr>*>(data);
1172         if (subscriber != nullptr && *subscriber != nullptr) {
1173             (*subscriber)->SetValid(false);
1174             delete subscriber;
1175         }
1176     }, nullptr, nullptr);
1177 
1178     return true;
1179 }
1180 
ParseInputToRegister(const napi_env env,const napi_callback_info cbInfo,RegisterPermStateChangeInfo & registerPermStateChangeInfo)1181 bool NapiAtManager::ParseInputToRegister(const napi_env env, const napi_callback_info cbInfo,
1182     RegisterPermStateChangeInfo& registerPermStateChangeInfo)
1183 {
1184     size_t argc = NapiContextCommon::MAX_PARAMS_FOUR;
1185     napi_value argv[NapiContextCommon::MAX_PARAMS_FOUR] = {nullptr};
1186     napi_value thisVar = nullptr;
1187     NAPI_CALL_BASE(env, napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr), false);
1188     if (argc < NapiContextCommon::MAX_PARAMS_FOUR) {
1189         napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, "Parameter is missing."));
1190         return false;
1191     }
1192     if (thisVar == nullptr) {
1193         ACCESSTOKEN_LOG_ERROR(LABEL, "ThisVar is nullptr");
1194         return false;
1195     }
1196     napi_valuetype valueTypeOfThis = napi_undefined;
1197     NAPI_CALL_BASE(env, napi_typeof(env, thisVar, &valueTypeOfThis), false);
1198     if (valueTypeOfThis == napi_undefined) {
1199         ACCESSTOKEN_LOG_ERROR(LABEL, "ThisVar is undefined");
1200         return false;
1201     }
1202     // 0: the first parameter of argv
1203     std::string type;
1204     if (!ParseString(env, argv[0], type)) {
1205         std::string errMsg = GetParamErrorMsg("type", "string");
1206         napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg));
1207         return false;
1208     }
1209     if (!FillPermStateChangeInfo(env, argv, type, thisVar, registerPermStateChangeInfo)) {
1210         return false;
1211     }
1212 
1213     return true;
1214 }
1215 
RegisterPermStateChangeCallback(napi_env env,napi_callback_info cbInfo)1216 napi_value NapiAtManager::RegisterPermStateChangeCallback(napi_env env, napi_callback_info cbInfo)
1217 {
1218     RegisterPermStateChangeInfo* registerPermStateChangeInfo =
1219         new (std::nothrow) RegisterPermStateChangeInfo();
1220     if (registerPermStateChangeInfo == nullptr) {
1221         ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for subscribeCBInfo!");
1222         return nullptr;
1223     }
1224     std::unique_ptr<RegisterPermStateChangeInfo> callbackPtr {registerPermStateChangeInfo};
1225     if (!ParseInputToRegister(env, cbInfo, *registerPermStateChangeInfo)) {
1226         return nullptr;
1227     }
1228     if (IsExistRegister(env, registerPermStateChangeInfo)) {
1229         ACCESSTOKEN_LOG_ERROR(LABEL, "Subscribe failed. The current subscriber has been existed");
1230         std::string errMsg = GetErrorMessage(JsErrorCode::JS_ERROR_PARAM_INVALID);
1231         NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_INVALID, errMsg)));
1232         return nullptr;
1233     }
1234     int32_t result = AccessTokenKit::RegisterPermStateChangeCallback(registerPermStateChangeInfo->subscriber);
1235     if (result != RET_SUCCESS) {
1236         ACCESSTOKEN_LOG_ERROR(LABEL, "RegisterPermStateChangeCallback failed");
1237         registerPermStateChangeInfo->errCode = result;
1238         int32_t jsCode = NapiContextCommon::GetJsErrorCode(result);
1239         std::string errMsg = GetErrorMessage(jsCode);
1240         NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, jsCode, errMsg)));
1241         return nullptr;
1242     }
1243     {
1244         std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
1245         g_permStateChangeRegisters.emplace_back(registerPermStateChangeInfo);
1246         ACCESSTOKEN_LOG_DEBUG(LABEL, "Add g_PermStateChangeRegisters.size = %{public}zu",
1247             g_permStateChangeRegisters.size());
1248     }
1249     callbackPtr.release();
1250     return nullptr;
1251 }
1252 
ParseInputToUnregister(const napi_env env,napi_callback_info cbInfo,UnregisterPermStateChangeInfo & unregisterPermStateChangeInfo)1253 bool NapiAtManager::ParseInputToUnregister(const napi_env env, napi_callback_info cbInfo,
1254     UnregisterPermStateChangeInfo& unregisterPermStateChangeInfo)
1255 {
1256     size_t argc = NapiContextCommon::MAX_PARAMS_FOUR;
1257     napi_value argv[NapiContextCommon::MAX_PARAMS_FOUR] = {nullptr};
1258     napi_value thisVar = nullptr;
1259     napi_ref callback = nullptr;
1260     std::string errMsg;
1261     if (napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr) != napi_ok) {
1262         ACCESSTOKEN_LOG_ERROR(LABEL, "Napi_get_cb_info failed");
1263         return false;
1264     }
1265     // 1: off required minnum argc
1266     if (argc < NapiContextCommon::MAX_PARAMS_FOUR - 1) {
1267         napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, "Parameter is missing."));
1268         return false;
1269     }
1270     // 0: the first parameter of argv
1271     std::string type;
1272     if (!ParseString(env, argv[0], type)) {
1273         errMsg = GetParamErrorMsg("type", "permissionStateChange");
1274         napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg));
1275         return false;
1276     }
1277     PermStateChangeScope scopeInfo;
1278     // 1: the second parameter of argv
1279     if (!ParseAccessTokenIDArray(env, argv[1], scopeInfo.tokenIDs)) {
1280         errMsg = GetParamErrorMsg("tokenIDList", "Array<number>");
1281         napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg));
1282         return false;
1283     }
1284     // 2: the third parameter of argv
1285     if (!ParseStringArray(env, argv[2], scopeInfo.permList)) {
1286         errMsg = GetParamErrorMsg("permissionNameList", "Array<string>");
1287         napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg));
1288         return false;
1289     }
1290     if (argc == NapiContextCommon::MAX_PARAMS_FOUR) {
1291         // 3: the fourth parameter of argv
1292         if (!ParseCallback(env, argv[3], callback)) {
1293             errMsg = GetParamErrorMsg("callback", "Callback<PermissionStateChangeInfo>");
1294             napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg));
1295             return false;
1296         }
1297     }
1298 
1299     std::sort(scopeInfo.tokenIDs.begin(), scopeInfo.tokenIDs.end());
1300     std::sort(scopeInfo.permList.begin(), scopeInfo.permList.end());
1301     unregisterPermStateChangeInfo.env = env;
1302     unregisterPermStateChangeInfo.callbackRef = callback;
1303     unregisterPermStateChangeInfo.permStateChangeType = type;
1304     unregisterPermStateChangeInfo.scopeInfo = scopeInfo;
1305     unregisterPermStateChangeInfo.threadId_ = std::this_thread::get_id();
1306     return true;
1307 }
1308 
UnregisterPermStateChangeCallback(napi_env env,napi_callback_info cbInfo)1309 napi_value NapiAtManager::UnregisterPermStateChangeCallback(napi_env env, napi_callback_info cbInfo)
1310 {
1311     UnregisterPermStateChangeInfo* unregisterPermStateChangeInfo =
1312         new (std::nothrow) UnregisterPermStateChangeInfo();
1313     if (unregisterPermStateChangeInfo == nullptr) {
1314         ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for subscribeCBInfo!");
1315         return nullptr;
1316     }
1317     std::unique_ptr<UnregisterPermStateChangeInfo> callbackPtr {unregisterPermStateChangeInfo};
1318     if (!ParseInputToUnregister(env, cbInfo, *unregisterPermStateChangeInfo)) {
1319         return nullptr;
1320     }
1321     std::vector<RegisterPermStateChangeInfo*> batchPermStateChangeRegisters;
1322     if (!FindAndGetSubscriberInVector(unregisterPermStateChangeInfo, batchPermStateChangeRegisters, env)) {
1323         ACCESSTOKEN_LOG_ERROR(LABEL, "Unsubscribe failed. The current subscriber does not exist");
1324         std::string errMsg = GetErrorMessage(JsErrorCode::JS_ERROR_PARAM_INVALID);
1325         NAPI_CALL(env,
1326             napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_INVALID, errMsg)));
1327         return nullptr;
1328     }
1329     for (const auto& item : batchPermStateChangeRegisters) {
1330         PermStateChangeScope scopeInfo;
1331         item->subscriber->GetScope(scopeInfo);
1332         int32_t result = AccessTokenKit::UnRegisterPermStateChangeCallback(item->subscriber);
1333         if (result == RET_SUCCESS) {
1334             DeleteRegisterFromVector(scopeInfo, env, item->callbackRef);
1335         } else {
1336             ACCESSTOKEN_LOG_ERROR(LABEL, "Batch UnregisterPermActiveChangeCompleted failed");
1337             int32_t jsCode = NapiContextCommon::GetJsErrorCode(result);
1338             std::string errMsg = GetErrorMessage(jsCode);
1339             NAPI_CALL(env, napi_throw(env, GenerateBusinessError(env, jsCode, errMsg)));
1340         }
1341     }
1342     return nullptr;
1343 }
1344 
FindAndGetSubscriberInVector(UnregisterPermStateChangeInfo * unregisterPermStateChangeInfo,std::vector<RegisterPermStateChangeInfo * > & batchPermStateChangeRegisters,const napi_env env)1345 bool NapiAtManager::FindAndGetSubscriberInVector(UnregisterPermStateChangeInfo* unregisterPermStateChangeInfo,
1346     std::vector<RegisterPermStateChangeInfo*>& batchPermStateChangeRegisters, const napi_env env)
1347 {
1348     std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
1349     std::vector<AccessTokenID> targetTokenIDs = unregisterPermStateChangeInfo->scopeInfo.tokenIDs;
1350     std::vector<std::string> targetPermList = unregisterPermStateChangeInfo->scopeInfo.permList;
1351     for (const auto& item : g_permStateChangeRegisters) {
1352         if (unregisterPermStateChangeInfo->callbackRef != nullptr) {
1353             if (!CompareCallbackRef(env, item->callbackRef, unregisterPermStateChangeInfo->callbackRef,
1354                 item->threadId_)) {
1355                 continue;
1356             }
1357         } else {
1358             // batch delete currentThread callback
1359             if (!IsCurrentThread(item->threadId_)) {
1360                 continue;
1361             }
1362         }
1363         PermStateChangeScope scopeInfo;
1364         item->subscriber->GetScope(scopeInfo);
1365         if (scopeInfo.tokenIDs == targetTokenIDs && scopeInfo.permList == targetPermList) {
1366             ACCESSTOKEN_LOG_DEBUG(LABEL, "Find subscriber in map");
1367             unregisterPermStateChangeInfo->subscriber = item->subscriber;
1368             batchPermStateChangeRegisters.emplace_back(item);
1369         }
1370     }
1371     if (!batchPermStateChangeRegisters.empty()) {
1372         return true;
1373     }
1374     return false;
1375 }
1376 
IsExistRegister(const napi_env env,const RegisterPermStateChangeInfo * registerPermStateChangeInfo)1377 bool NapiAtManager::IsExistRegister(const napi_env env, const RegisterPermStateChangeInfo* registerPermStateChangeInfo)
1378 {
1379     PermStateChangeScope targetScopeInfo;
1380     registerPermStateChangeInfo->subscriber->GetScope(targetScopeInfo);
1381     std::vector<AccessTokenID> targetTokenIDs = targetScopeInfo.tokenIDs;
1382     std::vector<std::string> targetPermList = targetScopeInfo.permList;
1383     std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
1384 
1385     for (const auto& item : g_permStateChangeRegisters) {
1386         PermStateChangeScope scopeInfo;
1387         item->subscriber->GetScope(scopeInfo);
1388 
1389         bool hasPermIntersection = false;
1390         // Special cases:
1391         // 1.Have registered full, and then register some
1392         // 2.Have registered some, then register full
1393         if (scopeInfo.permList.empty() || targetPermList.empty()) {
1394             hasPermIntersection = true;
1395         }
1396         for (const auto& PermItem : targetPermList) {
1397             if (hasPermIntersection) {
1398                 break;
1399             }
1400             auto iter = std::find(scopeInfo.permList.begin(), scopeInfo.permList.end(), PermItem);
1401             if (iter != scopeInfo.permList.end()) {
1402                 hasPermIntersection = true;
1403             }
1404         }
1405 
1406         bool hasTokenIdIntersection = false;
1407 
1408         if (scopeInfo.tokenIDs.empty() || targetTokenIDs.empty()) {
1409             hasTokenIdIntersection = true;
1410         }
1411         for (const auto& tokenItem : targetTokenIDs) {
1412             if (hasTokenIdIntersection) {
1413                 break;
1414             }
1415             auto iter = std::find(scopeInfo.tokenIDs.begin(), scopeInfo.tokenIDs.end(), tokenItem);
1416             if (iter != scopeInfo.tokenIDs.end()) {
1417                 hasTokenIdIntersection = true;
1418             }
1419         }
1420 
1421         if (hasTokenIdIntersection && hasPermIntersection &&
1422             CompareCallbackRef(env, item->callbackRef, registerPermStateChangeInfo->callbackRef, item->threadId_)) {
1423             return true;
1424         }
1425     }
1426     ACCESSTOKEN_LOG_DEBUG(LABEL, "Cannot find subscriber in vector");
1427     return false;
1428 }
1429 
DeleteRegisterFromVector(const PermStateChangeScope & scopeInfo,const napi_env env,napi_ref subscriberRef)1430 void NapiAtManager::DeleteRegisterFromVector(const PermStateChangeScope& scopeInfo, const napi_env env,
1431     napi_ref subscriberRef)
1432 {
1433     std::vector<AccessTokenID> targetTokenIDs = scopeInfo.tokenIDs;
1434     std::vector<std::string> targetPermList = scopeInfo.permList;
1435     std::lock_guard<std::mutex> lock(g_lockForPermStateChangeRegisters);
1436     auto item = g_permStateChangeRegisters.begin();
1437     while (item != g_permStateChangeRegisters.end()) {
1438         PermStateChangeScope stateChangeScope;
1439         (*item)->subscriber->GetScope(stateChangeScope);
1440         if ((stateChangeScope.tokenIDs == targetTokenIDs) && (stateChangeScope.permList == targetPermList) &&
1441             CompareCallbackRef(env, (*item)->callbackRef, subscriberRef, (*item)->threadId_)) {
1442             ACCESSTOKEN_LOG_DEBUG(LABEL, "Find subscribers in vector, delete");
1443             delete *item;
1444             *item = nullptr;
1445             g_permStateChangeRegisters.erase(item);
1446             break;
1447         } else {
1448             ++item;
1449         }
1450     }
1451 }
1452 }  // namespace AccessToken
1453 }  // namespace Security
1454 }  // namespace OHOS
1455 
1456 EXTERN_C_START
1457 /*
1458  * function for module exports
1459  */
Init(napi_env env,napi_value exports)1460 static napi_value Init(napi_env env, napi_value exports)
1461 {
1462     ACCESSTOKEN_LOG_DEBUG(OHOS::Security::AccessToken::LABEL, "Register end, start init.");
1463     OHOS::Security::AccessToken::NapiAtManager::Init(env, exports);
1464     return exports;
1465 }
1466 EXTERN_C_END
1467 
1468 /*
1469  * Module define
1470  */
1471 static napi_module g_module = {
1472     .nm_version = 1,
1473     .nm_flags = 0,
1474     .nm_filename = nullptr,
1475     .nm_register_func = Init,
1476     .nm_modname = "abilityAccessCtrl",
1477     .nm_priv = static_cast<void *>(nullptr),
1478     .reserved = {nullptr}
1479 };
1480 
1481 /*
1482  * Module register function
1483  */
AbilityAccessCtrlmoduleRegister(void)1484 extern "C" __attribute__((constructor)) void AbilityAccessCtrlmoduleRegister(void)
1485 {
1486     napi_module_register(&g_module);
1487 }
1488