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