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