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