• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "napi_request_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