• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 
16 #include "napi_enable_notification.h"
17 
18 #include "napi_base_context.h"
19 
20 #include "ans_dialog_host_client.h"
21 #include "ans_inner_errors.h"
22 #include "enable_notification.h"
23 #include "js_ans_dialog_callback.h"
24 #include "common_event_manager.h"
25 
26 namespace OHOS {
27 namespace NotificationNapi {
28 const int IS_NOTIFICATION_ENABLE_MAX_PARA = 2;
AsyncCompleteCallbackNapiEnableNotification(napi_env env,napi_status status,void * data)29 void AsyncCompleteCallbackNapiEnableNotification(napi_env env, napi_status status, void *data)
30 {
31     ANS_LOGD("enter");
32     if (!data) {
33         ANS_LOGE("Invalid async callback data");
34         return;
35     }
36     AsyncCallbackInfoEnable *asynccallbackinfo = static_cast<AsyncCallbackInfoEnable *>(data);
37     if (asynccallbackinfo) {
38         Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env));
39         if (asynccallbackinfo->info.callback != nullptr) {
40             ANS_LOGD("Delete napiEnableNotification callback reference.");
41             napi_delete_reference(env, asynccallbackinfo->info.callback);
42         }
43         napi_delete_async_work(env, asynccallbackinfo->asyncWork);
44         delete asynccallbackinfo;
45         asynccallbackinfo = nullptr;
46     }
47 }
48 
NapiEnableNotification(napi_env env,napi_callback_info info)49 napi_value NapiEnableNotification(napi_env env, napi_callback_info info)
50 {
51     ANS_LOGD("enter");
52     EnableParams params {};
53     if (ParseParameters(env, info, params) == nullptr) {
54         Common::NapiThrow(env, ERROR_PARAM_INVALID);
55         return Common::NapiGetUndefined(env);
56     }
57 
58     AsyncCallbackInfoEnable *asynccallbackinfo =
59         new (std::nothrow) AsyncCallbackInfoEnable {.env = env, .asyncWork = nullptr, .params = params};
60     if (!asynccallbackinfo) {
61         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
62         return Common::JSParaError(env, params.callback);
63     }
64     napi_value promise = nullptr;
65     Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
66 
67     napi_value resourceName = nullptr;
68     napi_create_string_latin1(env, "enableNotification", NAPI_AUTO_LENGTH, &resourceName);
69     // Asynchronous function call
70     napi_create_async_work(env,
71         nullptr,
72         resourceName,
73         [](napi_env env, void *data) {
74             ANS_LOGD("NapiEnableNotification work excute.");
75             AsyncCallbackInfoEnable *asynccallbackinfo = static_cast<AsyncCallbackInfoEnable *>(data);
76             if (asynccallbackinfo) {
77                 std::string deviceId {""};
78                 asynccallbackinfo->info.errorCode = NotificationHelper::SetNotificationsEnabledForSpecifiedBundle(
79                     asynccallbackinfo->params.option, deviceId, asynccallbackinfo->params.enable);
80                 ANS_LOGI("asynccallbackinfo->info.errorCode = %{public}d", asynccallbackinfo->info.errorCode);
81             }
82         },
83         AsyncCompleteCallbackNapiEnableNotification,
84         (void *)asynccallbackinfo,
85         &asynccallbackinfo->asyncWork);
86 
87     bool isCallback = asynccallbackinfo->info.isCallback;
88     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
89 
90     if (isCallback) {
91         ANS_LOGD("napiEnableNotification callback is nullptr.");
92         return Common::NapiGetNull(env);
93     } else {
94         return promise;
95     }
96 }
97 
AsyncCompleteCallbackNapiIsNotificationEnabled(napi_env env,napi_status status,void * data)98 void AsyncCompleteCallbackNapiIsNotificationEnabled(napi_env env, napi_status status, void *data)
99 {
100     ANS_LOGD("enter");
101     if (!data) {
102         ANS_LOGE("Invalid async callback data");
103         return;
104     }
105     AsyncCallbackInfoIsEnable *asynccallbackinfo = static_cast<AsyncCallbackInfoIsEnable *>(data);
106     if (asynccallbackinfo) {
107         napi_value result = nullptr;
108         napi_get_boolean(env, asynccallbackinfo->allowed, &result);
109         Common::CreateReturnValue(env, asynccallbackinfo->info, result);
110         if (asynccallbackinfo->info.callback != nullptr) {
111             napi_delete_reference(env, asynccallbackinfo->info.callback);
112         }
113         napi_delete_async_work(env, asynccallbackinfo->asyncWork);
114         delete asynccallbackinfo;
115         asynccallbackinfo = nullptr;
116     }
117 }
118 
NapiIsNotificationEnabled(napi_env env,napi_callback_info info)119 __attribute__((no_sanitize("cfi"))) napi_value NapiIsNotificationEnabled(napi_env env, napi_callback_info info)
120 {
121     ANS_LOGD("enter");
122     IsEnableParams params {};
123     if (ParseParameters(env, info, params) == nullptr) {
124         ANS_LOGD("ParseParameters is nullptr.");
125         Common::NapiThrow(env, ERROR_PARAM_INVALID);
126         return Common::NapiGetUndefined(env);
127     }
128 
129     AsyncCallbackInfoIsEnable *asynccallbackinfo =
130         new (std::nothrow) AsyncCallbackInfoIsEnable {.env = env, .asyncWork = nullptr, .params = params};
131     if (!asynccallbackinfo) {
132         ANS_LOGD("Asynccallbackinfo is nullptr.");
133         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
134         return Common::JSParaError(env, params.callback);
135     }
136     napi_value promise = nullptr;
137     Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
138 
139     napi_value resourceName = nullptr;
140     napi_create_string_latin1(env, "isNotificationEnabled", NAPI_AUTO_LENGTH, &resourceName);
141     // Asynchronous function call
142     napi_create_async_work(env,
143         nullptr,
144         resourceName,
145         [](napi_env env, void *data) {
146             ANS_LOGD("NapiIsNotificationEnabled work excute.");
147             AsyncCallbackInfoIsEnable *asynccallbackinfo = static_cast<AsyncCallbackInfoIsEnable *>(data);
148             if (asynccallbackinfo) {
149                 if (asynccallbackinfo->params.hasBundleOption) {
150                     ANS_LOGI("option.bundle : %{public}s option.uid : %{public}d",
151                         asynccallbackinfo->params.option.GetBundleName().c_str(),
152                         asynccallbackinfo->params.option.GetUid());
153                     asynccallbackinfo->info.errorCode = NotificationHelper::IsAllowedNotify(
154                         asynccallbackinfo->params.option, asynccallbackinfo->allowed);
155                 } else if (asynccallbackinfo->params.hasUserId) {
156                     ANS_LOGI("userId : %{public}d", asynccallbackinfo->params.userId);
157                     asynccallbackinfo->info.errorCode = NotificationHelper::IsAllowedNotify(
158                         asynccallbackinfo->params.userId, asynccallbackinfo->allowed);
159                 } else {
160                     asynccallbackinfo->info.errorCode = NotificationHelper::IsAllowedNotifySelf(
161                         asynccallbackinfo->allowed);
162                 }
163                 ANS_LOGI("asynccallbackinfo->info.errorCode : %{public}d, allowed : %{public}d",
164                     asynccallbackinfo->info.errorCode, asynccallbackinfo->allowed);
165             }
166         },
167         AsyncCompleteCallbackNapiIsNotificationEnabled,
168         (void *)asynccallbackinfo,
169         &asynccallbackinfo->asyncWork);
170 
171     bool isCallback = asynccallbackinfo->info.isCallback;
172     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
173 
174     if (isCallback) {
175         ANS_LOGD("napiIsNotificationEnabled callback is nullptr.");
176         return Common::NapiGetNull(env);
177     } else {
178         return promise;
179     }
180 }
181 
NapiIsNotificationEnabledSelf(napi_env env,napi_callback_info info)182 napi_value NapiIsNotificationEnabledSelf(napi_env env, napi_callback_info info)
183 {
184     ANS_LOGD("enter");
185     IsEnableParams params {};
186     if (ParseParameters(env, info, params) == nullptr) {
187         Common::NapiThrow(env, ERROR_PARAM_INVALID);
188         return Common::NapiGetUndefined(env);
189     }
190 
191     AsyncCallbackInfoIsEnable *asynccallbackinfo =
192         new (std::nothrow) AsyncCallbackInfoIsEnable {.env = env, .asyncWork = nullptr, .params = params};
193     if (!asynccallbackinfo) {
194         ANS_LOGD("Asynccallbackinfo is null.");
195         return Common::JSParaError(env, params.callback);
196     }
197     napi_value promise = nullptr;
198     Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
199 
200     napi_value resourceName = nullptr;
201     napi_create_string_latin1(env, "IsNotificationEnabledSelf", NAPI_AUTO_LENGTH, &resourceName);
202     // Asynchronous function call
203     napi_create_async_work(env,
204         nullptr,
205         resourceName,
206         [](napi_env env, void *data) {
207             ANS_LOGD("NapiIsNotificationEnabledSelf work excute.");
208             AsyncCallbackInfoIsEnable *asynccallbackinfo = static_cast<AsyncCallbackInfoIsEnable *>(data);
209             if (asynccallbackinfo) {
210                 if (asynccallbackinfo->params.hasBundleOption) {
211                     ANS_LOGE("Not allowed to query another application");
212                 } else {
213                     asynccallbackinfo->info.errorCode =
214                         NotificationHelper::IsAllowedNotifySelf(asynccallbackinfo->allowed);
215                 }
216                 ANS_LOGD("asynccallbackinfo->info.errorCode = %{public}d, allowed = %{public}d",
217                     asynccallbackinfo->info.errorCode, asynccallbackinfo->allowed);
218             }
219         },
220         AsyncCompleteCallbackNapiIsNotificationEnabled,
221         (void *)asynccallbackinfo,
222         &asynccallbackinfo->asyncWork);
223 
224     bool isCallback = asynccallbackinfo->info.isCallback;
225     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
226 
227     if (isCallback) {
228         ANS_LOGD("napiIsNotificationEnabledSelf callback is nullptr.");
229         return Common::NapiGetNull(env);
230     } else {
231         return promise;
232     }
233 }
234 
NapiAsyncCompleteCallbackRequestEnableNotification(napi_env env,void * data)235 void NapiAsyncCompleteCallbackRequestEnableNotification(napi_env env, void *data)
236 {
237     ANS_LOGD("enter");
238     if (data == nullptr) {
239         ANS_LOGE("Invalid async callback data.");
240         return;
241     }
242     auto* asynccallbackinfo = static_cast<AsyncCallbackInfoIsEnable*>(data);
243     napi_value result = nullptr;
244     napi_get_undefined(env, &result);
245     Common::CreateReturnValue(env, asynccallbackinfo->info, result);
246     if (asynccallbackinfo->info.callback != nullptr) {
247         napi_delete_reference(env, asynccallbackinfo->info.callback);
248     }
249     napi_delete_async_work(env, asynccallbackinfo->asyncWork);
250     delete asynccallbackinfo;
251 }
252 
NapiRequestEnableNotification(napi_env env,napi_callback_info info)253 napi_value NapiRequestEnableNotification(napi_env env, napi_callback_info info)
254 {
255     ANS_LOGI("NapiRequestEnableNotification enter");
256     IsEnableParams params {};
257     if (ParseRequestEnableParameters(env, info, params) == nullptr) {
258         Common::NapiThrow(env, ERROR_PARAM_INVALID);
259         return Common::NapiGetUndefined(env);
260     }
261 
262     AsyncCallbackInfoIsEnable *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoIsEnable {
263             .env = env, .params = params, .newInterface = true};
264     if (!asynccallbackinfo) {
265         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
266         return Common::JSParaError(env, params.callback);
267     }
268     napi_value promise = nullptr;
269     Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
270 
271     napi_value resourceName = nullptr;
272     napi_create_string_latin1(env, "RequestEnableNotification", NAPI_AUTO_LENGTH, &resourceName);
273 
274     auto ipcCall = [](napi_env env, void* data) {
275         ANS_LOGD("enter");
276         if (data == nullptr) {
277             ANS_LOGE("data is invalid");
278             return;
279         }
280         auto* asynccallbackinfo = static_cast<AsyncCallbackInfoIsEnable*>(data);
281         sptr<AnsDialogHostClient> client = nullptr;
282         AnsDialogHostClient::CreateIfNullptr(client);
283         if (client == nullptr) {
284             ANS_LOGE("create client fail");
285             asynccallbackinfo->info.errorCode = ERROR_INTERNAL_ERROR;
286             return;
287         }
288 
289         if (asynccallbackinfo->params.context != nullptr) {
290             ANS_LOGD("stage mode");
291             bool canPop = false;
292             std::string bundleName {""};
293             ErrCode errCode = NotificationHelper::CanPopEnableNotificationDialog(client, canPop, bundleName);
294             ANS_LOGI("CanPopEnableNotificationDialog  result , errCode = %{public}d , canPop = %{public}d",
295                 errCode, canPop);
296             if (canPop == false) {
297                 asynccallbackinfo->info.errorCode = errCode;
298                 return;
299             }
300             asynccallbackinfo->bundleName = bundleName;
301         } else {
302             ANS_LOGD("un stage mode");
303             std::string deviceId {""};
304             asynccallbackinfo->info.errorCode =
305             NotificationHelper::RequestEnableNotification(deviceId, client,
306                 asynccallbackinfo->params.callerToken);
307         }
308         ANS_LOGI("done, code is %{public}d.", asynccallbackinfo->info.errorCode);
309     };
310     auto jsCb = [](napi_env env, napi_status status, void* data) {
311         ANS_LOGD("enter");
312         if (data == nullptr) {
313             ANS_LOGE("data is nullptr");
314             return;
315         }
316         auto* asynccallbackinfo = static_cast<AsyncCallbackInfoIsEnable*>(data);
317         if (!asynccallbackinfo->bundleName.empty()) {
318             bool success = CreateUIExtension(asynccallbackinfo->params.context, asynccallbackinfo->bundleName);
319             if (success) {
320                 asynccallbackinfo->info.errorCode = ERR_ANS_DIALOG_POP_SUCCEEDED;
321             } else {
322                 asynccallbackinfo->info.errorCode = ERROR_INTERNAL_ERROR;
323                 NotificationHelper::RemoveEnableNotificationDialog();
324             }
325         }
326         ErrCode errCode = asynccallbackinfo->info.errorCode;
327         if (errCode != ERR_ANS_DIALOG_POP_SUCCEEDED) {
328             ANS_LOGE("error, code is %{public}d.", errCode);
329             NapiAsyncCompleteCallbackRequestEnableNotification(env, static_cast<void*>(asynccallbackinfo));
330             return;
331         }
332         // Dialog is popped
333         auto jsCallback = std::make_unique<JsAnsDialogCallback>();
334         if (!jsCallback->Init(env, asynccallbackinfo, NapiAsyncCompleteCallbackRequestEnableNotification) ||
335             !AnsDialogHostClient::SetDialogCallbackInterface(std::move(jsCallback))
336         ) {
337             ANS_LOGE("error");
338             asynccallbackinfo->info.errorCode = ERROR_INTERNAL_ERROR;
339             NapiAsyncCompleteCallbackRequestEnableNotification(env, static_cast<void*>(asynccallbackinfo));
340             return;
341         }
342     };
343 
344     // Asynchronous function call
345     napi_create_async_work(env,
346         nullptr,
347         resourceName,
348         ipcCall,
349         jsCb,
350         static_cast<void*>(asynccallbackinfo),
351         &asynccallbackinfo->asyncWork);
352 
353     bool isCallback = asynccallbackinfo->info.isCallback;
354     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
355 
356     if (isCallback) {
357         ANS_LOGD("napiRequestEnableNotification callback is nullptr.");
358         return Common::NapiGetNull(env);
359     } else {
360         return promise;
361     }
362 }
363 
ParseRequestEnableParameters(const napi_env & env,const napi_callback_info & info,IsEnableParams & params)364 napi_value ParseRequestEnableParameters(const napi_env &env, const napi_callback_info &info, IsEnableParams &params)
365 {
366     ANS_LOGD("enter");
367 
368     size_t argc = IS_NOTIFICATION_ENABLE_MAX_PARA;
369     napi_value argv[IS_NOTIFICATION_ENABLE_MAX_PARA] = {nullptr};
370     napi_value thisVar = nullptr;
371     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
372 
373     if (argc == 0) {
374         return Common::NapiGetNull(env);
375     }
376 
377     // argv[0]: context / callback
378     napi_valuetype valuetype = napi_undefined;
379     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
380     if ((valuetype != napi_object) && (valuetype != napi_function)) {
381         ANS_LOGW("Wrong argument type. Function or object expected. Excute promise.");
382         return Common::NapiGetNull(env);
383     }
384     if (valuetype == napi_object) {
385         bool stageMode = false;
386         napi_status status = OHOS::AbilityRuntime::IsStageContext(env, argv[PARAM0], stageMode);
387         if (status == napi_ok && stageMode) {
388             SetEnableParam(params, env, argv[PARAM0]);
389         } else {
390             ANS_LOGE("Only support stage mode");
391             std::string msg = "Incorrect parameter types.Only support stage mode.";
392             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
393             return nullptr;
394         }
395     } else {
396         napi_create_reference(env, argv[PARAM0], 1, &params.callback);
397     }
398     // argv[1]:context
399     if (argc >= IS_NOTIFICATION_ENABLE_MAX_PARA && valuetype == napi_object) {
400         NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
401         if (valuetype != napi_function) {
402             ANS_LOGW("Callback is not function excute promise.");
403             return Common::NapiGetNull(env);
404         }
405         napi_create_reference(env, argv[PARAM1], 1, &params.callback);
406     }
407 
408     return Common::NapiGetNull(env);
409 }
410 
AsyncCompleteCallbackNapiGetAllNotificationEnableStatus(napi_env env,napi_status status,void * data)411 void AsyncCompleteCallbackNapiGetAllNotificationEnableStatus(napi_env env, napi_status status, void *data)
412 {
413     ANS_LOGD("Called.");
414     if (!data) {
415         ANS_LOGE("Invalid async callback data");
416         return;
417     }
418     napi_value result = nullptr;
419     AsyncCallbackInfoEnableStatus *asynccallbackinfo = static_cast<AsyncCallbackInfoEnableStatus *>(data);
420     if (asynccallbackinfo == nullptr) {
421         ANS_LOGE("asynccallbackinfo is nullptr");
422         return;
423     }
424     if (asynccallbackinfo->info.errorCode != ERR_OK) {
425         result = Common::NapiGetNull(env);
426     }
427     napi_value arr = nullptr;
428     napi_create_array(env, &arr);
429     size_t count = 0;
430     for (auto vec : asynccallbackinfo->bundleOptionVector) {
431         napi_value nSlot = nullptr;
432         napi_create_object(env, &nSlot);
433         Common::SetNotificationEnableStatus(env, vec, nSlot);
434         napi_set_element(env, arr, count, nSlot);
435         count++;
436     }
437     result = arr;
438     Common::CreateReturnValue(env, asynccallbackinfo->info, result);
439     if (asynccallbackinfo->info.callback != nullptr) {
440         ANS_LOGD("Delete napiGetSlots callback reference.");
441         napi_delete_reference(env, asynccallbackinfo->info.callback);
442     }
443     napi_delete_async_work(env, asynccallbackinfo->asyncWork);
444     delete asynccallbackinfo;
445     asynccallbackinfo = nullptr;
446 }
447 
NapiGetAllNotificationEnabledBundles(napi_env env,napi_callback_info info)448 napi_value NapiGetAllNotificationEnabledBundles(napi_env env, napi_callback_info info)
449 {
450     ANS_LOGD("Called");
451     napi_ref callback = nullptr;
452     AsyncCallbackInfoEnableStatus *asynccallbackinfo =
453         new (std::nothrow) AsyncCallbackInfoEnableStatus{ .env = env, .asyncWork = nullptr };
454     if (asynccallbackinfo == nullptr) {
455         ANS_LOGE("asynccallbackinfo is nullptr");
456         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
457         return Common::NapiGetUndefined(env);
458     }
459     napi_value promise = nullptr;
460     Common::PaddingCallbackPromiseInfo(env, callback, asynccallbackinfo->info, promise);
461     napi_value resourceName = nullptr;
462     napi_create_string_latin1(env, "getAllNotificationEnabledBundles", NAPI_AUTO_LENGTH, &resourceName);
463     napi_create_async_work(
464         env, nullptr, resourceName,
465         [](napi_env env, void *data) {
466             AsyncCallbackInfoEnableStatus *asynccallbackinfo = static_cast<AsyncCallbackInfoEnableStatus *>(data);
467             if (asynccallbackinfo != nullptr) {
468                 asynccallbackinfo->info.errorCode =
469                     NotificationHelper::GetAllNotificationEnabledBundles(asynccallbackinfo->bundleOptionVector);
470                 ANS_LOGD("asynccallbackinfo->info.errorCode = %{public}d", asynccallbackinfo->info.errorCode);
471             }
472         },
473         AsyncCompleteCallbackNapiGetAllNotificationEnableStatus, (void *)asynccallbackinfo,
474         &asynccallbackinfo->asyncWork);
475     bool isCallback = asynccallbackinfo->info.isCallback;
476     napi_status status = napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
477     if (status != napi_ok) {
478         asynccallbackinfo->info.errorCode = ERROR_INTERNAL_ERROR;
479         Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env));
480         if (asynccallbackinfo->info.callback != nullptr) {
481             ANS_LOGD("Delete callback reference.");
482             napi_delete_reference(env, asynccallbackinfo->info.callback);
483         }
484         napi_delete_async_work(env, asynccallbackinfo->asyncWork);
485         delete asynccallbackinfo;
486         asynccallbackinfo = nullptr;
487     }
488 
489     if (isCallback) {
490         ANS_LOGD("Callback is nullptr.");
491         return Common::NapiGetNull(env);
492     } else {
493         return promise;
494     }
495 }
496 
NapiIsNotificationEnabledSync(napi_env env,napi_callback_info info)497 napi_value NapiIsNotificationEnabledSync(napi_env env, napi_callback_info info)
498 {
499     ANS_LOGD("enter");
500     IsEnableParams params {};
501     if (ParseParameters(env, info, params) == nullptr) {
502         ANS_LOGD("ParseParameters is nullptr.");
503         Common::NapiThrow(env, ERROR_PARAM_INVALID);
504         return Common::NapiGetUndefined(env);
505     }
506 
507     bool allowed = false;
508     NotificationHelper::IsAllowedNotifySelf(allowed);
509     napi_value result = nullptr;
510     napi_get_boolean(env, allowed, &result);
511     return result;
512 }
513 
CreateUIExtension(std::shared_ptr<OHOS::AbilityRuntime::Context> context,std::string & bundleName)514 bool CreateUIExtension(std::shared_ptr<OHOS::AbilityRuntime::Context> context, std::string &bundleName)
515 {
516     if (context == nullptr) {
517         ANS_LOGE("Get context failed");
518         return false;
519     }
520 
521     std::shared_ptr<OHOS::AbilityRuntime::AbilityContext> abilityContext =
522         OHOS::AbilityRuntime::Context::ConvertTo<OHOS::AbilityRuntime::AbilityContext>(context);
523     if (abilityContext == nullptr) {
524         ANS_LOGE("abilityContext is null");
525         return false;
526     }
527     auto uiContent = abilityContext->GetUIContent();
528     if (uiContent == nullptr) {
529         ANS_LOGE("uiContent is null");
530         return false;
531     }
532 
533     AAFwk::Want want;
534     std::string targetBundleName = "com.ohos.notificationdialog";
535     std::string targetAbilityName = "EnableNotificationDialog";
536     want.SetElementName(targetBundleName, targetAbilityName);
537 
538     std::string typeKey = "ability.want.params.uiExtensionType";
539     std::string typeValue = "sysDialog/common";
540     want.SetParam(typeKey, typeValue);
541 
542     auto uiExtCallback = std::make_shared<ModalExtensionCallback>();
543     uiExtCallback->SetAbilityContext(abilityContext);
544     uiExtCallback->SetBundleName(bundleName);
545     Ace::ModalUIExtensionCallbacks uiExtensionCallbacks = {
546         .onRelease = std::bind(&ModalExtensionCallback::OnRelease, uiExtCallback, std::placeholders::_1),
547         .onResult = std::bind(&ModalExtensionCallback::OnResult, uiExtCallback,
548             std::placeholders::_1, std::placeholders::_2),
549         .onReceive = std::bind(&ModalExtensionCallback::OnReceive, uiExtCallback, std::placeholders::_1),
550         .onError = std::bind(&ModalExtensionCallback::OnError, uiExtCallback,
551             std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
552         .onRemoteReady = std::bind(&ModalExtensionCallback::OnRemoteReady, uiExtCallback, std::placeholders::_1),
553         .onDestroy = std::bind(&ModalExtensionCallback::OnDestroy, uiExtCallback),
554     };
555 
556     Ace::ModalUIExtensionConfig config;
557     config.isProhibitBack = true;
558 
559     int32_t sessionId = uiContent->CreateModalUIExtension(want, uiExtensionCallbacks, config);
560     ANS_LOGI("Create end, sessionId: %{public}d", sessionId);
561     if (sessionId == 0) {
562         ANS_LOGE("Create component failed, sessionId is 0");
563         return false;
564     }
565     uiExtCallback->SetSessionId(sessionId);
566     return true;
567 }
568 
SetEnableParam(IsEnableParams & params,const napi_env & env,napi_value & object)569 void SetEnableParam(IsEnableParams &params, const napi_env &env, napi_value &object)
570 {
571     auto context = OHOS::AbilityRuntime::GetStageModeContext(env, object);
572     sptr<IRemoteObject> callerToken = nullptr;
573     if (context != nullptr) {
574         callerToken = context->GetToken();
575     }
576     params.context = context;
577     params.callerToken = callerToken;
578     params.hasCallerToken = true;
579 }
580 
ModalExtensionCallback()581 ModalExtensionCallback::ModalExtensionCallback()
582 {}
583 
~ModalExtensionCallback()584 ModalExtensionCallback::~ModalExtensionCallback()
585 {}
586 
587 
588 /*
589  * when UIExtensionAbility use terminateSelfWithResult
590  */
OnResult(int32_t resultCode,const AAFwk::Want & result)591 void ModalExtensionCallback::OnResult(int32_t resultCode, const AAFwk::Want& result)
592 {
593     ANS_LOGD("OnResult");
594 }
595 
596 /*
597  * when UIExtensionAbility send message to UIExtensionComponent
598  */
OnReceive(const AAFwk::WantParams & receive)599 void ModalExtensionCallback::OnReceive(const AAFwk::WantParams& receive)
600 {
601     ANS_LOGD("OnReceive");
602 }
603 
604 /*
605  * when UIExtensionAbility disconnect or use terminate or process die
606  * releaseCode is 0 when process normal exit
607  */
OnRelease(int32_t releaseCode)608 void ModalExtensionCallback::OnRelease(int32_t releaseCode)
609 {
610     ANS_LOGI("OnRelease");
611     ReleaseOrErrorHandle(releaseCode);
612 }
613 
614 /*
615  * when UIExtensionComponent init or turn to background or destroy UIExtensionAbility occur error
616  */
OnError(int32_t code,const std::string & name,const std::string & message)617 void ModalExtensionCallback::OnError(int32_t code, const std::string& name, const std::string& message)
618 {
619     ANS_LOGE("OnError, name = %{public}s, message = %{public}s", name.c_str(), message.c_str());
620     ReleaseOrErrorHandle(code);
621     NotificationHelper::RemoveEnableNotificationDialog();
622 }
623 
624 /*
625  * when UIExtensionComponent connect to UIExtensionAbility, ModalUIExtensionProxy will init,
626  * UIExtensionComponent can send message to UIExtensionAbility by ModalUIExtensionProxy
627  */
OnRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy> & uiProxy)628 void ModalExtensionCallback::OnRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy>& uiProxy)
629 {
630     ANS_LOGD("OnRemoteReady");
631 }
632 
633 /*
634  * when UIExtensionComponent destructed
635  */
OnDestroy()636 void ModalExtensionCallback::OnDestroy()
637 {
638     ANS_LOGD("OnDestroy");
639 }
640 
641 
SetSessionId(int32_t sessionId)642 void ModalExtensionCallback::SetSessionId(int32_t sessionId)
643 {
644     this->sessionId_ = sessionId;
645 }
646 
SetBundleName(std::string bundleName)647 void ModalExtensionCallback::SetBundleName(std::string bundleName)
648 {
649     this->bundleName_ = bundleName;
650 }
651 
SetAbilityContext(std::shared_ptr<OHOS::AbilityRuntime::AbilityContext> abilityContext)652 void ModalExtensionCallback::SetAbilityContext(std::shared_ptr<OHOS::AbilityRuntime::AbilityContext> abilityContext)
653 {
654     this->abilityContext_ = abilityContext;
655 }
656 
ReleaseOrErrorHandle(int32_t code)657 void ModalExtensionCallback::ReleaseOrErrorHandle(int32_t code)
658 {
659     ANS_LOGD("ReleaseOrErrorHandle start");
660     Ace::UIContent* uiContent = this->abilityContext_->GetUIContent();
661     if (uiContent == nullptr) {
662         ANS_LOGE("uiContent is null");
663         return;
664     }
665     uiContent->CloseModalUIExtension(this->sessionId_);
666     ANS_LOGD("ReleaseOrErrorHandle end");
667     return;
668 }
669 
670 }  // namespace NotificationNapi
671 }  // namespace OHOS
672