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