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