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