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