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