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 "display_badge.h"
17 #include "ans_inner_errors.h"
18 
19 namespace OHOS {
20 namespace NotificationNapi {
21 const int ENABLE_BADGE_DISPLAYED_MAX_PARA = 3;
22 const int ENABLE_BADGE_DISPLAYED_MIN_PARA = 2;
23 const int IS_DISPLAY_BADGE_MAX_PARA = 2;
24 const int IS_DISPLAY_BADGE_MIN_PARA = 1;
25 
ParseParameters(const napi_env & env,const napi_callback_info & info,EnableBadgeParams & params)26 napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, EnableBadgeParams &params)
27 {
28     ANS_LOGD("enter");
29 
30     size_t argc = ENABLE_BADGE_DISPLAYED_MAX_PARA;
31     napi_value argv[ENABLE_BADGE_DISPLAYED_MAX_PARA] = {nullptr};
32     napi_value thisVar = nullptr;
33     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
34     if (argc < ENABLE_BADGE_DISPLAYED_MIN_PARA) {
35         ANS_LOGW("Wrong number of arguments.");
36         Common::NapiThrow(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED);
37         return nullptr;
38     }
39 
40     // argv[0]: bundle
41     napi_valuetype valuetype = napi_undefined;
42     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
43     if (valuetype != napi_object) {
44         ANS_LOGW("Wrong argument type. Object expected");
45         std::string msg = "Incorrect parameter types.The type of param must be object.";
46         Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
47         return nullptr;
48     }
49 
50     auto retValue = Common::GetBundleOption(env, argv[PARAM0], params.option);
51     if (retValue == nullptr) {
52         ANS_LOGE("GetBundleOption failed");
53         Common::NapiThrow(env, ERROR_PARAM_INVALID, PARAMETER_VERIFICATION_FAILED);
54         return nullptr;
55     }
56 
57     // argv[1]: enable
58     NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
59     if (valuetype != napi_boolean) {
60         ANS_LOGW("Wrong argument type. Bool expected.");
61         std::string msg = "Incorrect parameter types.The type of param must be boolean.";
62         Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
63         return nullptr;
64     }
65     napi_get_value_bool(env, argv[PARAM1], &params.enable);
66 
67     // argv[2]:callback
68     if (argc >= ENABLE_BADGE_DISPLAYED_MAX_PARA) {
69         NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valuetype));
70         if (valuetype != napi_function) {
71             ANS_LOGW("Callback is not function excute promise.");
72             return Common::NapiGetNull(env);
73         }
74         napi_create_reference(env, argv[PARAM2], 1, &params.callback);
75     }
76 
77     return Common::NapiGetNull(env);
78 }
79 
ParseParameters(const napi_env & env,const napi_callback_info & info,IsDisplayBadgeParams & params)80 napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, IsDisplayBadgeParams &params)
81 {
82     ANS_LOGD("enter");
83 
84     size_t argc = IS_DISPLAY_BADGE_MAX_PARA;
85     napi_value argv[IS_DISPLAY_BADGE_MAX_PARA] = {nullptr};
86     napi_value thisVar = nullptr;
87     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
88 
89     if (argc < IS_DISPLAY_BADGE_MIN_PARA) {
90         ANS_LOGW("Wrong number of arguments.");
91         Common::NapiThrow(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED);
92         return nullptr;
93     }
94 
95     // argv[0]: bundle / callback
96     napi_valuetype valuetype = napi_undefined;
97     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
98 
99     if ((valuetype != napi_function) && (valuetype != napi_object)) {
100         ANS_LOGW("Wrong argument type. Function or object expected, %{public}d", valuetype);
101         std::string msg = "Incorrect parameter types.The type of param must be function or object.";
102         Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
103         return nullptr;
104     }
105 
106     if (valuetype == napi_object) {
107         auto retValue = Common::GetBundleOption(env, argv[PARAM0], params.option);
108         if (retValue == nullptr) {
109             ANS_LOGE("GetBundleOption failed.");
110             Common::NapiThrow(env, ERROR_PARAM_INVALID, PARAMETER_VERIFICATION_FAILED);
111             return nullptr;
112         }
113         params.hasBundleOption = true;
114     } else {
115         napi_create_reference(env, argv[PARAM0], 1, &params.callback);
116     }
117 
118     // argv[1]:callback
119     if (argc >= IS_DISPLAY_BADGE_MAX_PARA) {
120         NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
121         if (valuetype != napi_function) {
122             ANS_LOGW("Callback is not function excute promise.");
123             return Common::NapiGetNull(env);
124         }
125         napi_create_reference(env, argv[PARAM1], 1, &params.callback);
126     }
127 
128     return Common::NapiGetNull(env);
129 }
130 
DisplayBadge(napi_env env,napi_callback_info info)131 napi_value DisplayBadge(napi_env env, napi_callback_info info)
132 {
133     ANS_LOGD("enter");
134 
135     EnableBadgeParams params {};
136     if (ParseParameters(env, info, params) == nullptr) {
137         return Common::NapiGetUndefined(env);
138     }
139 
140     AsyncCallbackInfoEnableBadge *asynccallbackinfo =
141         new (std::nothrow) AsyncCallbackInfoEnableBadge {.env = env, .asyncWork = nullptr, .params = params};
142     if (!asynccallbackinfo) {
143         ANS_LOGD("Asynccallbackinfo is nullptr.");
144         return Common::JSParaError(env, params.callback);
145     }
146     napi_value promise = nullptr;
147     Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
148 
149     ANS_LOGD("Create DisplayBadge string.");
150     napi_value resourceName = nullptr;
151     napi_create_string_latin1(env, "DisplayBadge", NAPI_AUTO_LENGTH, &resourceName);
152     // Asynchronous function call
153     napi_create_async_work(env,
154         nullptr,
155         resourceName,
156         [](napi_env env, void *data) {
157             ANS_LOGD("DisplayBadge work excute.");
158             AsyncCallbackInfoEnableBadge *asynccallbackinfo = static_cast<AsyncCallbackInfoEnableBadge *>(data);
159             if (asynccallbackinfo) {
160                 ANS_LOGI("option.bundle : %{public}s option.uid : %{public}d enable = %{public}d",
161                     asynccallbackinfo->params.option.GetBundleName().c_str(),
162                     asynccallbackinfo->params.option.GetUid(),
163                     asynccallbackinfo->params.enable);
164                 asynccallbackinfo->info.errorCode = NotificationHelper::SetShowBadgeEnabledForBundle(
165                     asynccallbackinfo->params.option, asynccallbackinfo->params.enable);
166                 ANS_LOGI("asynccallbackinfo->info.errorCode : %{public}d", asynccallbackinfo->info.errorCode);
167             }
168         },
169         [](napi_env env, napi_status status, void *data) {
170             ANS_LOGD("DisplayBadge work complete.");
171             AsyncCallbackInfoEnableBadge *asynccallbackinfo = static_cast<AsyncCallbackInfoEnableBadge *>(data);
172             if (asynccallbackinfo) {
173                 Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
174                 if (asynccallbackinfo->info.callback != nullptr) {
175                     ANS_LOGD("Delete DisplayBadge callback reference.");
176                     napi_delete_reference(env, asynccallbackinfo->info.callback);
177                 }
178                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
179                 delete asynccallbackinfo;
180                 asynccallbackinfo = nullptr;
181             }
182             ANS_LOGD("DisplayBadge work complete end.");
183         },
184         (void *)asynccallbackinfo,
185         &asynccallbackinfo->asyncWork);
186 
187     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
188 
189     if (asynccallbackinfo->info.isCallback) {
190         ANS_LOGD("DisplayBadge callback is nullptr.");
191         return Common::NapiGetNull(env);
192     } else {
193         return promise;
194     }
195 }
196 
AsyncCompleteCallbackIsBadgeDisplayed(napi_env env,napi_status status,void * data)197 void AsyncCompleteCallbackIsBadgeDisplayed(napi_env env, napi_status status, void *data)
198 {
199     ANS_LOGD("enter");
200     if (!data) {
201         ANS_LOGE("Invalidity async callback data");
202         return;
203     }
204     AsyncCallbackInfoIsDisplayBadge *asynccallbackinfo = static_cast<AsyncCallbackInfoIsDisplayBadge *>(data);
205     if (asynccallbackinfo) {
206         napi_value result = nullptr;
207         napi_get_boolean(env, asynccallbackinfo->enabled, &result);
208         Common::ReturnCallbackPromise(env, asynccallbackinfo->info, result);
209         if (asynccallbackinfo->info.callback != nullptr) {
210             napi_delete_reference(env, asynccallbackinfo->info.callback);
211         }
212         napi_delete_async_work(env, asynccallbackinfo->asyncWork);
213         delete asynccallbackinfo;
214         asynccallbackinfo = nullptr;
215     }
216 }
217 
IsBadgeDisplayed(napi_env env,napi_callback_info info)218 napi_value IsBadgeDisplayed(napi_env env, napi_callback_info info)
219 {
220     ANS_LOGD("enter");
221 
222     IsDisplayBadgeParams params {};
223     if (ParseParameters(env, info, params) == nullptr) {
224         ANS_LOGE("Parse params fail!");
225         return Common::NapiGetUndefined(env);
226     }
227 
228     AsyncCallbackInfoIsDisplayBadge *asynccallbackinfo =
229         new (std::nothrow) AsyncCallbackInfoIsDisplayBadge {.env = env, .asyncWork = nullptr, .params = params};
230     if (!asynccallbackinfo) {
231         ANS_LOGD("Create asynccallbackinfo fail.");
232         return Common::JSParaError(env, params.callback);
233     }
234     napi_value promise = nullptr;
235     Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
236 
237     ANS_LOGD("Create IsBadgeDisplayed string.");
238     napi_value resourceName = nullptr;
239     napi_create_string_latin1(env, "IsBadgeDisplayed", NAPI_AUTO_LENGTH, &resourceName);
240     // Asynchronous function call
241     napi_create_async_work(env,
242         nullptr,
243         resourceName,
244         [](napi_env env, void *data) {
245             ANS_LOGD("IsBadgeDisplayed work excute.");
246             AsyncCallbackInfoIsDisplayBadge *asynccallbackinfo = static_cast<AsyncCallbackInfoIsDisplayBadge *>(data);
247             if (asynccallbackinfo) {
248                 if (asynccallbackinfo->params.hasBundleOption) {
249                     ANS_LOGI("option.bundle : %{public}s option.uid : %{public}d",
250                         asynccallbackinfo->params.option.GetBundleName().c_str(),
251                         asynccallbackinfo->params.option.GetUid());
252                     asynccallbackinfo->info.errorCode = NotificationHelper::GetShowBadgeEnabledForBundle(
253                         asynccallbackinfo->params.option, asynccallbackinfo->enabled);
254                 } else {
255                     asynccallbackinfo->info.errorCode = NotificationHelper::GetShowBadgeEnabled(
256                         asynccallbackinfo->enabled);
257                 }
258                 ANS_LOGI("asynccallbackinfo->info.errorCode : %{public}d, enabled : %{public}d",
259                     asynccallbackinfo->info.errorCode, asynccallbackinfo->enabled);
260             }
261         },
262         AsyncCompleteCallbackIsBadgeDisplayed,
263         (void *)asynccallbackinfo,
264         &asynccallbackinfo->asyncWork);
265 
266     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
267 
268     if (asynccallbackinfo->info.isCallback) {
269         ANS_LOGD("IsBadgeDisplayed callback is nullptr.");
270         return Common::NapiGetNull(env);
271     } else {
272         return promise;
273     }
274 }
275 }  // namespace NotificationNapi
276 }  // namespace OHOS
277