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