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