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 TOKEN_KEY = "ohos.ability.params.token";
44 const std::string CALLBACK_KEY = "ohos.ability.params.callback";
45 
46 const std::string WINDOW_RECTANGLE_LEFT_KEY = "ohos.ability.params.request.left";
47 const std::string WINDOW_RECTANGLE_TOP_KEY = "ohos.ability.params.request.top";
48 const std::string WINDOW_RECTANGLE_HEIGHT_KEY = "ohos.ability.params.request.height";
49 const std::string WINDOW_RECTANGLE_WIDTH_KEY = "ohos.ability.params.request.width";
50 const std::string REQUEST_TOKEN_KEY = "ohos.ability.params.request.token";
51 
ReturnPromiseResult(napi_env env,int32_t contextResult,napi_deferred deferred,napi_value result)52 static void ReturnPromiseResult(napi_env env, int32_t contextResult, napi_deferred deferred, napi_value result)
53 {
54     if (contextResult != RET_SUCCESS) {
55         int32_t jsCode = NapiContextCommon::GetJsErrorCode(contextResult);
56         napi_value businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
57         NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, deferred, businessError));
58     } else {
59         NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, deferred, result));
60     }
61 }
62 
ReturnCallbackResult(napi_env env,int32_t contextResult,napi_ref & callbackRef,napi_value result)63 static void ReturnCallbackResult(napi_env env, int32_t contextResult, napi_ref &callbackRef, napi_value result)
64 {
65     napi_value businessError = GetNapiNull(env);
66     if (contextResult != RET_SUCCESS) {
67         int32_t jsCode = NapiContextCommon::GetJsErrorCode(contextResult);
68         businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
69     }
70     napi_value results[ASYNC_CALL_BACK_VALUES_NUM] = { businessError, result };
71 
72     napi_value callback = nullptr;
73     napi_value thisValue = nullptr;
74     napi_value thatValue = nullptr;
75     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &thisValue));
76     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, 0, &thatValue));
77     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callbackRef, &callback));
78     NAPI_CALL_RETURN_VOID(env,
79         napi_call_function(env, thisValue, callback, ASYNC_CALL_BACK_VALUES_NUM, results, &thatValue));
80 }
81 } // namespace
82 
WrapVoidToJS(napi_env env)83 static napi_value WrapVoidToJS(napi_env env)
84 {
85     napi_value result = nullptr;
86     NAPI_CALL(env, napi_get_null(env, &result));
87     return result;
88 }
89 
GetUIContent(std::shared_ptr<RequestAsyncContext> asyncContext)90 static Ace::UIContent* GetUIContent(std::shared_ptr<RequestAsyncContext> asyncContext)
91 {
92     if (asyncContext == nullptr) {
93         return nullptr;
94     }
95     Ace::UIContent* uiContent = nullptr;
96     if (asyncContext->uiAbilityFlag) {
97         uiContent = asyncContext->abilityContext->GetUIContent();
98     } else {
99         uiContent = asyncContext->uiExtensionContext->GetUIContent();
100     }
101     return uiContent;
102 }
103 
GetInstanceId(std::shared_ptr<RequestAsyncContext> & asyncContext)104 static void GetInstanceId(std::shared_ptr<RequestAsyncContext>& asyncContext)
105 {
106     auto task = [asyncContext]() {
107         Ace::UIContent* uiContent = GetUIContent(asyncContext);
108         if (uiContent == nullptr) {
109             ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!");
110             return;
111         }
112         asyncContext->uiContentFlag = true;
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, uiContentFlag: %{public}d",
125         asyncContext->instanceId, asyncContext->uiContentFlag);
126 }
127 
CreateUIExtensionMainThread(std::shared_ptr<RequestAsyncContext> & asyncContext,const AAFwk::Want & want,const Ace::ModalUIExtensionCallbacks & uiExtensionCallbacks,const std::shared_ptr<UIExtensionCallback> & uiExtCallback)128 static void CreateUIExtensionMainThread(std::shared_ptr<RequestAsyncContext>& asyncContext, const AAFwk::Want& want,
129     const Ace::ModalUIExtensionCallbacks& uiExtensionCallbacks,
130     const std::shared_ptr<UIExtensionCallback>& uiExtCallback)
131 {
132     auto task = [asyncContext, want, uiExtensionCallbacks, uiExtCallback]() {
133         Ace::UIContent* uiContent = GetUIContent(asyncContext);
134         if (uiContent == nullptr) {
135             ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!");
136             asyncContext->result = RET_FAILED;
137             asyncContext->uiExtensionFlag = false;
138             return;
139         }
140 
141         Ace::ModalUIExtensionConfig config;
142         config.isProhibitBack = true;
143         int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config);
144 
145         ACCESSTOKEN_LOG_INFO(LABEL, "Create end, sessionId: %{public}d, tokenId: %{public}d, permNum: %{public}zu",
146             sessionId, asyncContext->tokenId, asyncContext->permissionList.size());
147         if (sessionId == 0) {
148             ACCESSTOKEN_LOG_ERROR(LABEL, "Create component failed, sessionId is 0");
149             asyncContext->result = RET_FAILED;
150             asyncContext->uiExtensionFlag = false;
151             return;
152         }
153         uiExtCallback->SetSessionId(sessionId);
154     };
155 #ifdef EVENTHANDLER_ENABLE
156     if (asyncContext->handler_ != nullptr) {
157         asyncContext->handler_->PostSyncTask(task, "AT:CreateUIExtensionMainThread");
158     } else {
159         task();
160     }
161 #else
162     task();
163 #endif
164     ACCESSTOKEN_LOG_INFO(LABEL, "Instance id: %{public}d", asyncContext->instanceId);
165 }
166 
CloseModalUIExtensionMainThread(std::shared_ptr<RequestAsyncContext> & asyncContext,int32_t sessionId)167 static void CloseModalUIExtensionMainThread(std::shared_ptr<RequestAsyncContext>& asyncContext, int32_t sessionId)
168 {
169     auto task = [asyncContext, sessionId]() {
170         Ace::UIContent* uiContent = GetUIContent(asyncContext);
171         if (uiContent == nullptr) {
172             ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!");
173             asyncContext->result = RET_FAILED;
174             return;
175         }
176         uiContent->CloseModalUIExtension(sessionId);
177         ACCESSTOKEN_LOG_INFO(LABEL, "Close end, sessionId: %{public}d", sessionId);
178     };
179 #ifdef EVENTHANDLER_ENABLE
180     if (asyncContext->handler_ != nullptr) {
181         asyncContext->handler_->PostSyncTask(task, "AT:CloseModalUIExtensionMainThread");
182     } else {
183         task();
184     }
185 #else
186     task();
187 #endif
188     ACCESSTOKEN_LOG_INFO(LABEL, "Instance id: %{public}d", asyncContext->instanceId);
189 }
190 
GetContext(const napi_env & env,const napi_value & value,std::shared_ptr<RequestAsyncContext> & asyncContext)191 static napi_value GetContext(
192     const napi_env &env, const napi_value &value, std::shared_ptr<RequestAsyncContext>& asyncContext)
193 {
194     bool stageMode = false;
195     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, value, stageMode);
196     if (status != napi_ok || !stageMode) {
197         ACCESSTOKEN_LOG_ERROR(LABEL, "It is not a stage mode");
198         return nullptr;
199     } else {
200         auto context = AbilityRuntime::GetStageModeContext(env, value);
201         if (context == nullptr) {
202             ACCESSTOKEN_LOG_ERROR(LABEL, "Get context failed");
203             return nullptr;
204         }
205         asyncContext->abilityContext =
206             AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
207         if ((asyncContext->abilityContext != nullptr) &&
208             (asyncContext->abilityContext->GetApplicationInfo() != nullptr)) {
209             asyncContext->uiAbilityFlag = true;
210             asyncContext->tokenId = asyncContext->abilityContext->GetApplicationInfo()->accessTokenId;
211             asyncContext->bundleName = asyncContext->abilityContext->GetApplicationInfo()->bundleName;
212         } else {
213             ACCESSTOKEN_LOG_WARN(LABEL, "Convert to ability context failed");
214             asyncContext->uiExtensionContext =
215                 AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context);
216             if ((asyncContext->uiExtensionContext == nullptr) ||
217                 (asyncContext->uiExtensionContext->GetApplicationInfo() == nullptr)) {
218                 ACCESSTOKEN_LOG_ERROR(LABEL, "Convert to ui extension context failed");
219                 return nullptr;
220             }
221             asyncContext->tokenId = asyncContext->uiExtensionContext->GetApplicationInfo()->accessTokenId;
222             asyncContext->bundleName = asyncContext->uiExtensionContext->GetApplicationInfo()->bundleName;
223         }
224         return WrapVoidToJS(env);
225     }
226 }
227 
WrapRequestResult(const napi_env & env,const std::vector<std::string> & permissions,const std::vector<int> & grantResults,const std::vector<bool> & dialogShownResults)228 static napi_value WrapRequestResult(const napi_env& env, const std::vector<std::string>& permissions,
229     const std::vector<int>& grantResults, const std::vector<bool>& dialogShownResults)
230 {
231     napi_value result = nullptr;
232     NAPI_CALL(env, napi_create_object(env, &result));
233 
234     napi_value objPermissions;
235     NAPI_CALL(env, napi_create_array(env, &objPermissions));
236     for (size_t i = 0; i < permissions.size(); i++) {
237         napi_value nPerm = nullptr;
238         NAPI_CALL(env, napi_create_string_utf8(env, permissions[i].c_str(), NAPI_AUTO_LENGTH, &nPerm));
239         NAPI_CALL(env, napi_set_element(env, objPermissions, i, nPerm));
240     }
241     NAPI_CALL(env, napi_set_named_property(env, result, "permissions", objPermissions));
242 
243     napi_value objGrantResults;
244     NAPI_CALL(env, napi_create_array(env, &objGrantResults));
245     for (size_t i = 0; i < grantResults.size(); i++) {
246         napi_value nGrantResult = nullptr;
247         NAPI_CALL(env, napi_create_int32(env, grantResults[i], &nGrantResult));
248         NAPI_CALL(env, napi_set_element(env, objGrantResults, i, nGrantResult));
249     }
250     NAPI_CALL(env, napi_set_named_property(env, result, "authResults", objGrantResults));
251 
252     napi_value objDialogShown;
253     NAPI_CALL(env, napi_create_array(env, &objDialogShown));
254     for (size_t i = 0; i < dialogShownResults.size(); i++) {
255         napi_value nDialogShown = nullptr;
256         NAPI_CALL(env, napi_get_boolean(env, dialogShownResults[i], &nDialogShown));
257         NAPI_CALL(env, napi_set_element(env, objDialogShown, i, nDialogShown));
258     }
259     NAPI_CALL(env, napi_set_named_property(env, result, "dialogShownResults", objDialogShown));
260 
261     return result;
262 }
263 
ResultCallbackJSThreadWorker(uv_work_t * work,int32_t status)264 static void ResultCallbackJSThreadWorker(uv_work_t* work, int32_t status)
265 {
266     (void)status;
267     if (work == nullptr) {
268         ACCESSTOKEN_LOG_ERROR(LABEL, "Uv_queue_work_with_qos input work is nullptr");
269         return;
270     }
271     std::unique_ptr<uv_work_t> uvWorkPtr {work};
272     ResultCallback *retCB = reinterpret_cast<ResultCallback*>(work->data);
273     if (retCB == nullptr) {
274         ACCESSTOKEN_LOG_ERROR(LABEL, "RetCB is nullptr");
275         return;
276     }
277     std::unique_ptr<ResultCallback> callbackPtr {retCB};
278 
279     int32_t result = JsErrorCode::JS_OK;
280     if (retCB->data->result != RET_SUCCESS) {
281         ACCESSTOKEN_LOG_ERROR(LABEL, "Result is: %{public}d", retCB->data->result);
282         result = RET_FAILED;
283     }
284     if (retCB->grantResults.empty()) {
285         ACCESSTOKEN_LOG_ERROR(LABEL, "GrantResults empty");
286         result = RET_FAILED;
287     }
288     napi_handle_scope scope = nullptr;
289     napi_open_handle_scope(retCB->data->env, &scope);
290     if (scope == nullptr) {
291         ACCESSTOKEN_LOG_ERROR(LABEL, "Napi_open_handle_scope failed");
292         return;
293     }
294     napi_value requestResult = WrapRequestResult(
295         retCB->data->env, retCB->permissions, retCB->grantResults, retCB->dialogShownResults);
296     if (requestResult == nullptr) {
297         ACCESSTOKEN_LOG_ERROR(LABEL, "Wrap requestResult failed");
298         result = RET_FAILED;
299     }
300 
301     if (retCB->data->deferred != nullptr) {
302         ReturnPromiseResult(retCB->data->env, result, retCB->data->deferred, requestResult);
303     } else {
304         ReturnCallbackResult(retCB->data->env, result, retCB->data->callbackRef, requestResult);
305     }
306     napi_close_handle_scope(retCB->data->env, scope);
307 }
308 
UpdateGrantPermissionResultOnly(const std::vector<std::string> & permissions,const std::vector<int> & grantResults,std::shared_ptr<RequestAsyncContext> & data,std::vector<int> & newGrantResults)309 static void UpdateGrantPermissionResultOnly(const std::vector<std::string>& permissions,
310     const std::vector<int>& grantResults, std::shared_ptr<RequestAsyncContext>& data, std::vector<int>& newGrantResults)
311 {
312     uint32_t size = permissions.size();
313 
314     for (uint32_t i = 0; i < size; i++) {
315         int result = data->permissionsState[i];
316         if (data->permissionsState[i] == DYNAMIC_OPER) {
317             result = data->result == RET_SUCCESS ? grantResults[i] : INVALID_OPER;
318         }
319         newGrantResults.emplace_back(result);
320     }
321 }
322 
RequestResultsHandler(const std::vector<std::string> & permissionList,const std::vector<int32_t> & permissionStates,std::shared_ptr<RequestAsyncContext> & data)323 static void RequestResultsHandler(const std::vector<std::string>& permissionList,
324     const std::vector<int32_t>& permissionStates, std::shared_ptr<RequestAsyncContext>& data)
325 {
326     auto* retCB = new (std::nothrow) ResultCallback();
327     if (retCB == nullptr) {
328         ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for work!");
329         return;
330     }
331 
332     // only permissions which need to grant change the result, other keey as GetSelfPermissionsState result
333     std::vector<int> newGrantResults;
334     UpdateGrantPermissionResultOnly(permissionList, permissionStates, data, newGrantResults);
335 
336     std::unique_ptr<ResultCallback> callbackPtr {retCB};
337     retCB->permissions = permissionList;
338     retCB->grantResults = newGrantResults;
339     retCB->dialogShownResults = data->dialogShownResults;
340     retCB->data = data;
341 
342     uv_loop_s* loop = nullptr;
343     NAPI_CALL_RETURN_VOID(data->env, napi_get_uv_event_loop(data->env, &loop));
344     if (loop == nullptr) {
345         ACCESSTOKEN_LOG_ERROR(LABEL, "Loop instance is nullptr");
346         return;
347     }
348     uv_work_t* work = new (std::nothrow) uv_work_t;
349     if (work == nullptr) {
350         ACCESSTOKEN_LOG_ERROR(LABEL, "Insufficient memory for work!");
351         return;
352     }
353     std::unique_ptr<uv_work_t> uvWorkPtr {work};
354     work->data = reinterpret_cast<void *>(retCB);
355     NAPI_CALL_RETURN_VOID(data->env, uv_queue_work_with_qos(
356         loop, work, [](uv_work_t* work) {}, ResultCallbackJSThreadWorker, uv_qos_user_initiated));
357 
358     uvWorkPtr.release();
359     callbackPtr.release();
360 }
361 
GrantResultsCallback(const std::vector<std::string> & permissionList,const std::vector<int> & grantResults)362 void AuthorizationResult::GrantResultsCallback(const std::vector<std::string>& permissionList,
363     const std::vector<int>& grantResults)
364 {
365     ACCESSTOKEN_LOG_INFO(LABEL, "Called.");
366     std::shared_ptr<RequestAsyncContext> asyncContext = data_;
367     if (asyncContext == nullptr) {
368         return;
369     }
370     RequestResultsHandler(permissionList, grantResults, asyncContext);
371 }
372 
WindowShownCallback()373 void AuthorizationResult::WindowShownCallback()
374 {
375     ACCESSTOKEN_LOG_INFO(LABEL, "Called.");
376 
377     std::shared_ptr<RequestAsyncContext> asyncContext = data_;
378     if (asyncContext == nullptr) {
379         return;
380     }
381 
382     Ace::UIContent* uiContent = GetUIContent(asyncContext);
383     // get uiContent failed when request or when callback called
384     if ((uiContent == nullptr) || !(asyncContext->uiContentFlag)) {
385         ACCESSTOKEN_LOG_ERROR(LABEL, "Get ui content failed!");
386         return;
387     }
388     RequestAsyncInstanceControl::ExecCallback(asyncContext->instanceId);
389     ACCESSTOKEN_LOG_DEBUG(LABEL, "OnRequestPermissionsFromUser async callback is called end");
390 }
391 
CreateServiceExtension(std::shared_ptr<RequestAsyncContext> asyncContext)392 static void CreateServiceExtension(std::shared_ptr<RequestAsyncContext> asyncContext)
393 {
394     if ((asyncContext == nullptr) || (asyncContext->abilityContext == nullptr)) {
395         return;
396     }
397     if (!asyncContext->uiAbilityFlag) {
398         ACCESSTOKEN_LOG_ERROR(LABEL, "UIExtension ability can not pop service ablility window!");
399         asyncContext->needDynamicRequest = false;
400         asyncContext->result = RET_FAILED;
401         return;
402     }
403     sptr<IRemoteObject> remoteObject = new (std::nothrow) AccessToken::AuthorizationResult(asyncContext);
404     if (remoteObject == nullptr) {
405         ACCESSTOKEN_LOG_ERROR(LABEL, "Create window failed!");
406         asyncContext->needDynamicRequest = false;
407         asyncContext->result = RET_FAILED;
408         return;
409     }
410     AAFwk::Want want;
411     want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.grantServiceAbilityName);
412     want.SetParam(PERMISSION_KEY, asyncContext->permissionList);
413     want.SetParam(STATE_KEY, asyncContext->permissionsState);
414     want.SetParam(TOKEN_KEY, asyncContext->abilityContext->GetToken());
415     want.SetParam(CALLBACK_KEY, remoteObject);
416 
417     int32_t left;
418     int32_t top;
419     int32_t width;
420     int32_t height;
421     asyncContext->abilityContext->GetWindowRect(left, top, width, height);
422     want.SetParam(WINDOW_RECTANGLE_LEFT_KEY, left);
423     want.SetParam(WINDOW_RECTANGLE_TOP_KEY, top);
424     want.SetParam(WINDOW_RECTANGLE_WIDTH_KEY, width);
425     want.SetParam(WINDOW_RECTANGLE_HEIGHT_KEY, height);
426     want.SetParam(REQUEST_TOKEN_KEY, asyncContext->abilityContext->GetToken());
427     int32_t ret = AAFwk::AbilityManagerClient::GetInstance()->RequestDialogService(
428         want, asyncContext->abilityContext->GetToken());
429 
430     ACCESSTOKEN_LOG_INFO(LABEL, "Request end, ret: %{public}d, tokenId: %{public}d, permNum: %{public}zu",
431         ret, asyncContext->tokenId, asyncContext->permissionList.size());
432 }
433 
IsDynamicRequest(std::shared_ptr<RequestAsyncContext> & asyncContext)434 bool NapiRequestPermission::IsDynamicRequest(std::shared_ptr<RequestAsyncContext>& asyncContext)
435 {
436     std::vector<PermissionListState> permList;
437     for (const auto& permission : asyncContext->permissionList) {
438         PermissionListState permState;
439         permState.permissionName = permission;
440         permState.state = INVALID_OPER;
441         permList.emplace_back(permState);
442     }
443     auto ret = AccessTokenKit::GetSelfPermissionsState(permList, asyncContext->info);
444     if (ret == FORBIDDEN_OPER) { // if app is under control, change state from default -1 to 2
445         for (auto& perm : permList) {
446             perm.state = INVALID_OPER;
447         }
448     }
449     ACCESSTOKEN_LOG_INFO(LABEL,
450         "TokenID: %{public}d, bundle: %{public}s, uiExAbility: %{public}s, serExAbility: %{public}s.",
451         asyncContext->tokenId, asyncContext->info.grantBundleName.c_str(),
452         asyncContext->info.grantAbilityName.c_str(), asyncContext->info.grantServiceAbilityName.c_str());
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     AccessTokenID selfTokenID = static_cast<AccessTokenID>(GetSelfTokenID());
675     if (asyncContextHandle->asyncContextPtr->tokenId != selfTokenID) {
676         ACCESSTOKEN_LOG_ERROR(LABEL, "The context tokenID: %{public}d, selfTokenID: %{public}d.",
677             asyncContextHandle->asyncContextPtr->tokenId, selfTokenID);
678         asyncContextHandle->asyncContextPtr->result = RET_FAILED;
679         return;
680     }
681 
682     if (!IsDynamicRequest(asyncContextHandle->asyncContextPtr)) {
683         ACCESSTOKEN_LOG_INFO(LABEL, "It does not need to request permission");
684         asyncContextHandle->asyncContextPtr->needDynamicRequest = false;
685         return;
686     }
687     GetInstanceId(asyncContextHandle->asyncContextPtr);
688     // service extension dialog
689     if (asyncContextHandle->asyncContextPtr->info.grantBundleName == ORI_PERMISSION_MANAGER_BUNDLE_NAME) {
690         ACCESSTOKEN_LOG_INFO(LABEL, "Pop service extension dialog, uiContentFlag=%{public}d",
691             asyncContextHandle->asyncContextPtr->uiContentFlag);
692         if (asyncContextHandle->asyncContextPtr->uiContentFlag) {
693             RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContextHandle->asyncContextPtr);
694         } else {
695             CreateServiceExtension(asyncContextHandle->asyncContextPtr);
696         }
697     } else if (asyncContextHandle->asyncContextPtr->instanceId == -1) {
698         ACCESSTOKEN_LOG_INFO(LABEL, "Pop service extension dialog, instanceId is -1.");
699         CreateServiceExtension(asyncContextHandle->asyncContextPtr);
700         HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::ACCESS_TOKEN, "REQUEST_PERMISSIONS_FROM_USER",
701             HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
702             "BUNDLENAME", asyncContextHandle->asyncContextPtr->bundleName,
703             "UIEXTENSION_FLAG", false);
704     } else {
705         ACCESSTOKEN_LOG_INFO(LABEL, "Pop ui extension dialog");
706         asyncContextHandle->asyncContextPtr->uiExtensionFlag = true;
707         RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContextHandle->asyncContextPtr);
708         HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::ACCESS_TOKEN, "REQUEST_PERMISSIONS_FROM_USER",
709             HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
710             "BUNDLENAME", asyncContextHandle->asyncContextPtr->bundleName,
711             "UIEXTENSION_FLAG", asyncContextHandle->asyncContextPtr->uiExtensionFlag);
712         if (!asyncContextHandle->asyncContextPtr->uiExtensionFlag) {
713             ACCESSTOKEN_LOG_WARN(LABEL, "Pop uiextension dialog fail, start to pop service extension dialog.");
714             RequestAsyncInstanceControl::AddCallbackByInstanceId(asyncContextHandle->asyncContextPtr);
715         }
716     }
717 }
718 
RequestPermissionsFromUserComplete(napi_env env,napi_status status,void * data)719 void NapiRequestPermission::RequestPermissionsFromUserComplete(napi_env env, napi_status status, void* data)
720 {
721     RequestAsyncContextHandle* asyncContextHandle = reinterpret_cast<RequestAsyncContextHandle*>(data);
722     std::unique_ptr<RequestAsyncContextHandle> callbackPtr {asyncContextHandle};
723 
724     if (asyncContextHandle->asyncContextPtr->needDynamicRequest) {
725         return;
726     }
727     if ((asyncContextHandle->asyncContextPtr->permissionsState.empty()) &&
728         (asyncContextHandle->asyncContextPtr->result == JsErrorCode::JS_OK)) {
729         ACCESSTOKEN_LOG_ERROR(LABEL, "GrantResults empty");
730         asyncContextHandle->asyncContextPtr->result = RET_FAILED;
731     }
732     napi_value requestResult = WrapRequestResult(env, asyncContextHandle->asyncContextPtr->permissionList,
733         asyncContextHandle->asyncContextPtr->permissionsState, asyncContextHandle->asyncContextPtr->dialogShownResults);
734     if (requestResult == nullptr) {
735         ACCESSTOKEN_LOG_ERROR(LABEL, "Wrap requestResult failed");
736         if (asyncContextHandle->asyncContextPtr->result == JsErrorCode::JS_OK) {
737             asyncContextHandle->asyncContextPtr->result = RET_FAILED;
738         }
739     } else {
740         asyncContextHandle->asyncContextPtr->requestResult = requestResult;
741     }
742     if (asyncContextHandle->asyncContextPtr->deferred != nullptr) {
743         ReturnPromiseResult(env, asyncContextHandle->asyncContextPtr->result,
744             asyncContextHandle->asyncContextPtr->deferred, asyncContextHandle->asyncContextPtr->requestResult);
745     } else {
746         ReturnCallbackResult(env, asyncContextHandle->asyncContextPtr->result,
747             asyncContextHandle->asyncContextPtr->callbackRef, asyncContextHandle->asyncContextPtr->requestResult);
748     }
749 }
750 
GetPermissionsStatus(napi_env env,napi_callback_info info)751 napi_value NapiRequestPermission::GetPermissionsStatus(napi_env env, napi_callback_info info)
752 {
753     ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionsStatus begin.");
754 
755     auto* asyncContext = new (std::nothrow) RequestAsyncContext(env);
756     if (asyncContext == nullptr) {
757         ACCESSTOKEN_LOG_ERROR(LABEL, "New struct fail.");
758         return nullptr;
759     }
760 
761     std::unique_ptr<RequestAsyncContext> context {asyncContext};
762     if (!ParseInputToGetQueryResult(env, info, *asyncContext)) {
763         return nullptr;
764     }
765 
766     napi_value result = nullptr;
767     napi_create_promise(env, &(asyncContext->deferred), &result); // create delay promise object
768 
769     napi_value resource = nullptr; // resource name
770     napi_create_string_utf8(env, "GetPermissionsStatus", NAPI_AUTO_LENGTH, &resource);
771 
772     napi_create_async_work(
773         env, nullptr, resource, GetPermissionsStatusExecute, GetPermissionsStatusComplete,
774         reinterpret_cast<void *>(asyncContext), &(asyncContext->work));
775     // add async work handle to the napi queue and wait for result
776     napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default);
777 
778     ACCESSTOKEN_LOG_DEBUG(LABEL, "GetPermissionsStatus end.");
779     context.release();
780     return result;
781 }
782 
ParseInputToGetQueryResult(const napi_env & env,const napi_callback_info & info,RequestAsyncContext & asyncContext)783 bool NapiRequestPermission::ParseInputToGetQueryResult(const napi_env& env, const napi_callback_info& info,
784     RequestAsyncContext& asyncContext)
785 {
786     size_t argc = NapiContextCommon::MAX_PARAMS_TWO;
787     napi_value argv[NapiContextCommon::MAX_PARAMS_TWO] = {nullptr};
788     napi_value thatVar = nullptr;
789 
790     void *data = nullptr;
791     NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &thatVar, &data), false);
792     // 1: can request permissions minnum argc
793     if (argc < NapiContextCommon::MAX_PARAMS_TWO - 1) {
794         NAPI_CALL_BASE(env, napi_throw(env,
795             GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
796         return false;
797     }
798 
799     std::string errMsg;
800     asyncContext.env = env;
801     // the first parameter of argv
802     if (!ParseUint32(env, argv[0], asyncContext.tokenId)) {
803         errMsg = GetParamErrorMsg("tokenId", "number");
804         NAPI_CALL_BASE(env,
805             napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
806         return false;
807     }
808 
809     // the second parameter of argv
810     if (!ParseStringArray(env, argv[1], asyncContext.permissionList)) {
811         errMsg = GetParamErrorMsg("permissions", "Array<string>");
812         NAPI_CALL_BASE(
813             env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
814         return false;
815     }
816     ACCESSTOKEN_LOG_DEBUG(LABEL, "TokenID = %{public}d, permissionList size = %{public}zu", asyncContext.tokenId,
817         asyncContext.permissionList.size());
818     return true;
819 }
820 
GetPermissionsStatusExecute(napi_env env,void * data)821 void NapiRequestPermission::GetPermissionsStatusExecute(napi_env env, void *data)
822 {
823     RequestAsyncContext* asyncContext = reinterpret_cast<RequestAsyncContext*>(data);
824 
825     std::vector<PermissionListState> permList;
826     for (const auto& permission : asyncContext->permissionList) {
827         ACCESSTOKEN_LOG_DEBUG(LABEL, "Permission: %{public}s.", permission.c_str());
828         PermissionListState permState;
829         permState.permissionName = permission;
830         permState.state = INVALID_OPER;
831         permList.emplace_back(permState);
832     }
833     ACCESSTOKEN_LOG_DEBUG(LABEL, "PermList size: %{public}zu, asyncContext->permissionList size: %{public}zu.",
834         permList.size(), asyncContext->permissionList.size());
835 
836     asyncContext->result = AccessTokenKit::GetPermissionsStatus(asyncContext->tokenId, permList);
837     for (const auto& permState : permList) {
838         ACCESSTOKEN_LOG_DEBUG(LABEL, "Permission: %{public}s", permState.permissionName.c_str());
839         asyncContext->permissionQueryResults.emplace_back(permState.state);
840     }
841 }
842 
GetPermissionsStatusComplete(napi_env env,napi_status status,void * data)843 void NapiRequestPermission::GetPermissionsStatusComplete(napi_env env, napi_status status, void *data)
844 {
845     RequestAsyncContext* asyncContext = reinterpret_cast<RequestAsyncContext*>(data);
846     std::unique_ptr<RequestAsyncContext> callbackPtr {asyncContext};
847 
848     if ((asyncContext->permissionQueryResults.empty()) && asyncContext->result == JsErrorCode::JS_OK) {
849         ACCESSTOKEN_LOG_ERROR(LABEL, "PermissionQueryResults empty");
850         asyncContext->result = RET_FAILED;
851     }
852     napi_value result;
853     NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &result));
854 
855     for (size_t i = 0; i < asyncContext->permissionQueryResults.size(); i++) {
856         napi_value nPermissionQueryResult = nullptr;
857         NAPI_CALL_RETURN_VOID(env, napi_create_int32(env,
858             asyncContext->permissionQueryResults[i], &nPermissionQueryResult));
859         NAPI_CALL_RETURN_VOID(env, napi_set_element(env, result, i, nPermissionQueryResult));
860     }
861     ReturnPromiseResult(env, asyncContext->result, asyncContext->deferred, result);
862 }
863 
CheckDynamicRequest(std::shared_ptr<RequestAsyncContext> & asyncContext,bool & isDynamic)864 void RequestAsyncInstanceControl::CheckDynamicRequest(
865     std::shared_ptr<RequestAsyncContext>& asyncContext, bool& isDynamic)
866 {
867     asyncContext->permissionsState.clear();
868     asyncContext->dialogShownResults.clear();
869     if (!NapiRequestPermission::IsDynamicRequest(asyncContext)) {
870         ACCESSTOKEN_LOG_INFO(LABEL, "It does not need to request permission exsion");
871         RequestResultsHandler(asyncContext->permissionList, asyncContext->permissionsState, asyncContext);
872         return;
873     }
874     isDynamic = true;
875 }
876 
AddCallbackByInstanceId(std::shared_ptr<RequestAsyncContext> & asyncContext)877 void RequestAsyncInstanceControl::AddCallbackByInstanceId(std::shared_ptr<RequestAsyncContext>& asyncContext)
878 {
879     ACCESSTOKEN_LOG_INFO(LABEL, "InstanceId: %{public}d", asyncContext->instanceId);
880     {
881         std::lock_guard<std::mutex> lock(instanceIdMutex_);
882         auto iter = instanceIdMap_.find(asyncContext->instanceId);
883         // id is existed mean a pop window is showing, add context to waiting queue
884         if (iter != instanceIdMap_.end()) {
885             ACCESSTOKEN_LOG_INFO(LABEL, "InstanceId: %{public}d has existed.", asyncContext->instanceId);
886             instanceIdMap_[asyncContext->instanceId].emplace_back(asyncContext);
887             return;
888         }
889         // make sure id is in map to indicate a pop-up window is showing
890         instanceIdMap_[asyncContext->instanceId] = {};
891     }
892 
893     if (asyncContext->uiExtensionFlag) {
894         CreateUIExtension(asyncContext);
895     } else {
896         CreateServiceExtension(asyncContext);
897     }
898 }
899 
ExecCallback(int32_t id)900 void RequestAsyncInstanceControl::ExecCallback(int32_t id)
901 {
902     std::shared_ptr<RequestAsyncContext> asyncContext = nullptr;
903     bool isDynamic = false;
904     {
905         std::lock_guard<std::mutex> lock(instanceIdMutex_);
906         auto iter = instanceIdMap_.find(id);
907         if (iter == instanceIdMap_.end()) {
908             ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d not existed.", id);
909             return;
910         }
911         while (!iter->second.empty()) {
912             ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d, map size: %{public}zu.", id, iter->second.size());
913             asyncContext = iter->second[0];
914             iter->second.erase(iter->second.begin());
915             CheckDynamicRequest(asyncContext, isDynamic);
916             if (isDynamic) {
917                 break;
918             }
919         }
920         if (iter->second.empty()) {
921             ACCESSTOKEN_LOG_INFO(LABEL, "Id: %{public}d, map is empty", id);
922             instanceIdMap_.erase(id);
923         }
924     }
925     if (isDynamic) {
926         if (asyncContext->uiExtensionFlag) {
927             CreateUIExtension(asyncContext);
928         } else {
929             CreateServiceExtension(asyncContext);
930         }
931     }
932 }
933 }  // namespace AccessToken
934 }  // namespace Security
935 }  // namespace OHOS