1 /*
2  * Copyright (c) 2021-2024 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 "subscribe.h"
17 #include "ans_inner_errors.h"
18 #include "inner_event.h"
19 #include <mutex>
20 #include <uv.h>
21 
22 namespace OHOS {
23 namespace NotificationNapi {
24 const int32_t SUBSRIBE_MAX_PARA = 3;
25 const int32_t NO_DELETE_REASON = -1;
26 
27 const std::string CONSUME = "onConsume";
28 const std::string CANCEL = "onCancel";
29 const std::string UPDATE = "onUpdate";
30 const std::string CONNECTED = "onConnect";
31 const std::string DIS_CONNECTED = "onDisconnect";
32 const std::string DIE = "onDestroy";
33 const std::string DISTURB_MODE_CHANGE = "onDisturbModeChange";
34 const std::string DISTURB_DATE_CHANGE = "onDoNotDisturbDateChange";
35 const std::string DISTURB_CHANGED = "onDoNotDisturbChanged";
36 const std::string ENABLE_NOTIFICATION_CHANGED = "OnEnabledNotificationChanged";
37 const std::string BADGE_CHANGED = "OnBadgeChanged";
38 const std::string BADGE_ENABLED_CHANGED = "OnBadgeEnabledChanged";
39 const std::string BATCH_CANCEL = "onBatchCancel";
40 
41 enum class Type {
42     UNKNOWN,
43     CANCEL,
44     BATCH_CANCEL,
45     CONSUME,
46     UPDATE,
47     CONNECTED,
48     DIS_CONNECTED,
49     DIE,
50     DISTURB_DATE_CHANGE,
51     DISTURB_CHANGED,
52     ENABLE_NOTIFICATION_CHANGED,
53     BADGE_CHANGED,
54     BADGE_ENABLED_CHANGED
55 };
56 
57 struct NotificationReceiveDataWorker {
58     napi_env env = nullptr;
59     napi_ref ref = nullptr;
60     std::shared_ptr<OHOS::Notification::Notification> request;
61     std::vector<std::shared_ptr<OHOS::Notification::Notification>> requestList;
62     std::shared_ptr<NotificationSortingMap> sortingMap;
63     NotificationDoNotDisturbDate date;
64     EnabledNotificationCallbackData callbackData;
65     BadgeNumberCallbackData badge;
66     int32_t deleteReason = 0;
67     int32_t result = 0;
68     int32_t disturbMode = 0;
69     std::shared_ptr<SubscriberInstance> subscriber = nullptr;
70     Type type;
71 };
72 
SetSubscribeCallbackData(const napi_env & env,const std::shared_ptr<OHOS::Notification::Notification> & request,const std::shared_ptr<NotificationSortingMap> & sortingMap,int32_t deleteReason,napi_value & result)73 napi_value SetSubscribeCallbackData(const napi_env &env,
74     const std::shared_ptr<OHOS::Notification::Notification> &request,
75     const std::shared_ptr<NotificationSortingMap> &sortingMap, int32_t deleteReason, napi_value &result)
76 {
77     ANS_LOGD("enter");
78     if (request == nullptr) {
79         ANS_LOGE("request is null");
80         return Common::NapiGetBoolean(env, false);
81     }
82 
83     if (sortingMap == nullptr) {
84         ANS_LOGE("sortingMap is null");
85         return Common::NapiGetBoolean(env, false);
86     }
87 
88     // request: NotificationRequest
89     napi_value requestResult = nullptr;
90     napi_create_object(env, &requestResult);
91     if (!Common::SetNotification(env, request.get(), requestResult)) {
92         ANS_LOGE("SetNotification call failed");
93         return Common::NapiGetBoolean(env, false);
94     }
95     napi_set_named_property(env, result, "request", requestResult);
96 
97     // sortingMap?: NotificationSortingMap
98     napi_value sortingMapResult = nullptr;
99     napi_create_object(env, &sortingMapResult);
100     if (!Common::SetNotificationSortingMap(env, sortingMap, sortingMapResult)) {
101         ANS_LOGE("SetNotificationSortingMap call failed");
102         return Common::NapiGetBoolean(env, false);
103     }
104     napi_set_named_property(env, result, "sortingMap", sortingMapResult);
105 
106     // reason?: number
107     if (deleteReason != NO_DELETE_REASON) {
108         napi_value value = nullptr;
109         int32_t outReason = 0;
110         if (!AnsEnumUtil::ReasonCToJS(deleteReason, outReason)) {
111             return Common::NapiGetBoolean(env, false);
112         }
113         napi_create_int32(env, outReason, &value);
114         napi_set_named_property(env, result, "reason", value);
115     }
116 
117     // sound?: string
118     napi_value soundResult = nullptr;
119     std::string sound;
120     if (request->EnableSound()) {
121         sound = request->GetSound().ToString();
122     }
123     napi_create_string_utf8(env, sound.c_str(), NAPI_AUTO_LENGTH, &soundResult);
124     napi_set_named_property(env, result, "sound", soundResult);
125 
126     // vibrationValues?: Array<number>
127     napi_value arr = nullptr;
128     napi_create_array(env, &arr);
129     if (request->EnableVibrate()) {
130         uint32_t count = 0;
131         for (auto vec : request->GetVibrationStyle()) {
132             napi_value nVibrationValue = nullptr;
133             napi_create_int64(env, vec, &nVibrationValue);
134             napi_set_element(env, arr, count, nVibrationValue);
135             count++;
136         }
137     }
138     napi_set_named_property(env, result, "vibrationValues", arr);
139 
140     return Common::NapiGetBoolean(env, true);
141 }
142 
SubscriberInstance()143 SubscriberInstance::SubscriberInstance()
144 {}
145 
~SubscriberInstance()146 SubscriberInstance::~SubscriberInstance()
147 {
148     if (tsfn_ != nullptr) {
149         napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
150     }
151     if (canceCallbackInfo_.ref != nullptr) {
152         napi_delete_reference(canceCallbackInfo_.env, canceCallbackInfo_.ref);
153     }
154     if (consumeCallbackInfo_.ref != nullptr) {
155         napi_delete_reference(consumeCallbackInfo_.env, consumeCallbackInfo_.ref);
156     }
157     if (updateCallbackInfo_.ref != nullptr) {
158         napi_delete_reference(updateCallbackInfo_.env, updateCallbackInfo_.ref);
159     }
160     if (subscribeCallbackInfo_.ref != nullptr) {
161         napi_delete_reference(subscribeCallbackInfo_.env, subscribeCallbackInfo_.ref);
162     }
163     if (unsubscribeCallbackInfo_.ref != nullptr) {
164         napi_delete_reference(unsubscribeCallbackInfo_.env, unsubscribeCallbackInfo_.ref);
165     }
166     if (dieCallbackInfo_.ref != nullptr) {
167         napi_delete_reference(dieCallbackInfo_.env, dieCallbackInfo_.ref);
168     }
169     if (disturbModeCallbackInfo_.ref != nullptr) {
170         napi_delete_reference(disturbModeCallbackInfo_.env, disturbModeCallbackInfo_.ref);
171     }
172     if (enabledNotificationCallbackInfo_.ref != nullptr) {
173         napi_delete_reference(enabledNotificationCallbackInfo_.env, enabledNotificationCallbackInfo_.ref);
174     }
175     if (batchCancelCallbackInfo_.ref != nullptr) {
176         napi_delete_reference(batchCancelCallbackInfo_.env, batchCancelCallbackInfo_.ref);
177     }
178 }
179 
ThreadSafeOnCancel(napi_env env,napi_value jsCallback,void * context,void * data)180 void ThreadSafeOnCancel(napi_env env, napi_value jsCallback, void* context, void* data)
181 {
182     ANS_LOGI("OnCanceled thread safe start");
183 
184     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
185     if (dataWorkerData == nullptr) {
186         ANS_LOGE("Create dataWorkerData failed.");
187         return;
188     }
189 
190     napi_value result = nullptr;
191     napi_handle_scope scope;
192     napi_open_handle_scope(dataWorkerData->env, &scope);
193     if (scope == nullptr) {
194         ANS_LOGE("Scope is null");
195         return;
196     }
197     napi_create_object(dataWorkerData->env, &result);
198     if (!SetSubscribeCallbackData(dataWorkerData->env,
199         dataWorkerData->request,
200         dataWorkerData->sortingMap,
201         dataWorkerData->deleteReason,
202         result)) {
203         ANS_LOGE("Failed to convert data to JS");
204     } else {
205         Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
206     }
207     napi_close_handle_scope(dataWorkerData->env, scope);
208 
209     delete dataWorkerData;
210     dataWorkerData = nullptr;
211 }
212 
OnCanceled(const std::shared_ptr<OHOS::Notification::Notification> & request,const std::shared_ptr<NotificationSortingMap> & sortingMap,int32_t deleteReason)213 void SubscriberInstance::OnCanceled(const std::shared_ptr<OHOS::Notification::Notification> &request,
214     const std::shared_ptr<NotificationSortingMap> &sortingMap, int32_t deleteReason)
215 {
216     ANS_LOGD("enter");
217 
218     if (canceCallbackInfo_.ref == nullptr || canceCallbackInfo_.env == nullptr) {
219         ANS_LOGI("cancel callback or env unset");
220         return;
221     }
222 
223     if (request == nullptr) {
224         ANS_LOGE("request is null");
225         return;
226     }
227 
228     if (sortingMap == nullptr) {
229         ANS_LOGE("sortingMap is null");
230         return;
231     }
232     ANS_LOGI("OnCanceled NotificationKey = %{public}s. sortingMap size = %{public}zu. deleteReason = %{public}d",
233         request->GetKey().c_str(), sortingMap->GetKey().size(), deleteReason);
234 
235     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
236     if (dataWorker == nullptr) {
237         ANS_LOGE("DataWorker is nullptr.");
238         return;
239     }
240 
241     dataWorker->request = request;
242     dataWorker->sortingMap = sortingMap;
243     dataWorker->deleteReason = deleteReason;
244     dataWorker->env = canceCallbackInfo_.env;
245     dataWorker->ref = canceCallbackInfo_.ref;
246     dataWorker->type = Type::CANCEL;
247 
248     napi_acquire_threadsafe_function(tsfn_);
249     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
250     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
251 }
252 
ThreadSafeOnBatchCancel(napi_env env,napi_value jsCallback,void * context,void * data)253 void ThreadSafeOnBatchCancel(napi_env env, napi_value jsCallback, void* context, void* data)
254 {
255     ANS_LOGI("OnBatchCancel thread safe start");
256 
257     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
258     if (dataWorkerData == nullptr) {
259         ANS_LOGE("Create dataWorkerData failed.");
260         return;
261     }
262 
263     napi_value resultArray = nullptr;
264     napi_handle_scope scope;
265     napi_open_handle_scope(dataWorkerData->env, &scope);
266     if (scope == nullptr) {
267         ANS_LOGE("Scope is null");
268         return;
269     }
270     napi_create_array(dataWorkerData->env, &resultArray);
271     int index = 0;
272     for (auto request : dataWorkerData->requestList) {
273         napi_value result = nullptr;
274         napi_create_object(dataWorkerData->env, &result);
275         if (SetSubscribeCallbackData(dataWorkerData->env, request,
276             dataWorkerData->sortingMap, dataWorkerData->deleteReason, result)) {
277             napi_set_element(dataWorkerData->env, resultArray, index, result);
278             index++;
279         }
280     }
281     uint32_t elementCount = 0;
282     napi_get_array_length(dataWorkerData->env, resultArray, &elementCount);
283     ANS_LOGI("notification array length: %{public}d ", elementCount);
284     if (elementCount > 0) {
285         Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, resultArray);
286     }
287 
288     napi_close_handle_scope(dataWorkerData->env, scope);
289 
290     delete dataWorkerData;
291     dataWorkerData = nullptr;
292 }
293 
OnBatchCanceled(const std::vector<std::shared_ptr<OHOS::Notification::Notification>> & requestList,const std::shared_ptr<NotificationSortingMap> & sortingMap,int32_t deleteReason)294 void SubscriberInstance::OnBatchCanceled(const std::vector<std::shared_ptr<OHOS::Notification::Notification>>
295     &requestList, const std::shared_ptr<NotificationSortingMap> &sortingMap, int32_t deleteReason)
296 {
297     ANS_LOGI("OnBatchCancel");
298     if (batchCancelCallbackInfo_.ref == nullptr || batchCancelCallbackInfo_.env == nullptr) {
299         ANS_LOGI("batchCancelCallbackInfo_ callback or env unset");
300         return;
301     }
302     if (requestList.empty()) {
303         ANS_LOGE("requestList is empty");
304         return;
305     }
306     if (sortingMap == nullptr) {
307         ANS_LOGE("sortingMap is null");
308         return;
309     }
310     ANS_LOGI("OnBatchCancel sortingMap size = %{public}zu", sortingMap->GetKey().size());
311     ANS_LOGI("OnBatchCancel deleteReason = %{public}d", deleteReason);
312     std::string notificationKeys = "";
313     for (auto notification : requestList) {
314         notificationKeys.append(notification->GetKey()).append("-");
315     }
316     ANS_LOGI("OnBatchCancel. cancel keys = %{public}s", notificationKeys.c_str());
317 
318     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
319     if (dataWorker == nullptr) {
320         ANS_LOGE("DataWorker is nullptr.");
321         return;
322     }
323     dataWorker->requestList = requestList;
324     dataWorker->sortingMap = sortingMap;
325     dataWorker->deleteReason = deleteReason;
326     dataWorker->env = batchCancelCallbackInfo_.env;
327     dataWorker->ref = batchCancelCallbackInfo_.ref;
328     dataWorker->type = Type::BATCH_CANCEL;
329 
330     napi_acquire_threadsafe_function(tsfn_);
331     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
332     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
333     return;
334 }
335 
HasOnBatchCancelCallback()336 bool SubscriberInstance::HasOnBatchCancelCallback()
337 {
338     if (batchCancelCallbackInfo_.ref == nullptr) {
339         ANS_LOGI("batchCancelCallbackInfo_ callback unset");
340         return false;
341     }
342     return true;
343 }
344 
ThreadSafeOnConsumed(napi_env env,napi_value jsCallback,void * context,void * data)345 void ThreadSafeOnConsumed(napi_env env, napi_value jsCallback, void* context, void* data)
346 {
347     ANS_LOGI("OnConsumed thread safe start");
348 
349     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
350     if (dataWorkerData == nullptr) {
351         ANS_LOGD("dataWorkerData is null.");
352         return;
353     }
354     napi_value result = nullptr;
355     napi_handle_scope scope;
356     napi_open_handle_scope(dataWorkerData->env, &scope);
357     if (scope == nullptr) {
358         ANS_LOGE("Scope is null");
359         return;
360     }
361     napi_create_object(dataWorkerData->env, &result);
362     if (!SetSubscribeCallbackData(dataWorkerData->env,
363         dataWorkerData->request,
364         dataWorkerData->sortingMap,
365         NO_DELETE_REASON,
366         result)) {
367         ANS_LOGE("Convert data to JS fail.");
368     } else {
369         Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
370     }
371     napi_close_handle_scope(dataWorkerData->env, scope);
372 
373     delete dataWorkerData;
374     dataWorkerData = nullptr;
375 }
376 
OnConsumed(const std::shared_ptr<OHOS::Notification::Notification> & request,const std::shared_ptr<NotificationSortingMap> & sortingMap)377 void SubscriberInstance::OnConsumed(const std::shared_ptr<OHOS::Notification::Notification> &request,
378     const std::shared_ptr<NotificationSortingMap> &sortingMap)
379 {
380     ANS_LOGD("enter");
381 
382     if (consumeCallbackInfo_.ref == nullptr || consumeCallbackInfo_.env == nullptr) {
383         ANS_LOGI("consume callback or env unset");
384         return;
385     }
386 
387     if (tsfn_ == nullptr) {
388         ANS_LOGI("consume tsfn is null");
389         return;
390     }
391 
392     if (request == nullptr) {
393         ANS_LOGE("request is nullptr.");
394         return;
395     }
396 
397     if (sortingMap == nullptr) {
398         ANS_LOGE("sortingMap is nullptr.");
399         return;
400     }
401     auto notificationFlags = request->GetNotificationRequest().GetFlags();
402     ANS_LOGI("OnConsumed Notification key = %{public}s, sortingMap size = %{public}zu, notificationFlag = %{public}s",
403         request->GetKey().c_str(), sortingMap->GetKey().size(),
404         notificationFlags == nullptr ? "null" : notificationFlags->Dump().c_str());
405     ANS_LOGD("OnConsumed Notification info is %{public}s", request->GetNotificationRequest().Dump().c_str());
406 
407     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
408     if (dataWorker == nullptr) {
409         ANS_LOGE("new dataWorker failed");
410         return;
411     }
412 
413     dataWorker->request = request;
414     dataWorker->sortingMap = sortingMap;
415     dataWorker->env = consumeCallbackInfo_.env;
416     dataWorker->ref = consumeCallbackInfo_.ref;
417     dataWorker->type = Type::CONSUME;
418     napi_acquire_threadsafe_function(tsfn_);
419     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
420     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
421 }
422 
ThreadSafeOnUpdate(napi_env env,napi_value jsCallback,void * context,void * data)423 void ThreadSafeOnUpdate(napi_env env, napi_value jsCallback, void* context, void* data)
424 {
425     ANS_LOGI("OnUpdate thread safe start");
426 
427     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
428     if (dataWorkerData == nullptr) {
429         ANS_LOGE("dataWorkerData is nullptr");
430         return;
431     }
432     napi_value result = nullptr;
433     napi_handle_scope scope;
434     napi_open_handle_scope(dataWorkerData->env, &scope);
435     if (scope == nullptr) {
436         ANS_LOGE("Scope is null");
437         return;
438     }
439     napi_create_object(dataWorkerData->env, &result);
440     if (!Common::SetNotificationSortingMap(dataWorkerData->env, dataWorkerData->sortingMap, result)) {
441         ANS_LOGE("Failed to convert data to JS");
442     } else {
443         Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
444     }
445     napi_close_handle_scope(dataWorkerData->env, scope);
446 
447     delete dataWorkerData;
448     dataWorkerData = nullptr;
449 }
450 
OnUpdate(const std::shared_ptr<NotificationSortingMap> & sortingMap)451 void SubscriberInstance::OnUpdate(const std::shared_ptr<NotificationSortingMap> &sortingMap)
452 {
453     ANS_LOGD("enter");
454 
455     if (updateCallbackInfo_.ref == nullptr || updateCallbackInfo_.env == nullptr) {
456         ANS_LOGI("update callback or env unset");
457         return;
458     }
459 
460     if (sortingMap == nullptr) {
461         ANS_LOGE("sortingMap is null");
462         return;
463     }
464     ANS_LOGI("OnUpdate sortingMap size = %{public}zu", sortingMap->GetKey().size());
465 
466     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
467     if (dataWorker == nullptr) {
468         ANS_LOGE("new dataWorker failed");
469         return;
470     }
471 
472     dataWorker->sortingMap = sortingMap;
473     dataWorker->env = updateCallbackInfo_.env;
474     dataWorker->ref = updateCallbackInfo_.ref;
475     dataWorker->type = Type::UPDATE;
476 
477     napi_acquire_threadsafe_function(tsfn_);
478     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
479     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
480 }
481 
ThreadSafeOnConnected(napi_env env,napi_value jsCallback,void * context,void * data)482 void ThreadSafeOnConnected(napi_env env, napi_value jsCallback, void* context, void* data)
483 {
484     ANS_LOGD("OnConnected thread safe start");
485     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
486     if (dataWorkerData == nullptr) {
487         ANS_LOGE("dataWorkerData is nullptr.");
488         return;
489     }
490 
491     Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, Common::NapiGetNull(dataWorkerData->env));
492 
493     delete dataWorkerData;
494     dataWorkerData = nullptr;
495 }
496 
OnConnected()497 void SubscriberInstance::OnConnected()
498 {
499     ANS_LOGD("enter");
500 
501     if (subscribeCallbackInfo_.ref == nullptr || subscribeCallbackInfo_.env == nullptr) {
502         ANS_LOGI("subscribe callback or env unset");
503         return;
504     }
505 
506     if (tsfn_ == nullptr) {
507         ANS_LOGI("subscribe tsfn is null");
508         return;
509     }
510 
511     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
512     if (dataWorker == nullptr) {
513         ANS_LOGE("new dataWorker failed");
514         return;
515     }
516 
517     dataWorker->env = subscribeCallbackInfo_.env;
518     dataWorker->ref = subscribeCallbackInfo_.ref;
519     dataWorker->type = Type::CONNECTED;
520 
521     napi_acquire_threadsafe_function(tsfn_);
522     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
523     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
524 }
525 
ThreadSafeOnDisconnected(napi_env env,napi_value jsCallback,void * context,void * data)526 void ThreadSafeOnDisconnected(napi_env env, napi_value jsCallback, void* context, void* data)
527 {
528     ANS_LOGI("OnDisconnected thread safe start");
529 
530     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
531     if (dataWorkerData == nullptr) {
532         ANS_LOGE("Failed to create dataWorkerData.");
533         return;
534     }
535 
536     Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, Common::NapiGetNull(dataWorkerData->env));
537     DelSubscriberInstancesInfo(dataWorkerData->env, dataWorkerData->subscriber);
538     delete dataWorkerData;
539     dataWorkerData = nullptr;
540 }
541 
OnDisconnected()542 void SubscriberInstance::OnDisconnected()
543 {
544     ANS_LOGD("enter");
545 
546     if (unsubscribeCallbackInfo_.ref == nullptr) {
547         ANS_LOGI("unsubscribe callback unset");
548         return;
549     }
550 
551     if (tsfn_ == nullptr) {
552         ANS_LOGI("unsubscribe tsfn is null");
553         return;
554     }
555 
556     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
557     if (dataWorker == nullptr) {
558         ANS_LOGE("new dataWorker failed");
559         return;
560     }
561 
562     dataWorker->env = unsubscribeCallbackInfo_.env;
563     dataWorker->ref = unsubscribeCallbackInfo_.ref;
564     dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
565     dataWorker->type = Type::DIS_CONNECTED;
566 
567     napi_acquire_threadsafe_function(tsfn_);
568     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
569     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
570 }
571 
ThreadSafeOnDestroy(napi_env env,napi_value jsCallback,void * context,void * data)572 void ThreadSafeOnDestroy(napi_env env, napi_value jsCallback, void* context, void* data)
573 {
574     ANS_LOGI("OnDied thread safe start");
575 
576     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
577     if (dataWorkerData == nullptr) {
578         ANS_LOGE("dataWorkerData is null");
579         return;
580     }
581 
582     Common::SetCallback(
583         dataWorkerData->env, dataWorkerData->ref, Common::NapiGetNull(dataWorkerData->env));
584 
585     delete dataWorkerData;
586     dataWorkerData = nullptr;
587 }
588 
OnDied()589 void SubscriberInstance::OnDied()
590 {
591     ANS_LOGD("enter");
592 
593     if (dieCallbackInfo_.ref == nullptr) {
594         ANS_LOGE("die callback unset");
595         return;
596     }
597 
598     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
599     if (dataWorker == nullptr) {
600         ANS_LOGE("new dataWorker failed");
601         return;
602     }
603 
604     dataWorker->env = dieCallbackInfo_.env;
605     dataWorker->ref = dieCallbackInfo_.ref;
606     dataWorker->type = Type::DIE;
607 
608     napi_acquire_threadsafe_function(tsfn_);
609     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
610     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
611 }
612 
ThreadSafeOnDoNotDisturbDateChange(napi_env env,napi_value jsCallback,void * context,void * data)613 void ThreadSafeOnDoNotDisturbDateChange(napi_env env, napi_value jsCallback, void* context, void* data)
614 {
615     ANS_LOGI("OnDoNotDisturbDateChange thread safe start");
616 
617     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
618     if (dataWorkerData == nullptr) {
619         ANS_LOGE("Data worker data is null.");
620         return;
621     }
622 
623     napi_value result = nullptr;
624     napi_handle_scope scope;
625     napi_open_handle_scope(dataWorkerData->env, &scope);
626     if (scope == nullptr) {
627         ANS_LOGE("Scope is null");
628         return;
629     }
630     napi_create_object(dataWorkerData->env, &result);
631 
632     if (!Common::SetDoNotDisturbDate(dataWorkerData->env, dataWorkerData->date, result)) {
633         result = Common::NapiGetNull(dataWorkerData->env);
634     }
635 
636     Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
637     napi_close_handle_scope(dataWorkerData->env, scope);
638 
639     delete dataWorkerData;
640     dataWorkerData = nullptr;
641 }
642 
OnDoNotDisturbDateChange(const std::shared_ptr<NotificationDoNotDisturbDate> & date)643 void SubscriberInstance::OnDoNotDisturbDateChange(const std::shared_ptr<NotificationDoNotDisturbDate> &date)
644 {
645     ANS_LOGD("enter");
646 
647     onDoNotDisturbChanged(date);
648 
649     if (disturbDateCallbackInfo_.ref == nullptr || disturbDateCallbackInfo_.env == nullptr) {
650         ANS_LOGI("disturbDateCallbackInfo_ callback or env unset");
651         return;
652     }
653 
654     if (date == nullptr) {
655         ANS_LOGE("date is null");
656         return;
657     }
658 
659     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
660     if (dataWorker == nullptr) {
661         ANS_LOGE("new dataWorker failed");
662         return;
663     }
664 
665     dataWorker->date = *date;
666     dataWorker->env = disturbDateCallbackInfo_.env;
667     dataWorker->ref = disturbDateCallbackInfo_.ref;
668     dataWorker->type = Type::DISTURB_DATE_CHANGE;
669 
670     napi_acquire_threadsafe_function(tsfn_);
671     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
672     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
673 }
674 
675 
ThreadSafeOnDoNotDisturbChanged(napi_env env,napi_value jsCallback,void * context,void * data)676 void ThreadSafeOnDoNotDisturbChanged(napi_env env, napi_value jsCallback, void* context, void* data)
677 {
678     ANS_LOGI("OnDoNotDisturbChanged thread safe start");
679 
680     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
681     if (dataWorkerData == nullptr) {
682         ANS_LOGE("Data worker data is null.");
683         return;
684     }
685 
686     napi_value result = nullptr;
687     napi_handle_scope scope;
688     napi_open_handle_scope(dataWorkerData->env, &scope);
689     napi_create_object(dataWorkerData->env, &result);
690 
691     if (!Common::SetDoNotDisturbDate(dataWorkerData->env, dataWorkerData->date, result)) {
692         result = Common::NapiGetNull(dataWorkerData->env);
693     }
694 
695     Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
696     napi_close_handle_scope(dataWorkerData->env, scope);
697 
698     delete dataWorkerData;
699     dataWorkerData = nullptr;
700 }
701 
onDoNotDisturbChanged(const std::shared_ptr<NotificationDoNotDisturbDate> & date)702 void SubscriberInstance::onDoNotDisturbChanged(const std::shared_ptr<NotificationDoNotDisturbDate>& date)
703 {
704     ANS_LOGD("enter");
705 
706     if (disturbChangedCallbackInfo_.ref == nullptr || disturbChangedCallbackInfo_.env == nullptr) {
707         ANS_LOGE("disturbChangedCallbackInfo_ callback or env unset");
708         return;
709     }
710 
711     if (date == nullptr) {
712         ANS_LOGE("date is null");
713         return;
714     }
715 
716     NotificationReceiveDataWorker* dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
717     if (dataWorker == nullptr) {
718         ANS_LOGE("new dataWorker failed");
719         return;
720     }
721 
722     dataWorker->date = *date;
723     dataWorker->env = disturbChangedCallbackInfo_.env;
724     dataWorker->ref = disturbChangedCallbackInfo_.ref;
725     dataWorker->type = Type::DISTURB_CHANGED;
726 
727     napi_acquire_threadsafe_function(tsfn_);
728     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
729     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
730 }
731 
ThreadSafeOnEnabledNotificationChanged(napi_env env,napi_value jsCallback,void * context,void * data)732 void ThreadSafeOnEnabledNotificationChanged(napi_env env, napi_value jsCallback, void* context, void* data)
733 {
734     ANS_LOGI("OnEnabledNotificationChanged thread safe start");
735 
736     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
737     if (dataWorkerData == nullptr) {
738         ANS_LOGE("Data worker data is null.");
739         return;
740     }
741 
742     napi_value result = nullptr;
743     napi_handle_scope scope;
744     napi_open_handle_scope(dataWorkerData->env, &scope);
745     if (scope == nullptr) {
746         ANS_LOGE("Scope is null");
747         return;
748     }
749     napi_create_object(dataWorkerData->env, &result);
750 
751     if (!Common::SetEnabledNotificationCallbackData(dataWorkerData->env, dataWorkerData->callbackData, result)) {
752         result = Common::NapiGetNull(dataWorkerData->env);
753     }
754 
755     Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
756     napi_close_handle_scope(dataWorkerData->env, scope);
757 
758     delete dataWorkerData;
759     dataWorkerData = nullptr;
760 }
761 
OnEnabledNotificationChanged(const std::shared_ptr<EnabledNotificationCallbackData> & callbackData)762 void SubscriberInstance::OnEnabledNotificationChanged(
763     const std::shared_ptr<EnabledNotificationCallbackData> &callbackData)
764 {
765     ANS_LOGD("enter");
766 
767     if (enabledNotificationCallbackInfo_.ref == nullptr || enabledNotificationCallbackInfo_.env == nullptr) {
768         ANS_LOGI("enabledNotificationCallbackInfo_ callback or env unset");
769         return;
770     }
771 
772     if (callbackData == nullptr) {
773         ANS_LOGE("callbackData is null");
774         return;
775     }
776 
777     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
778     if (dataWorker == nullptr) {
779         ANS_LOGE("new dataWorker failed");
780         return;
781     }
782 
783     dataWorker->callbackData = *callbackData;
784     dataWorker->env = enabledNotificationCallbackInfo_.env;
785     dataWorker->ref = enabledNotificationCallbackInfo_.ref;
786     dataWorker->type = Type::ENABLE_NOTIFICATION_CHANGED;
787 
788     napi_acquire_threadsafe_function(tsfn_);
789     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
790     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
791 }
792 
ThreadSafeOnBadgeChanged(napi_env env,napi_value jsCallback,void * context,void * data)793 void ThreadSafeOnBadgeChanged(napi_env env, napi_value jsCallback, void* context, void* data)
794 {
795     ANS_LOGI("OnBadgeChanged thread safe start");
796 
797     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
798     if (dataWorkerData == nullptr) {
799         ANS_LOGE("dataWorkerData is null");
800         return;
801     }
802 
803     napi_value result = nullptr;
804     napi_handle_scope scope;
805     napi_open_handle_scope(dataWorkerData->env, &scope);
806     if (scope == nullptr) {
807         ANS_LOGE("Scope is null");
808         return;
809     }
810     napi_create_object(dataWorkerData->env, &result);
811 
812     if (!Common::SetBadgeCallbackData(dataWorkerData->env, dataWorkerData->badge, result)) {
813         result = Common::NapiGetNull(dataWorkerData->env);
814     }
815 
816     Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
817     napi_close_handle_scope(dataWorkerData->env, scope);
818 
819     delete dataWorkerData;
820     dataWorkerData = nullptr;
821 }
822 
OnBadgeChanged(const std::shared_ptr<BadgeNumberCallbackData> & badgeData)823 void SubscriberInstance::OnBadgeChanged(
824     const std::shared_ptr<BadgeNumberCallbackData> &badgeData)
825 {
826     ANS_LOGD("enter");
827 
828     if (setBadgeCallbackInfo_.ref == nullptr || setBadgeCallbackInfo_.env == nullptr) {
829         return;
830     }
831 
832     if (badgeData == nullptr) {
833         ANS_LOGE("badgeData is null");
834         return;
835     }
836 
837     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
838     if (dataWorker == nullptr) {
839         ANS_LOGE("new dataWorker failed");
840         return;
841     }
842 
843     dataWorker->badge = *badgeData;
844     dataWorker->env = setBadgeCallbackInfo_.env;
845     dataWorker->ref = setBadgeCallbackInfo_.ref;
846     dataWorker->type = Type::BADGE_CHANGED;
847 
848     napi_acquire_threadsafe_function(tsfn_);
849     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
850     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
851 }
852 
ThreadSafeOnBadgeEnabledChanged(napi_env env,napi_value jsCallback,void * context,void * data)853 void ThreadSafeOnBadgeEnabledChanged(napi_env env, napi_value jsCallback, void* context, void* data)
854 {
855     ANS_LOGI("OnBadgeEnabledChanged thread safe start.");
856 
857     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
858     if (dataWorkerData == nullptr) {
859         ANS_LOGE("Data worker is null.");
860         return;
861     }
862 
863     napi_value result = nullptr;
864     napi_handle_scope scope;
865     napi_open_handle_scope(dataWorkerData->env, &scope);
866     if (scope == nullptr) {
867         ANS_LOGE("Scope is null");
868         return;
869     }
870     napi_create_object(dataWorkerData->env, &result);
871     if (!Common::SetEnabledNotificationCallbackData(dataWorkerData->env, dataWorkerData->callbackData, result)) {
872         result = Common::NapiGetNull(dataWorkerData->env);
873     }
874 
875     Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
876     napi_close_handle_scope(dataWorkerData->env, scope);
877 
878     delete dataWorkerData;
879     dataWorkerData = nullptr;
880 }
881 
OnBadgeEnabledChanged(const sptr<EnabledNotificationCallbackData> & callbackData)882 void SubscriberInstance::OnBadgeEnabledChanged(
883     const sptr<EnabledNotificationCallbackData> &callbackData)
884 {
885     if (setBadgeEnabledCallbackInfo_.ref == nullptr) {
886         ANS_LOGE("Set badge enabled callback info is null.");
887         return;
888     }
889     if (callbackData == nullptr) {
890         ANS_LOGE("Callback data is null.");
891         return;
892     }
893 
894     NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
895     if (dataWorker == nullptr) {
896         ANS_LOGE("Create new data worker failed.");
897         return;
898     }
899 
900     dataWorker->callbackData = *callbackData;
901     dataWorker->env = setBadgeEnabledCallbackInfo_.env;
902     dataWorker->ref = setBadgeEnabledCallbackInfo_.ref;
903     dataWorker->type = Type::BADGE_ENABLED_CHANGED;
904 
905     napi_acquire_threadsafe_function(tsfn_);
906     napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
907     napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
908 }
909 
SetThreadSafeFunction(const napi_threadsafe_function & tsfn)910 void SubscriberInstance::SetThreadSafeFunction(const napi_threadsafe_function &tsfn)
911 {
912     tsfn_ = tsfn;
913 }
914 
SetCancelCallbackInfo(const napi_env & env,const napi_ref & ref)915 void SubscriberInstance::SetCancelCallbackInfo(const napi_env &env, const napi_ref &ref)
916 {
917     canceCallbackInfo_.env = env;
918     canceCallbackInfo_.ref = ref;
919 }
920 
SetConsumeCallbackInfo(const napi_env & env,const napi_ref & ref)921 void SubscriberInstance::SetConsumeCallbackInfo(const napi_env &env, const napi_ref &ref)
922 {
923     consumeCallbackInfo_.env = env;
924     consumeCallbackInfo_.ref = ref;
925 }
926 
SetUpdateCallbackInfo(const napi_env & env,const napi_ref & ref)927 void SubscriberInstance::SetUpdateCallbackInfo(const napi_env &env, const napi_ref &ref)
928 {
929     updateCallbackInfo_.env = env;
930     updateCallbackInfo_.ref = ref;
931 }
932 
SetSubscribeCallbackInfo(const napi_env & env,const napi_ref & ref)933 void SubscriberInstance::SetSubscribeCallbackInfo(const napi_env &env, const napi_ref &ref)
934 {
935     subscribeCallbackInfo_.env = env;
936     subscribeCallbackInfo_.ref = ref;
937 }
938 
SetUnsubscribeCallbackInfo(const napi_env & env,const napi_ref & ref)939 void SubscriberInstance::SetUnsubscribeCallbackInfo(const napi_env &env, const napi_ref &ref)
940 {
941     unsubscribeCallbackInfo_.env = env;
942     unsubscribeCallbackInfo_.ref = ref;
943 }
944 
SetDieCallbackInfo(const napi_env & env,const napi_ref & ref)945 void SubscriberInstance::SetDieCallbackInfo(const napi_env &env, const napi_ref &ref)
946 {
947     dieCallbackInfo_.env = env;
948     dieCallbackInfo_.ref = ref;
949 }
950 
SetDisturbModeCallbackInfo(const napi_env & env,const napi_ref & ref)951 void SubscriberInstance::SetDisturbModeCallbackInfo(const napi_env &env, const napi_ref &ref)
952 {
953     disturbModeCallbackInfo_.env = env;
954     disturbModeCallbackInfo_.ref = ref;
955 }
956 
SetEnabledNotificationCallbackInfo(const napi_env & env,const napi_ref & ref)957 void SubscriberInstance::SetEnabledNotificationCallbackInfo(const napi_env &env, const napi_ref &ref)
958 {
959     enabledNotificationCallbackInfo_.env = env;
960     enabledNotificationCallbackInfo_.ref = ref;
961 }
962 
SetDisturbDateCallbackInfo(const napi_env & env,const napi_ref & ref)963 void SubscriberInstance::SetDisturbDateCallbackInfo(const napi_env &env, const napi_ref &ref)
964 {
965     disturbDateCallbackInfo_.env = env;
966     disturbDateCallbackInfo_.ref = ref;
967 }
968 
SetDisturbChangedCallbackInfo(const napi_env & env,const napi_ref & ref)969 void SubscriberInstance::SetDisturbChangedCallbackInfo(const napi_env &env, const napi_ref &ref)
970 {
971     disturbChangedCallbackInfo_.env = env;
972     disturbChangedCallbackInfo_.ref = ref;
973 }
974 
SetBadgeCallbackInfo(const napi_env & env,const napi_ref & ref)975 void SubscriberInstance::SetBadgeCallbackInfo(const napi_env &env, const napi_ref &ref)
976 {
977     setBadgeCallbackInfo_.env = env;
978     setBadgeCallbackInfo_.ref = ref;
979 }
980 
981 
SetBadgeEnabledCallbackInfo(const napi_env & env,const napi_ref & ref)982 void SubscriberInstance::SetBadgeEnabledCallbackInfo(const napi_env &env, const napi_ref &ref)
983 {
984     setBadgeEnabledCallbackInfo_.env = env;
985     setBadgeEnabledCallbackInfo_.ref = ref;
986 }
987 
SetBatchCancelCallbackInfo(const napi_env & env,const napi_ref & ref)988 void SubscriberInstance::SetBatchCancelCallbackInfo(const napi_env &env, const napi_ref &ref)
989 {
990     batchCancelCallbackInfo_.env = env;
991     batchCancelCallbackInfo_.ref = ref;
992 }
993 
SetCallbackInfo(const napi_env & env,const std::string & type,const napi_ref & ref)994 void SubscriberInstance::SetCallbackInfo(const napi_env &env, const std::string &type, const napi_ref &ref)
995 {
996     if (type == CONSUME) {
997         SetConsumeCallbackInfo(env, ref);
998     } else if (type == CANCEL) {
999         SetCancelCallbackInfo(env, ref);
1000     } else if (type == UPDATE) {
1001         SetUpdateCallbackInfo(env, ref);
1002     } else if (type == CONNECTED) {
1003         SetSubscribeCallbackInfo(env, ref);
1004     } else if (type == DIS_CONNECTED) {
1005         SetUnsubscribeCallbackInfo(env, ref);
1006     } else if (type == DIE) {
1007         SetDieCallbackInfo(env, ref);
1008     } else if (type == DISTURB_MODE_CHANGE) {
1009         SetDisturbModeCallbackInfo(env, ref);
1010     } else if (type == DISTURB_DATE_CHANGE) {
1011         SetDisturbDateCallbackInfo(env, ref);
1012     } else if (type == DISTURB_CHANGED) {
1013         SetDisturbChangedCallbackInfo(env, ref);
1014     } else if (type == ENABLE_NOTIFICATION_CHANGED) {
1015         SetEnabledNotificationCallbackInfo(env, ref);
1016     } else if (type == BADGE_CHANGED) {
1017         SetBadgeCallbackInfo(env, ref);
1018     } else if (type == BADGE_ENABLED_CHANGED) {
1019         SetBadgeEnabledCallbackInfo(env, ref);
1020     } else if (type == BATCH_CANCEL) {
1021         SetBatchCancelCallbackInfo(env, ref);
1022     } else {
1023         ANS_LOGW("type is error");
1024     }
1025 }
1026 
HasNotificationSubscriber(const napi_env & env,const napi_value & value,SubscriberInstancesInfo & subscriberInfo)1027 bool HasNotificationSubscriber(const napi_env &env, const napi_value &value, SubscriberInstancesInfo &subscriberInfo)
1028 {
1029     std::lock_guard<std::mutex> lock(mutex_);
1030     for (auto vec : subscriberInstances_) {
1031         napi_value callback = nullptr;
1032         napi_get_reference_value(env, vec.ref, &callback);
1033         bool isEquals = false;
1034         napi_strict_equals(env, value, callback, &isEquals);
1035         if (isEquals) {
1036             subscriberInfo = vec;
1037             return true;
1038         }
1039     }
1040     return false;
1041 }
1042 
1043 void ThreadFinished(napi_env env, void* data, [[maybe_unused]] void* context)
1044 {
1045     ANS_LOGD("ThreadFinished");
1046 }
1047 
ThreadSafeCommon(napi_env env,napi_value jsCallback,void * context,void * data)1048 void ThreadSafeCommon(napi_env env, napi_value jsCallback, void* context, void* data)
1049 {
1050     ANS_LOGI("common thread safe start");
1051     auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
1052     switch (dataWorkerData->type) {
1053         case Type::CANCEL:
1054             ThreadSafeOnCancel(env, jsCallback, context, data);
1055             break;
1056         case Type::BATCH_CANCEL:
1057             ThreadSafeOnBatchCancel(env, jsCallback, context, data);
1058             break;
1059         case Type::CONSUME:
1060             ThreadSafeOnConsumed(env, jsCallback, context, data);
1061             break;
1062         case Type::UPDATE:
1063             ThreadSafeOnUpdate(env, jsCallback, context, data);
1064             break;
1065         case Type::CONNECTED:
1066             ThreadSafeOnConnected(env, jsCallback, context, data);
1067             break;
1068         case Type::DIS_CONNECTED:
1069             ThreadSafeOnDisconnected(env, jsCallback, context, data);
1070             break;
1071         case Type::DIE:
1072             ThreadSafeOnDestroy(env, jsCallback, context, data);
1073             break;
1074         case Type::DISTURB_DATE_CHANGE:
1075             ThreadSafeOnDoNotDisturbDateChange(env, jsCallback, context, data);
1076             break;
1077         case Type::DISTURB_CHANGED:
1078             ThreadSafeOnDoNotDisturbChanged(env, jsCallback, context, data);
1079             break;
1080         case Type::ENABLE_NOTIFICATION_CHANGED:
1081             ThreadSafeOnEnabledNotificationChanged(env, jsCallback, context, data);
1082             break;
1083         case Type::BADGE_CHANGED:
1084             ThreadSafeOnBadgeChanged(env, jsCallback, context, data);
1085             break;
1086         case Type::BADGE_ENABLED_CHANGED:
1087             ThreadSafeOnBadgeEnabledChanged(env, jsCallback, context, data);
1088             break;
1089         default:
1090             break;
1091     }
1092 }
1093 
GetNotificationSubscriber(const napi_env & env,const napi_value & value,SubscriberInstancesInfo & subscriberInfo)1094 napi_value GetNotificationSubscriber(
1095     const napi_env &env, const napi_value &value, SubscriberInstancesInfo &subscriberInfo)
1096 {
1097     ANS_LOGD("enter");
1098     bool hasProperty = false;
1099     napi_valuetype valuetype = napi_undefined;
1100     napi_ref result = nullptr;
1101 
1102     subscriberInfo.subscriber = std::make_shared<SubscriberInstance>();
1103     if (subscriberInfo.subscriber == nullptr) {
1104         ANS_LOGE("subscriber is null");
1105         std::string msg = "Mandatory parameters are left unspecified. subscriber is null";
1106         Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1107         return nullptr;
1108     }
1109 
1110     napi_create_reference(env, value, 1, &subscriberInfo.ref);
1111 
1112     napi_value resourceName = nullptr;
1113     napi_create_string_latin1(env, "tsfn", NAPI_AUTO_LENGTH, &resourceName);
1114     napi_threadsafe_function tsfn = nullptr;
1115     napi_create_threadsafe_function(env, nullptr, nullptr, resourceName, 0, 1, subscriberInfo.ref,
1116         ThreadFinished, nullptr, ThreadSafeCommon, &tsfn);
1117     subscriberInfo.subscriber->SetThreadSafeFunction(tsfn);
1118 
1119     // onConsume?:(data: SubscribeCallbackData) => void
1120     NAPI_CALL(env, napi_has_named_property(env, value, "onConsume", &hasProperty));
1121     if (hasProperty) {
1122         napi_value nOnConsumed = nullptr;
1123         napi_get_named_property(env, value, "onConsume", &nOnConsumed);
1124         NAPI_CALL(env, napi_typeof(env, nOnConsumed, &valuetype));
1125         if (valuetype != napi_function) {
1126             ANS_LOGE("Wrong argument type. Function expected.");
1127             std::string msg = "Incorrect parameter types.The type of param must be function.";
1128             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1129             return nullptr;
1130         }
1131         napi_create_reference(env, nOnConsumed, 1, &result);
1132         subscriberInfo.subscriber->SetCallbackInfo(env, CONSUME, result);
1133     }
1134     // onCancel?:(data: SubscribeCallbackData) => void
1135     NAPI_CALL(env, napi_has_named_property(env, value, "onCancel", &hasProperty));
1136     if (hasProperty) {
1137         napi_value nOnCanceled = nullptr;
1138         napi_get_named_property(env, value, "onCancel", &nOnCanceled);
1139         NAPI_CALL(env, napi_typeof(env, nOnCanceled, &valuetype));
1140         if (valuetype != napi_function) {
1141             ANS_LOGE("Wrong argument type. Function expected.");
1142             std::string msg = "Incorrect parameter types.The type of param must be function.";
1143             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1144             return nullptr;
1145         }
1146         napi_create_reference(env, nOnCanceled, 1, &result);
1147         subscriberInfo.subscriber->SetCallbackInfo(env, CANCEL, result);
1148     }
1149     // onUpdate?:(data: NotificationSortingMap) => void
1150     NAPI_CALL(env, napi_has_named_property(env, value, "onUpdate", &hasProperty));
1151     if (hasProperty) {
1152         napi_value nOnUpdate = nullptr;
1153         napi_get_named_property(env, value, "onUpdate", &nOnUpdate);
1154         NAPI_CALL(env, napi_typeof(env, nOnUpdate, &valuetype));
1155         if (valuetype != napi_function) {
1156             ANS_LOGE("Wrong argument type. Function expected.");
1157             std::string msg = "Incorrect parameter types.The type of param must be function.";
1158             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1159             return nullptr;
1160         }
1161         napi_create_reference(env, nOnUpdate, 1, &result);
1162         subscriberInfo.subscriber->SetCallbackInfo(env, UPDATE, result);
1163     }
1164     // onConnect?:() => void
1165     NAPI_CALL(env, napi_has_named_property(env, value, "onConnect", &hasProperty));
1166     if (hasProperty) {
1167         napi_value nOnConnected = nullptr;
1168         napi_get_named_property(env, value, "onConnect", &nOnConnected);
1169         NAPI_CALL(env, napi_typeof(env, nOnConnected, &valuetype));
1170         if (valuetype != napi_function) {
1171             ANS_LOGE("Wrong argument type. Function expected.");
1172             std::string msg = "Incorrect parameter types.The type of param must be function.";
1173             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1174             return nullptr;
1175         }
1176         napi_create_reference(env, nOnConnected, 1, &result);
1177         subscriberInfo.subscriber->SetCallbackInfo(env, CONNECTED, result);
1178     }
1179     // onDisconnect?:() => void
1180     NAPI_CALL(env, napi_has_named_property(env, value, "onDisconnect", &hasProperty));
1181     if (hasProperty) {
1182         napi_value nOnDisConnect = nullptr;
1183         napi_get_named_property(env, value, "onDisconnect", &nOnDisConnect);
1184         NAPI_CALL(env, napi_typeof(env, nOnDisConnect, &valuetype));
1185         if (valuetype != napi_function) {
1186             ANS_LOGE("Wrong argument type. Function expected.");
1187             std::string msg = "Incorrect parameter types.The type of param must be function.";
1188             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1189             return nullptr;
1190         }
1191         napi_create_reference(env, nOnDisConnect, 1, &result);
1192         subscriberInfo.subscriber->SetCallbackInfo(env, DIS_CONNECTED, result);
1193     }
1194     // onDestroy?:() => void
1195     NAPI_CALL(env, napi_has_named_property(env, value, "onDestroy", &hasProperty));
1196     if (hasProperty) {
1197         napi_value nOnDied = nullptr;
1198         napi_get_named_property(env, value, "onDestroy", &nOnDied);
1199         NAPI_CALL(env, napi_typeof(env, nOnDied, &valuetype));
1200         if (valuetype != napi_function) {
1201             ANS_LOGE("Wrong argument type. Function expected.");
1202             std::string msg = "Incorrect parameter types.The type of param must be function.";
1203             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1204             return nullptr;
1205         }
1206         napi_create_reference(env, nOnDied, 1, &result);
1207         subscriberInfo.subscriber->SetCallbackInfo(env, DIE, result);
1208     }
1209     // onDisturbModeChange?:(mode: notification.DoNotDisturbMode) => void
1210     NAPI_CALL(env, napi_has_named_property(env, value, "onDisturbModeChange", &hasProperty));
1211     if (hasProperty) {
1212         napi_value nOnDisturbModeChanged = nullptr;
1213         napi_get_named_property(env, value, "onDisturbModeChange", &nOnDisturbModeChanged);
1214         NAPI_CALL(env, napi_typeof(env, nOnDisturbModeChanged, &valuetype));
1215         if (valuetype != napi_function) {
1216             ANS_LOGE("Wrong argument type. Function expected.");
1217             std::string msg = "Incorrect parameter types.The type of param must be function.";
1218             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1219             return nullptr;
1220         }
1221         napi_create_reference(env, nOnDisturbModeChanged, 1, &result);
1222         subscriberInfo.subscriber->SetCallbackInfo(env, DISTURB_MODE_CHANGE, result);
1223     }
1224 
1225     // onDoNotDisturbDateChange?:(mode: notification.DoNotDisturbDate) => void
1226     NAPI_CALL(env, napi_has_named_property(env, value, "onDoNotDisturbDateChange", &hasProperty));
1227     if (hasProperty) {
1228         napi_value nOnDisturbDateChanged = nullptr;
1229         napi_get_named_property(env, value, "onDoNotDisturbDateChange", &nOnDisturbDateChanged);
1230         NAPI_CALL(env, napi_typeof(env, nOnDisturbDateChanged, &valuetype));
1231         if (valuetype != napi_function) {
1232             ANS_LOGE("Wrong argument type. Function expected.");
1233             std::string msg = "Incorrect parameter types.The type of param must be function.";
1234             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1235             return nullptr;
1236         }
1237         napi_create_reference(env, nOnDisturbDateChanged, 1, &result);
1238         subscriberInfo.subscriber->SetCallbackInfo(env, DISTURB_DATE_CHANGE, result);
1239     }
1240 
1241     // onDoNotDisturbChanged?:(mode: notificationManager.DoNotDisturbDate) => void
1242     NAPI_CALL(env, napi_has_named_property(env, value, "onDoNotDisturbChanged", &hasProperty));
1243     if (hasProperty) {
1244         napi_value nOnDoNotDisturbChanged = nullptr;
1245         napi_get_named_property(env, value, "onDoNotDisturbChanged", &nOnDoNotDisturbChanged);
1246         NAPI_CALL(env, napi_typeof(env, nOnDoNotDisturbChanged, &valuetype));
1247         if (valuetype != napi_function) {
1248             ANS_LOGE("Wrong argument type. Function expected.");
1249             std::string msg = "Incorrect parameter types.The type of param must be function.";
1250             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1251             return nullptr;
1252         }
1253         napi_create_reference(env, nOnDoNotDisturbChanged, 1, &result);
1254         subscriberInfo.subscriber->SetCallbackInfo(env, DISTURB_CHANGED, result);
1255     }
1256 
1257     // onEnabledNotificationChanged?:(data: notification.EnabledNotificationCallbackData) => void
1258     NAPI_CALL(env, napi_has_named_property(env, value, "onEnabledNotificationChanged", &hasProperty));
1259     if (hasProperty) {
1260         napi_value nOnEnabledNotificationChanged = nullptr;
1261         napi_get_named_property(env, value, "onEnabledNotificationChanged", &nOnEnabledNotificationChanged);
1262         NAPI_CALL(env, napi_typeof(env, nOnEnabledNotificationChanged, &valuetype));
1263         if (valuetype != napi_function) {
1264             ANS_LOGE("Wrong argument type. Function expected.");
1265             std::string msg = "Incorrect parameter types.The type of param must be function.";
1266             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1267             return nullptr;
1268         }
1269         napi_create_reference(env, nOnEnabledNotificationChanged, 1, &result);
1270         subscriberInfo.subscriber->SetCallbackInfo(env, ENABLE_NOTIFICATION_CHANGED, result);
1271     }
1272 
1273     // onBadgeChanged?:(data: BadgeNumberCallbackData) => void
1274     NAPI_CALL(env, napi_has_named_property(env, value, "onBadgeChanged", &hasProperty));
1275     if (hasProperty) {
1276         napi_value nOnBadgeChanged = nullptr;
1277         napi_get_named_property(env, value, "onBadgeChanged", &nOnBadgeChanged);
1278         NAPI_CALL(env, napi_typeof(env, nOnBadgeChanged, &valuetype));
1279         if (valuetype != napi_function) {
1280             ANS_LOGE("Wrong argument type. Function expected.");
1281             std::string msg = "Incorrect parameter types.The type of param must be function.";
1282             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1283             return nullptr;
1284         }
1285         napi_create_reference(env, nOnBadgeChanged, 1, &result);
1286         subscriberInfo.subscriber->SetCallbackInfo(env, BADGE_CHANGED, result);
1287     }
1288 
1289     // onBadgeEnabledChanged?:(data: EnabledNotificationCallbackData) => void
1290     NAPI_CALL(env, napi_has_named_property(env, value, "onBadgeEnabledChanged", &hasProperty));
1291     if (hasProperty) {
1292         napi_value nOnBadgeEnabledChanged = nullptr;
1293         napi_get_named_property(env, value, "onBadgeEnabledChanged", &nOnBadgeEnabledChanged);
1294         NAPI_CALL(env, napi_typeof(env, nOnBadgeEnabledChanged, &valuetype));
1295         if (valuetype != napi_function) {
1296             ANS_LOGE("Wrong argument type. Function expected.");
1297             std::string msg = "Incorrect parameter types.The type of param must be function.";
1298             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1299             return nullptr;
1300         }
1301         napi_create_reference(env, nOnBadgeEnabledChanged, 1, &result);
1302         subscriberInfo.subscriber->SetCallbackInfo(env, BADGE_ENABLED_CHANGED, result);
1303     }
1304 
1305     // onBatchCancel?:(data: Array<SubscribeCallbackData>) => void
1306     NAPI_CALL(env, napi_has_named_property(env, value, "onBatchCancel", &hasProperty));
1307     if (hasProperty) {
1308         napi_value onBatchCancel = nullptr;
1309         napi_get_named_property(env, value, "onBatchCancel", &onBatchCancel);
1310         NAPI_CALL(env, napi_typeof(env, onBatchCancel, &valuetype));
1311         if (valuetype != napi_function) {
1312             ANS_LOGE("Wrong argument type. Function expected.");
1313             std::string msg = "Incorrect parameter types.The type of param must be function.";
1314             Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1315             return nullptr;
1316         }
1317         napi_create_reference(env, onBatchCancel, 1, &result);
1318         subscriberInfo.subscriber->SetCallbackInfo(env, BATCH_CANCEL, result);
1319     }
1320 
1321     return Common::NapiGetNull(env);
1322 }
1323 
AddSubscriberInstancesInfo(const napi_env & env,const SubscriberInstancesInfo & subscriberInfo)1324 bool AddSubscriberInstancesInfo(const napi_env &env, const SubscriberInstancesInfo &subscriberInfo)
1325 {
1326     ANS_LOGD("enter");
1327     if (subscriberInfo.ref == nullptr) {
1328         ANS_LOGE("subscriberInfo.ref is null");
1329         return false;
1330     }
1331     if (subscriberInfo.subscriber == nullptr) {
1332         ANS_LOGE("subscriberInfo.subscriber is null");
1333         return false;
1334     }
1335     std::lock_guard<std::mutex> lock(mutex_);
1336     subscriberInstances_.emplace_back(subscriberInfo);
1337 
1338     return true;
1339 }
1340 
DelSubscriberInstancesInfo(const napi_env & env,const std::shared_ptr<SubscriberInstance> subscriber)1341 bool DelSubscriberInstancesInfo(const napi_env &env, const std::shared_ptr<SubscriberInstance> subscriber)
1342 {
1343     ANS_LOGD("enter");
1344     if (subscriber == nullptr) {
1345         ANS_LOGE("subscriber is null");
1346         return false;
1347     }
1348     std::lock_guard<std::mutex> lock(delMutex_);
1349     auto iter = std::find(DeletingSubscriber.begin(), DeletingSubscriber.end(), subscriber);
1350     if (iter != DeletingSubscriber.end()) {
1351         DeletingSubscriber.erase(iter);
1352         std::lock_guard<std::mutex> lock(mutex_);
1353         for (auto it = subscriberInstances_.begin(); it != subscriberInstances_.end(); ++it) {
1354             if ((*it).subscriber == subscriber) {
1355                 if ((*it).ref != nullptr) {
1356                     napi_delete_reference(env, (*it).ref);
1357                 }
1358                 subscriberInstances_.erase(it);
1359                 return true;
1360             }
1361         }
1362     }
1363     return false;
1364 }
1365 
ParseParameters(const napi_env & env,const napi_callback_info & info,NotificationSubscribeInfo & subscriberInfo,std::shared_ptr<SubscriberInstance> & subscriber,napi_ref & callback)1366 napi_value ParseParameters(const napi_env &env, const napi_callback_info &info,
1367     NotificationSubscribeInfo &subscriberInfo, std::shared_ptr<SubscriberInstance> &subscriber, napi_ref &callback)
1368 {
1369     ANS_LOGD("enter");
1370 
1371     size_t argc = SUBSRIBE_MAX_PARA;
1372     napi_value argv[SUBSRIBE_MAX_PARA] = {nullptr};
1373     napi_value thisVar = nullptr;
1374     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
1375     if (argc < 1) {
1376         ANS_LOGE("Wrong number of arguments");
1377         Common::NapiThrow(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED);
1378         return nullptr;
1379     }
1380 
1381     napi_valuetype valuetype = napi_undefined;
1382 
1383     // argv[0]:subscriber
1384     NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
1385     if (valuetype != napi_object) {
1386         ANS_LOGE("Wrong argument type for arg0. NotificationSubscriber object expected.");
1387         std::string msg = "Incorrect parameter types.The type of param must be NotificationSubscriber.";
1388         Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1389         return nullptr;
1390     }
1391 
1392     SubscriberInstancesInfo subscriberInstancesInfo;
1393     if (!HasNotificationSubscriber(env, argv[PARAM0], subscriberInstancesInfo)) {
1394         if (GetNotificationSubscriber(env, argv[PARAM0], subscriberInstancesInfo) == nullptr) {
1395             ANS_LOGE("NotificationSubscriber parse failed");
1396             return nullptr;
1397         }
1398         if (!AddSubscriberInstancesInfo(env, subscriberInstancesInfo)) {
1399             ANS_LOGE("AddSubscriberInstancesInfo add failed");
1400             return nullptr;
1401         }
1402     }
1403     subscriber = subscriberInstancesInfo.subscriber;
1404 
1405     // argv[1]:callback or NotificationSubscribeInfo
1406     if (argc >= SUBSRIBE_MAX_PARA - 1) {
1407         NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
1408         if ((valuetype != napi_function) && (valuetype != napi_object)) {
1409             ANS_LOGE("Wrong argument type for arg1."
1410                 "Function or NotificationSubscribeInfo object expected. Excute promise");
1411             return Common::NapiGetNull(env);
1412         }
1413         if (valuetype == napi_function) {
1414             napi_create_reference(env, argv[PARAM1], 1, &callback);
1415         } else {
1416             if (Common::GetNotificationSubscriberInfo(env, argv[PARAM1], subscriberInfo) == nullptr) {
1417                 ANS_LOGE("NotificationSubscribeInfo parse failed");
1418                 return nullptr;
1419             }
1420         }
1421     }
1422 
1423     // argv[2]:callback
1424     if (argc >= SUBSRIBE_MAX_PARA) {
1425         NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valuetype));
1426         if (valuetype != napi_function) {
1427             ANS_LOGE("Callback is not function enforce promise.");
1428             return Common::NapiGetNull(env);
1429         }
1430         napi_create_reference(env, argv[PARAM2], 1, &callback);
1431     }
1432 
1433     return Common::NapiGetNull(env);
1434 }
1435 
Subscribe(napi_env env,napi_callback_info info)1436 napi_value Subscribe(napi_env env, napi_callback_info info)
1437 {
1438     ANS_LOGD("enter");
1439 
1440     napi_ref callback = nullptr;
1441     std::shared_ptr<SubscriberInstance> objectInfo = nullptr;
1442     NotificationSubscribeInfo subscriberInfo;
1443     if (ParseParameters(env, info, subscriberInfo, objectInfo, callback) == nullptr) {
1444         ANS_LOGD("ParseParameters is nullptr.");
1445         return Common::NapiGetUndefined(env);
1446     }
1447 
1448     AsyncCallbackInfoSubscribe *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoSubscribe {
1449         .env = env, .asyncWork = nullptr, .objectInfo = objectInfo, .subscriberInfo = subscriberInfo
1450     };
1451     if (!asynccallbackinfo) {
1452         ANS_LOGD("Asynccallbackinfo is nullptr.");
1453         return Common::JSParaError(env, callback);
1454     }
1455     napi_value promise = nullptr;
1456     Common::PaddingCallbackPromiseInfo(env, callback, asynccallbackinfo->info, promise);
1457 
1458     ANS_LOGD("Create subscribeNotification string.");
1459     napi_value resourceName = nullptr;
1460     napi_create_string_latin1(env, "subscribeNotification", NAPI_AUTO_LENGTH, &resourceName);
1461     // Asynchronous function call
1462     napi_create_async_work(env,
1463         nullptr,
1464         resourceName,
1465         [](napi_env env, void *data) {
1466             ANS_LOGD("Subscribe work excuted.");
1467             if (!data) {
1468                 ANS_LOGE("Invalid asynccallbackinfo!");
1469                 return;
1470             }
1471             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
1472             if (asynccallbackinfo) {
1473                 if (asynccallbackinfo->subscriberInfo.hasSubscribeInfo) {
1474                     ANS_LOGD("Subscribe with NotificationSubscribeInfo excute.");
1475                     OHOS::Notification::NotificationSubscribeInfo subscribeInfo;
1476                     subscribeInfo.AddAppNames(asynccallbackinfo->subscriberInfo.bundleNames);
1477                     subscribeInfo.AddAppUserId(asynccallbackinfo->subscriberInfo.userId);
1478                     asynccallbackinfo->info.errorCode =
1479                         NotificationHelper::SubscribeNotification(*(asynccallbackinfo->objectInfo), subscribeInfo);
1480                 } else {
1481                     ANS_LOGD("SubscribeNotification execute.");
1482                     asynccallbackinfo->info.errorCode =
1483                         NotificationHelper::SubscribeNotification(*(asynccallbackinfo->objectInfo));
1484                 }
1485             }
1486         },
1487         [](napi_env env, napi_status status, void *data) {
1488             ANS_LOGD("Subscribe work complete.");
1489             if (!data) {
1490                 ANS_LOGE("Invalid asynccallbackinfo!");
1491                 return;
1492             }
1493             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
1494             if (asynccallbackinfo) {
1495                 Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
1496                 if (asynccallbackinfo->info.callback != nullptr) {
1497                     ANS_LOGD("Delete subscribe callback reference.");
1498                     napi_delete_reference(env, asynccallbackinfo->info.callback);
1499                 }
1500                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
1501                 delete asynccallbackinfo;
1502                 asynccallbackinfo = nullptr;
1503             }
1504             ANS_LOGD("Subscribe work complete end.");
1505         },
1506         (void *)asynccallbackinfo,
1507         &asynccallbackinfo->asyncWork);
1508 
1509     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
1510 
1511     if (asynccallbackinfo->info.isCallback) {
1512         ANS_LOGD("subscribe callback is nullptr.");
1513         return Common::NapiGetNull(env);
1514     } else {
1515         return promise;
1516     }
1517 }
1518 
AddDeletingSubscriber(std::shared_ptr<SubscriberInstance> subscriber)1519 bool AddDeletingSubscriber(std::shared_ptr<SubscriberInstance> subscriber)
1520 {
1521     std::lock_guard<std::mutex> lock(delMutex_);
1522     auto iter = std::find(DeletingSubscriber.begin(), DeletingSubscriber.end(), subscriber);
1523     if (iter != DeletingSubscriber.end()) {
1524         return false;
1525     }
1526 
1527     DeletingSubscriber.push_back(subscriber);
1528     return true;
1529 }
1530 
DelDeletingSubscriber(std::shared_ptr<SubscriberInstance> subscriber)1531 void DelDeletingSubscriber(std::shared_ptr<SubscriberInstance> subscriber)
1532 {
1533     std::lock_guard<std::mutex> lock(delMutex_);
1534     auto iter = std::find(DeletingSubscriber.begin(), DeletingSubscriber.end(), subscriber);
1535     if (iter != DeletingSubscriber.end()) {
1536         DeletingSubscriber.erase(iter);
1537     }
1538 }
1539 }  // namespace NotificationNapi
1540 }  // namespace OHOS