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