1 /*
2 * Copyright (c) 2021-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
16 #include "cancel.h"
17 #include "js_native_api_types.h"
18 #include "ans_inner_errors.h"
19
20 namespace OHOS {
21 namespace NotificationNapi {
22 constexpr int8_t CANCEL_MAX_PARA = 3;
23 constexpr int8_t CANCEL_GROUP_MAX_PARA = 2;
24 constexpr int8_t CANCEL_GROUP_MIN_PARA = 1;
25 constexpr int8_t CANCEL_AS_BUNDLE_MAX_PARA = 4;
26 constexpr int8_t CANCEL_AS_BUNDLEOPTION_MAX_PARA = 2;
27
ParseParameters(const napi_env & env,const napi_callback_info & info,ParametersInfoCancel & paras)28 napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, ParametersInfoCancel ¶s)
29 {
30 ANS_LOGD("enter");
31
32 size_t argc = CANCEL_MAX_PARA;
33 napi_value argv[CANCEL_MAX_PARA] = {nullptr};
34 napi_value thisVar = nullptr;
35 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
36 if (argc < 1) {
37 ANS_LOGW("Wrong number of arguments");
38 Common::NapiThrow(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED);
39 return nullptr;
40 }
41
42 napi_valuetype valuetype = napi_undefined;
43 // argv[0]: id: number / representativeBundle: BundleOption
44 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
45 if (valuetype != napi_number && valuetype != napi_object) {
46 ANS_LOGW("Wrong argument type. Number object expected.");
47 std::string msg = "Incorrect parameter types.The type of param must be number or object.";
48 Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
49 return nullptr;
50 }
51
52 if (valuetype == napi_number) {
53 NAPI_CALL(env, napi_get_value_int32(env, argv[PARAM0], ¶s.id));
54 } else {
55 auto retValue = Common::GetBundleOption(env, argv[PARAM0], paras.option);
56 if (retValue == nullptr) {
57 ANS_LOGE("GetBundleOption failed.");
58 Common::NapiThrow(env, ERROR_PARAM_INVALID, PARAMETER_VERIFICATION_FAILED);
59 return nullptr;
60 }
61 paras.hasOption = true;
62 }
63
64 // argv[1]: label: string / callback / id : number
65 if (argc >= CANCEL_MAX_PARA - 1 && !paras.hasOption) {
66 NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
67 if (valuetype == napi_undefined || valuetype == napi_null) {
68 return Common::NapiGetNull(env);
69 }
70 if (valuetype != napi_number && valuetype != napi_boolean &&
71 valuetype != napi_string && valuetype != napi_function) {
72 ANS_LOGW("Wrong argument type. String or function expected.");
73 std::string msg = "Incorrect parameter types.The type of param must be string or function.";
74 Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
75 return nullptr;
76 }
77 if (valuetype == napi_number) {
78 int64_t number = 0;
79 NAPI_CALL(env, napi_get_value_int64(env, argv[PARAM1], &number));
80 paras.label = std::to_string(number);
81 } else if (valuetype == napi_boolean) {
82 bool result = false;
83 NAPI_CALL(env, napi_get_value_bool(env, argv[PARAM1], &result));
84 paras.label = std::to_string(result);
85 } else if (valuetype == napi_string) {
86 char str[STR_MAX_SIZE] = {0};
87 size_t strLen = 0;
88 NAPI_CALL(env, napi_get_value_string_utf8(env, argv[PARAM1], str, STR_MAX_SIZE - 1, &strLen));
89 paras.label = str;
90 } else {
91 napi_create_reference(env, argv[PARAM1], 1, ¶s.callback);
92 }
93 } else if (argc >= CANCEL_MAX_PARA - 1 && paras.hasOption) {
94 NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
95 if (valuetype != napi_number) {
96 ANS_LOGW("Wrong argument type. Number expected.");
97 std::string msg = "Incorrect parameter types.The type of param must be number.";
98 Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
99 return nullptr;
100 }
101 NAPI_CALL(env, napi_get_value_int32(env, argv[PARAM1], ¶s.id));
102 }
103
104 // argv[2]: callback
105 if (argc >= CANCEL_MAX_PARA) {
106 NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valuetype));
107 if (valuetype != napi_function) {
108 ANS_LOGW("Callback is not function excute promise.");
109 return Common::NapiGetNull(env);
110 }
111 napi_create_reference(env, argv[PARAM2], 1, ¶s.callback);
112 }
113
114 return Common::NapiGetNull(env);
115 }
116
ParseParameters(const napi_env & env,const napi_callback_info & info,ParametersInfoCancelGroup & paras)117 napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, ParametersInfoCancelGroup ¶s)
118 {
119 ANS_LOGD("enter");
120
121 size_t argc = CANCEL_GROUP_MAX_PARA;
122 napi_value argv[CANCEL_GROUP_MAX_PARA] = {nullptr};
123 napi_value thisVar = nullptr;
124 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
125 if (argc < CANCEL_GROUP_MIN_PARA) {
126 ANS_LOGW("Wrong number of arguments");
127 Common::NapiThrow(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED);
128 return nullptr;
129 }
130
131 napi_valuetype valuetype = napi_undefined;
132 // argv[0]: groupName: string
133 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
134 if (valuetype != napi_string && valuetype != napi_number && valuetype != napi_boolean) {
135 ANS_LOGW("Wrong argument type. String number boolean expected.");
136 std::string msg = "Incorrect parameter types.The type of param must be number or string or boolean.";
137 Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
138 return nullptr;
139 }
140 if (valuetype == napi_string) {
141 char str[STR_MAX_SIZE] = {0};
142 size_t strLen = 0;
143 NAPI_CALL(env, napi_get_value_string_utf8(env, argv[PARAM0], str, STR_MAX_SIZE - 1, &strLen));
144 paras.groupName = str;
145 } else if (valuetype == napi_number) {
146 int64_t number = 0;
147 NAPI_CALL(env, napi_get_value_int64(env, argv[PARAM0], &number));
148 paras.groupName = std::to_string(number);
149 } else {
150 bool result = false;
151 NAPI_CALL(env, napi_get_value_bool(env, argv[PARAM0], &result));
152 paras.groupName = std::to_string(result);
153 }
154
155 // argv[1]: callback
156 if (argc >= CANCEL_GROUP_MAX_PARA) {
157 NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
158 if (valuetype != napi_function) {
159 ANS_LOGW("Callback is not function excute promise.");
160 return Common::NapiGetNull(env);
161 }
162 napi_create_reference(env, argv[PARAM1], 1, ¶s.callback);
163 }
164
165 return Common::NapiGetNull(env);
166 }
167
Cancel(napi_env env,napi_callback_info info)168 napi_value Cancel(napi_env env, napi_callback_info info)
169 {
170 ANS_LOGD("enter");
171
172 ParametersInfoCancel paras;
173 if (ParseParameters(env, info, paras) == nullptr) {
174 return Common::NapiGetUndefined(env);
175 }
176
177 AsyncCallbackInfoCancel *asynccallbackinfo = new (std::nothrow)
178 AsyncCallbackInfoCancel {.env = env, .asyncWork = nullptr, .id = paras.id, .label = paras.label};
179 if (!asynccallbackinfo) {
180 ANS_LOGD("AsyncCallbackinfo is nullptr.");
181 return Common::JSParaError(env, paras.callback);
182 }
183 napi_value promise = nullptr;
184 Common::PaddingCallbackPromiseInfo(env, paras.callback, asynccallbackinfo->info, promise);
185
186 ANS_LOGD("Create cancel string.");
187 napi_value resourceName = nullptr;
188 napi_create_string_latin1(env, "cancel", NAPI_AUTO_LENGTH, &resourceName);
189 // Async function call
190 napi_create_async_work(env,
191 nullptr,
192 resourceName,
193 [](napi_env env, void *data) {
194 ANS_LOGD("Cancel work excute.");
195 AsyncCallbackInfoCancel *asynccallbackinfo = static_cast<AsyncCallbackInfoCancel *>(data);
196
197 if (asynccallbackinfo) {
198 asynccallbackinfo->info.errorCode =
199 NotificationHelper::CancelNotification(asynccallbackinfo->label, asynccallbackinfo->id);
200 }
201 },
202 [](napi_env env, napi_status status, void *data) {
203 ANS_LOGD("Cancel work complete.");
204 AsyncCallbackInfoCancel *asynccallbackinfo = static_cast<AsyncCallbackInfoCancel *>(data);
205 if (asynccallbackinfo) {
206 Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
207 if (asynccallbackinfo->info.callback != nullptr) {
208 ANS_LOGD("Delete cancel callback reference.");
209 napi_delete_reference(env, asynccallbackinfo->info.callback);
210 }
211 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
212 delete asynccallbackinfo;
213 asynccallbackinfo = nullptr;
214 }
215 ANS_LOGD("Cancel work complete end.");
216 },
217 (void *)asynccallbackinfo,
218 &asynccallbackinfo->asyncWork);
219
220 napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
221
222 if (asynccallbackinfo->info.isCallback) {
223 ANS_LOGD("cancel callback is nullptr.");
224 return Common::NapiGetNull(env);
225 } else {
226 return promise;
227 }
228 }
229
CancelAll(napi_env env,napi_callback_info info)230 napi_value CancelAll(napi_env env, napi_callback_info info)
231 {
232 ANS_LOGD("enter");
233
234 napi_ref callback = nullptr;
235 if (Common::ParseParaOnlyCallback(env, info, callback) == nullptr) {
236 return Common::NapiGetUndefined(env);
237 }
238
239 auto asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoCancel {.env = env, .asyncWork = nullptr};
240 if (!asynccallbackinfo) {
241 ANS_LOGD("Asynccallbackinfo is nullptr.");
242 return Common::JSParaError(env, callback);
243 }
244 napi_value promise = nullptr;
245 Common::PaddingCallbackPromiseInfo(env, callback, asynccallbackinfo->info, promise);
246
247 ANS_LOGD("Create cancelAll string.");
248 napi_value resourceName = nullptr;
249 napi_create_string_latin1(env, "cancelAll", NAPI_AUTO_LENGTH, &resourceName);
250 // Asynchronous function call
251 napi_create_async_work(env,
252 nullptr,
253 resourceName,
254 [](napi_env env, void *data) {
255 ANS_LOGD("CancelAll work excute.");
256 AsyncCallbackInfoCancel *asynccallbackinfo = static_cast<AsyncCallbackInfoCancel *>(data);
257 if (asynccallbackinfo) {
258 asynccallbackinfo->info.errorCode = NotificationHelper::CancelAllNotifications();
259 }
260 },
261 [](napi_env env, napi_status status, void *data) {
262 ANS_LOGD("CancelAll work complete.");
263 AsyncCallbackInfoCancel *asynccallbackinfo = static_cast<AsyncCallbackInfoCancel *>(data);
264 if (asynccallbackinfo) {
265 Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
266 if (asynccallbackinfo->info.callback != nullptr) {
267 ANS_LOGD("Delete CancelAll callback reference.");
268 napi_delete_reference(env, asynccallbackinfo->info.callback);
269 }
270 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
271 delete asynccallbackinfo;
272 asynccallbackinfo = nullptr;
273 }
274 ANS_LOGD("CancelAll work complete end.");
275 },
276 (void *)asynccallbackinfo,
277 &asynccallbackinfo->asyncWork);
278
279 napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
280
281 if (asynccallbackinfo->info.isCallback) {
282 ANS_LOGD("CancelAll callback is nullptr.");
283 return Common::NapiGetNull(env);
284 } else {
285 return promise;
286 }
287 }
288
CancelGroup(napi_env env,napi_callback_info info)289 napi_value CancelGroup(napi_env env, napi_callback_info info)
290 {
291 ANS_LOGD("enter");
292
293 ParametersInfoCancelGroup params {};
294 if (ParseParameters(env, info, params) == nullptr) {
295 return Common::NapiGetUndefined(env);
296 }
297
298 AsyncCallbackInfoCancelGroup *asynccallbackinfo = new (std::nothrow)
299 AsyncCallbackInfoCancelGroup {.env = env, .asyncWork = nullptr, .params = params};
300 if (!asynccallbackinfo) {
301 ANS_LOGD("Create asynccallbackinfo fail.");
302 return Common::JSParaError(env, params.callback);
303 }
304 napi_value promise = nullptr;
305 Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
306
307 ANS_LOGD("Create cancelGroup string.");
308 napi_value resourceName = nullptr;
309 napi_create_string_latin1(env, "cancelGroup", NAPI_AUTO_LENGTH, &resourceName);
310 // Asynchronous function call
311 napi_create_async_work(env,
312 nullptr,
313 resourceName,
314 [](napi_env env, void *data) {
315 ANS_LOGD("CancelGroup work excute.");
316 AsyncCallbackInfoCancelGroup *asynccallbackinfo = static_cast<AsyncCallbackInfoCancelGroup *>(data);
317 if (asynccallbackinfo) {
318 ANS_LOGI("asynccallbackinfo->params.groupName = %{public}s",
319 asynccallbackinfo->params.groupName.c_str());
320 asynccallbackinfo->info.errorCode =
321 NotificationHelper::CancelGroup(asynccallbackinfo->params.groupName);
322 }
323 },
324 [](napi_env env, napi_status status, void *data) {
325 ANS_LOGD("CancelGroup work complete.");
326 AsyncCallbackInfoCancelGroup *asynccallbackinfo = static_cast<AsyncCallbackInfoCancelGroup *>(data);
327 if (asynccallbackinfo) {
328 Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
329 if (asynccallbackinfo->info.callback != nullptr) {
330 ANS_LOGD("Delete CancelGroup callback reference.");
331 napi_delete_reference(env, asynccallbackinfo->info.callback);
332 }
333 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
334 delete asynccallbackinfo;
335 asynccallbackinfo = nullptr;
336 }
337 ANS_LOGD("CancelGroup work complete end.");
338 },
339 (void *)asynccallbackinfo,
340 &asynccallbackinfo->asyncWork);
341
342 napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
343
344 if (asynccallbackinfo->info.isCallback) {
345 ANS_LOGD("CancelGroup callback is nullptr.");
346 return Common::NapiGetNull(env);
347 } else {
348 return promise;
349 }
350 }
351
ParseParameters(const napi_env & env,const napi_callback_info & info,ParametersInfoCancelAsBundle & paras)352 napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, ParametersInfoCancelAsBundle ¶s)
353 {
354 ANS_LOGD("enter");
355
356 size_t argc = CANCEL_AS_BUNDLE_MAX_PARA;
357 napi_value argv[CANCEL_AS_BUNDLE_MAX_PARA] = {nullptr};
358 napi_value thisVar = nullptr;
359 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
360 if (argc < 1) {
361 ANS_LOGW("Wrong number of arguments");
362 Common::NapiThrow(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED);
363 return nullptr;
364 }
365
366 napi_valuetype valuetype = napi_undefined;
367 // argv[0]: id: number / bundleOption
368 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
369 if (valuetype != napi_number && valuetype != napi_object) {
370 ANS_LOGW("Wrong argument type. Number object expected.");
371 std::string msg = "Incorrect parameter types.The type of param must be number.";
372 Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
373 return nullptr;
374 }
375 if (argc > CANCEL_AS_BUNDLEOPTION_MAX_PARA) {
376 NAPI_CALL(env, napi_get_value_int32(env, argv[PARAM0], ¶s.id));
377 } else {
378 auto retValue = Common::GetBundleOption(env, argv[PARAM0], paras.option);
379 if (retValue == nullptr) {
380 ANS_LOGE("GetBundleOption failed.");
381 Common::NapiThrow(env, ERROR_PARAM_INVALID, PARAMETER_VERIFICATION_FAILED);
382 return nullptr;
383 }
384 paras.hasOption = true;
385 }
386 // argv[1]: representativeBundle: string / id
387 NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
388 if (valuetype != napi_string && valuetype != napi_number && valuetype != napi_boolean) {
389 ANS_LOGW("Wrong argument type. String number boolean expected.");
390 std::string msg = "Incorrect parameter types.The type of param must be number or string or boolean.";
391 Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
392 return nullptr;
393 }
394 if (argc > CANCEL_AS_BUNDLEOPTION_MAX_PARA) {
395 if (valuetype == napi_string) {
396 char str[STR_MAX_SIZE] = {0};
397 size_t strLen = 0;
398 napi_get_value_string_utf8(env, argv[PARAM1], str, STR_MAX_SIZE - 1, &strLen);
399 paras.representativeBundle = str;
400 } else if (valuetype == napi_number) {
401 int64_t number = 0;
402 NAPI_CALL(env, napi_get_value_int64(env, argv[PARAM1], &number));
403 paras.representativeBundle = std::to_string(number);
404 } else {
405 bool result = false;
406 NAPI_CALL(env, napi_get_value_bool(env, argv[PARAM1], &result));
407 paras.representativeBundle = std::to_string(result);
408 }
409 } else {
410 NAPI_CALL(env, napi_get_value_int32(env, argv[PARAM1], ¶s.id));
411 }
412
413 // argv[2] : userId
414 if (argc > CANCEL_AS_BUNDLEOPTION_MAX_PARA) {
415 NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valuetype));
416 if (valuetype != napi_number) {
417 ANS_LOGW("Wrong argument type. Number expected.");
418 std::string msg = "Incorrect parameter types.The type of param must be number.";
419 Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
420 return nullptr;
421 }
422 napi_get_value_int32(env, argv[PARAM2], ¶s.userId);
423 }
424 // argv[3]: callback
425 if (argc >= CANCEL_AS_BUNDLE_MAX_PARA) {
426 NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &valuetype));
427 if (valuetype != napi_function) {
428 ANS_LOGW("Callback is not function excute promise.");
429 return Common::NapiGetNull(env);
430 }
431 napi_create_reference(env, argv[PARAM3], 1, ¶s.callback);
432 }
433
434 return Common::NapiGetNull(env);
435 }
436
CancelAsBundle(napi_env env,napi_callback_info info)437 napi_value CancelAsBundle(napi_env env, napi_callback_info info)
438 {
439 ANS_LOGD("enter");
440
441 ParametersInfoCancelAsBundle paras;
442 if (ParseParameters(env, info, paras) == nullptr) {
443 return Common::NapiGetUndefined(env);
444 }
445
446 AsyncCallbackInfoCancelAsBundle *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoCancelAsBundle {
447 .env = env, .asyncWork = nullptr,
448 .id = paras.id,
449 .representativeBundle = paras.representativeBundle,
450 .userId = paras.userId
451 };
452 if (!asynccallbackinfo) {
453 ANS_LOGD("AsyncCallbackinfo is nullptr.");
454 return Common::JSParaError(env, paras.callback);
455 }
456 napi_value promise = nullptr;
457 Common::PaddingCallbackPromiseInfo(env, paras.callback, asynccallbackinfo->info, promise);
458
459 ANS_LOGD("Create cancelasbundle string.");
460 napi_value resourceName = nullptr;
461 napi_create_string_latin1(env, "cancelasbundle", NAPI_AUTO_LENGTH, &resourceName);
462 // Asynchronous function call
463 napi_create_async_work(env,
464 nullptr,
465 resourceName,
466 [](napi_env env, void *data) {
467 ANS_LOGD("CancelAsBundle work excute.");
468 AsyncCallbackInfoCancelAsBundle *asynccallbackinfo = static_cast<AsyncCallbackInfoCancelAsBundle *>(data);
469
470 if (asynccallbackinfo) {
471 asynccallbackinfo->info.errorCode = NotificationHelper::CancelAsBundle(
472 asynccallbackinfo->id, asynccallbackinfo->representativeBundle, asynccallbackinfo->userId);
473 }
474 },
475 [](napi_env env, napi_status status, void *data) {
476 ANS_LOGD("CancelAsBundle work complete");
477 AsyncCallbackInfoCancelAsBundle *asynccallbackinfo = static_cast<AsyncCallbackInfoCancelAsBundle *>(data);
478 if (asynccallbackinfo) {
479 Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
480 if (asynccallbackinfo->info.callback != nullptr) {
481 ANS_LOGD("Delete CancelAsBundle 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 ANS_LOGD("CancelAsBundle work complete end.");
489 },
490 (void *)asynccallbackinfo,
491 &asynccallbackinfo->asyncWork);
492
493 napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
494
495 if (asynccallbackinfo->info.isCallback) {
496 ANS_LOGD("CancelAsBundle callback is nullptr.");
497 return Common::NapiGetNull(env);
498 } else {
499 return promise;
500 }
501 }
502 } // namespace NotificationNapi
503 } // namespace OHOS
504