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