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_global_switch_on_setting.h"
16
17 #include "ability.h"
18 #include "accesstoken_kit.h"
19 #include "accesstoken_common_log.h"
20 #include "napi_base_context.h"
21 #include "token_setproc.h"
22 #include "want.h"
23
24 namespace OHOS {
25 namespace Security {
26 namespace AccessToken {
27 namespace {
28 const std::string GLOBAL_SWITCH_KEY = "ohos.user.setting.global_switch";
29 const std::string GLOBAL_SWITCH_RESULT_KEY = "ohos.user.setting.global_switch.result";
30 const std::string RESULT_ERROR_KEY = "ohos.user.setting.error_code";
31 const std::string EXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType";
32 const std::string UI_EXTENSION_TYPE = "sys/commonUI";
33
34 // error code from dialog
35 const int32_t REQUEST_REALDY_EXIST = 1;
36 const int32_t GLOBAL_TYPE_IS_NOT_SUPPORT = 2;
37 const int32_t SWITCH_IS_ALREADY_OPEN = 3;
38 std::mutex g_lockFlag;
39 } // namespace
ReturnPromiseResult(napi_env env,int32_t jsCode,napi_deferred deferred,napi_value result)40 static void ReturnPromiseResult(napi_env env, int32_t jsCode, napi_deferred deferred, napi_value result)
41 {
42 if (jsCode != JS_OK) {
43 napi_value businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
44 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, deferred, businessError));
45 } else {
46 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, deferred, result));
47 }
48 }
49
WrapVoidToJS(napi_env env)50 static napi_value WrapVoidToJS(napi_env env)
51 {
52 napi_value result = nullptr;
53 NAPI_CALL(env, napi_get_null(env, &result));
54 return result;
55 }
56
GetUIContent(std::shared_ptr<RequestGlobalSwitchAsyncContext> asyncContext)57 static Ace::UIContent* GetUIContent(std::shared_ptr<RequestGlobalSwitchAsyncContext> asyncContext)
58 {
59 if (asyncContext == nullptr) {
60 return nullptr;
61 }
62 Ace::UIContent* uiContent = nullptr;
63 if (asyncContext->uiAbilityFlag) {
64 uiContent = asyncContext->abilityContext->GetUIContent();
65 } else {
66 uiContent = asyncContext->uiExtensionContext->GetUIContent();
67 }
68 return uiContent;
69 }
70
GetContext(const napi_env & env,const napi_value & value,std::shared_ptr<RequestGlobalSwitchAsyncContext> & asyncContext)71 static napi_value GetContext(
72 const napi_env &env, const napi_value &value, std::shared_ptr<RequestGlobalSwitchAsyncContext>& asyncContext)
73 {
74 bool stageMode = false;
75 napi_status status = OHOS::AbilityRuntime::IsStageContext(env, value, stageMode);
76 if (status != napi_ok || !stageMode) {
77 LOGE(ATM_DOMAIN, ATM_TAG, "It is not a stage mode.");
78 return nullptr;
79 } else {
80 auto context = AbilityRuntime::GetStageModeContext(env, value);
81 if (context == nullptr) {
82 LOGE(ATM_DOMAIN, ATM_TAG, "Failed to Get application context.");
83 return nullptr;
84 }
85 asyncContext->abilityContext =
86 AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
87 if (asyncContext->abilityContext != nullptr) {
88 asyncContext->uiAbilityFlag = true;
89 } else {
90 LOGW(ATM_DOMAIN, ATM_TAG, "Failed to convert to ability context.");
91 asyncContext->uiExtensionContext =
92 AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context);
93 if (asyncContext->uiExtensionContext == nullptr) {
94 LOGE(ATM_DOMAIN, ATM_TAG, "Failed to convert to ui extension context.");
95 return nullptr;
96 }
97 }
98 return WrapVoidToJS(env);
99 }
100 }
101
102
TransferToJsErrorCode(int32_t errCode)103 static int32_t TransferToJsErrorCode(int32_t errCode)
104 {
105 int32_t jsCode = JS_OK;
106 switch (errCode) {
107 case RET_SUCCESS:
108 jsCode = JS_OK;
109 break;
110 case REQUEST_REALDY_EXIST:
111 jsCode = JS_ERROR_REQUEST_IS_ALREADY_EXIST;
112 break;
113 case GLOBAL_TYPE_IS_NOT_SUPPORT:
114 jsCode = JS_ERROR_PARAM_INVALID;
115 break;
116 case SWITCH_IS_ALREADY_OPEN:
117 jsCode = JS_ERROR_GLOBAL_SWITCH_IS_ALREADY_OPEN;
118 break;
119 default:
120 jsCode = JS_ERROR_INNER;
121 break;
122 }
123 LOGI(ATM_DOMAIN, ATM_TAG, "dialog error(%{public}d) jsCode(%{public}d).", errCode, jsCode);
124 return jsCode;
125 }
126
GlobalSwitchResultsCallbackUI(int32_t jsCode,bool switchStatus,std::shared_ptr<RequestGlobalSwitchAsyncContext> & data)127 static void GlobalSwitchResultsCallbackUI(int32_t jsCode,
128 bool switchStatus, std::shared_ptr<RequestGlobalSwitchAsyncContext>& data)
129 {
130 auto* retCB = new (std::nothrow) SwitchOnSettingResultCallback();
131 if (retCB == nullptr) {
132 LOGE(ATM_DOMAIN, ATM_TAG, "Insufficient memory for work!");
133 return;
134 }
135 std::unique_ptr<SwitchOnSettingResultCallback> callbackPtr {retCB};
136 retCB->jsCode = jsCode;
137 retCB->switchStatus = switchStatus;
138 retCB->data = data;
139 auto task = [retCB]() {
140 std::unique_ptr<SwitchOnSettingResultCallback> callback {retCB};
141 std::shared_ptr<RequestGlobalSwitchAsyncContext> asyncContext = retCB->data;
142 if (asyncContext == nullptr) {
143 return;
144 }
145 napi_handle_scope scope = nullptr;
146 napi_open_handle_scope(asyncContext->env, &scope);
147 if (scope == nullptr) {
148 LOGE(ATM_DOMAIN, ATM_TAG, "Napi_open_handle_scope failed");
149 return;
150 }
151 napi_value requestResult = nullptr;
152 NAPI_CALL_RETURN_VOID(asyncContext->env,
153 napi_get_boolean(asyncContext->env, retCB->switchStatus, &requestResult));
154
155 ReturnPromiseResult(asyncContext->env, retCB->jsCode, asyncContext->deferred, requestResult);
156 napi_close_handle_scope(asyncContext->env, scope);
157 };
158 if (napi_status::napi_ok != napi_send_event(data->env, task, napi_eprio_immediate)) {
159 LOGE(ATM_DOMAIN, ATM_TAG, "GlobalSwitchResultsCallbackUI: Failed to SendEvent");
160 } else {
161 callbackPtr.release();
162 }
163 }
164
CloseModalUIExtensionMainThread(std::shared_ptr<RequestGlobalSwitchAsyncContext> & asyncContext,int32_t sessionId)165 static void CloseModalUIExtensionMainThread(std::shared_ptr<RequestGlobalSwitchAsyncContext>& asyncContext,
166 int32_t sessionId)
167 {
168 auto task = [asyncContext, sessionId]() {
169 Ace::UIContent* uiContent = GetUIContent(asyncContext);
170 if (uiContent == nullptr) {
171 LOGE(ATM_DOMAIN, ATM_TAG, "Get ui content failed!");
172 return;
173 }
174 LOGI(ATM_DOMAIN, ATM_TAG, "Close uiextension component");
175 uiContent->CloseModalUIExtension(sessionId);
176 };
177 #ifdef EVENTHANDLER_ENABLE
178 if (asyncContext->handler_ != nullptr) {
179 asyncContext->handler_->PostSyncTask(task, "AT:CloseModalUIExtensionMainThread");
180 } else {
181 task();
182 }
183 #else
184 task();
185 #endif
186 }
187
ReleaseHandler(int32_t code)188 void SwitchOnSettingUICallback::ReleaseHandler(int32_t code)
189 {
190 {
191 std::lock_guard<std::mutex> lock(g_lockFlag);
192 if (this->reqContext_->releaseFlag) {
193 LOGW(ATM_DOMAIN, ATM_TAG, "Callback has executed.");
194 return;
195 }
196 this->reqContext_->releaseFlag = true;
197 }
198 CloseModalUIExtensionMainThread(this->reqContext_, this->sessionId_);
199 if (code == -1) {
200 this->reqContext_->errorCode = code;
201 }
202 GlobalSwitchResultsCallbackUI(
203 TransferToJsErrorCode(this->reqContext_->errorCode), this->reqContext_->switchStatus, this->reqContext_);
204 }
205
SwitchOnSettingUICallback(const std::shared_ptr<RequestGlobalSwitchAsyncContext> & reqContext)206 SwitchOnSettingUICallback::SwitchOnSettingUICallback(
207 const std::shared_ptr<RequestGlobalSwitchAsyncContext>& reqContext)
208 {
209 this->reqContext_ = reqContext;
210 }
211
~SwitchOnSettingUICallback()212 SwitchOnSettingUICallback::~SwitchOnSettingUICallback()
213 {}
214
SetSessionId(int32_t sessionId)215 void SwitchOnSettingUICallback::SetSessionId(int32_t sessionId)
216 {
217 this->sessionId_ = sessionId;
218 }
219
220 /*
221 * when UIExtensionAbility use terminateSelfWithResult
222 */
OnResult(int32_t resultCode,const AAFwk::Want & result)223 void SwitchOnSettingUICallback::OnResult(int32_t resultCode, const AAFwk::Want& result)
224 {
225 this->reqContext_->errorCode = result.GetIntParam(RESULT_ERROR_KEY, 0);
226 this->reqContext_->switchStatus = result.GetBoolParam(GLOBAL_SWITCH_RESULT_KEY, 0);
227 LOGI(ATM_DOMAIN, ATM_TAG, "ResultCode is %{public}d, errorCode=%{public}d, switchStatus=%{public}d",
228 resultCode, this->reqContext_->errorCode, this->reqContext_->switchStatus);
229 ReleaseHandler(0);
230 }
231
232 /*
233 * when UIExtensionAbility send message to UIExtensionComponent
234 */
OnReceive(const AAFwk::WantParams & receive)235 void SwitchOnSettingUICallback::OnReceive(const AAFwk::WantParams& receive)
236 {
237 LOGI(ATM_DOMAIN, ATM_TAG, "Called!");
238 }
239
240 /*
241 * when UIExtensionAbility disconnect or use terminate or process die
242 * releaseCode is 0 when process normal exit
243 */
OnRelease(int32_t releaseCode)244 void SwitchOnSettingUICallback::OnRelease(int32_t releaseCode)
245 {
246 LOGI(ATM_DOMAIN, ATM_TAG, "ReleaseCode is %{public}d", releaseCode);
247
248 ReleaseHandler(-1);
249 }
250
251 /*
252 * when UIExtensionComponent init or turn to background or destroy UIExtensionAbility occur error
253 */
OnError(int32_t code,const std::string & name,const std::string & message)254 void SwitchOnSettingUICallback::OnError(int32_t code, const std::string& name, const std::string& message)
255 {
256 LOGI(ATM_DOMAIN, ATM_TAG, "Code is %{public}d, name is %{public}s, message is %{public}s",
257 code, name.c_str(), message.c_str());
258
259 ReleaseHandler(-1);
260 }
261
262 /*
263 * when UIExtensionComponent connect to UIExtensionAbility, ModalUIExtensionProxy will init,
264 * UIExtensionComponent can send message to UIExtensionAbility by ModalUIExtensionProxy
265 */
OnRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy> & uiProxy)266 void SwitchOnSettingUICallback::OnRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy>& uiProxy)
267 {
268 LOGI(ATM_DOMAIN, ATM_TAG, "Connect to UIExtensionAbility successfully.");
269 }
270
271 /*
272 * when UIExtensionComponent destructed
273 */
OnDestroy()274 void SwitchOnSettingUICallback::OnDestroy()
275 {
276 LOGI(ATM_DOMAIN, ATM_TAG, "UIExtensionAbility destructed.");
277 ReleaseHandler(-1);
278 }
279
CreateUIExtensionMainThread(std::shared_ptr<RequestGlobalSwitchAsyncContext> & asyncContext,const AAFwk::Want & want,const Ace::ModalUIExtensionCallbacks & uiExtensionCallbacks,const std::shared_ptr<SwitchOnSettingUICallback> & uiExtCallback)280 static void CreateUIExtensionMainThread(std::shared_ptr<RequestGlobalSwitchAsyncContext>& asyncContext,
281 const AAFwk::Want& want, const Ace::ModalUIExtensionCallbacks& uiExtensionCallbacks,
282 const std::shared_ptr<SwitchOnSettingUICallback>& uiExtCallback)
283 {
284 auto task = [asyncContext, want, uiExtensionCallbacks, uiExtCallback]() {
285 Ace::UIContent* uiContent = GetUIContent(asyncContext);
286 if (uiContent == nullptr) {
287 LOGE(ATM_DOMAIN, ATM_TAG, "Failed to get ui content!");
288 asyncContext->result = RET_FAILED;
289 return;
290 }
291
292 Ace::ModalUIExtensionConfig config;
293 config.isProhibitBack = true;
294 int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config);
295 LOGI(ATM_DOMAIN, ATM_TAG, "Create end, sessionId: %{public}d, tokenId: %{public}d, switchType: %{public}d.",
296 sessionId, asyncContext->tokenId, asyncContext->switchType);
297 if (sessionId == 0) {
298 LOGE(ATM_DOMAIN, ATM_TAG, "Failed to create component, sessionId is 0.");
299 asyncContext->result = RET_FAILED;
300 return;
301 }
302 uiExtCallback->SetSessionId(sessionId);
303 };
304 #ifdef EVENTHANDLER_ENABLE
305 if (asyncContext->handler_ != nullptr) {
306 asyncContext->handler_->PostSyncTask(task, "AT:CreateUIExtensionMainThread");
307 } else {
308 task();
309 }
310 #else
311 task();
312 #endif
313 }
314
CreateUIExtension(const Want & want,std::shared_ptr<RequestGlobalSwitchAsyncContext> asyncContext)315 static int32_t CreateUIExtension(const Want &want, std::shared_ptr<RequestGlobalSwitchAsyncContext> asyncContext)
316 {
317 auto uiExtCallback = std::make_shared<SwitchOnSettingUICallback>(asyncContext);
318 Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = {
319 [uiExtCallback](int32_t releaseCode) {
320 uiExtCallback->OnRelease(releaseCode);
321 },
322 [uiExtCallback](int32_t resultCode, const AAFwk::Want &result) {
323 uiExtCallback->OnResult(resultCode, result);
324 },
325 [uiExtCallback](const AAFwk::WantParams &receive) {
326 uiExtCallback->OnReceive(receive);
327 },
328 [uiExtCallback](int32_t code, const std::string &name, [[maybe_unused]] const std::string &message) {
329 uiExtCallback->OnError(code, name, name);
330 },
331 [uiExtCallback](const std::shared_ptr<Ace::ModalUIExtensionProxy> &uiProxy) {
332 uiExtCallback->OnRemoteReady(uiProxy);
333 },
334 [uiExtCallback]() {
335 uiExtCallback->OnDestroy();
336 },
337 };
338
339 CreateUIExtensionMainThread(asyncContext, want, uiExtensionCallbacks, uiExtCallback);
340 if (asyncContext->result == RET_FAILED) {
341 return RET_FAILED;
342 }
343 return JS_OK;
344 }
345
StartUIExtension(std::shared_ptr<RequestGlobalSwitchAsyncContext> asyncContext)346 static int32_t StartUIExtension(std::shared_ptr<RequestGlobalSwitchAsyncContext> asyncContext)
347 {
348 AAFwk::Want want;
349 AccessTokenKit::GetPermissionManagerInfo(asyncContext->info);
350 LOGI(ATM_DOMAIN, ATM_TAG, "bundleName: %{public}s, globalSwitchAbilityName: %{public}s.",
351 asyncContext->info.grantBundleName.c_str(), asyncContext->info.globalSwitchAbilityName.c_str());
352 want.SetElementName(asyncContext->info.grantBundleName, asyncContext->info.globalSwitchAbilityName);
353 want.SetParam(GLOBAL_SWITCH_KEY, asyncContext->switchType);
354 want.SetParam(EXTENSION_TYPE_KEY, UI_EXTENSION_TYPE);
355
356 return CreateUIExtension(want, asyncContext);
357 }
358
RequestGlobalSwitch(napi_env env,napi_callback_info info)359 napi_value NapiRequestGlobalSwitch::RequestGlobalSwitch(napi_env env, napi_callback_info info)
360 {
361 LOGD(ATM_DOMAIN, ATM_TAG, "RequestGlobalSwitch begin.");
362 // use handle to protect asyncContext
363 std::shared_ptr<RequestGlobalSwitchAsyncContext> asyncContext =
364 std::make_shared<RequestGlobalSwitchAsyncContext>(env);
365
366 if (!ParseRequestGlobalSwitch(env, info, asyncContext)) {
367 return nullptr;
368 }
369 auto asyncContextHandle = std::make_unique<RequestGlobalSwitchAsyncContextHandle>(asyncContext);
370 napi_value result = nullptr;
371 if (asyncContextHandle->asyncContextPtr->callbackRef == nullptr) {
372 NAPI_CALL(env, napi_create_promise(env, &(asyncContextHandle->asyncContextPtr->deferred), &result));
373 } else {
374 NAPI_CALL(env, napi_get_undefined(env, &result));
375 }
376
377 napi_value resource = nullptr; // resource name
378 NAPI_CALL(env, napi_create_string_utf8(env, "RequestGlobalSwitch", NAPI_AUTO_LENGTH, &resource));
379 NAPI_CALL(env, napi_create_async_work(
380 env, nullptr, resource, RequestGlobalSwitchExecute, RequestGlobalSwitchComplete,
381 reinterpret_cast<void *>(asyncContextHandle.get()), &(asyncContextHandle->asyncContextPtr->work)));
382
383 NAPI_CALL(env,
384 napi_queue_async_work_with_qos(env, asyncContextHandle->asyncContextPtr->work, napi_qos_user_initiated));
385
386 LOGD(ATM_DOMAIN, ATM_TAG, "RequestGlobalSwitch end.");
387 asyncContextHandle.release();
388 return result;
389 }
390
ParseRequestGlobalSwitch(const napi_env & env,const napi_callback_info & cbInfo,std::shared_ptr<RequestGlobalSwitchAsyncContext> & asyncContext)391 bool NapiRequestGlobalSwitch::ParseRequestGlobalSwitch(const napi_env& env,
392 const napi_callback_info& cbInfo, std::shared_ptr<RequestGlobalSwitchAsyncContext>& asyncContext)
393 {
394 size_t argc = NapiContextCommon::MAX_PARAMS_TWO;
395 napi_value argv[NapiContextCommon::MAX_PARAMS_TWO] = { nullptr };
396 napi_value thisVar = nullptr;
397
398 if (napi_get_cb_info(env, cbInfo, &argc, argv, &thisVar, nullptr) != napi_ok) {
399 LOGE(ATM_DOMAIN, ATM_TAG, "Napi_get_cb_info failed");
400 return false;
401 }
402 if (argc < NapiContextCommon::MAX_PARAMS_TWO - 1) {
403 NAPI_CALL_BASE(env, napi_throw(env, GenerateBusinessError(env,
404 JsErrorCode::JS_ERROR_PARAM_ILLEGAL, "Parameter is missing.")), false);
405 return false;
406 }
407 asyncContext->env = env;
408 std::string errMsg;
409
410 // argv[0] : context : AbilityContext
411 if (GetContext(env, argv[0], asyncContext) == nullptr) {
412 errMsg = GetParamErrorMsg("context", "UIAbility or UIExtension Context");
413 NAPI_CALL_BASE(
414 env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
415 return false;
416 }
417 LOGI(ATM_DOMAIN, ATM_TAG, "AsyncContext.uiAbilityFlag is: %{public}d.", asyncContext->uiAbilityFlag);
418
419 // argv[1] : type
420 if (!ParseInt32(env, argv[1], asyncContext->switchType)) {
421 errMsg = GetParamErrorMsg("type", "SwitchType");
422 NAPI_CALL_BASE(
423 env, napi_throw(env, GenerateBusinessError(env, JsErrorCode::JS_ERROR_PARAM_ILLEGAL, errMsg)), false);
424 return false;
425 }
426 #ifdef EVENTHANDLER_ENABLE
427 asyncContext->handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
428 #endif
429 return true;
430 }
431
RequestGlobalSwitchExecute(napi_env env,void * data)432 void NapiRequestGlobalSwitch::RequestGlobalSwitchExecute(napi_env env, void* data)
433 {
434 // asyncContext release in complete
435 RequestGlobalSwitchAsyncContextHandle* asyncContextHandle =
436 reinterpret_cast<RequestGlobalSwitchAsyncContextHandle*>(data);
437 if ((asyncContextHandle == nullptr) || (asyncContextHandle->asyncContextPtr == nullptr)) {
438 return;
439 }
440 if (asyncContextHandle->asyncContextPtr->uiAbilityFlag) {
441 if ((asyncContextHandle->asyncContextPtr->abilityContext == nullptr) ||
442 (asyncContextHandle->asyncContextPtr->abilityContext->GetApplicationInfo() == nullptr)) {
443 return;
444 }
445 asyncContextHandle->asyncContextPtr->tokenId =
446 asyncContextHandle->asyncContextPtr->abilityContext->GetApplicationInfo()->accessTokenId;
447 } else {
448 if ((asyncContextHandle->asyncContextPtr->uiExtensionContext == nullptr) ||
449 (asyncContextHandle->asyncContextPtr->uiExtensionContext->GetApplicationInfo() == nullptr)) {
450 return;
451 }
452 asyncContextHandle->asyncContextPtr->tokenId =
453 asyncContextHandle->asyncContextPtr->uiExtensionContext->GetApplicationInfo()->accessTokenId;
454 }
455 static AccessTokenID currToken = static_cast<AccessTokenID>(GetSelfTokenID());
456 if (asyncContextHandle->asyncContextPtr->tokenId != currToken) {
457 LOGE(ATM_DOMAIN, ATM_TAG,
458 "The context(token=%{public}d) is not belong to the current application(currToken=%{public}d).",
459 asyncContextHandle->asyncContextPtr->tokenId, currToken);
460 asyncContextHandle->asyncContextPtr->result = ERR_PARAM_INVALID;
461 return;
462 }
463
464 LOGI(ATM_DOMAIN, ATM_TAG, "Start to pop ui extension dialog");
465 StartUIExtension(asyncContextHandle->asyncContextPtr);
466 if (asyncContextHandle->asyncContextPtr->result != JsErrorCode::JS_OK) {
467 LOGW(ATM_DOMAIN, ATM_TAG, "Failed to pop uiextension dialog.");
468 }
469 }
470
RequestGlobalSwitchComplete(napi_env env,napi_status status,void * data)471 void NapiRequestGlobalSwitch::RequestGlobalSwitchComplete(napi_env env, napi_status status, void* data)
472 {
473 LOGD(ATM_DOMAIN, ATM_TAG, "RequestGlobalSwitchComplete begin.");
474 RequestGlobalSwitchAsyncContextHandle* asyncContextHandle =
475 reinterpret_cast<RequestGlobalSwitchAsyncContextHandle*>(data);
476 if (asyncContextHandle == nullptr || asyncContextHandle->asyncContextPtr == nullptr) {
477 return;
478 }
479 std::unique_ptr<RequestGlobalSwitchAsyncContextHandle> callbackPtr {asyncContextHandle};
480
481 // need pop dialog
482 if (asyncContextHandle->asyncContextPtr->result == RET_SUCCESS) {
483 return;
484 }
485 // return error
486 if (asyncContextHandle->asyncContextPtr->deferred != nullptr) {
487 int32_t jsCode = NapiContextCommon::GetJsErrorCode(asyncContextHandle->asyncContextPtr->result);
488 napi_value businessError = GenerateBusinessError(env, jsCode, GetErrorMessage(jsCode));
489 NAPI_CALL_RETURN_VOID(env,
490 napi_reject_deferred(env, asyncContextHandle->asyncContextPtr->deferred, businessError));
491 }
492 }
493 } // namespace AccessToken
494 } // namespace Security
495 } // namespace OHOS