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