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