• 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 "reminder/reminder_common.h"
17 
18 #include "ans_log_wrapper.h"
19 #include "common.h"
20 #include "ipc_skeleton.h"
21 #include "reminder_request_alarm.h"
22 #include "reminder_request_calendar.h"
23 #include "reminder_request_timer.h"
24 #include "tokenid_kit.h"
25 
26 namespace OHOS {
27 namespace ReminderAgentNapi {
28 using namespace OHOS::Notification;
29 const uint32_t ASYNC_CALLBACK_PARAM_NUM = 2;
30 
GetReminderRequest(const napi_env & env,const napi_value & value,std::shared_ptr<ReminderRequest> & reminder)31 napi_value ReminderCommon::GetReminderRequest(
32     const napi_env &env, const napi_value &value, std::shared_ptr<ReminderRequest>& reminder)
33 {
34     napi_valuetype valuetype = napi_undefined;
35     NAPI_CALL(env, napi_typeof(env, value, &valuetype));
36     if (valuetype != napi_object) {
37         ANSR_LOGW("Wrong argument type. Object expected.");
38         return nullptr;
39     }
40 
41     // gen reminder
42     if (GenReminder(env, value, reminder) == nullptr) {
43         return nullptr;
44     }
45     return NotificationNapi::Common::NapiGetNull(env);
46 }
47 
GenActionButtons(const napi_env & env,const napi_value & value,std::shared_ptr<ReminderRequest> & reminder,bool isSysApp)48 bool ReminderCommon::GenActionButtons(
49     const napi_env &env, const napi_value &value, std::shared_ptr<ReminderRequest>& reminder, bool isSysApp)
50 {
51     char str[NotificationNapi::STR_MAX_SIZE] = {0};
52     napi_valuetype valuetype = napi_undefined;
53     napi_value actionButtons = nullptr;
54     if (!GetObject(env, value, ReminderAgentNapi::ACTION_BUTTON, actionButtons)) {
55         return true;
56     }
57     bool isArray = false;
58     napi_is_array(env, actionButtons, &isArray);
59     if (!isArray) {
60         ANSR_LOGW("Wrong argument type:%{public}s. array expected.", ACTION_BUTTON);
61         return false;
62     }
63 
64     uint32_t length = 0;
65     napi_get_array_length(env, actionButtons, &length);
66     for (size_t i = 0; i < length; i++) {
67         napi_value actionButton = nullptr;
68         napi_get_element(env, actionButtons, i, &actionButton);
69         NAPI_CALL_BASE(env, napi_typeof(env, actionButton, &valuetype), false);
70         if (valuetype != napi_object) {
71             ANSR_LOGW("Wrong element type:%{public}s. object expected.", ACTION_BUTTON);
72             return false;
73         }
74 
75         int32_t buttonType = static_cast<int32_t>(ReminderRequest::ActionButtonType::INVALID);
76         if (GetStringUtf8(env, actionButton,
77             ReminderAgentNapi::ACTION_BUTTON_TITLE, str, NotificationNapi::STR_MAX_SIZE) &&
78             GetInt32(env, actionButton, ReminderAgentNapi::ACTION_BUTTON_TYPE, buttonType, false)) {
79             if (!(ReminderRequest::ActionButtonType(buttonType) == ReminderRequest::ActionButtonType::CLOSE ||
80                 ReminderRequest::ActionButtonType(buttonType) == ReminderRequest::ActionButtonType::SNOOZE ||
81                 (ReminderRequest::ActionButtonType(buttonType) == ReminderRequest::ActionButtonType::CUSTOM &&
82                 isSysApp))) {
83                 ANSR_LOGW("Wrong argument type:%{public}s. buttonType not support.", ACTION_BUTTON);
84                 return false;
85             }
86             std::string title(str);
87             auto buttonWantAgent = std::make_shared<ReminderRequest::ButtonWantAgent>();
88             if (ReminderRequest::ActionButtonType(buttonType) == ReminderRequest::ActionButtonType::CUSTOM) {
89                 GetButtonWantAgent(env, actionButton, reminder, buttonWantAgent);
90             }
91             reminder->SetActionButton(title, static_cast<ReminderRequest::ActionButtonType>(buttonType),
92                 buttonWantAgent);
93             ANSR_LOGD("button title=%{public}s, type=%{public}d", title.c_str(), buttonType);
94         } else {
95             ANSR_LOGW("Parse action button error.");
96             return false;
97         }
98     }
99     return true;
100 }
101 
IsSelfSystemApp(std::shared_ptr<ReminderRequest> & reminder)102 bool ReminderCommon::IsSelfSystemApp(std::shared_ptr<ReminderRequest>& reminder)
103 {
104     auto selfToken = IPCSkeleton::GetSelfTokenID();
105     if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) {
106         ANSR_LOGW("This application is not system-app, can not use system-api");
107         return false;
108     }
109     reminder->SetSystemApp(true);
110     return true;
111 }
112 
GetButtonWantAgent(const napi_env & env,const napi_value & value,std::shared_ptr<ReminderRequest> & reminder,std::shared_ptr<ReminderRequest::ButtonWantAgent> & buttonWantAgent)113 void ReminderCommon::GetButtonWantAgent(const napi_env &env, const napi_value &value,
114     std::shared_ptr<ReminderRequest>& reminder, std::shared_ptr<ReminderRequest::ButtonWantAgent>& buttonWantAgent)
115 {
116     char str[NotificationNapi::STR_MAX_SIZE] = {0};
117     napi_value wantAgent = nullptr;
118     if (GetObject(env, value, ReminderAgentNapi::BUTTON_WANT_AGENT, wantAgent)) {
119         if (GetStringUtf8(env, wantAgent,
120             ReminderAgentNapi::BUTTON_WANT_AGENT_PKG, str, NotificationNapi::STR_MAX_SIZE)) {
121             buttonWantAgent->pkgName = str;
122         }
123         if (GetStringUtf8(env, wantAgent,
124             ReminderAgentNapi::BUTTON_WANT_AGENT_ABILITY, str, NotificationNapi::STR_MAX_SIZE)) {
125             buttonWantAgent->abilityName = str;
126         }
127         if (GetStringUtf8(env, wantAgent,
128             ReminderAgentNapi::BUTTON_WANT_AGENT_URI, str, NotificationNapi::STR_MAX_SIZE)) {
129             reminder->SetCustomButtonUri(str);
130         }
131     }
132 }
133 
GenWantAgent(const napi_env & env,const napi_value & value,std::shared_ptr<ReminderRequest> & reminder)134 void ReminderCommon::GenWantAgent(
135     const napi_env &env, const napi_value &value, std::shared_ptr<ReminderRequest>& reminder)
136 {
137     char str[NotificationNapi::STR_MAX_SIZE] = {0};
138     napi_value wantAgent = nullptr;
139     if (GetObject(env, value, ReminderAgentNapi::WANT_AGENT, wantAgent)) {
140         auto wantAgentInfo = std::make_shared<ReminderRequest::WantAgentInfo>();
141         if (GetStringUtf8(env, wantAgent, ReminderAgentNapi::WANT_AGENT_PKG, str, NotificationNapi::STR_MAX_SIZE)) {
142             wantAgentInfo->pkgName = str;
143         }
144         if (GetStringUtf8(env, wantAgent,
145             ReminderAgentNapi::WANT_AGENT_ABILITY, str, NotificationNapi::STR_MAX_SIZE)) {
146             wantAgentInfo->abilityName = str;
147         }
148         reminder->SetWantAgentInfo(wantAgentInfo);
149     }
150 }
151 
GenMaxScreenWantAgent(const napi_env & env,const napi_value & value,std::shared_ptr<ReminderRequest> & reminder)152 void ReminderCommon::GenMaxScreenWantAgent(
153     const napi_env &env, const napi_value &value, std::shared_ptr<ReminderRequest>& reminder)
154 {
155     char str[NotificationNapi::STR_MAX_SIZE] = {0};
156     napi_value maxScreenWantAgent = nullptr;
157     if (GetObject(env, value, ReminderAgentNapi::MAX_SCREEN_WANT_AGENT, maxScreenWantAgent)) {
158         auto maxScreenWantAgentInfo = std::make_shared<ReminderRequest::MaxScreenAgentInfo>();
159         if (GetStringUtf8(env, maxScreenWantAgent,
160             ReminderAgentNapi::MAX_SCREEN_WANT_AGENT_PKG, str, NotificationNapi::STR_MAX_SIZE)) {
161             maxScreenWantAgentInfo->pkgName = str;
162         }
163         if (GetStringUtf8(env, maxScreenWantAgent,
164             ReminderAgentNapi::MAX_SCREEN_WANT_AGENT_ABILITY, str, NotificationNapi::STR_MAX_SIZE)) {
165             maxScreenWantAgentInfo->abilityName = str;
166         }
167         reminder->SetMaxScreenWantAgentInfo(maxScreenWantAgentInfo);
168     }
169 }
CreateReminder(const napi_env & env,const napi_value & value,std::shared_ptr<ReminderRequest> & reminder)170 bool ReminderCommon::CreateReminder(
171     const napi_env &env, const napi_value &value, std::shared_ptr<ReminderRequest>& reminder)
172 {
173     napi_value result = nullptr;
174     napi_get_named_property(env, value, ReminderAgentNapi::REMINDER_TYPE, &result);
175     int32_t reminderType = -1;
176     napi_get_value_int32(env, result, &reminderType);
177     switch (ReminderRequest::ReminderType(reminderType)) {
178         case ReminderRequest::ReminderType::TIMER:
179             CreateReminderTimer(env, value, reminder);
180             break;
181         case ReminderRequest::ReminderType::ALARM:
182             CreateReminderAlarm(env, value, reminder);
183             break;
184         case ReminderRequest::ReminderType::CALENDAR:
185             CreateReminderCalendar(env, value, reminder);
186             break;
187         default:
188             ANSR_LOGW("Reminder type is not support. (type:%{public}d)", reminderType);
189             break;
190     }
191     if (reminder == nullptr) {
192         ANSR_LOGW("Instance of reminder error.");
193         return false;
194     }
195     return true;
196 }
197 
GenReminder(const napi_env & env,const napi_value & value,std::shared_ptr<ReminderRequest> & reminder)198 napi_value ReminderCommon::GenReminder(
199     const napi_env &env, const napi_value &value, std::shared_ptr<ReminderRequest>& reminder)
200 {
201     // reminderType
202     bool hasProperty = false;
203     NAPI_CALL(env, napi_has_named_property(env, value, ReminderAgentNapi::REMINDER_TYPE, &hasProperty));
204     if (!hasProperty) {
205         ANSR_LOGW("Property %{public}s expected.", ReminderAgentNapi::REMINDER_TYPE);
206         return nullptr;
207     }
208 
209     // createReminder
210     if (!CreateReminder(env, value, reminder)) {
211         return nullptr;
212     }
213     bool isSysApp = IsSelfSystemApp(reminder);
214     char str[NotificationNapi::STR_MAX_SIZE] = {0};
215 
216     // title
217     if (GetStringUtf8(env, value, ReminderAgentNapi::TITLE, str, NotificationNapi::STR_MAX_SIZE)) {
218         reminder->SetTitle(std::string(str));
219     }
220 
221     // content
222     if (GetStringUtf8(env, value, ReminderAgentNapi::CONTENT, str, NotificationNapi::STR_MAX_SIZE)) {
223         reminder->SetContent(std::string(str));
224     }
225 
226     // expiredContent
227     if (GetStringUtf8(env, value, ReminderAgentNapi::EXPIRED_CONTENT, str, NotificationNapi::STR_MAX_SIZE)) {
228         reminder->SetExpiredContent(std::string(str));
229     }
230 
231     // snoozeContent
232     if (GetStringUtf8(env, value, ReminderAgentNapi::SNOOZE_CONTENT, str, NotificationNapi::STR_MAX_SIZE)) {
233         reminder->SetSnoozeContent(std::string(str));
234     }
235 
236     // ringDuration
237     int64_t propVal = 0;
238     if (GetInt64(env, value, ReminderAgentNapi::RING_DURATION, propVal)) {
239         if (propVal < 0) {
240             reminder->SetRingDuration(0);
241         } else {
242             uint64_t ringDuration = static_cast<uint64_t>(propVal);
243             reminder->SetRingDuration(ringDuration);
244         }
245     }
246 
247     // timeInterval
248     if (GetInt64(env, value, ReminderAgentNapi::TIME_INTERVAL, propVal)) {
249         if (propVal < 0) {
250             reminder->SetTimeInterval(0);
251         } else {
252             uint64_t timeInterval = static_cast<uint64_t>(propVal);
253             reminder->SetTimeInterval(timeInterval);
254         }
255     }
256 
257     // notificationId
258     int32_t propertyVal = 0;
259     if (GetInt32(env, value, ReminderAgentNapi::NOTIFICATION_ID, propertyVal, false)) {
260         reminder->SetNotificationId(propertyVal);
261     }
262 
263     // snoozeTimes
264     if (GetInt32(env, value, ReminderAgentNapi::SNOOZE_TIMES, propertyVal, false)) {
265         if (propertyVal < 0) {
266             reminder->SetSnoozeTimes(0);
267         } else {
268             uint8_t snoozeTimes = propertyVal > UINT8_MAX ? UINT8_MAX : static_cast<uint8_t>(propertyVal);
269             reminder->SetSnoozeTimes(static_cast<uint8_t>(snoozeTimes));
270         }
271     }
272 
273     // slotType
274     int32_t slotType = 0;
275     if (GetInt32(env, value, ReminderAgentNapi::SLOT_TYPE, slotType, false)) {
276         enum NotificationConstant::SlotType actureType = NotificationConstant::SlotType::OTHER;
277         if (!NotificationNapi::Common::SlotTypeJSToC(NotificationNapi::SlotType(slotType), actureType)) {
278             ANSR_LOGW("slot type not support.");
279             return nullptr;
280         }
281         reminder->SetSlotType(actureType);
282     }
283 
284     // tapDismissed
285     bool tapDismissed = false;
286     if (GetBool(env, value, ReminderAgentNapi::TAPDISMISSED, tapDismissed)) {
287         reminder->SetTapDismissed(tapDismissed);
288     }
289 
290     //autoDeletedTime
291     int64_t autoDeletedTime = 0;
292     if (GetInt64(env, value, ReminderAgentNapi::AUTODELETEDTIME, autoDeletedTime)) {
293         if (autoDeletedTime > 0) {
294             reminder->SetAutoDeletedTime(autoDeletedTime);
295         }
296     }
297 
298     // wantAgent
299     GenWantAgent(env, value, reminder);
300 
301     // maxScreenWantAgent
302     GenMaxScreenWantAgent(env, value, reminder);
303 
304     // actionButtons
305     if (!GenActionButtons(env, value, reminder, isSysApp)) {
306         return nullptr;
307     }
308     return NotificationNapi::Common::NapiGetNull(env);
309 }
310 
GetStringUtf8(const napi_env & env,const napi_value & value,const char * propertyName,char * propertyVal,const int32_t size)311 bool ReminderCommon::GetStringUtf8(const napi_env &env, const napi_value &value,
312     const char* propertyName, char* propertyVal, const int32_t size)
313 {
314     bool hasProperty = false;
315     napi_value result = nullptr;
316     napi_valuetype valuetype = napi_undefined;
317     size_t strLen = 0;
318 
319     NAPI_CALL_BASE(env, napi_has_named_property(env, value, propertyName, &hasProperty), false);
320     if (hasProperty) {
321         napi_get_named_property(env, value, propertyName, &result);
322         NAPI_CALL_BASE(env, napi_typeof(env, result, &valuetype), false);
323         if (valuetype != napi_string) {
324             ANSR_LOGW("Wrong argument type:%{public}s. string expected.", propertyName);
325             return false;
326         }
327         NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, result, propertyVal, size - 1, &strLen), false);
328     }
329     return hasProperty;
330 }
331 
GetBool(const napi_env & env,const napi_value & value,const char * propertyName,bool & propertyVal)332 bool ReminderCommon::GetBool(const napi_env &env, const napi_value &value,
333     const char* propertyName, bool& propertyVal)
334 {
335     bool hasProperty = false;
336     napi_value result = nullptr;
337     napi_valuetype valuetype = napi_undefined;
338     NAPI_CALL_BASE(env, napi_has_named_property(env, value, propertyName, &hasProperty), false);
339     if (!hasProperty) {
340         ANSR_LOGW("Does not have argument type:%{public}s.", propertyName);
341         return false;
342     }
343     napi_get_named_property(env, value, propertyName, &result);
344     NAPI_CALL_BASE(env, napi_typeof(env, result, &valuetype), false);
345     if (valuetype != napi_boolean) {
346         ANSR_LOGW("Wrong argument type:%{public}s. boolean expected.", propertyName);
347         return false;
348     }
349     napi_get_value_bool(env, result, &propertyVal);
350     return true;
351 }
352 
GetInt32(const napi_env & env,const napi_value & value,const char * propertyName,int32_t & propertyVal,bool isNecessary)353 bool ReminderCommon::GetInt32(const napi_env &env, const napi_value &value,
354     const char* propertyName, int32_t& propertyVal, bool isNecessary)
355 {
356     napi_value result = nullptr;
357     if (!GetPropertyValIfExist(env, value, propertyName, result)) {
358         if (isNecessary) {
359             ANSR_LOGW("Correct property %{public}s expected.", propertyName);
360         }
361         return false;
362     }
363     napi_get_value_int32(env, result, &propertyVal);
364     return true;
365 }
366 
GetInt64(const napi_env & env,const napi_value & value,const char * propertyName,int64_t & propertyVal)367 bool ReminderCommon::GetInt64(const napi_env &env, const napi_value &value,
368     const char* propertyName, int64_t& propertyVal)
369 {
370     napi_value result = nullptr;
371     if (!GetPropertyValIfExist(env, value, propertyName, result)) {
372         return false;
373     }
374     napi_get_value_int64(env, result, &propertyVal);
375     return true;
376 }
377 
GetPropertyValIfExist(const napi_env & env,const napi_value & value,const char * propertyName,napi_value & propertyVal)378 bool ReminderCommon::GetPropertyValIfExist(const napi_env &env, const napi_value &value,
379     const char* propertyName, napi_value& propertyVal)
380 {
381     napi_valuetype valuetype = napi_undefined;
382     if (propertyName == nullptr) {
383         propertyVal = value;
384     } else {
385         bool hasProperty = false;
386         napi_status status = napi_has_named_property(env, value, propertyName, &hasProperty);
387         if (status != napi_ok || !hasProperty) {
388             return false;
389         }
390         napi_get_named_property(env, value, propertyName, &propertyVal);
391     }
392     napi_status status = napi_typeof(env, propertyVal, &valuetype);
393     if (status != napi_ok || valuetype != napi_number) {
394         if (propertyName == nullptr) {
395             ANSR_LOGW("Wrong argument type. number expected.");
396         } else {
397             ANSR_LOGW("Wrong argument type:%{public}s, number expected.", propertyName);
398         }
399         return false;
400     }
401     return true;
402 }
403 
GetObject(const napi_env & env,const napi_value & value,const char * propertyName,napi_value & propertyVal)404 bool ReminderCommon::GetObject(const napi_env &env, const napi_value &value,
405     const char* propertyName, napi_value& propertyVal)
406 {
407     bool hasProperty = false;
408     napi_valuetype valuetype = napi_undefined;
409 
410     NAPI_CALL_BASE(env, napi_has_named_property(env, value, propertyName, &hasProperty), false);
411     if (!hasProperty) {
412         return false;
413     }
414     napi_get_named_property(env, value, propertyName, &propertyVal);
415     NAPI_CALL_BASE(env, napi_typeof(env, propertyVal, &valuetype), false);
416     if (valuetype != napi_object) {
417         ANSR_LOGW("Wrong argument type:%{public}s. object expected.", propertyName);
418         return false;
419     }
420     return true;
421 }
422 
CreateReminderTimer(const napi_env & env,const napi_value & value,std::shared_ptr<ReminderRequest> & reminder)423 napi_value ReminderCommon::CreateReminderTimer(
424     const napi_env &env, const napi_value &value, std::shared_ptr<ReminderRequest>& reminder)
425 {
426     int64_t propertyCountDownTime = 0;
427     if (!GetInt64(env, value, ReminderAgentNapi::TIMER_COUNT_DOWN_TIME, propertyCountDownTime)) {
428         ANSR_LOGW("Correct property %{public}s expected.", ReminderAgentNapi::TIMER_COUNT_DOWN_TIME);
429         return nullptr;
430     }
431 
432     auto countDownTimeInSeconds = static_cast<uint64_t>(propertyCountDownTime);
433     if (propertyCountDownTime <= 0 || countDownTimeInSeconds >= (UINT64_MAX / ReminderRequest::MILLI_SECONDS)) {
434         ANSR_LOGW("Create countDown reminder fail: designated %{public}s is illegal.",
435             ReminderAgentNapi::TIMER_COUNT_DOWN_TIME);
436         return nullptr;
437     }
438 
439     reminder = std::make_shared<ReminderRequestTimer>(countDownTimeInSeconds);
440     return NotificationNapi::Common::NapiGetNull(env);
441 }
442 
CreateReminderAlarm(const napi_env & env,const napi_value & value,std::shared_ptr<ReminderRequest> & reminder)443 napi_value ReminderCommon::CreateReminderAlarm(
444     const napi_env &env, const napi_value &value, std::shared_ptr<ReminderRequest>& reminder)
445 {
446     // hour
447     int32_t propertyHourVal = 0;
448     const int32_t maxHour = 23;
449     if (!GetInt32(env, value, ReminderAgentNapi::ALARM_HOUR, propertyHourVal, true)) {
450         return nullptr;
451     }
452 
453     // minute
454     int32_t propertyMinuteVal = 0;
455     const int32_t maxMinute = 59;
456     if (!GetInt32(env, value, ReminderAgentNapi::ALARM_MINUTE, propertyMinuteVal, true)) {
457         return nullptr;
458     }
459 
460     if ((propertyHourVal < 0) || (propertyHourVal > maxHour)) {
461         ANSR_LOGW("Create alarm reminder fail: designated %{public}s must between [0, 23].",
462             ReminderAgentNapi::ALARM_HOUR);
463         return nullptr;
464     }
465     if ((propertyMinuteVal < 0) || (propertyMinuteVal > maxMinute)) {
466         ANSR_LOGW("Create alarm reminder fail: designated %{public}s must between [0, 59].",
467             ReminderAgentNapi::ALARM_MINUTE);
468         return nullptr;
469     }
470 
471     // daysOfWeek
472     std::vector<uint8_t> daysOfWeek;
473     uint8_t maxDaysOfWeek = 7;
474     if (ParseInt32Array(env, value, ReminderAgentNapi::ALARM_DAYS_OF_WEEK, daysOfWeek, maxDaysOfWeek) == nullptr) {
475         return nullptr;
476     }
477     reminder = std::make_shared<ReminderRequestAlarm>(
478         static_cast<uint8_t>(propertyHourVal), static_cast<uint8_t>(propertyMinuteVal), daysOfWeek);
479     return NotificationNapi::Common::NapiGetNull(env);
480 }
481 
CreateReminderCalendar(const napi_env & env,const napi_value & value,std::shared_ptr<ReminderRequest> & reminder)482 napi_value ReminderCommon::CreateReminderCalendar(
483     const napi_env &env, const napi_value &value, std::shared_ptr<ReminderRequest>& reminder)
484 {
485     napi_value dateTimeObj = nullptr;
486     if (!GetObject(env, value, ReminderAgentNapi::CALENDAR_DATE_TIME, dateTimeObj)) {
487         ANSR_LOGW("Create calendar reminder fail: dateTime must be setted.");
488         return nullptr;
489     }
490 
491     // year month day hour minute second
492     int32_t propertyYearVal = 0;
493     int32_t propertyMonthVal = 0;
494     int32_t propertyDayVal = 0;
495     int32_t propertyHourVal = 0;
496     int32_t propertyMinteVal = 0;
497     if (!GetInt32(env, dateTimeObj, ReminderAgentNapi::CALENDAR_YEAR, propertyYearVal, true) ||
498         !GetInt32(env, dateTimeObj, ReminderAgentNapi::CALENDAR_MONTH, propertyMonthVal, true) ||
499         !GetInt32(env, dateTimeObj, ReminderAgentNapi::CALENDAR_DAY, propertyDayVal, true) ||
500         !GetInt32(env, dateTimeObj, ReminderAgentNapi::CALENDAR_HOUR, propertyHourVal, true) ||
501         !GetInt32(env, dateTimeObj, ReminderAgentNapi::CALENDAR_MINUTE, propertyMinteVal, true)) {
502         return nullptr;
503     }
504     if (!CheckCalendarParams(propertyYearVal, propertyMonthVal, propertyDayVal,
505         propertyHourVal, propertyMinteVal)) {
506         return nullptr;
507     }
508 
509     // repeatMonth
510     std::vector<uint8_t> repeatMonths;
511     if (ParseInt32Array(env, value, ReminderAgentNapi::CALENDAR_REPEAT_MONTHS, repeatMonths,
512         ReminderRequestCalendar::MAX_MONTHS_OF_YEAR) == nullptr) {
513         return nullptr;
514     }
515 
516     // repeatDay
517     std::vector<uint8_t> repeatDays;
518     if (ParseInt32Array(env, value, ReminderAgentNapi::CALENDAR_REPEAT_DAYS, repeatDays,
519         ReminderRequestCalendar::MAX_DAYS_OF_MONTH) == nullptr) {
520         return nullptr;
521     }
522 
523     tm dateTime;
524     dateTime.tm_year = ReminderRequest::GetCTime(ReminderRequest::TimeTransferType::YEAR, propertyYearVal);
525     dateTime.tm_mon = ReminderRequest::GetCTime(ReminderRequest::TimeTransferType::MONTH, propertyMonthVal);
526     dateTime.tm_mday = propertyDayVal;
527     dateTime.tm_hour = propertyHourVal;
528     dateTime.tm_min = propertyMinteVal;
529     dateTime.tm_sec = 0;
530     dateTime.tm_isdst = -1;
531     reminder = std::make_shared<ReminderRequestCalendar>(dateTime, repeatMonths, repeatDays);
532     if (!(reminder->SetNextTriggerTime())) {
533         return nullptr;
534     }
535     return NotificationNapi::Common::NapiGetNull(env);
536 }
537 
CheckCalendarParams(const int32_t & year,const int32_t & month,const int32_t & day,const int32_t & hour,const int32_t & min)538 bool ReminderCommon::CheckCalendarParams(const int32_t &year, const int32_t &month, const int32_t &day,
539     const int32_t &hour, const int32_t &min)
540 {
541     if ((year < 0) || (year > UINT16_MAX)) {
542         ANSR_LOGW("Create calendar reminder fail: designated %{public}s must between [0, %{public}d]",
543             ReminderAgentNapi::CALENDAR_YEAR, UINT16_MAX);
544         return false;
545     }
546     if ((month < 1) || (month > ReminderRequestCalendar::MAX_MONTHS_OF_YEAR)) {
547         ANSR_LOGW("Create calendar reminder fail: designated %{public}s must between [1, %{public}hhu]",
548             ReminderAgentNapi::CALENDAR_MONTH, ReminderRequestCalendar::MAX_MONTHS_OF_YEAR);
549         return false;
550     }
551     uint8_t maxDaysOfMonth = ReminderRequestCalendar::GetDaysOfMonth(static_cast<uint16_t>(year), month);
552     if ((day < 1) || (day > maxDaysOfMonth)) {
553         ANSR_LOGW("Create calendar reminder fail: designated %{public}s must between [1, %{public}hhu]",
554             ReminderAgentNapi::CALENDAR_DAY, maxDaysOfMonth);
555         return false;
556     }
557     uint8_t maxHour = 23;
558     if (hour < 0 || hour > maxHour) {
559         ANSR_LOGW("Create calendar reminder fail: designated %{public}s must between [0, %{public}hhu]",
560             ReminderAgentNapi::CALENDAR_HOUR, maxHour);
561         return false;
562     }
563     uint8_t maxMinute = 59;
564     if (min < 0 || min > maxMinute) {
565         ANSR_LOGW("Create calendar reminder fail: designated %{public}s must between [0, %{public}hhu]",
566             ReminderAgentNapi::CALENDAR_MINUTE, maxMinute);
567         return false;
568     }
569     return true;
570 }
571 
ParseInt32Array(const napi_env & env,const napi_value & value,const char * propertyName,std::vector<uint8_t> & propertyVal,uint8_t maxLen)572 napi_value ReminderCommon::ParseInt32Array(const napi_env &env, const napi_value &value,
573     const char* propertyName, std::vector<uint8_t> &propertyVal, uint8_t maxLen)
574 {
575     napi_value result = nullptr;
576     if (!GetObject(env, value, propertyName, result)) {
577         return NotificationNapi::Common::NapiGetNull(env);
578     }
579     if (result != nullptr) {
580         bool isArray = false;
581         napi_is_array(env, result, &isArray);
582         if (!isArray) {
583             ANSR_LOGW("Property %{public}s is expected to be an array.", propertyName);
584             return nullptr;
585         }
586         uint32_t length = 0;
587         napi_get_array_length(env, result, &length);
588         if (length > maxLen) {
589             ANSR_LOGW("The max length of array of %{public}s is %{public}hhu.", propertyName, maxLen);
590             return nullptr;
591         }
592         napi_valuetype valuetype = napi_undefined;
593         for (size_t i = 0; i < length; i++) {
594             int32_t propertyDayVal = 10;
595             napi_value repeatDayVal = nullptr;
596             napi_get_element(env, result, i, &repeatDayVal);
597             NAPI_CALL(env, napi_typeof(env, repeatDayVal, &valuetype));
598             if (valuetype != napi_number) {
599                 ANSR_LOGW("%{public}s's element is expected to be number.", propertyName);
600                 return nullptr;
601             }
602             napi_get_value_int32(env, repeatDayVal, &propertyDayVal);
603             if (propertyDayVal < 1 || propertyDayVal > static_cast<int32_t>(maxLen)) {
604                 ANSR_LOGW("%{public}s's element must between [1, %{public}d].", propertyName, maxLen);
605                 return nullptr;
606             }
607             propertyVal.push_back(static_cast<uint8_t>(propertyDayVal));
608         }
609     }
610     return NotificationNapi::Common::NapiGetNull(env);
611 }
612 
PaddingCallbackPromiseInfo(const napi_env & env,const napi_ref & callback,CallbackPromiseInfo & info,napi_value & promise)613 void ReminderCommon::PaddingCallbackPromiseInfo(
614     const napi_env &env, const napi_ref &callback, CallbackPromiseInfo &info, napi_value &promise)
615 {
616     if (callback) {
617         info.callback = callback;
618         info.isCallback = true;
619     } else {
620         napi_deferred deferred = nullptr;
621         NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, &deferred, &promise));
622         info.deferred = deferred;
623         info.isCallback = false;
624     }
625 }
626 
HandleErrCode(const napi_env & env,int32_t errCode)627 void ReminderCommon::HandleErrCode(const napi_env &env, int32_t errCode)
628 {
629     if (errCode == ERR_OK) {
630         return;
631     }
632     std::string errCodeMsg = reminderErrCodeMsgMap[errCode];
633     napi_throw_error(env, std::to_string(errCode).c_str(), errCodeMsg.c_str());
634 }
635 
FindErrMsg(const napi_env & env,const int32_t errCode)636 std::string ReminderCommon::FindErrMsg(const napi_env &env, const int32_t errCode)
637 {
638     auto findMsg = reminderErrCodeMsgMap.find(errCode);
639     if (findMsg == reminderErrCodeMsgMap.end()) {
640         ANSR_LOGI("Inner error.");
641         return "Inner error.";
642     }
643     return reminderErrCodeMsgMap[errCode];
644 }
645 
ReturnCallbackPromise(const napi_env & env,const CallbackPromiseInfo & info,const napi_value & result,bool isThrow)646 void ReminderCommon::ReturnCallbackPromise(const napi_env &env, const CallbackPromiseInfo &info,
647     const napi_value &result, bool isThrow)
648 {
649     ANSR_LOGI("enter errorCode=%{public}d", info.errorCode);
650     if (info.isCallback) {
651         if (isThrow) {
652             SetCallback(env, info.callback, info.errorCode, result);
653         } else {
654             NotificationNapi::Common::SetCallback(env, info.callback, info.errorCode, result, false);
655         }
656     } else {
657         SetPromise(env, info, result);
658     }
659     ANSR_LOGI("end");
660 }
661 
SetCallback(const napi_env & env,const napi_ref & callbackIn,const int32_t & errCode,const napi_value & result)662 void ReminderCommon::SetCallback(
663     const napi_env &env, const napi_ref &callbackIn, const int32_t &errCode, const napi_value &result)
664 {
665     napi_value undefined = nullptr;
666     napi_get_undefined(env, &undefined);
667 
668     napi_value callback = nullptr;
669     napi_value resultout = nullptr;
670     napi_get_reference_value(env, callbackIn, &callback);
671     napi_value results[ASYNC_CALLBACK_PARAM_NUM] = {nullptr};
672     if (errCode == ERR_OK) {
673         results[0] = NotificationNapi::Common::NapiGetNull(env);
674     } else {
675         std::string errMsg = FindErrMsg(env, errCode);
676         results[0] = GetCallbackErrorValue(env, errCode, errMsg);
677     }
678     results[1] = result;
679     NAPI_CALL_RETURN_VOID(env,
680         napi_call_function(env, undefined, callback, ASYNC_CALLBACK_PARAM_NUM, &results[0], &resultout));
681 }
682 
GetCallbackErrorValue(napi_env env,const int32_t errCode,const std::string errMsg)683 napi_value ReminderCommon::GetCallbackErrorValue(napi_env env, const int32_t errCode, const std::string errMsg)
684 {
685     if (errCode == ERR_OK) {
686         return NotificationNapi::Common::NapiGetNull(env);
687     }
688     napi_value error = nullptr;
689     napi_value eCode = nullptr;
690     napi_value eMsg = nullptr;
691     NAPI_CALL(env, napi_create_int32(env, errCode, &eCode));
692     NAPI_CALL(env, napi_create_string_utf8(env, errMsg.c_str(),
693         errMsg.length(), &eMsg));
694     NAPI_CALL(env, napi_create_object(env, &error));
695     NAPI_CALL(env, napi_set_named_property(env, error, "code", eCode));
696     NAPI_CALL(env, napi_set_named_property(env, error, "message", eMsg));
697     return error;
698 }
699 
SetPromise(const napi_env & env,const CallbackPromiseInfo & info,const napi_value & result)700 napi_value  ReminderCommon::SetPromise(
701     const napi_env &env, const CallbackPromiseInfo &info, const napi_value &result)
702 {
703     if (info.errorCode == ERR_OK) {
704         napi_resolve_deferred(env, info.deferred, result);
705     } else {
706         std::string errMsg = FindErrMsg(env, info.errorCode);
707         if (errMsg == "") {
708             return nullptr;
709         }
710         napi_value error = nullptr;
711         napi_value eCode = nullptr;
712         napi_value eMsg = nullptr;
713         NAPI_CALL(env, napi_create_int32(env, info.errorCode, &eCode));
714         NAPI_CALL(env, napi_create_string_utf8(env, errMsg.c_str(),
715             errMsg.length(), &eMsg));
716         NAPI_CALL(env, napi_create_object(env, &error));
717         NAPI_CALL(env, napi_set_named_property(env, error, "data", eCode));
718         NAPI_CALL(env, napi_set_named_property(env, error, "code", eCode));
719         NAPI_CALL(env, napi_set_named_property(env, error, "message", eMsg));
720         napi_reject_deferred(env, info.deferred, error);
721     }
722     return result;
723 }
724 
JSParaError(const napi_env & env,const napi_ref & callback)725 napi_value ReminderCommon::JSParaError(const napi_env &env, const napi_ref &callback)
726 {
727     if (callback) {
728         SetCallback(env, callback, ERR_REMINDER_INVALID_PARAM, nullptr);
729         return NotificationNapi::Common::NapiGetNull(env);
730     } else {
731         napi_value promise = nullptr;
732         napi_deferred deferred = nullptr;
733         napi_create_promise(env, &deferred, &promise);
734 
735         napi_value res = nullptr;
736         napi_value eCode = nullptr;
737         napi_value eMsg = nullptr;
738         std::string errMsg = FindErrMsg(env, ERR_REMINDER_INVALID_PARAM);
739         NAPI_CALL(env, napi_create_int32(env, ERR_REMINDER_INVALID_PARAM, &eCode));
740         NAPI_CALL(env, napi_create_string_utf8(env, errMsg.c_str(),
741             errMsg.length(), &eMsg));
742         NAPI_CALL(env, napi_create_object(env, &res));
743         NAPI_CALL(env, napi_set_named_property(env, res, "data", eCode));
744         NAPI_CALL(env, napi_set_named_property(env, res, "code", eCode));
745         NAPI_CALL(env, napi_set_named_property(env, res, "message", eMsg));
746         napi_reject_deferred(env, deferred, res);
747         return promise;
748     }
749 }
750 }
751 }