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