1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "napi_request_permission.h"
16
17 #include "ability.h"
18 #include "ability_manager_client.h"
19 #include "access_token.h"
20 #include "accesstoken_kit.h"
21 #include "accesstoken_log.h"
22 #include "hisysevent.h"
23 #include "napi_base_context.h"
24 #include "token_setproc.h"
25 #include "want.h"
26
27 namespace OHOS {
28 namespace Security {
29 namespace AccessToken {
30 std::mutex g_lockFlag;
31 std::map<int32_t, std::vector<std::shared_ptr<RequestAsyncContext>>> RequestAsyncInstanceControl::instanceIdMap_;
32 std::mutex RequestAsyncInstanceControl::instanceIdMutex_;
33 namespace {
34 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
35 LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "NapiRequestPermission"
36 };
37 const std::string PERMISSION_KEY = "ohos.user.grant.permission";
38 const std::string STATE_KEY = "ohos.user.grant.permission.state";
39 const std::string RESULT_KEY = "ohos.user.grant.permission.result";
40 const std::string EXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType";
41 const std::string UI_EXTENSION_TYPE = "sys/commonUI";
42 const std::string ORI_PERMISSION_MANAGER_BUNDLE_NAME = "com.ohos.permissionmanager";
43 const std::string ORI_PERMISSION_MANAGER_ABILITY_NAME = "com.ohos.permissionmanager.GrantAbility";
44 const std::string TOKEN_KEY = "ohos.ability.params.token";
45 const std::string CALLBACK_KEY = "ohos.ability.params.callback";
46
47 const std::string WINDOW_RECTANGLE_LEFT_KEY = "ohos.ability.params.request.left";
48 const std::string WINDOW_RECTANGLE_TOP_KEY = "ohos.ability.params.request.top";
49 const std::string WINDOW_RECTANGLE_HEIGHT_KEY = "ohos.ability.params.request.height";
50 const std::string WINDOW_RECTANGLE_WIDTH_KEY = "ohos.ability.params.request.width";
51 const std::string REQUEST_TOKEN_KEY = "ohos.ability.params.request.token";
52
ReturnPromiseResult(napi_env env,int32_t contextResult,napi_deferred deferred,napi_value result)53 static void ReturnPromiseResult(napi_env env, int32_t contextResult, napi_deferred deferred, napi_value result)
54 {
55 if (contextResult != RET_SUCCESS) {
56 int32_t jsCode = NapiContextCommon::GetJsErrorCode(contextResult);
57 napi_value businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
58 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, deferred, businessError));
59 } else {
60 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, deferred, result));
61 }
62 }
63
ReturnCallbackResult(napi_env env,int32_t contextResult,napi_ref & callbackRef,napi_value result)64 static void ReturnCallbackResult(napi_env env, int32_t contextResult, napi_ref &callbackRef, napi_value result)
65 {
66 napi_value businessError = GetNapiNull(env);
67 if (contextResult != RET_SUCCESS) {
68 int32_t jsCode = NapiContextCommon::GetJsErrorCode(contextResult);
69 businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
70 }
71 napi_value results[ASYNC_CALL_BACK_VALUES_NUM] = { businessError, result };
72
73 napi_value callback = nullptr;
74 napi_value thisValue = nullptr;
75 napi_value thatValue = nullptr;
76 NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &thisValue));
77 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, 0, &thatValue));
78 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callbackRef, &callback));
79 NAPI_CALL_RETURN_VOID(env,
80 napi_call_function(env, thisValue, callback, ASYNC_CALL_BACK_VALUES_NUM, results, &thatValue));
81 }
82 } // namespace
83
WrapVoidToJS(napi_env env)84 static napi_value WrapVoidToJS(napi_env env)
85 {
86 napi_value result = nullptr;
87 NAPI_CALL(env, napi_get_null(env, &result));
88 return result;
89 }
90
GetUIContent(std::shared_ptr<RequestAsyncContext> asyncContext)91 static Ace::UIContent* GetUIContent(std::shared_ptr<RequestAsyncContext> asyncContext)
92 {
93 if (asyncContext == nullptr) {
94 return nullptr;
95 }
96 Ace::UIContent* uiContent = nullptr;
97 if (asyncContext->uiAbilityFlag) {
98 uiContent = asyncContext->abilityContext->GetUIContent();
99 } else {
100 uiContent = asyncContext->uiExtensionContext->GetUIContent();
101 }
102 return uiContent;
103 }
104
GetInstanceId(std::shared_ptr<RequestAsyncContext> & asyncContext)105 static void GetInstanceId(std::shared_ptr<RequestAsyncContext>& asyncContext)
106 {
107 auto task = [asyncContext]() {
108 Ace::UIContent* uiContent = GetUIContent(asyncContext);
109 if (uiContent == nullptr) {
110 ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!");
111 return;
112 }
113 asyncContext->instanceId = uiContent->GetInstanceId();
114 };
115 #ifdef EVENTHANDLER_ENABLE
116 if (asyncContext->handler_ != nullptr) {
117 asyncContext->handler_->PostSyncTask(task, "AT:GetInstanceId");
118 } else {
119 task();
120 }
121 #else
122 task();
123 #endif
124 ACCESSTOKEN_LOG_INFO(LABEL, "Instance id: %{public}d", asyncContext->instanceId);
125 }
126
CreateUIExtensionMainThread(std::shared_ptr<RequestAsyncContext> & asyncContext,const AAFwk::Want & want,const Ace::ModalUIExtensionCallbacks & uiExtensionCallbacks,const std::shared_ptr<UIExtensionCallback> & uiExtCallback)127 static void CreateUIExtensionMainThread(std::shared_ptr<RequestAsyncContext>& asyncContext, const AAFwk::Want& want,
128 const Ace::ModalUIExtensionCallbacks& uiExtensionCallbacks,
129 const std::shared_ptr<UIExtensionCallback>& uiExtCallback)
130 {
131 auto task = [asyncContext, want, uiExtensionCallbacks, uiExtCallback]() {
132 Ace::UIContent* uiContent = GetUIContent(asyncContext);
133 if (uiContent == nullptr) {
134 ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!");
135 asyncContext->result = RET_FAILED;
136 asyncContext->uiExtensionFlag = false;
137 return;
138 }
139
140 Ace::ModalUIExtensionConfig config;
141 config.isProhibitBack = true;
142 int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config);
143
144 ACCESSTOKEN_LOG_INFO(LABEL, "Create end, sessionId: %{public}d, tokenId: %{public}d, permNum: %{public}zu",
145 sessionId, asyncContext->tokenId, asyncContext->permissionList.size());
146 if (sessionId == 0) {
147 ACCESSTOKEN_LOG_ERROR(LABEL, "Create component failed, sessionId is 0");
148 asyncContext->result = RET_FAILED;
149 asyncContext->uiExtensionFlag = false;
150 return;
151 }
152 uiExtCallback->SetSessionId(sessionId);
153 };
154 #ifdef EVENTHANDLER_ENABLE
155 if (asyncContext->handler_ != nullptr) {
156 asyncContext->handler_->PostSyncTask(task, "AT:CreateUIExtensionMainThread");
157 } else {
158 task();
159 }
160 #else
161 task();
162 #endif
163 ACCESSTOKEN_LOG_INFO(LABEL, "Instance id: %{public}d", asyncContext->instanceId);
164 }
165
CloseModalUIExtensionMainThread(std::shared_ptr<RequestAsyncContext> & asyncContext,int32_t sessionId)166 static void CloseModalUIExtensionMainThread(std::shared_ptr<RequestAsyncContext>& asyncContext, int32_t sessionId)
167 {
168 auto task = [asyncContext, sessionId]() {
169 Ace::UIContent* uiContent = GetUIContent(asyncContext);
170 if (uiContent == nullptr) {
171 ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!");
172 asyncContext->result = RET_FAILED;
173 return;
174 }
175 uiContent->CloseModalUIExtension(sessionId);
176 ACCESSTOKEN_LOG_INFO(LABEL, "Close end, sessionId: %{public}d", sessionId);
177 };
178 #ifdef EVENTHANDLER_ENABLE
179 if (asyncContext->handler_ != nullptr) {
180 asyncContext->handler_->PostSyncTask(task, "AT:CloseModalUIExtensionMainThread");
181 } else {
182 task();
183 }
184 #else
185 task();
186 #endif
187 ACCESSTOKEN_LOG_INFO(LABEL, "Instance id: %{public}d", asyncContext->instanceId);
188 }
189
GetContext(const napi_env & env,const napi_value & value,std::shared_ptr<RequestAsyncContext> & asyncContext)190 static napi_value GetContext(
191 const napi_env &env, const napi_value &value, std::shared_ptr<RequestAsyncContext>& asyncContext)
192 {
193 bool stageMode = false;
194 napi_status status = OHOS::AbilityRuntime::IsStageContext(env, value, stageMode);
195 if (status != napi_ok || !stageMode) {
196 ACCESSTOKEN_LOG_ERROR(LABEL, "It is not a stage mode");
197 return nullptr;
198 } else {
199 auto context = AbilityRuntime::GetStageModeContext(env, value);
200 if (context == nullptr) {
201 ACCESSTOKEN_LOG_ERROR(LABEL, "Get context failed");
202 return nullptr;
203 }
204 asyncContext->abilityContext =
205 AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
206 if (asyncContext->abilityContext != nullptr) {
207 asyncContext->uiAbilityFlag = true;
208 } else {
209 ACCESSTOKEN_LOG_WARN(LABEL, "Convert to ability context failed");
210 asyncContext->uiExtensionContext =
211 AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context);
212 if (asyncContext->uiExtensionContext == nullptr) {
213 ACCESSTOKEN_LOG_ERROR(LABEL, "Convert to ui extension context failed");
214 return nullptr;
215 }
216 }
217 return WrapVoidToJS(env);
218 }
219 }
220
WrapRequestResult(const napi_env & env,const std::vector<std::string> & permissions,const std::vector<int> & grantResults,const std::vector<bool> & dialogShownResults)221 static napi_value WrapRequestResult(const napi_env& env, const std::vector<std::string>& permissions,
222 const std::vector<int>& grantResults, const std::vector<bool>& dialogShownResults)
223 {
224 napi_value result = nullptr;
225 NAPI_CALL(env, napi_create_object(env, &result));
226
227 napi_value objPermissions;
228 NAPI_CALL(env, napi_create_array(env, &objPermissions));
229 for (size_t i = 0; i < permissions.size(); i++) {
230 napi_value nPerm = nullptr;
231 NAPI_CALL(env, napi_create_string_utf8(env, permissions[i].c_str(), NAPI_AUTO_LENGTH, &nPerm));
232 NAPI_CALL(env, napi_set_element(env, objPermissions, i, nPerm));
233 }
234 NAPI_CALL(env, napi_set_named_property(env, result, "permissions", objPermissions));
235
236 napi_value objGrantResults;
237 NAPI_CALL(env, napi_create_array(env, &objGrantResults));
238 for (size_t i = 0; i < grantResults.size(); i++) {
239 napi_value nGrantResult = nullptr;
240 NAPI_CALL(env, napi_create_int32(env, grantResults[i], &nGrantResult));
241 NAPI_CALL(env, napi_set_element(env, objGrantResults, i, nGrantResult));
242 }
243 NAPI_CALL(env, napi_set_named_property(env, result, "authResults", objGrantResults));
244
245 napi_value objDialogShown;
246 NAPI_CALL(env, napi_create_array(env, &objDialogShown));
247 for (size_t i = 0; i < dialogShownResults.size(); i++) {
248 napi_value nDialogShown = nullptr;
249 NAPI_CALL(env, napi_get_boolean(env, dialogShownResults[i], &nDialogShown));
250 NAPI_CALL(env, napi_set_element(env, objDialogShown, i, nDialogShown));
251 }
252 NAPI_CALL(env, napi_set_named_property(env, result, "dialogShownResults", objDialogShown));
253
254 return result;
255 }
256
ResultCallbackJSThreadWorker(uv_work_t * work,int32_t status)257 static void ResultCallbackJSThreadWorker(uv_work_t* work, int32_t status)
258 {
259 (void)status;
260 if (work == nullptr) {
261 ACCESSTOKEN_LOG_ERROR(LABEL, "Uv_queue_work_with_qos input work is nullptr");
262 return;
263 }
264 std::unique_ptr<uv_work_t> uvWorkPtr {work};
265 ResultCallback *retCB = reinterpret_cast<ResultCallback*>(work->data);
266 if (retCB == nullptr) {
267 ACCESSTOKEN_LOG_ERROR(LABEL, "RetCB is nullptr");
268 return;
269 }
270 std::unique_ptr<ResultCallback> callbackPtr {retCB};
271
272 int32_t result = JsErrorCode::JS_OK;
273 if (retCB->data->result != RET_SUCCESS) {
274 ACCESSTOKEN_LOG_ERROR(LABEL, "Result is: %{public}d", retCB->data->result);
275 result = RET_FAILED;
276 }
277 if (retCB->grantResults.empty()) {
278 ACCESSTOKEN_LOG_ERROR(LABEL, "GrantResults empty");
279 result = RET_FAILED;
280 }
281 napi_handle_scope scope = nullptr;
282 napi_open_handle_scope(retCB->data->env, &scope);
283 if (scope == nullptr) {
284 ACCESSTOKEN_LOG_ERROR(LABEL, "Napi_open_handle_scope failed");
285 return;
286 }
287 napi_value requestResult = WrapRequestResult(
288 retCB->data->env, retCB->permissions, retCB->grantResults, retCB->dialogShownResults);
289 if (requestResult == nullptr) {
290 ACCESSTOKEN_LOG_ERROR(LABEL, "Wrap requestResult failed");
291 result = RET_FAILED;
292 }
293
294 if (retCB->data->deferred != nullptr) {
295 ReturnPromiseResult(retCB->data->env, result, retCB->data->deferred, requestResult);
296 } else {
297 ReturnCallbackResult(retCB->data->env, result, retCB->data->callbackRef, requestResult);
298 }
299 napi_close_handle_scope(retCB->data->env, scope);
300 }
301
UpdateGrantPermissionResultOnly(const std::vector<std::string> & permissions,const std::vector<int> & grantResults,std::shared_ptr<RequestAsyncContext> & data,std::vector<int> & newGrantResults)302 static void UpdateGrantPermissionResultOnly(const std::vector<std::string>& permissions,
303 const std::vector<int>& grantResults, std::shared_ptr<RequestAsyncContext>& data, std::vector<int>& newGrantResults)
304 {
305 uint32_t size = permissions.size();
306
307 for (uint32_t i = 0; i < size; i++) {
308 int result = data->permissionsState[i];
309 if (data->permissionsState[i] == DYNAMIC_OPER) {
310 result = data->result == RET_SUCCESS ? grantResults[i] : INVALID_OPER;
311 }
312 newGrantResults.emplace_back(result);
313 }
314 }
315
RequestResultsHandler(const std::vector<std::string> & permissionList,const std::vector<int32_t> & permissionStates,std::shared_ptr<RequestAsyncContext> & data)316 static void RequestResultsHandler(const std::vector<std::string>& permissionList,
317 const std::vector<int32_t>& permissionStates, std::shared_ptr<RequestAsyncContext>& data)
318 {
319 auto* retCB = new (std::nothrow) ResultCallback();
320 if (retCB == nullptr) {
321 ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for work!");
322 return;
323 }
324
325 // only permissions which need to grant change the result, other keey as GetSelfPermissionsState result
326 std::vector<int> newGrantResults;
327 UpdateGrantPermissionResultOnly(permissionList, permissionStates, data, newGrantResults);
328
329 std::unique_ptr<ResultCallback> callbackPtr {retCB};
330 retCB->permissions = permissionList;
331 retCB->grantResults = newGrantResults;
332 retCB->dialogShownResults = data->dialogShownResults;
333 retCB->data = data;
334
335 uv_loop_s* loop = nullptr;
336 NAPI_CALL_RETURN_VOID(data->env, napi_get_uv_event_loop(data->env, &loop));
337 if (loop == nullptr) {
338 ACCESSTOKEN_LOG_ERROR(LABEL, "Loop instance is nullptr");
339 return;
340 }
341 uv_work_t* work = new (std::nothrow) uv_work_t;
342 if (work == nullptr) {
343 ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for work!");
344 return;
345 }
346 std::unique_ptr<uv_work_t> uvWorkPtr {work};
347 work->data = reinterpret_cast<void *>(retCB);
348 NAPI_CALL_RETURN_VOID(data->env, uv_queue_work_with_qos(
349 loop, work, [](uv_work_t* work) {}, ResultCallbackJSThreadWorker, uv_qos_user_initiated));
350
351 uvWorkPtr.release();
352 callbackPtr.release();
353 }
354
GrantResultsCallback(const std::vector<std::string> & permissionList,const std::vector<int> & grantResults)355 void AuthorizationResult::GrantResultsCallback(const std::vector<std::string>& permissionList,
356 const std::vector<int>& grantResults)
357 {
358 ACCESSTOKEN_LOG_INFO(LABEL, "Called.");
359 std::shared_ptr<RequestAsyncContext> asyncContext = data_;
360 if (asyncContext == nullptr) {
361 return;
362 }
363 RequestResultsHandler(permissionList, grantResults, asyncContext);
364 }
365
WindowShownCallback()366 void AuthorizationResult::WindowShownCallback()
367 {
368 ACCESSTOKEN_LOG_INFO(LABEL, "Called.");
369
370 std::shared_ptr<RequestAsyncContext> asyncContext = data_;
371 if (asyncContext == nullptr) {
372 return;
373 }
374
375 Ace::UIContent* uiContent = GetUIContent(asyncContext);
376 // get uiContent failed when request or when callback called
377 if ((uiContent == nullptr) || !(asyncContext->uiContentFlag)) {
378 ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!");
379 return;
380 }
381 RequestAsyncInstanceControl::ExecCallback(asyncContext->instanceId);
382 ACCESSTOKEN_LOG_DEBUG(LABEL, "OnRequestPermissionsFromUser async callback is called end");
383 }
384
CreateServiceExtension(std::shared_ptr<RequestAsyncContext> asyncContext)385 static void CreateServiceExtension(std::shared_ptr<RequestAsyncContext> asyncContext)
386 {
387 if (!asyncContext->uiAbilityFlag) {
388 ACCESSTOKEN_LOG_ERROR(LABEL, "UIExtension ability can not pop service ablility window!");
389 asyncContext->needDynamicRequest = false;
390 asyncContext->result = RET_FAILED;
391 return;
392 }
393 sptr<IRemoteObject> remoteObject = new (std::nothrow) AccessToken::AuthorizationResult(asyncContext);
394 if (remoteObject == nullptr) {
395 ACCESSTOKEN_LOG_ERROR(LABEL, "Create window failed!");
396 asyncContext->needDynamicRequest = false;
397 asyncContext->result = RET_FAILED;
398 return;
399 }
400 AAFwk::Want want;
401 want.SetElementName(ORI_PERMISSION_MANAGER_BUNDLE_NAME, ORI_PERMISSION_MANAGER_ABILITY_NAME);
402 want.SetParam(PERMISSION_KEY, asyncContext->permissionList);
403 want.SetParam(STATE_KEY, asyncContext->permissionsState);
404 want.SetParam(TOKEN_KEY, asyncContext->abilityContext->GetToken());
405 want.SetParam(CALLBACK_KEY, remoteObject);
406
407 int32_t left;
408 int32_t top;
409 int32_t width;
410 int32_t height;
411 asyncContext->abilityContext->GetWindowRect(left, top, width, height);
412 want.SetParam(WINDOW_RECTANGLE_LEFT_KEY, left);
413 want.SetParam(WINDOW_RECTANGLE_TOP_KEY, top);
414 want.SetParam(WINDOW_RECTANGLE_WIDTH_KEY, width);
415 want.SetParam(WINDOW_RECTANGLE_HEIGHT_KEY, height);
416 want.SetParam(REQUEST_TOKEN_KEY, asyncContext->abilityContext->GetToken());
417 int32_t ret = AAFwk::AbilityManagerClient::GetInstance()->RequestDialogService(
418 want, asyncContext->abilityContext->GetToken());
419
420 ACCESSTOKEN_LOG_INFO(LABEL, "Request end, ret: %{public}d, tokenId: %{public}d, permNum: %{public}zu",
421 ret, asyncContext->tokenId, asyncContext->permissionList.size());
422 }
423
StartServiceExtension(std::shared_ptr<RequestAsyncContext> & asyncContext)424 void NapiRequestPermission::StartServiceExtension(std::shared_ptr<RequestAsyncContext>& asyncContext)
425 {
426 asyncContext->result = RET_SUCCESS;
427 Ace::UIContent* uiContent = GetUIContent(asyncContext);
428 if (uiContent == nullptr) {
429 ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!");
430 CreateServiceExtension(asyncContext);
431 return;
432 }
433 asyncContext->uiContentFlag = true;
434 RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContext);
435 }
436
IsDynamicRequest(std::shared_ptr<RequestAsyncContext> & asyncContext)437 bool NapiRequestPermission::IsDynamicRequest(std::shared_ptr<RequestAsyncContext>& asyncContext)
438 {
439 std::vector<PermissionListState> permList;
440 for (const auto& permission : asyncContext->permissionList) {
441 PermissionListState permState;
442 permState.permissionName = permission;
443 permState.state = INVALID_OPER;
444 permList.emplace_back(permState);
445 }
446 ACCESSTOKEN_LOG_INFO(LABEL, "TokenID: %{public}d.", asyncContext->tokenId);
447 auto ret = AccessTokenKit::GetSelfPermissionsState(permList, asyncContext->info);
448 if (ret == FORBIDDEN_OPER) { // if app is under control, change state from default -1 to 2
449 for (auto& perm : permList) {
450 perm.state = INVALID_OPER;
451 }
452 }
453
454 for (const auto& permState : permList) {
455 ACCESSTOKEN_LOG_INFO(LABEL, "Permission: %{public}s: state: %{public}d",
456 permState.permissionName.c_str(), permState.state);
457 asyncContext->permissionsState.emplace_back(permState.state);
458 asyncContext->dialogShownResults.emplace_back(permState.state == TypePermissionOper::DYNAMIC_OPER);
459 }
460 if (permList.size() != asyncContext->permissionList.size()) {
461 ACCESSTOKEN_LOG_ERROR(LABEL, "Returned permList size: %{public}zu.", permList.size());
462 return false;
463 }
464 return ret == TypePermissionOper::DYNAMIC_OPER;
465 }
466
ReleaseHandler(int32_t code)467 void UIExtensionCallback::ReleaseHandler(int32_t code)
468 {
469 {
470 std::lock_guard<std::mutex> lock(g_lockFlag);
471 if (this->reqContext_->releaseFlag) {
472 ACCESSTOKEN_LOG_WARN(LABEL, "Callback has executed.");
473 return;
474 }
475 this->reqContext_->releaseFlag = true;
476 }
477 CloseModalUIExtensionMainThread(this->reqContext_, this->sessionId_);
478 this->reqContext_->result = code;
479 RequestAsyncInstanceControl::ExecCallback(this->reqContext_->instanceId);
480 RequestResultsHandler(this->reqContext_->permissionList, this->reqContext_->permissionsState, this->reqContext_);
481 }
482
UIExtensionCallback(const std::shared_ptr<RequestAsyncContext> & reqContext)483 UIExtensionCallback::UIExtensionCallback(const std::shared_ptr<RequestAsyncContext>& reqContext)
484 {
485 this->reqContext_ = reqContext;
486 }
487
~UIExtensionCallback()488 UIExtensionCallback::~UIExtensionCallback()
489 {}
490
SetSessionId(int32_t sessionId)491 void UIExtensionCallback::SetSessionId(int32_t sessionId)
492 {
493 this->sessionId_ = sessionId;
494 }
495
496 /*
497 * when UIExtensionAbility use terminateSelfWithResult
498 */
OnResult(int32_t resultCode,const AAFwk::Want & result)499 void UIExtensionCallback::OnResult(int32_t resultCode, const AAFwk::Want& result)
500 {
501 ACCESSTOKEN_LOG_INFO(LABEL, "ResultCode is %{public}d", resultCode);
502 this->reqContext_->permissionList = result.GetStringArrayParam(PERMISSION_KEY);
503 this->reqContext_->permissionsState = result.GetIntArrayParam(RESULT_KEY);
504 ReleaseHandler(0);
505 }
506
507 /*
508 * when UIExtensionAbility send message to UIExtensionComponent
509 */
OnReceive(const AAFwk::WantParams & receive)510 void UIExtensionCallback::OnReceive(const AAFwk::WantParams& receive)
511 {
512 ACCESSTOKEN_LOG_INFO(LABEL, "Called!");
513 }
514
515 /*
516 * when UIExtensionAbility disconnect or use terminate or process die
517 * releaseCode is 0 when process normal exit
518 */
OnRelease(int32_t releaseCode)519 void UIExtensionCallback::OnRelease(int32_t releaseCode)
520 {
521 ACCESSTOKEN_LOG_INFO(LABEL, "ReleaseCode is %{public}d", releaseCode);
522
523 ReleaseHandler(-1);
524 }
525
526 /*
527 * when UIExtensionComponent init or turn to background or destroy UIExtensionAbility occur error
528 */
OnError(int32_t code,const std::string & name,const std::string & message)529 void UIExtensionCallback::OnError(int32_t code, const std::string& name, const std::string& message)
530 {
531 ACCESSTOKEN_LOG_INFO(LABEL, "Code is %{public}d, name is %{public}s, message is %{public}s",
532 code, name.c_str(), message.c_str());
533
534 ReleaseHandler(-1);
535 }
536
537 /*
538 * when UIExtensionComponent connect to UIExtensionAbility, ModalUIExtensionProxy will init,
539 * UIExtensionComponent can send message to UIExtensionAbility by ModalUIExtensionProxy
540 */
OnRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy> & uiProxy)541 void UIExtensionCallback::OnRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy>& uiProxy)
542 {
543 ACCESSTOKEN_LOG_INFO(LABEL, "Connect to UIExtensionAbility successfully.");
544 }
545
546 /*
547 * when UIExtensionComponent destructed
548 */
OnDestroy()549 void UIExtensionCallback::OnDestroy()
550 {
551 ACCESSTOKEN_LOG_INFO(LABEL, "UIExtensionAbility destructed.");
552 ReleaseHandler(-1);
553 }
554
CreateUIExtension(std::shared_ptr<RequestAsyncContext> asyncContext)555 static void CreateUIExtension(std::shared_ptr<RequestAsyncContext> asyncContext)
556 {
557 AAFwk::Want want;
558 want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantAbilityName);
559 want.SetParam(PERMISSION_KEY, asyncContext->permissionList);
560 want.SetParam(STATE_KEY, asyncContext->permissionsState);
561 want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE);
562
563 auto uiExtCallback = std::make_shared<UIExtensionCallback>(asyncContext);
564 Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = {
565 [uiExtCallback](int32_t releaseCode) {
566 uiExtCallback->OnRelease(releaseCode);
567 },
568 [uiExtCallback](int32_t resultCode, const AAFwk::Want &result) {
569 uiExtCallback->OnResult(resultCode, result);
570 },
571 [uiExtCallback](const AAFwk::WantParams &receive) {
572 uiExtCallback->OnReceive(receive);
573 },
574 [uiExtCallback](int32_t code, const std::string &name, [[maybe_unused]] const std::string &message) {
575 uiExtCallback->OnError(code, name, name);
576 },
577 [uiExtCallback](const std::shared_ptr<Ace::ModalUIExtensionProxy> &uiProxy) {
578 uiExtCallback->OnRemoteReady(uiProxy);
579 },
580 [uiExtCallback]() {
581 uiExtCallback->OnDestroy();
582 },
583 };
584 CreateUIExtensionMainThread(asyncContext, want, uiExtensionCallbacks, uiExtCallback);
585 }
586
587
RequestPermissionsFromUser(napi_env env,napi_callback_info info)588 napi_value NapiRequestPermission::RequestPermissionsFromUser(napi_env env, napi_callback_info info)
589 {
590 ACCESSTOKEN_LOG_DEBUG(LABEL, "RequestPermissionsFromUser begin.");
591 // use handle to protect asyncContext
592 std::shared_ptr<RequestAsyncContext> asyncContext = std::make_shared<RequestAsyncContext>(env);
593
594 if (!ParseRequestPermissionFromUser(env, info, asyncContext)) {
595 return nullptr;
596 }
597 auto asyncContextHandle = std::make_unique<RequestAsyncContextHandle>(asyncContext);
598 napi_value result = nullptr;
599 if (asyncContextHandle->asyncContextPtr->callbackRef == nullptr) {
600 NAPI_CALL(env, napi_create_promise(env, &(asyncContextHandle->asyncContextPtr->deferred), &result));
601 } else {
602 NAPI_CALL(env, napi_get_undefined(env, &result));
603 }
604
605 napi_value resource = nullptr; // resource name
606 NAPI_CALL(env, napi_create_string_utf8(env, "RequestPermissionsFromUser", NAPI_AUTO_LENGTH, &resource));
607 NAPI_CALL(env, napi_create_async_work(
608 env, nullptr, resource, RequestPermissionsFromUserExecute, RequestPermissionsFromUserComplete,
609 reinterpret_cast<void *>(asyncContextHandle.get()), &(asyncContextHandle->asyncContextPtr->work)));
610
611 NAPI_CALL(env,
612 napi_queue_async_work_with_qos(env, asyncContextHandle->asyncContextPtr->work, napi_qos_user_initiated));
613
614 ACCESSTOKEN_LOG_DEBUG(LABEL, "RequestPermissionsFromUser end.");
615 asyncContextHandle.release();
616 return result;
617 }
618
ParseRequestPermissionFromUser(const napi_env & env,const napi_callback_info & cbInfo,std::shared_ptr<RequestAsyncContext> & asyncContext)619 bool NapiRequestPermission::ParseRequestPermissionFromUser(const napi_env& env,
620 const napi_callback_info& cbInfo, std::shared_ptr<RequestAsyncContext>& asyncContext)
621 {
622 size_t argc = NapiContextCommon::MAX_PARAMS_THREE;
623 napi_value argv[NapiContextCommon::MAX_PARAMS_THREE] = { nullptr };
624 napi_value thisVar = nullptr;
625
626 if (napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr) != napi_ok) {
627 ACCESSTOKEN_LOG_ERROR(LABEL, "Napi_get_cb_info failed");
628 return false;
629 }
630 if (argc < NapiContextCommon::MAX_PARAMS_THREE - 1) {
631 NAPI_CALL_BASE(env, napi_throw(env, GenerateBusinessError(env,
632 JsErrorCode::JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
633 return false;
634 }
635 asyncContext->env = env;
636 std::string errMsg;
637
638 // argv[0] : context : AbilityContext
639 if (GetContext(env, argv[0], asyncContext) == nullptr) {
640 errMsg = GetParamErrorMsg("context", "UIAbility or UIExtension Context");
641 NAPI_CALL_BASE(
642 env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
643 return false;
644 }
645 ACCESSTOKEN_LOG_INFO(LABEL, "AsyncContext.uiAbilityFlag is: %{public}d.", asyncContext->uiAbilityFlag);
646
647 // argv[1] : permissionList
648 if (!ParseStringArray(env, argv[1], asyncContext->permissionList) ||
649 (asyncContext->permissionList.empty())) {
650 errMsg = GetParamErrorMsg("permissionList", "Array<string>");
651 NAPI_CALL_BASE(
652 env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
653 return false;
654 }
655
656 if (argc == NapiContextCommon::MAX_PARAMS_THREE) {
657 // argv[2] : callback
658 if (!IsUndefinedOrNull(env, argv[2]) && !ParseCallback(env, argv[2], asyncContext->callbackRef)) {
659 errMsg = GetParamErrorMsg("callback", "Callback<PermissionRequestResult>");
660 napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg));
661 return false;
662 }
663 }
664 #ifdef EVENTHANDLER_ENABLE
665 asyncContext->handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
666 #endif
667 return true;
668 }
669
RequestPermissionsFromUserExecute(napi_env env,void * data)670 void NapiRequestPermission::RequestPermissionsFromUserExecute(napi_env env, void* data)
671 {
672 // asyncContext release in complete
673 RequestAsyncContextHandle* asyncContextHandle = reinterpret_cast<RequestAsyncContextHandle*>(data);
674 std::string bundleName = "";
675 if (asyncContextHandle->asyncContextPtr->uiAbilityFlag) {
676 asyncContextHandle->asyncContextPtr->tokenId =
677 asyncContextHandle->asyncContextPtr->abilityContext->GetApplicationInfo()->accessTokenId;
678 bundleName = asyncContextHandle->asyncContextPtr->abilityContext->GetApplicationInfo()->bundleName;
679 } else {
680 asyncContextHandle->asyncContextPtr->tokenId =
681 asyncContextHandle->asyncContextPtr->uiExtensionContext->GetApplicationInfo()->accessTokenId;
682 bundleName = asyncContextHandle->asyncContextPtr->uiExtensionContext->GetApplicationInfo()->bundleName;
683 }
684 AccessTokenID selfTokenID = static_cast<AccessTokenID>(GetSelfTokenID());
685 if (asyncContextHandle->asyncContextPtr->tokenId != selfTokenID) {
686 ACCESSTOKEN_LOG_ERROR(LABEL, "The context tokenID: %{public}d, selfTokenID: %{public}d.",
687 asyncContextHandle->asyncContextPtr->tokenId, selfTokenID);
688 asyncContextHandle->asyncContextPtr->result = RET_FAILED;
689 return;
690 }
691
692 if (!IsDynamicRequest(asyncContextHandle->asyncContextPtr)) {
693 ACCESSTOKEN_LOG_INFO(LABEL, "It does not need to request permission");
694 asyncContextHandle->asyncContextPtr->needDynamicRequest = false;
695 return;
696 }
697 GetInstanceId(asyncContextHandle->asyncContextPtr);
698 // service extension dialog
699 if (asyncContextHandle->asyncContextPtr->info.grantBundleName == ORI_PERMISSION_MANAGER_BUNDLE_NAME) {
700 ACCESSTOKEN_LOG_INFO(LABEL, "Pop service extension dialog");
701 StartServiceExtension(asyncContextHandle->asyncContextPtr);
702 } else if (asyncContextHandle->asyncContextPtr->instanceId == -1) {
703 CreateServiceExtension(asyncContextHandle->asyncContextPtr);
704 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::ACCESS_TOKEN, "REQUEST_PERMISSIONS_FROM_USER",
705 HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "BUNDLENAME", bundleName, "UIEXTENSION_FLAG", false);
706 } else {
707 ACCESSTOKEN_LOG_INFO(LABEL, "Pop ui extension dialog");
708 asyncContextHandle->asyncContextPtr->uiExtensionFlag = true;
709 RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContextHandle->asyncContextPtr);
710 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::ACCESS_TOKEN, "REQUEST_PERMISSIONS_FROM_USER",
711 HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "BUNDLENAME", bundleName,
712 "UIEXTENSION_FLAG", asyncContextHandle->asyncContextPtr->uiExtensionFlag);
713 if (!asyncContextHandle->asyncContextPtr->uiExtensionFlag) {
714 ACCESSTOKEN_LOG_WARN(LABEL, "Pop uiextension dialog fail, start to pop service extension dialog");
715 StartServiceExtension(asyncContextHandle->asyncContextPtr);
716 }
717 }
718 }
719
RequestPermissionsFromUserComplete(napi_env env,napi_status status,void * data)720 void NapiRequestPermission::RequestPermissionsFromUserComplete(napi_env env, napi_status status, void* data)
721 {
722 RequestAsyncContextHandle* asyncContextHandle = reinterpret_cast<RequestAsyncContextHandle*>(data);
723 std::unique_ptr<RequestAsyncContextHandle> callbackPtr {asyncContextHandle};
724
725 if (asyncContextHandle->asyncContextPtr->needDynamicRequest) {
726 return;
727 }
728 if ((asyncContextHandle->asyncContextPtr->permissionsState.empty()) &&
729 (asyncContextHandle->asyncContextPtr->result == JsErrorCode::JS_OK)) {
730 ACCESSTOKEN_LOG_ERROR(LABEL, "GrantResults empty");
731 asyncContextHandle->asyncContextPtr->result = RET_FAILED;
732 }
733 napi_value requestResult = WrapRequestResult(env, asyncContextHandle->asyncContextPtr->permissionList,
734 asyncContextHandle->asyncContextPtr->permissionsState, asyncContextHandle->asyncContextPtr->dialogShownResults);
735 if (requestResult == nullptr) {
736 ACCESSTOKEN_LOG_ERROR(LABEL, "Wrap requestResult failed");
737 if (asyncContextHandle->asyncContextPtr->result == JsErrorCode::JS_OK) {
738 asyncContextHandle->asyncContextPtr->result = RET_FAILED;
739 }
740 } else {
741 asyncContextHandle->asyncContextPtr->requestResult = requestResult;
742 }
743 if (asyncContextHandle->asyncContextPtr->deferred != nullptr) {
744 ReturnPromiseResult(env, asyncContextHandle->asyncContextPtr->result,
745 asyncContextHandle->asyncContextPtr->deferred, asyncContextHandle->asyncContextPtr->requestResult);
746 } else {
747 ReturnCallbackResult(env, asyncContextHandle->asyncContextPtr->result,
748 asyncContextHandle->asyncContextPtr->callbackRef, asyncContextHandle->asyncContextPtr->requestResult);
749 }
750 }
751
GetPermissionsStatus(napi_env env,napi_callback_info info)752 napi_value NapiRequestPermission::GetPermissionsStatus(napi_env env, napi_callback_info info)
753 {
754 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionsStatus begin.");
755
756 auto* asyncContext = new (std::nothrow) RequestAsyncContext(env);
757 if (asyncContext == nullptr) {
758 ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
759 return nullptr;
760 }
761
762 std::unique_ptr<RequestAsyncContext> context {asyncContext};
763 if (!ParseInputToGetQueryResult(env, info, *asyncContext)) {
764 return nullptr;
765 }
766
767 napi_value result = nullptr;
768 napi_create_promise(env, &(asyncContext->deferred), &result); // create delay promise object
769
770 napi_value resource = nullptr; // resource name
771 napi_create_string_utf8(env, "GetPermissionsStatus", NAPI_AUTO_LENGTH, &resource);
772
773 napi_create_async_work(
774 env, nullptr, resource, GetPermissionsStatusExecute, GetPermissionsStatusComplete,
775 reinterpret_cast<void *>(asyncContext), &(asyncContext->work));
776 // add async work handle to the napi queue and wait for result
777 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
778
779 ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionsStatus end.");
780 context.release();
781 return result;
782 }
783
ParseInputToGetQueryResult(const napi_env & env,const napi_callback_info & info,RequestAsyncContext & asyncContext)784 bool NapiRequestPermission::ParseInputToGetQueryResult(const napi_env& env, const napi_callback_info& info,
785 RequestAsyncContext& asyncContext)
786 {
787 size_t argc = NapiContextCommon::MAX_PARAMS_TWO;
788 napi_value argv[NapiContextCommon::MAX_PARAMS_TWO] = {nullptr};
789 napi_value thatVar = nullptr;
790
791 void *data = nullptr;
792 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thatVar, &data), false);
793 // 1: can request permissions minnum argc
794 if (argc < NapiContextCommon::MAX_PARAMS_TWO - 1) {
795 NAPI_CALL_BASE(env, napi_throw(env,
796 GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
797 return false;
798 }
799
800 std::string errMsg;
801 asyncContext.env = env;
802 // the first parameter of argv
803 if (!ParseUint32(env, argv[0], asyncContext.tokenId)) {
804 errMsg = GetParamErrorMsg("tokenId", "number");
805 NAPI_CALL_BASE(env,
806 napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
807 return false;
808 }
809
810 // the second parameter of argv
811 if (!ParseStringArray(env, argv[1], asyncContext.permissionList)) {
812 errMsg = GetParamErrorMsg("permissions", "Array<string>");
813 NAPI_CALL_BASE(
814 env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
815 return false;
816 }
817 ACCESSTOKEN_LOG_DEBUG(LABEL, "TokenID = %{public}d, permissionList size = %{public}zu", asyncContext.tokenId,
818 asyncContext.permissionList.size());
819 return true;
820 }
821
GetPermissionsStatusExecute(napi_env env,void * data)822 void NapiRequestPermission::GetPermissionsStatusExecute(napi_env env, void *data)
823 {
824 RequestAsyncContext* asyncContext = reinterpret_cast<RequestAsyncContext*>(data);
825
826 std::vector<PermissionListState> permList;
827 for (const auto& permission : asyncContext->permissionList) {
828 ACCESSTOKEN_LOG_DEBUG(LABEL, "Permission: %{public}s.", permission.c_str());
829 PermissionListState permState;
830 permState.permissionName = permission;
831 permState.state = INVALID_OPER;
832 permList.emplace_back(permState);
833 }
834 ACCESSTOKEN_LOG_DEBUG(LABEL, "PermList size: %{public}zu, asyncContext->permissionList size: %{public}zu.",
835 permList.size(), asyncContext->permissionList.size());
836
837 asyncContext->result = AccessTokenKit::GetPermissionsStatus(asyncContext->tokenId, permList);
838 for (const auto& permState : permList) {
839 ACCESSTOKEN_LOG_DEBUG(LABEL, "Permission: %{public}s", permState.permissionName.c_str());
840 asyncContext->permissionQueryResults.emplace_back(permState.state);
841 }
842 }
843
GetPermissionsStatusComplete(napi_env env,napi_status status,void * data)844 void NapiRequestPermission::GetPermissionsStatusComplete(napi_env env, napi_status status, void *data)
845 {
846 RequestAsyncContext* asyncContext = reinterpret_cast<RequestAsyncContext*>(data);
847 std::unique_ptr<RequestAsyncContext> callbackPtr {asyncContext};
848
849 if ((asyncContext->permissionQueryResults.empty()) && asyncContext->result == JsErrorCode::JS_OK) {
850 ACCESSTOKEN_LOG_ERROR(LABEL, "PermissionQueryResults empty");
851 asyncContext->result = RET_FAILED;
852 }
853 napi_value result;
854 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &result));
855
856 for (size_t i = 0; i < asyncContext->permissionQueryResults.size(); i++) {
857 napi_value nPermissionQueryResult = nullptr;
858 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env,
859 asyncContext->permissionQueryResults[i], &nPermissionQueryResult));
860 NAPI_CALL_RETURN_VOID(env, napi_set_element(env, result, i, nPermissionQueryResult));
861 }
862 ReturnPromiseResult(env, asyncContext->result, asyncContext->deferred, result);
863 }
864
CheckDynamicRequest(std::shared_ptr<RequestAsyncContext> & asyncContext,bool & isDynamic)865 void RequestAsyncInstanceControl::CheckDynamicRequest(
866 std::shared_ptr<RequestAsyncContext>& asyncContext, bool& isDynamic)
867 {
868 asyncContext->permissionsState.clear();
869 asyncContext->dialogShownResults.clear();
870 if (!NapiRequestPermission::IsDynamicRequest(asyncContext)) {
871 ACCESSTOKEN_LOG_INFO(LABEL, "It does not need to request permission exsion");
872 RequestResultsHandler(asyncContext->permissionList, asyncContext->permissionsState, asyncContext);
873 return;
874 }
875 isDynamic = true;
876 }
877
AddCallbackByInstanceId(std::shared_ptr<RequestAsyncContext> & asyncContext)878 void RequestAsyncInstanceControl::AddCallbackByInstanceId(std::shared_ptr<RequestAsyncContext>& asyncContext)
879 {
880 ACCESSTOKEN_LOG_INFO(LABEL, "InstanceId: %{public}d", asyncContext->instanceId);
881 {
882 std::lock_guard<std::mutex> lock(instanceIdMutex_);
883 auto iter = instanceIdMap_.find(asyncContext->instanceId);
884 // id is existed mean a pop window is showing, add context to waiting queue
885 if (iter != instanceIdMap_.end()) {
886 ACCESSTOKEN_LOG_INFO(LABEL, "InstanceId: %{public}d has existed.", asyncContext->instanceId);
887 instanceIdMap_[asyncContext->instanceId].emplace_back(asyncContext);
888 return;
889 }
890 // make sure id is in map to indicate a pop-up window is showing
891 instanceIdMap_[asyncContext->instanceId] = {};
892 }
893
894 if (asyncContext->uiExtensionFlag) {
895 CreateUIExtension(asyncContext);
896 } else {
897 CreateServiceExtension(asyncContext);
898 }
899 }
900
ExecCallback(int32_t id)901 void RequestAsyncInstanceControl::ExecCallback(int32_t id)
902 {
903 std::shared_ptr<RequestAsyncContext> asyncContext = nullptr;
904 bool isDynamic = false;
905 {
906 std::lock_guard<std::mutex> lock(instanceIdMutex_);
907 auto iter = instanceIdMap_.find(id);
908 if (iter == instanceIdMap_.end()) {
909 ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d not existed.", id);
910 return;
911 }
912 while (!iter->second.empty()) {
913 ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d, map size: %{public}zu.", id, iter->second.size());
914 asyncContext = iter->second[0];
915 iter->second.erase(iter->second.begin());
916 CheckDynamicRequest(asyncContext, isDynamic);
917 if (isDynamic) {
918 break;
919 }
920 }
921 if (iter->second.empty()) {
922 ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d, map is empty", id);
923 instanceIdMap_.erase(id);
924 }
925 }
926 if (isDynamic) {
927 if (asyncContext->uiExtensionFlag) {
928 CreateUIExtension(asyncContext);
929 } else {
930 CreateServiceExtension(asyncContext);
931 }
932 }
933 }
934 } // namespace AccessToken
935 } // namespace Security
936 } // namespace OHOS