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