• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_subscribe.h"
17 
18 #include "ans_inner_errors.h"
19 #include "subscribe.h"
20 #include "unsubscribe.h"
21 #include <memory>
22 #include <new>
23 #include "distributed_operation_callback.h"
24 #include "notification_operation_info.h"
25 
26 namespace OHOS {
27 namespace NotificationNapi {
NapiDistributeOperationExecuteCallback(napi_env env,void * data)28 void NapiDistributeOperationExecuteCallback(napi_env env, void *data)
29 {
30     ANS_LOGI("DistributeOperation napi_create_async_work start");
31     auto asyncCallbackInfo = static_cast<AsyncOperationCallbackInfo *>(data);
32     if (asyncCallbackInfo == nullptr) {
33         ANS_LOGE("asyncCallbackInfo is nullptr");
34         return;
35     }
36     sptr<DistributedOperationCallback> callback = new (std::nothrow) DistributedOperationCallback(*asyncCallbackInfo);
37     if (callback == nullptr) {
38         ANS_LOGE("NAPI_Lock create callback object fail");
39         return;
40     }
41 
42     sptr<NotificationOperationInfo> operationInfo = new (std::nothrow) NotificationOperationInfo();
43     operationInfo->SetHashCode(asyncCallbackInfo->hashCode);
44     if (asyncCallbackInfo->operationInfo.withOperationInfo) {
45         operationInfo->SetOperationType(OperationType::DISTRIBUTE_OPERATION_REPLY);
46         operationInfo->SetActionName(asyncCallbackInfo->operationInfo.actionName);
47         operationInfo->SetUserInput(asyncCallbackInfo->operationInfo.userInput);
48     } else {
49         operationInfo->SetOperationType(OperationType::DISTRIBUTE_OPERATION_JUMP);
50     }
51     int32_t result = NotificationHelper::DistributeOperation(operationInfo, callback);
52     if (result != ERR_OK || !asyncCallbackInfo->operationInfo.withOperationInfo) {
53         callback->OnOperationCallback(result);
54     }
55 }
56 
NapiDistributeOperationCompleteCallback(napi_env env,napi_status status,void * data)57 void NapiDistributeOperationCompleteCallback(napi_env env, napi_status status, void *data)
58 {
59     ANS_LOGI("DistributeOperation napi_create_async_work end");
60     if (!data) {
61         ANS_LOGE("Invalid async callback data");
62         return;
63     }
64     auto distributeOperationInfo = static_cast<AsyncOperationCallbackInfo *>(data);
65     if (distributeOperationInfo) {
66         napi_delete_async_work(env, distributeOperationInfo->asyncWork);
67         delete distributeOperationInfo;
68         distributeOperationInfo = nullptr;
69     }
70 }
71 
NapiSubscribe(napi_env env,napi_callback_info info)72 napi_value NapiSubscribe(napi_env env, napi_callback_info info)
73 {
74     ANS_LOGD("enter");
75     napi_ref callback = nullptr;
76     std::shared_ptr<SubscriberInstance> objectInfo = nullptr;
77     NotificationSubscribeInfo subscriberInfo;
78     if (ParseParameters(env, info, subscriberInfo, objectInfo, callback) == nullptr) {
79         Common::NapiThrow(env, ERROR_PARAM_INVALID);
80         return Common::NapiGetUndefined(env);
81     }
82 
83     AsyncCallbackInfoSubscribe *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoSubscribe {
84         .env = env, .asyncWork = nullptr, .objectInfo = objectInfo, .subscriberInfo = subscriberInfo
85     };
86     if (!asynccallbackinfo) {
87         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
88         return Common::JSParaError(env, callback);
89     }
90     napi_value promise = nullptr;
91     Common::PaddingCallbackPromiseInfo(env, callback, asynccallbackinfo->info, promise);
92 
93     napi_value resourceName = nullptr;
94     napi_create_string_latin1(env, "subscribeNotification", NAPI_AUTO_LENGTH, &resourceName);
95     // Asynchronous function call
96     napi_create_async_work(env,
97         nullptr,
98         resourceName,
99         [](napi_env env, void *data) {
100             ANS_LOGD("NapiSubscribe work excute.");
101             if (!data) {
102                 ANS_LOGE("Invalid asynccallbackinfo!");
103                 return;
104             }
105             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
106             if (asynccallbackinfo) {
107                 if (asynccallbackinfo->subscriberInfo.hasSubscribeInfo) {
108                     ANS_LOGI("Subscribe with NotificationSubscribeInfo");
109                     sptr<OHOS::Notification::NotificationSubscribeInfo> subscribeInfo =
110                         new (std::nothrow) OHOS::Notification::NotificationSubscribeInfo();
111                     if (subscribeInfo == nullptr) {
112                         ANS_LOGE("Invalid subscribeInfo!");
113                         asynccallbackinfo->info.errorCode = OHOS::Notification::ErrorCode::ERR_ANS_NO_MEMORY;
114                         return;
115                     }
116                     subscribeInfo->AddAppNames(asynccallbackinfo->subscriberInfo.bundleNames);
117                     subscribeInfo->AddAppUserId(asynccallbackinfo->subscriberInfo.userId);
118                     subscribeInfo->AddDeviceType(asynccallbackinfo->subscriberInfo.deviceType);
119                     subscribeInfo->SetFilterType(asynccallbackinfo->subscriberInfo.filterType);
120                     subscribeInfo->SetSlotTypes(asynccallbackinfo->subscriberInfo.slotTypes);
121                     asynccallbackinfo->info.errorCode =
122                         NotificationHelper::SubscribeNotification(asynccallbackinfo->objectInfo, subscribeInfo);
123                 } else {
124                     asynccallbackinfo->info.errorCode =
125                         NotificationHelper::SubscribeNotification(asynccallbackinfo->objectInfo);
126                 }
127             }
128         },
129         [](napi_env env, napi_status status, void *data) {
130             ANS_LOGD("NapiSubscribe work complete.");
131             if (!data) {
132                 ANS_LOGE("Invalid asynccallbackinfo!");
133                 return;
134             }
135             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
136             if (asynccallbackinfo) {
137                 Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env));
138                 if (asynccallbackinfo->info.callback != nullptr) {
139                     ANS_LOGD("Delete napiSubscribe callback reference.");
140                     napi_delete_reference(env, asynccallbackinfo->info.callback);
141                 }
142                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
143                 delete asynccallbackinfo;
144                 asynccallbackinfo = nullptr;
145             }
146             ANS_LOGD("NapiSubscribe work complete end.");
147         },
148         (void *)asynccallbackinfo,
149         &asynccallbackinfo->asyncWork);
150 
151     bool isCallback = asynccallbackinfo->info.isCallback;
152     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
153 
154     if (isCallback) {
155         ANS_LOGD("napiSubscribe callback is nullptr.");
156         return Common::NapiGetNull(env);
157     } else {
158         return promise;
159     }
160 }
161 
NapiSubscribeSelf(napi_env env,napi_callback_info info)162 napi_value NapiSubscribeSelf(napi_env env, napi_callback_info info)
163 {
164     ANS_LOGD("enter");
165     napi_ref callback = nullptr;
166     std::shared_ptr<SubscriberInstance> objectInfo = nullptr;
167     NotificationSubscribeInfo subscriberInfo;
168     if (ParseParameters(env, info, subscriberInfo, objectInfo, callback) == nullptr) {
169         Common::NapiThrow(env, ERROR_PARAM_INVALID);
170         return Common::NapiGetUndefined(env);
171     }
172 
173     AsyncCallbackInfoSubscribe *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoSubscribe {
174         .env = env, .asyncWork = nullptr, .objectInfo = objectInfo, .subscriberInfo = subscriberInfo
175     };
176     if (!asynccallbackinfo) {
177         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
178         return Common::JSParaError(env, callback);
179     }
180     napi_value promise = nullptr;
181     Common::PaddingCallbackPromiseInfo(env, callback, asynccallbackinfo->info, promise);
182 
183     napi_value resourceName = nullptr;
184     napi_create_string_latin1(env, "subscribeNotificationSelf", NAPI_AUTO_LENGTH, &resourceName);
185     // Asynchronous function call
186     napi_create_async_work(env,
187         nullptr,
188         resourceName,
189         [](napi_env env, void *data) {
190             ANS_LOGD("NapiSubscribeSelf work excute.");
191             if (!data) {
192                 ANS_LOGE("Invalid asynccallbackinfo!");
193                 return;
194             }
195             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
196             if (asynccallbackinfo) {
197                 asynccallbackinfo->info.errorCode =
198                     NotificationHelper::SubscribeNotificationSelf(asynccallbackinfo->objectInfo);
199             }
200         },
201         [](napi_env env, napi_status status, void *data) {
202             ANS_LOGD("NapiSubscribeSelf work complete.");
203             if (!data) {
204                 ANS_LOGE("Invalid asynccallbackinfo!");
205                 return;
206             }
207             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
208             if (asynccallbackinfo) {
209                 Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env));
210                 if (asynccallbackinfo->info.callback != nullptr) {
211                     ANS_LOGD("Delete napiSubscribeSelf callback reference.");
212                     napi_delete_reference(env, asynccallbackinfo->info.callback);
213                 }
214                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
215                 delete asynccallbackinfo;
216                 asynccallbackinfo = nullptr;
217             }
218             ANS_LOGD("NapiSubscribeSelf work complete end.");
219         },
220         (void *)asynccallbackinfo,
221         &asynccallbackinfo->asyncWork);
222 
223     bool isCallback = asynccallbackinfo->info.isCallback;
224     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
225 
226     if (isCallback) {
227         ANS_LOGD("NapiSubscribeSelf callback is nullptr.");
228         return Common::NapiGetNull(env);
229     } else {
230         return promise;
231     }
232 }
233 
NapiUnsubscribe(napi_env env,napi_callback_info info)234 napi_value NapiUnsubscribe(napi_env env, napi_callback_info info)
235 {
236     ANS_LOGI("Unsubscribe start");
237     ParametersInfoUnsubscribe paras;
238     if (ParseParameters(env, info, paras) == nullptr) {
239         Common::NapiThrow(env, ERROR_PARAM_INVALID);
240         return Common::NapiGetUndefined(env);
241     }
242 
243     AsyncCallbackInfoUnsubscribe *asynccallbackinfo = new (std::nothrow)
244         AsyncCallbackInfoUnsubscribe {.env = env, .asyncWork = nullptr, .objectInfo = paras.objectInfo};
245     if (!asynccallbackinfo) {
246         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
247         return Common::JSParaError(env, paras.callback);
248     }
249     napi_value promise = nullptr;
250     Common::PaddingCallbackPromiseInfo(env, paras.callback, asynccallbackinfo->info, promise);
251 
252     napi_value resourceName = nullptr;
253     napi_create_string_latin1(env, "unsubscribe", NAPI_AUTO_LENGTH, &resourceName);
254 
255     // Asynchronous function call
256     napi_create_async_work(env,
257         nullptr,
258         resourceName,
259         [](napi_env env, void *data) {
260             ANS_LOGD("NapiUnsubscribe work excute.");
261             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoUnsubscribe *>(data);
262             if (asynccallbackinfo) {
263                 if (asynccallbackinfo->objectInfo == nullptr) {
264                     ANS_LOGE("invalid object info");
265                     asynccallbackinfo->info.errorCode = ERR_ANS_INVALID_PARAM;
266                     return;
267                 }
268 
269                 bool ret = AddDeletingSubscriber(asynccallbackinfo->objectInfo);
270                 if (ret) {
271                     asynccallbackinfo->info.errorCode =
272                         NotificationHelper::UnSubscribeNotification(asynccallbackinfo->objectInfo);
273                     if (asynccallbackinfo->info.errorCode != ERR_OK) {
274                         DelDeletingSubscriber(asynccallbackinfo->objectInfo);
275                     }
276                 } else {
277                     asynccallbackinfo->info.errorCode = ERR_ANS_SUBSCRIBER_IS_DELETING;
278                 }
279             }
280         },
281         [](napi_env env, napi_status status, void *data) {
282             ANS_LOGD("NapiUnsubscribe work complete.");
283             AsyncCallbackInfoUnsubscribe *asynccallbackinfo = static_cast<AsyncCallbackInfoUnsubscribe *>(data);
284             if (asynccallbackinfo) {
285                 Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env));
286                 if (asynccallbackinfo->info.callback != nullptr) {
287                     ANS_LOGD("Delete napiUnsubscribe callback reference.");
288                     napi_delete_reference(env, asynccallbackinfo->info.callback);
289                 }
290                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
291                 delete asynccallbackinfo;
292                 asynccallbackinfo = nullptr;
293             }
294             ANS_LOGD("NapiUnsubscribe work complete end.");
295         },
296         (void *)asynccallbackinfo,
297         &asynccallbackinfo->asyncWork);
298 
299     bool isCallback = asynccallbackinfo->info.isCallback;
300     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
301 
302     if (isCallback) {
303         ANS_LOGD("napiUnsubscribe callback is nullptr.");
304         return Common::NapiGetNull(env);
305     } else {
306         return promise;
307     }
308 }
309 
AsyncDistributeOperationCall(napi_env env,AsyncOperationCallbackInfo * distributeOperationInfo)310 void AsyncDistributeOperationCall(napi_env env, AsyncOperationCallbackInfo* distributeOperationInfo)
311 {
312     napi_value resourceName = nullptr;
313     napi_create_string_latin1(env, "distributeOperation", NAPI_AUTO_LENGTH, &resourceName);
314 
315     // Asynchronous function call
316     napi_create_async_work(env, nullptr, resourceName, NapiDistributeOperationExecuteCallback,
317         NapiDistributeOperationCompleteCallback, (void *)distributeOperationInfo, &distributeOperationInfo->asyncWork);
318     auto result = napi_queue_async_work_with_qos(env, distributeOperationInfo->asyncWork, napi_qos_user_initiated);
319     if (result != napi_ok) {
320         NapiDistributeOperationCompleteCallback(env, result, distributeOperationInfo);
321         NAPI_CALL_RETURN_VOID(env, result);
322     }
323 }
324 
NapiDistributeOperation(napi_env env,napi_callback_info info)325 napi_value NapiDistributeOperation(napi_env env, napi_callback_info info)
326 {
327     ANS_LOGI("Distribute operation called");
328     std::string hashCode;
329     napi_value thisVar = nullptr;
330     OperationInfo operationInfo;
331     if (ParseParameters(env, info, hashCode, thisVar, operationInfo) == nullptr) {
332         Common::NapiThrow(env, ERROR_PARAM_INVALID);
333         return Common::NapiGetUndefined(env);
334     }
335 
336     napi_value ret = nullptr;
337     napi_deferred deferred;
338     napi_create_promise(env, &deferred, &ret);
339     auto distributeOperationInfo = new (std::nothrow) AsyncOperationCallbackInfo {.env = env,
340         .thisVar = thisVar, .deferred = deferred, .hashCode = hashCode, .operationInfo = operationInfo};
341     if (distributeOperationInfo == nullptr) {
342         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
343         return Common::NapiGetNull(env);
344     }
345 
346     AsyncDistributeOperationCall(env, distributeOperationInfo);
347     return ret;
348 }
349 }  // namespace NotificationNapi
350 }  // namespace OHOS
351