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