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