1 /*
2 * Copyright (c) 2021 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 "enable_notification.h"
17
18 namespace OHOS {
19 namespace NotificationNapi {
20 const int ENABLE_NOTIFICATION_MAX_PARA = 3;
21 const int ENABLE_NOTIFICATION_MIN_PARA = 2;
22 const int IS_NOTIFICATION_ENABLE_MAX_PARA = 2;
23
24 struct EnableParams {
25 NotificationBundleOption option;
26 bool enable = false;
27 napi_ref callback = nullptr;
28 };
29
30 struct AsyncCallbackInfoEnable {
31 napi_env env = nullptr;
32 napi_async_work asyncWork = nullptr;
33 EnableParams params;
34 CallbackPromiseInfo info;
35 };
36
37 struct IsEnableParams {
38 NotificationBundleOption option;
39 napi_ref callback = nullptr;
40 bool hasBundleOption = false;
41 int32_t userId = SUBSCRIBE_USER_INIT;
42 bool hasUserId = false;
43 };
44
45 struct AsyncCallbackInfoIsEnable {
46 napi_env env = nullptr;
47 napi_async_work asyncWork = nullptr;
48 IsEnableParams params;
49 CallbackPromiseInfo info;
50 bool allowed = false;
51 };
52
ParseParameters(const napi_env & env,const napi_callback_info & info,EnableParams & params)53 napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, EnableParams ¶ms)
54 {
55 ANS_LOGI("enter");
56
57 size_t argc = ENABLE_NOTIFICATION_MAX_PARA;
58 napi_value argv[ENABLE_NOTIFICATION_MAX_PARA] = {nullptr};
59 napi_value thisVar = nullptr;
60 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
61 if (argc < ENABLE_NOTIFICATION_MIN_PARA) {
62 ANS_LOGW("Wrong number of arguments.");
63 return nullptr;
64 }
65
66 // argv[0]: bundle
67 napi_valuetype valuetype = napi_undefined;
68 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
69 if (valuetype != napi_object) {
70 ANS_LOGW("Wrong argument type. Object expected.");
71 return nullptr;
72 }
73 auto retValue = Common::GetBundleOption(env, argv[PARAM0], params.option);
74 if (retValue == nullptr) {
75 ANS_LOGE("GetBundleOption failed.");
76 return nullptr;
77 }
78
79 // argv[1]: enable
80 NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
81 if (valuetype != napi_boolean) {
82 ANS_LOGW("Wrong argument type. Bool expected.");
83 return nullptr;
84 }
85 napi_get_value_bool(env, argv[PARAM1], ¶ms.enable);
86
87 // argv[2]:callback
88 if (argc >= ENABLE_NOTIFICATION_MAX_PARA) {
89 NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valuetype));
90 if (valuetype != napi_function) {
91 ANS_LOGW("Wrong argument type. Function expected.");
92 return nullptr;
93 }
94 napi_create_reference(env, argv[PARAM2], 1, ¶ms.callback);
95 }
96
97 return Common::NapiGetNull(env);
98 }
99
ParseParameters(const napi_env & env,const napi_callback_info & info,IsEnableParams & params)100 napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, IsEnableParams ¶ms)
101 {
102 ANS_LOGI("enter");
103
104 size_t argc = IS_NOTIFICATION_ENABLE_MAX_PARA;
105 napi_value argv[IS_NOTIFICATION_ENABLE_MAX_PARA] = {nullptr};
106 napi_value thisVar = nullptr;
107 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
108
109 if (argc == 0) {
110 return Common::NapiGetNull(env);
111 }
112
113 // argv[0]: bundle / userId / callback
114 napi_valuetype valuetype = napi_undefined;
115 NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
116 if ((valuetype != napi_object) && (valuetype != napi_number) && (valuetype != napi_function)) {
117 ANS_LOGW("Wrong argument type. Function or object expected.");
118 return nullptr;
119 }
120 if (valuetype == napi_object) {
121 auto retValue = Common::GetBundleOption(env, argv[PARAM0], params.option);
122 if (retValue == nullptr) {
123 ANS_LOGE("GetBundleOption failed.");
124 return nullptr;
125 }
126 params.hasBundleOption = true;
127 } else if (valuetype == napi_number) {
128 NAPI_CALL(env, napi_get_value_int32(env, argv[PARAM0], ¶ms.userId));
129 params.hasUserId = true;
130 } else {
131 napi_create_reference(env, argv[PARAM0], 1, ¶ms.callback);
132 }
133
134 // argv[1]:callback
135 if (argc >= IS_NOTIFICATION_ENABLE_MAX_PARA) {
136 NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
137 if (valuetype != napi_function) {
138 ANS_LOGW("Wrong argument type. Function expected.");
139 return nullptr;
140 }
141 napi_create_reference(env, argv[PARAM1], 1, ¶ms.callback);
142 }
143
144 return Common::NapiGetNull(env);
145 }
146
AsyncCompleteCallbackEnableNotification(napi_env env,napi_status status,void * data)147 void AsyncCompleteCallbackEnableNotification(napi_env env, napi_status status, void *data)
148 {
149 ANS_LOGI("enter");
150 if (!data) {
151 ANS_LOGE("Invalid async callback data");
152 return;
153 }
154 AsyncCallbackInfoEnable *asynccallbackinfo = (AsyncCallbackInfoEnable *)data;
155
156 Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
157
158 if (asynccallbackinfo->info.callback != nullptr) {
159 napi_delete_reference(env, asynccallbackinfo->info.callback);
160 }
161
162 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
163 delete asynccallbackinfo;
164 asynccallbackinfo = nullptr;
165 }
166
EnableNotification(napi_env env,napi_callback_info info)167 napi_value EnableNotification(napi_env env, napi_callback_info info)
168 {
169 ANS_LOGI("enter");
170
171 EnableParams params {};
172 if (ParseParameters(env, info, params) == nullptr) {
173 return Common::NapiGetUndefined(env);
174 }
175
176 AsyncCallbackInfoEnable *asynccallbackinfo =
177 new (std::nothrow) AsyncCallbackInfoEnable {.env = env, .asyncWork = nullptr, .params = params};
178 if (!asynccallbackinfo) {
179 return Common::JSParaError(env, params.callback);
180 }
181 napi_value promise = nullptr;
182 Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
183
184 napi_value resourceName = nullptr;
185 napi_create_string_latin1(env, "enableNotification", NAPI_AUTO_LENGTH, &resourceName);
186 // Asynchronous function call
187 napi_create_async_work(env,
188 nullptr,
189 resourceName,
190 [](napi_env env, void *data) {
191 ANS_LOGI("EnableNotification napi_create_async_work start");
192 AsyncCallbackInfoEnable *asynccallbackinfo = (AsyncCallbackInfoEnable *)data;
193 std::string deviceId {""};
194 asynccallbackinfo->info.errorCode = NotificationHelper::SetNotificationsEnabledForSpecifiedBundle(
195 asynccallbackinfo->params.option, deviceId, asynccallbackinfo->params.enable);
196 ANS_LOGI("asynccallbackinfo->info.errorCode = %{public}d", asynccallbackinfo->info.errorCode);
197 },
198 AsyncCompleteCallbackEnableNotification,
199 (void *)asynccallbackinfo,
200 &asynccallbackinfo->asyncWork);
201
202 NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
203
204 if (asynccallbackinfo->info.isCallback) {
205 return Common::NapiGetNull(env);
206 } else {
207 return promise;
208 }
209 }
210
AsyncCompleteCallbackIsNotificationEnabled(napi_env env,napi_status status,void * data)211 void AsyncCompleteCallbackIsNotificationEnabled(napi_env env, napi_status status, void *data)
212 {
213 ANS_LOGI("enter");
214 if (!data) {
215 ANS_LOGE("Invalid async callback data");
216 return;
217 }
218 AsyncCallbackInfoIsEnable *asynccallbackinfo = (AsyncCallbackInfoIsEnable *)data;
219
220 napi_value result = nullptr;
221 napi_get_boolean(env, asynccallbackinfo->allowed, &result);
222 Common::ReturnCallbackPromise(env, asynccallbackinfo->info, result);
223
224 if (asynccallbackinfo->info.callback != nullptr) {
225 napi_delete_reference(env, asynccallbackinfo->info.callback);
226 }
227
228 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
229 delete asynccallbackinfo;
230 asynccallbackinfo = nullptr;
231 }
232
IsNotificationEnabled(napi_env env,napi_callback_info info)233 napi_value IsNotificationEnabled(napi_env env, napi_callback_info info)
234 {
235 ANS_LOGI("enter");
236
237 IsEnableParams params {};
238 if (ParseParameters(env, info, params) == nullptr) {
239 return Common::NapiGetUndefined(env);
240 }
241
242 AsyncCallbackInfoIsEnable *asynccallbackinfo =
243 new (std::nothrow) AsyncCallbackInfoIsEnable {.env = env, .asyncWork = nullptr, .params = params};
244 if (!asynccallbackinfo) {
245 return Common::JSParaError(env, params.callback);
246 }
247 napi_value promise = nullptr;
248 Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
249
250 napi_value resourceName = nullptr;
251 napi_create_string_latin1(env, "isNotificationEnabled", NAPI_AUTO_LENGTH, &resourceName);
252 // Asynchronous function call
253 napi_create_async_work(env,
254 nullptr,
255 resourceName,
256 [](napi_env env, void *data) {
257 ANS_LOGI("IsNotificationEnabled napi_create_async_work start");
258 AsyncCallbackInfoIsEnable *asynccallbackinfo = (AsyncCallbackInfoIsEnable *)data;
259
260 if (asynccallbackinfo->params.hasBundleOption) {
261 ANS_LOGI("option.bundle = %{public}s option.uid = %{public}d",
262 asynccallbackinfo->params.option.GetBundleName().c_str(),
263 asynccallbackinfo->params.option.GetUid());
264 asynccallbackinfo->info.errorCode =
265 NotificationHelper::IsAllowedNotify(asynccallbackinfo->params.option, asynccallbackinfo->allowed);
266 } else if (asynccallbackinfo->params.hasUserId) {
267 ANS_LOGI("userId = %{public}d", asynccallbackinfo->params.userId);
268 asynccallbackinfo->info.errorCode =
269 NotificationHelper::IsAllowedNotify(asynccallbackinfo->params.userId, asynccallbackinfo->allowed);
270 } else {
271 asynccallbackinfo->info.errorCode = NotificationHelper::IsAllowedNotify(asynccallbackinfo->allowed);
272 }
273 ANS_LOGI("asynccallbackinfo->info.errorCode = %{public}d, allowed = %{public}d",
274 asynccallbackinfo->info.errorCode, asynccallbackinfo->allowed);
275 },
276 AsyncCompleteCallbackIsNotificationEnabled,
277 (void *)asynccallbackinfo,
278 &asynccallbackinfo->asyncWork);
279
280 NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
281
282 if (asynccallbackinfo->info.isCallback) {
283 return Common::NapiGetNull(env);
284 } else {
285 return promise;
286 }
287 }
288
IsNotificationEnabledSelf(napi_env env,napi_callback_info info)289 napi_value IsNotificationEnabledSelf(napi_env env, napi_callback_info info)
290 {
291 ANS_LOGI("enter");
292
293 IsEnableParams params {};
294 if (ParseParameters(env, info, params) == nullptr) {
295 return Common::NapiGetUndefined(env);
296 }
297
298 AsyncCallbackInfoIsEnable *asynccallbackinfo =
299 new (std::nothrow) AsyncCallbackInfoIsEnable {.env = env, .asyncWork = nullptr, .params = params};
300 if (!asynccallbackinfo) {
301 return Common::JSParaError(env, params.callback);
302 }
303 napi_value promise = nullptr;
304 Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
305
306 napi_value resourceName = nullptr;
307 napi_create_string_latin1(env, "IsNotificationEnabledSelf", NAPI_AUTO_LENGTH, &resourceName);
308 // Asynchronous function call
309 napi_create_async_work(env,
310 nullptr,
311 resourceName,
312 [](napi_env env, void *data) {
313 ANS_LOGI("IsNotificationEnabledSelf napi_create_async_work start");
314 AsyncCallbackInfoIsEnable *asynccallbackinfo = (AsyncCallbackInfoIsEnable *)data;
315
316 if (asynccallbackinfo->params.hasBundleOption) {
317 ANS_LOGE("Not allowed to query another application");
318 } else {
319 asynccallbackinfo->info.errorCode = NotificationHelper::IsAllowedNotifySelf(asynccallbackinfo->allowed);
320 }
321 ANS_LOGI("asynccallbackinfo->info.errorCode = %{public}d, allowed = %{public}d",
322 asynccallbackinfo->info.errorCode, asynccallbackinfo->allowed);
323 },
324 AsyncCompleteCallbackIsNotificationEnabled,
325 (void *)asynccallbackinfo,
326 &asynccallbackinfo->asyncWork);
327
328 NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
329
330 if (asynccallbackinfo->info.isCallback) {
331 return Common::NapiGetNull(env);
332 } else {
333 return promise;
334 }
335 }
336
RequestEnableNotification(napi_env env,napi_callback_info info)337 napi_value RequestEnableNotification(napi_env env, napi_callback_info info)
338 {
339 ANS_LOGI("enter");
340
341 IsEnableParams params {};
342 if (ParseParameters(env, info, params) == nullptr) {
343 return Common::NapiGetUndefined(env);
344 }
345
346 AsyncCallbackInfoIsEnable *asynccallbackinfo =
347 new (std::nothrow) AsyncCallbackInfoIsEnable {.env = env, .asyncWork = nullptr, .params = params};
348
349 if (!asynccallbackinfo) {
350 return Common::JSParaError(env, params.callback);
351 }
352 napi_value promise = nullptr;
353 Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
354
355 napi_value resourceName = nullptr;
356 napi_create_string_latin1(env, "RequestEnableNotification", NAPI_AUTO_LENGTH, &resourceName);
357 // Asynchronous function call
358 napi_create_async_work(env,
359 nullptr,
360 resourceName,
361 [](napi_env env, void *data) {
362 ANS_LOGI("RequestEnableNotification napi_create_async_work start");
363 AsyncCallbackInfoIsEnable *asynccallbackinfo = (AsyncCallbackInfoIsEnable *)data;
364
365 std::string deviceId {""};
366 asynccallbackinfo->info.errorCode = NotificationHelper::RequestEnableNotification(deviceId);
367 ANS_LOGI("asynccallbackinfo->info.errorCode = %{public}d", asynccallbackinfo->info.errorCode);
368 },
369 AsyncCompleteCallbackIsNotificationEnabled,
370 (void *)asynccallbackinfo,
371 &asynccallbackinfo->asyncWork);
372
373 NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
374
375 if (asynccallbackinfo->info.isCallback) {
376 return Common::NapiGetNull(env);
377 } else {
378 return promise;
379 }
380 }
381 } // namespace NotificationNapi
382 } // namespace OHOS