• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "publish.h"
17 
18 #include "want_agent_helper.h"
19 
20 namespace OHOS {
21 namespace NotificationNapi {
22 using namespace AbilityRuntime::WantAgent;
23 
24 namespace {
25 constexpr int8_t PUBLISH_NOTIFICATION_MAX = 3;
26 constexpr int8_t SHOW_NOTIFICATION_MAX = 1;
27 constexpr int8_t PUBLISH_AS_BUNDLE_MAX = 4;
28 }
29 
GetCallback(const napi_env & env,const napi_value & value,ParametersInfoPublish & params)30 napi_value GetCallback(const napi_env &env, const napi_value &value, ParametersInfoPublish &params)
31 {
32     ANS_LOGI("enter");
33 
34     napi_valuetype valuetype = napi_undefined;
35     NAPI_CALL(env, napi_typeof(env, value, &valuetype));
36     if (valuetype != napi_function) {
37         ANS_LOGW("Wrong argument type. Function expected.");
38         return nullptr;
39     }
40     napi_create_reference(env, value, 1, &params.callback);
41     ANS_LOGI("end");
42     return Common::NapiGetNull(env);
43 }
44 
ParseParameters(const napi_env & env,const napi_callback_info & info,ParametersInfoPublish & params)45 napi_value ParseParameters(const napi_env &env, const napi_callback_info &info, ParametersInfoPublish &params)
46 {
47     ANS_LOGI("enter");
48 
49     size_t argc = PUBLISH_NOTIFICATION_MAX;
50     napi_value argv[PUBLISH_NOTIFICATION_MAX] = {nullptr};
51     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
52     if (argc < 1) {
53         ANS_LOGW("Wrong number of arguments.");
54         return nullptr;
55     }
56 
57     napi_valuetype valuetype = napi_undefined;
58     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
59     if (valuetype != napi_object) {
60         ANS_LOGW("Wrong argument type. Object expected.");
61         return nullptr;
62     }
63 
64     // argv[0] : NotificationRequest
65     if (Common::GetNotificationRequest(env, argv[PARAM0], params.request) == nullptr) {
66         return nullptr;
67     }
68 
69     // argv[1] : userId / callback
70     if (argc >= PUBLISH_NOTIFICATION_MAX - 1) {
71         NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
72         if ((valuetype != napi_number) && (valuetype != napi_function)) {
73             ANS_LOGW("Wrong argument type. Function or object expected.");
74             return nullptr;
75         }
76 
77         if (valuetype == napi_number) {
78             int32_t recvUserId = SUBSCRIBE_USER_INIT;
79             NAPI_CALL(env, napi_get_value_int32(env, argv[PARAM1], &recvUserId));
80             params.request.SetReceiverUserId(recvUserId);
81         } else {
82             napi_create_reference(env, argv[PARAM1], 1, &params.callback);
83         }
84     }
85 
86     // argv[2] : callback
87     if (argc >= PUBLISH_NOTIFICATION_MAX) {
88         if (GetCallback(env, argv[PARAM2], params) == nullptr) {
89             return nullptr;
90         }
91     }
92 
93     ANS_LOGI("end");
94     return Common::NapiGetNull(env);
95 }
96 
Publish(napi_env env,napi_callback_info info)97 napi_value Publish(napi_env env, napi_callback_info info)
98 {
99     ANS_LOGI("enter");
100 
101     ParametersInfoPublish params;
102     if (ParseParameters(env, info, params) == nullptr) {
103         return Common::NapiGetUndefined(env);
104     }
105 
106     napi_value promise = nullptr;
107     auto asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoPublish {.env = env, .asyncWork = nullptr};
108     if (!asynccallbackinfo) {
109         return Common::JSParaError(env, params.callback);
110     }
111 
112     asynccallbackinfo->request = params.request;
113     Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
114 
115     napi_value resourceName = nullptr;
116     napi_create_string_latin1(env, "publish", NAPI_AUTO_LENGTH, &resourceName);
117 
118     napi_create_async_work(env,
119         nullptr,
120         resourceName,
121         [](napi_env env, void *data) {
122             ANS_LOGI("Publish napi_create_async_work start");
123             AsyncCallbackInfoPublish *asynccallbackinfo = static_cast<AsyncCallbackInfoPublish *>(data);
124             if (asynccallbackinfo) {
125                 ANS_LOGI("Publish napi_create_async_work start notificationId = %{public}d, contentType = "
126                         "%{public}d",
127                     asynccallbackinfo->request.GetNotificationId(),
128                     asynccallbackinfo->request.GetContent()->GetContentType());
129 
130                 asynccallbackinfo->info.errorCode =
131                     NotificationHelper::PublishNotification(asynccallbackinfo->request);
132             }
133         },
134         [](napi_env env, napi_status status, void *data) {
135             ANS_LOGI("Publish napi_create_async_work complete start");
136             AsyncCallbackInfoPublish *asynccallbackinfo = static_cast<AsyncCallbackInfoPublish *>(data);
137             if (asynccallbackinfo) {
138                 Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
139                 if (asynccallbackinfo->info.callback != nullptr) {
140                     napi_delete_reference(env, asynccallbackinfo->info.callback);
141                 }
142                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
143                 delete asynccallbackinfo;
144                 asynccallbackinfo = nullptr;
145             }
146             ANS_LOGI("Publish napi_create_async_work complete end");
147         },
148         (void *)asynccallbackinfo,
149         &asynccallbackinfo->asyncWork);
150 
151     NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
152 
153     if (asynccallbackinfo->info.isCallback) {
154         return Common::NapiGetNull(env);
155     } else {
156         return promise;
157     }
158 }
159 
CheckProperty(const napi_env & env,const napi_value & content,const std::string & property)160 bool CheckProperty(const napi_env &env, const napi_value &content, const std::string &property)
161 {
162     ANS_LOGI("enter");
163 
164     bool hasProperty = false;
165 
166     NAPI_CALL_BASE(env, napi_has_named_property(env, content, property.data(), &hasProperty), false);
167     if (!hasProperty) {
168         ANS_LOGW("Property %{public}s expected.", property.c_str());
169     }
170     return hasProperty;
171 }
172 
GetStringProperty(const napi_env & env,const napi_value & content,const std::string & property,std::string & result)173 napi_value GetStringProperty(
174     const napi_env &env, const napi_value &content, const std::string &property, std::string &result)
175 {
176     ANS_LOGI("enter");
177 
178     if (!CheckProperty(env, content, property)) {
179         return nullptr;
180     }
181 
182     napi_valuetype valuetype = napi_undefined;
183     napi_value value = nullptr;
184     char str[STR_MAX_SIZE] = {0};
185     size_t strLen = 0;
186 
187     napi_get_named_property(env, content, property.data(), &value);
188     NAPI_CALL(env, napi_typeof(env, value, &valuetype));
189     if (valuetype != napi_string) {
190         ANS_LOGW("Wrong argument type. String expected.");
191         return nullptr;
192     }
193     NAPI_CALL(env, napi_get_value_string_utf8(env, value, str, STR_MAX_SIZE - 1, &strLen));
194     ANS_LOGI("normal::%{public}s = %{public}s", property.c_str(), str);
195     result = str;
196     return Common::NapiGetNull(env);
197 }
198 
GetObjectProperty(const napi_env & env,const napi_value & content,const std::string & property,napi_value & result)199 napi_value GetObjectProperty(
200     const napi_env &env, const napi_value &content, const std::string &property, napi_value &result)
201 {
202     ANS_LOGI("enter");
203 
204     if (!CheckProperty(env, content, property)) {
205         return nullptr;
206     }
207 
208     napi_valuetype valuetype = napi_undefined;
209     napi_get_named_property(env, content, property.data(), &result);
210     NAPI_CALL(env, napi_typeof(env, result, &valuetype));
211     if (valuetype != napi_object) {
212         ANS_LOGW("Wrong argument type. Object expected.");
213         return nullptr;
214     }
215     return Common::NapiGetNull(env);
216 }
217 
ParseShowOptions(const napi_env & env,const napi_callback_info & info,ParametersInfoPublish & params)218 napi_value ParseShowOptions(const napi_env &env, const napi_callback_info &info, ParametersInfoPublish &params)
219 {
220     ANS_LOGI("enter");
221 
222     size_t argc = SHOW_NOTIFICATION_MAX;
223     napi_value argv[SHOW_NOTIFICATION_MAX] = {nullptr};
224     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
225     if (argc == 0) {
226         ANS_LOGW("Wrong number of arguments.");
227         return nullptr;
228     }
229 
230     // argv[0] : ShowNotificationOptions
231     napi_valuetype valuetype = napi_undefined;
232     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
233     if (valuetype != napi_object) {
234         ANS_LOGW("Wrong argument type. Object expected.");
235         return nullptr;
236     }
237 
238     std::shared_ptr<NotificationNormalContent> normalContent = std::make_shared<NotificationNormalContent>();
239 
240     // contentTitle
241     std::string contentTitle;
242     if (GetStringProperty(env, argv[PARAM0], "contentTitle", contentTitle) != nullptr) {
243         normalContent->SetTitle(contentTitle);
244     }
245 
246     // contentText
247     std::string contentText;
248     if (GetStringProperty(env, argv[PARAM0], "contentText", contentText) != nullptr) {
249         normalContent->SetText(contentText);
250     }
251 
252     std::shared_ptr<NotificationContent> content = std::make_shared<NotificationContent>(normalContent);
253     params.request.SetContent(content);
254 
255     // clickAction
256     napi_value clickAction = nullptr;
257     if (GetObjectProperty(env, argv[PARAM0], "clickAction", clickAction) != nullptr) {
258         ANS_LOGD("create wantagent");
259         // bundleName & abilityName
260         std::shared_ptr<AAFwk::Want> want = std::make_shared<AAFwk::Want>();
261         std::string bundleName;
262         std::string abilityName;
263         if (GetStringProperty(env, clickAction, "bundleName", bundleName) == nullptr) {
264             return nullptr;
265         }
266         if (GetStringProperty(env, clickAction, "abilityName", abilityName) == nullptr) {
267             return nullptr;
268         }
269         want->SetElementName(bundleName, abilityName);
270         // uri
271         std::string uri;
272         if (GetStringProperty(env, clickAction, "uri", uri) == nullptr) {
273             return nullptr;
274         }
275         want->SetUri(uri);
276 
277         std::vector<std::shared_ptr<AAFwk::Want>> wants = {};
278         std::vector<WantAgentConstant::Flags> wantAgentFlags = {};
279         std::shared_ptr<AAFwk::WantParams> extraInfo = std::make_shared<AAFwk::WantParams>();
280         wants.emplace_back(want);
281         WantAgentInfo wantAgentInfo(-1, WantAgentConstant::OperationType::START_ABILITY, wantAgentFlags,
282             wants, extraInfo);
283         std::shared_ptr<AbilityRuntime::ApplicationContext> context = AbilityRuntime::Context::GetApplicationContext();
284 
285         std::shared_ptr<WantAgent> wantAgent = nullptr;
286         WantAgentHelper::GetWantAgent(context, wantAgentInfo, wantAgent);
287         params.request.SetWantAgent(wantAgent);
288     }
289 
290     ANS_LOGI("end");
291     return Common::NapiGetNull(env);
292 }
293 
ShowNotification(napi_env env,napi_callback_info info)294 napi_value ShowNotification(napi_env env, napi_callback_info info)
295 {
296     ANS_LOGI("enter");
297 
298     ParametersInfoPublish params;
299     if (ParseShowOptions(env, info, params) == nullptr) {
300         ANS_LOGW("parse showOptions failed");
301         return Common::NapiGetUndefined(env);
302     }
303 
304     auto asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoPublish {.env = env, .asyncWork = nullptr};
305     if (!asynccallbackinfo) {
306         ANS_LOGW("failed to create asynccallbackinfo");
307         return Common::JSParaError(env, params.callback);
308     }
309 
310     asynccallbackinfo->request = params.request;
311 
312     napi_value resourceName = nullptr;
313     napi_create_string_latin1(env, "show", NAPI_AUTO_LENGTH, &resourceName);
314 
315     ANS_LOGI("before napi_create_async_work");
316     napi_create_async_work(env,
317         nullptr,
318         resourceName,
319         [](napi_env env, void *data) {
320             ANS_LOGI("Show napi_create_async_work start");
321             AsyncCallbackInfoPublish *asynccallbackinfo = static_cast<AsyncCallbackInfoPublish *>(data);
322             if (asynccallbackinfo) {
323                 ANS_LOGI("Show napi_create_async_work start notificationId = %{public}d, contentType = "
324                         "%{public}d",
325                     asynccallbackinfo->request.GetNotificationId(),
326                     asynccallbackinfo->request.GetContent()->GetContentType());
327 
328                 asynccallbackinfo->info.errorCode =
329                     NotificationHelper::PublishNotification(asynccallbackinfo->request);
330             }
331         },
332         [](napi_env env, napi_status status, void *data) {
333             ANS_LOGI("Show napi_create_async_work complete start");
334             AsyncCallbackInfoPublish *asynccallbackinfo = static_cast<AsyncCallbackInfoPublish *>(data);
335             if (asynccallbackinfo) {
336                 if (asynccallbackinfo->info.callback != nullptr) {
337                     napi_delete_reference(env, asynccallbackinfo->info.callback);
338                 }
339                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
340                 delete asynccallbackinfo;
341                 asynccallbackinfo = nullptr;
342             }
343             ANS_LOGI("Show napi_create_async_work complete end");
344         },
345         (void *)asynccallbackinfo,
346         &asynccallbackinfo->asyncWork);
347 
348     NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
349     return nullptr;
350 }
351 
ParsePublishAsBundleParameters(const napi_env & env,const napi_callback_info & info,ParametersInfoPublish & params)352 napi_value ParsePublishAsBundleParameters(
353     const napi_env &env, const napi_callback_info &info, ParametersInfoPublish &params)
354 {
355     ANS_LOGI("enter");
356 
357     size_t argc = PUBLISH_AS_BUNDLE_MAX;
358     napi_value argv[PUBLISH_AS_BUNDLE_MAX] = {nullptr};
359     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
360     if (argc < 1) {
361         ANS_LOGW("Wrong number of arguments");
362         return nullptr;
363     }
364 
365     napi_valuetype valuetype = napi_undefined;
366     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
367     if (valuetype != napi_object) {
368         ANS_LOGW("Wrong argument type. Object expected.");
369         return nullptr;
370     }
371 
372     // argv[0] : NotificationRequest
373     if (Common::GetNotificationRequest(env, argv[PARAM0], params.request) == nullptr) {
374         return nullptr;
375     }
376 
377     // argv[1] : bundleName
378     NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
379     if (valuetype != napi_string) {
380         ANS_LOGW("Wrong argument type. String expected.");
381         return nullptr;
382     }
383 
384     char str[STR_MAX_SIZE] = {0};
385     size_t strLen = 0;
386     napi_get_value_string_utf8(env, argv[PARAM1], str, STR_MAX_SIZE - 1, &strLen);
387     params.request.SetOwnerBundleName(str);
388 
389     // argv[2] : userId
390     NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valuetype));
391     if (valuetype != napi_number) {
392         ANS_LOGW("Wrong argument type. Number expected.");
393         return nullptr;
394     }
395     int32_t userId = 0;
396     napi_get_value_int32(env, argv[PARAM2], &userId);
397     params.request.SetOwnerUserId(userId);
398     params.request.SetIsAgentNotification(true);
399 
400     // argv[3] : callback
401     if (argc >= PUBLISH_AS_BUNDLE_MAX) {
402         if (GetCallback(env, argv[PARAM3], params) == nullptr) {
403             return nullptr;
404         }
405     }
406 
407     ANS_LOGI("end");
408     return Common::NapiGetNull(env);
409 }
410 
PublishAsBundle(napi_env env,napi_callback_info info)411 napi_value PublishAsBundle(napi_env env, napi_callback_info info)
412 {
413     ANS_LOGI("enter");
414 
415     ParametersInfoPublish params;
416     if (ParsePublishAsBundleParameters(env, info, params) == nullptr) {
417         return Common::NapiGetUndefined(env);
418     }
419 
420     napi_value promise = nullptr;
421     auto asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoPublish {.env = env, .asyncWork = nullptr};
422     if (!asynccallbackinfo) {
423         return Common::JSParaError(env, params.callback);
424     }
425 
426     asynccallbackinfo->request = params.request;
427     Common::PaddingCallbackPromiseInfo(env, params.callback, asynccallbackinfo->info, promise);
428 
429     napi_value resourceName = nullptr;
430     napi_create_string_latin1(env, "publishasbundle", NAPI_AUTO_LENGTH, &resourceName);
431 
432     napi_create_async_work(env,
433         nullptr,
434         resourceName,
435         [](napi_env env, void *data) {
436             ANS_LOGI("PublishAsBundle napi_create_async_work start");
437             AsyncCallbackInfoPublish *asynccallbackinfo = static_cast<AsyncCallbackInfoPublish *>(data);
438             if (asynccallbackinfo) {
439                 ANS_LOGI("PublishAsBundle napi_create_async_work start notificationId = %{public}d, contentType = "
440                         "%{public}d",
441                     asynccallbackinfo->request.GetNotificationId(),
442                     asynccallbackinfo->request.GetContent()->GetContentType());
443 
444                 asynccallbackinfo->info.errorCode =
445                     NotificationHelper::PublishNotification(asynccallbackinfo->request);
446             }
447         },
448         [](napi_env env, napi_status status, void *data) {
449             ANS_LOGI("PublishAsBundle napi_create_async_work complete start");
450             AsyncCallbackInfoPublish *asynccallbackinfo = static_cast<AsyncCallbackInfoPublish *>(data);
451             if (asynccallbackinfo) {
452                 Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
453                 if (asynccallbackinfo->info.callback != nullptr) {
454                     napi_delete_reference(env, asynccallbackinfo->info.callback);
455                 }
456                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
457                 delete asynccallbackinfo;
458                 asynccallbackinfo = nullptr;
459             }
460             ANS_LOGI("PublishAsBundle napi_create_async_work complete end");
461         },
462         (void *)asynccallbackinfo,
463         &asynccallbackinfo->asyncWork);
464 
465     NAPI_CALL(env, napi_queue_async_work(env, asynccallbackinfo->asyncWork));
466 
467     if (asynccallbackinfo->info.isCallback) {
468         return Common::NapiGetNull(env);
469     } else {
470         return promise;
471     }
472 }
473 }  // namespace NotificationNapi
474 }  // namespace OHOS