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