• 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 "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 &params)
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], &params.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, &params.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 &params)
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], &params.userId));
103         params.hasUserId = true;
104     } else {
105         napi_create_reference(env, argv[PARAM0], 1, &params.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, &params.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_status status = napi_queue_async_work(env, asynccallbackinfo->asyncWork);
178     if (status != napi_ok) {
179         ANS_LOGE("napi_queue_async_work failed return: %{public}d", status);
180         if (asynccallbackinfo->info.callback != nullptr) {
181             napi_delete_reference(env, asynccallbackinfo->info.callback);
182         }
183         napi_delete_async_work(env, asynccallbackinfo->asyncWork);
184         delete asynccallbackinfo;
185         asynccallbackinfo = nullptr;
186         return Common::JSParaError(env, params.callback);
187     }
188 
189     if (asynccallbackinfo->info.isCallback) {
190         return Common::NapiGetNull(env);
191     } else {
192         return promise;
193     }
194 }
195 
AsyncCompleteCallbackIsNotificationEnabled(napi_env env,napi_status status,void * data)196 void AsyncCompleteCallbackIsNotificationEnabled(napi_env env, napi_status status, void *data)
197 {
198     ANS_LOGI("enter");
199     if (!data) {
200         ANS_LOGE("Invalid async callback data");
201         return;
202     }
203     AsyncCallbackInfoIsEnable *asynccallbackinfo = static_cast<AsyncCallbackInfoIsEnable *>(data);
204     if (asynccallbackinfo) {
205         napi_value result = nullptr;
206         napi_get_boolean(env, asynccallbackinfo->allowed, &result);
207         if (asynccallbackinfo->newInterface) {
208             Common::CreateReturnValue(env, asynccallbackinfo->info, result);
209         } else {
210             Common::ReturnCallbackPromise(env, asynccallbackinfo->info, result);
211         }
212         if (asynccallbackinfo->info.callback != nullptr) {
213             napi_delete_reference(env, asynccallbackinfo->info.callback);
214         }
215         napi_delete_async_work(env, asynccallbackinfo->asyncWork);
216         delete asynccallbackinfo;
217         asynccallbackinfo = nullptr;
218     }
219 }
220 
IsNotificationEnabled(napi_env env,napi_callback_info info)221 napi_value IsNotificationEnabled(napi_env env, napi_callback_info info)
222 {
223     ANS_LOGI("enter");
224 
225     IsEnableParams params {};
226     if (ParseParameters(env, info, params) == nullptr) {
227         return Common::NapiGetUndefined(env);
228     }
229 
230     AsyncCallbackInfoIsEnable *asynccallbackinfo =
231         new (std::nothrow) AsyncCallbackInfoIsEnable {.env = env, .asyncWork = nullptr, .params = params};
232     if (!asynccallbackinfo) {
233         return Common::JSParaError(env, params.callback);
234     }
235     napi_value promise = nullptr;
236     Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
237 
238     napi_value resourceName = nullptr;
239     napi_create_string_latin1(env, "isNotificationEnabled", 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_LOGI("IsNotificationEnabled napi_create_async_work start");
246             AsyncCallbackInfoIsEnable *asynccallbackinfo = static_cast<AsyncCallbackInfoIsEnable *>(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::IsAllowedNotify(
253                         asynccallbackinfo->params.option, asynccallbackinfo->allowed);
254                 } else if (asynccallbackinfo->params.hasUserId) {
255                     ANS_LOGI("userId = %{public}d", asynccallbackinfo->params.userId);
256                     asynccallbackinfo->info.errorCode = NotificationHelper::IsAllowedNotify(
257                         asynccallbackinfo->params.userId, asynccallbackinfo->allowed);
258                 } else {
259                     asynccallbackinfo->info.errorCode = NotificationHelper::IsAllowedNotify(
260                         asynccallbackinfo->allowed);
261                 }
262                 ANS_LOGI("asynccallbackinfo->info.errorCode = %{public}d, allowed = %{public}d",
263                     asynccallbackinfo->info.errorCode, asynccallbackinfo->allowed);
264             }
265         },
266         AsyncCompleteCallbackIsNotificationEnabled,
267         (void *)asynccallbackinfo,
268         &asynccallbackinfo->asyncWork);
269 
270     napi_status status = napi_queue_async_work(env, asynccallbackinfo->asyncWork);
271     if (status != napi_ok) {
272         ANS_LOGE("napi_queue_async_work failed return: %{public}d", status);
273         if (asynccallbackinfo->info.callback != nullptr) {
274             napi_delete_reference(env, asynccallbackinfo->info.callback);
275         }
276         napi_delete_async_work(env, asynccallbackinfo->asyncWork);
277         delete asynccallbackinfo;
278         asynccallbackinfo = nullptr;
279         return Common::JSParaError(env, params.callback);
280     }
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 = static_cast<AsyncCallbackInfoIsEnable *>(data);
315             if (asynccallbackinfo) {
316                 if (asynccallbackinfo->params.hasBundleOption) {
317                     ANS_LOGE("Not allowed to query another application");
318                 } else {
319                     asynccallbackinfo->info.errorCode = NotificationHelper::IsAllowedNotifySelf(
320                         asynccallbackinfo->allowed);
321                 }
322                 ANS_LOGI("asynccallbackinfo->info.errorCode = %{public}d, allowed = %{public}d",
323                     asynccallbackinfo->info.errorCode, asynccallbackinfo->allowed);
324             }
325         },
326         AsyncCompleteCallbackIsNotificationEnabled,
327         (void *)asynccallbackinfo,
328         &asynccallbackinfo->asyncWork);
329 
330     napi_status status = napi_queue_async_work(env, asynccallbackinfo->asyncWork);
331     if (status != napi_ok) {
332         ANS_LOGE("napi_queue_async_work failed return: %{public}d", status);
333         if (asynccallbackinfo->info.callback != nullptr) {
334             napi_delete_reference(env, asynccallbackinfo->info.callback);
335         }
336         napi_delete_async_work(env, asynccallbackinfo->asyncWork);
337         delete asynccallbackinfo;
338         asynccallbackinfo = nullptr;
339         return Common::JSParaError(env, params.callback);
340     }
341 
342     if (asynccallbackinfo->info.isCallback) {
343         return Common::NapiGetNull(env);
344     } else {
345         return promise;
346     }
347 }
348 
RequestEnableNotification(napi_env env,napi_callback_info info)349 napi_value RequestEnableNotification(napi_env env, napi_callback_info info)
350 {
351     ANS_LOGI("enter");
352 
353     IsEnableParams params {};
354     if (ParseParameters(env, info, params) == nullptr) {
355         return Common::NapiGetUndefined(env);
356     }
357 
358     AsyncCallbackInfoIsEnable *asynccallbackinfo =
359         new (std::nothrow) AsyncCallbackInfoIsEnable {.env = env, .asyncWork = nullptr, .params = params};
360 
361     if (!asynccallbackinfo) {
362         return Common::JSParaError(env, params.callback);
363     }
364     napi_value promise = nullptr;
365     Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
366 
367     napi_value resourceName = nullptr;
368     napi_create_string_latin1(env, "RequestEnableNotification", NAPI_AUTO_LENGTH, &resourceName);
369     // Asynchronous function call
370     napi_create_async_work(env,
371         nullptr,
372         resourceName,
373         [](napi_env env, void *data) {
374             AsyncCallbackInfoIsEnable *asynccallbackinfo = static_cast<AsyncCallbackInfoIsEnable *>(data);
375             if (asynccallbackinfo) {
376                 std::string deviceId {""};
377                 asynccallbackinfo->info.errorCode =
378                     NotificationHelper::RequestEnableNotification(deviceId);
379             }
380         },
381         [](napi_env env, napi_status status, void *data) {
382             AsyncCallbackInfoIsEnable *asynccallbackinfo = static_cast<AsyncCallbackInfoIsEnable *>(data);
383             if (asynccallbackinfo) {
384                 AsyncCompleteCallbackIsNotificationEnabled(env, status, data);
385             }
386         },
387         (void *)asynccallbackinfo,
388         &asynccallbackinfo->asyncWork);
389 
390     napi_status status = napi_queue_async_work(env, asynccallbackinfo->asyncWork);
391     if (status != napi_ok) {
392         ANS_LOGE("napi_queue_async_work failed return: %{public}d", status);
393         if (asynccallbackinfo->info.callback != nullptr) {
394             napi_delete_reference(env, asynccallbackinfo->info.callback);
395         }
396         napi_delete_async_work(env, asynccallbackinfo->asyncWork);
397         delete asynccallbackinfo;
398         asynccallbackinfo = nullptr;
399         return Common::JSParaError(env, params.callback);
400     }
401 
402     if (asynccallbackinfo->info.isCallback) {
403         return Common::NapiGetNull(env);
404     } else {
405         return promise;
406     }
407 }
408 }  // namespace NotificationNapi
409 }  // namespace OHOS