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