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