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 ¶ms)
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, ¶ms.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, ¶ms.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 ¶ms, 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