• 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_LOGD("called");
31     auto asyncCallbackInfo = static_cast<AsyncOperationCallbackInfo *>(data);
32     if (asyncCallbackInfo == nullptr) {
33         ANS_LOGE("null asyncCallbackInfo");
34         return;
35     }
36     sptr<DistributedOperationCallback> callback = new (std::nothrow) DistributedOperationCallback(*asyncCallbackInfo);
37     if (callback == nullptr) {
38         ANS_LOGE("null callback");
39         return;
40     }
41 
42     sptr<NotificationOperationInfo> operationInfo = new (std::nothrow) NotificationOperationInfo();
43     if (operationInfo == nullptr) {
44         ANS_LOGE("null operationInfo");
45         return;
46     }
47     operationInfo->SetHashCode(asyncCallbackInfo->hashCode);
48     if (asyncCallbackInfo->operationInfo.operationType == NotificationConstant::DISTRIBUTE_JUMP_INVALID &&
49         asyncCallbackInfo->operationInfo.withOperationInfo) {
50         operationInfo->SetOperationType(OperationType::DISTRIBUTE_OPERATION_REPLY);
51         operationInfo->SetActionName(asyncCallbackInfo->operationInfo.actionName);
52         operationInfo->SetUserInput(asyncCallbackInfo->operationInfo.userInput);
53     } else if (asyncCallbackInfo->operationInfo.operationType == NotificationConstant::DISTRIBUTE_JUMP_INVALID) {
54         operationInfo->SetOperationType(OperationType::DISTRIBUTE_OPERATION_JUMP);
55     } else if (asyncCallbackInfo->operationInfo.operationType >= NotificationConstant::DISTRIBUTE_JUMP_BY_LIVE_VIEW ||
56         asyncCallbackInfo->operationInfo.operationType == NotificationConstant::DISTRIBUTE_JUMP_BY_NTF ||
57         asyncCallbackInfo->operationInfo.operationType == NotificationConstant::DISTRIBUTE_JUMP_BY_BTN) {
58         operationInfo->SetOperationType(OperationType::DISTRIBUTE_OPERATION_JUMP_BY_TYPE);
59         operationInfo->SetJumpType(asyncCallbackInfo->operationInfo.operationType);
60         operationInfo->SetBtnIndex(asyncCallbackInfo->operationInfo.btnIndex);
61     } else {
62         ANS_LOGE("invalid param, operationType: %{public}d", asyncCallbackInfo->operationInfo.operationType);
63         callback->OnOperationCallback(ERR_ANS_INVALID_PARAM);
64         return;
65     }
66     int32_t result = NotificationHelper::DistributeOperation(operationInfo, callback);
67     if (result != ERR_OK ||
68         operationInfo->GetOperationType() != OperationType::DISTRIBUTE_OPERATION_REPLY) {
69         callback->OnOperationCallback(result);
70     }
71 }
72 
NapiDistributeOperationCompleteCallback(napi_env env,napi_status status,void * data)73 void NapiDistributeOperationCompleteCallback(napi_env env, napi_status status, void *data)
74 {
75     ANS_LOGD("called");
76     if (!data) {
77         ANS_LOGE("null data");
78         return;
79     }
80     auto distributeOperationInfo = static_cast<AsyncOperationCallbackInfo *>(data);
81     if (distributeOperationInfo) {
82         napi_delete_async_work(env, distributeOperationInfo->asyncWork);
83         delete distributeOperationInfo;
84         distributeOperationInfo = nullptr;
85     }
86 }
87 
ClearEnvCallback(void * data)88 static void ClearEnvCallback(void *data)
89 {
90     ANS_LOGD("Env expired, need to clear env");
91     SubscriberInstance *subscriber = reinterpret_cast<SubscriberInstance *>(data);
92     subscriber->ClearEnv();
93 }
94 
NapiSubscribe(napi_env env,napi_callback_info info)95 napi_value NapiSubscribe(napi_env env, napi_callback_info info)
96 {
97     ANS_LOGD("called");
98     napi_ref callback = nullptr;
99     std::shared_ptr<SubscriberInstance> objectInfo = nullptr;
100     NotificationSubscribeInfo subscriberInfo;
101     if (ParseParameters(env, info, subscriberInfo, objectInfo, callback) == nullptr) {
102         Common::NapiThrow(env, ERROR_PARAM_INVALID);
103         return Common::NapiGetUndefined(env);
104     }
105 
106     AsyncCallbackInfoSubscribe *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoSubscribe {
107         .env = env, .asyncWork = nullptr, .objectInfo = objectInfo, .subscriberInfo = subscriberInfo
108     };
109     if (!asynccallbackinfo) {
110         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
111         return Common::JSParaError(env, callback);
112     }
113     napi_value promise = nullptr;
114     Common::PaddingCallbackPromiseInfo(env, callback, asynccallbackinfo->info, promise);
115 
116     napi_value resourceName = nullptr;
117     napi_create_string_latin1(env, "subscribeNotification", NAPI_AUTO_LENGTH, &resourceName);
118     // Asynchronous function call
119     napi_create_async_work(env,
120         nullptr,
121         resourceName,
122         [](napi_env env, void *data) {
123             ANS_LOGD("NapiSubscribe work excute.");
124             if (!data) {
125                 ANS_LOGE("Invalid asynccallbackinfo!");
126                 return;
127             }
128             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
129             if (asynccallbackinfo) {
130                 if (asynccallbackinfo->subscriberInfo.hasSubscribeInfo) {
131                     ANS_LOGI("Subscribe with NotificationSubscribeInfo");
132                     sptr<OHOS::Notification::NotificationSubscribeInfo> subscribeInfo =
133                         new (std::nothrow) OHOS::Notification::NotificationSubscribeInfo();
134                     if (subscribeInfo == nullptr) {
135                         ANS_LOGE("Invalid subscribeInfo!");
136                         asynccallbackinfo->info.errorCode = OHOS::Notification::ErrorCode::ERR_ANS_NO_MEMORY;
137                         return;
138                     }
139                     subscribeInfo->AddAppNames(asynccallbackinfo->subscriberInfo.bundleNames);
140                     subscribeInfo->AddAppUserId(asynccallbackinfo->subscriberInfo.userId);
141                     subscribeInfo->AddDeviceType(asynccallbackinfo->subscriberInfo.deviceType);
142                     subscribeInfo->SetFilterType(asynccallbackinfo->subscriberInfo.filterType);
143                     subscribeInfo->SetSlotTypes(asynccallbackinfo->subscriberInfo.slotTypes);
144                     asynccallbackinfo->info.errorCode =
145                         NotificationHelper::SubscribeNotification(asynccallbackinfo->objectInfo, subscribeInfo);
146                 } else {
147                     asynccallbackinfo->info.errorCode =
148                         NotificationHelper::SubscribeNotification(asynccallbackinfo->objectInfo);
149                 }
150             }
151         },
152         [](napi_env env, napi_status status, void *data) {
153             ANS_LOGD("NapiSubscribe work complete.");
154             if (!data) {
155                 ANS_LOGE("Invalid asynccallbackinfo!");
156                 return;
157             }
158             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
159             if (asynccallbackinfo) {
160                 Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env));
161                 if (asynccallbackinfo->info.callback != nullptr) {
162                     ANS_LOGD("Delete napiSubscribe callback reference.");
163                     napi_delete_reference(env, asynccallbackinfo->info.callback);
164                 }
165                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
166                 delete asynccallbackinfo;
167                 asynccallbackinfo = nullptr;
168             }
169             ANS_LOGD("NapiSubscribe work complete end.");
170         },
171         (void *)asynccallbackinfo,
172         &asynccallbackinfo->asyncWork);
173 
174     bool isCallback = asynccallbackinfo->info.isCallback;
175     napi_add_env_cleanup_hook(env, ClearEnvCallback, objectInfo.get());
176     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
177 
178     if (isCallback) {
179         ANS_LOGD("null isCallback");
180         return Common::NapiGetNull(env);
181     } else {
182         return promise;
183     }
184 }
185 
NapiSubscribeSelf(napi_env env,napi_callback_info info)186 napi_value NapiSubscribeSelf(napi_env env, napi_callback_info info)
187 {
188     ANS_LOGD("called");
189     napi_ref callback = nullptr;
190     std::shared_ptr<SubscriberInstance> objectInfo = nullptr;
191     NotificationSubscribeInfo subscriberInfo;
192     if (ParseParameters(env, info, subscriberInfo, objectInfo, callback) == nullptr) {
193         Common::NapiThrow(env, ERROR_PARAM_INVALID);
194         return Common::NapiGetUndefined(env);
195     }
196 
197     AsyncCallbackInfoSubscribe *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoSubscribe {
198         .env = env, .asyncWork = nullptr, .objectInfo = objectInfo, .subscriberInfo = subscriberInfo
199     };
200     if (!asynccallbackinfo) {
201         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
202         return Common::JSParaError(env, callback);
203     }
204     napi_value promise = nullptr;
205     Common::PaddingCallbackPromiseInfo(env, callback, asynccallbackinfo->info, promise);
206 
207     napi_value resourceName = nullptr;
208     napi_create_string_latin1(env, "subscribeNotificationSelf", NAPI_AUTO_LENGTH, &resourceName);
209     // Asynchronous function call
210     napi_create_async_work(env,
211         nullptr,
212         resourceName,
213         [](napi_env env, void *data) {
214             ANS_LOGD("NapiSubscribeSelf work excute.");
215             if (!data) {
216                 ANS_LOGE("Invalid asynccallbackinfo!");
217                 return;
218             }
219             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
220             if (asynccallbackinfo) {
221                 asynccallbackinfo->info.errorCode =
222                     NotificationHelper::SubscribeNotificationSelf(asynccallbackinfo->objectInfo);
223             }
224         },
225         [](napi_env env, napi_status status, void *data) {
226             ANS_LOGD("NapiSubscribeSelf work complete.");
227             if (!data) {
228                 ANS_LOGE("Invalid asynccallbackinfo!");
229                 return;
230             }
231             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
232             if (asynccallbackinfo) {
233                 Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env));
234                 if (asynccallbackinfo->info.callback != nullptr) {
235                     ANS_LOGD("Delete napiSubscribeSelf callback reference.");
236                     napi_delete_reference(env, asynccallbackinfo->info.callback);
237                 }
238                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
239                 delete asynccallbackinfo;
240                 asynccallbackinfo = nullptr;
241             }
242             ANS_LOGD("NapiSubscribeSelf work complete end.");
243         },
244         (void *)asynccallbackinfo,
245         &asynccallbackinfo->asyncWork);
246 
247     bool isCallback = asynccallbackinfo->info.isCallback;
248     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
249 
250     if (isCallback) {
251         ANS_LOGD("null isCallback");
252         return Common::NapiGetNull(env);
253     } else {
254         return promise;
255     }
256 }
257 
NapiUnsubscribe(napi_env env,napi_callback_info info)258 napi_value NapiUnsubscribe(napi_env env, napi_callback_info info)
259 {
260     ANS_LOGD("called");
261     ParametersInfoUnsubscribe paras;
262     if (ParseParameters(env, info, paras) == nullptr) {
263         Common::NapiThrow(env, ERROR_PARAM_INVALID);
264         return Common::NapiGetUndefined(env);
265     }
266 
267     AsyncCallbackInfoUnsubscribe *asynccallbackinfo = new (std::nothrow)
268         AsyncCallbackInfoUnsubscribe {.env = env, .asyncWork = nullptr, .objectInfo = paras.objectInfo};
269     if (!asynccallbackinfo) {
270         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
271         return Common::JSParaError(env, paras.callback);
272     }
273     napi_value promise = nullptr;
274     Common::PaddingCallbackPromiseInfo(env, paras.callback, asynccallbackinfo->info, promise);
275 
276     napi_value resourceName = nullptr;
277     napi_create_string_latin1(env, "unsubscribe", NAPI_AUTO_LENGTH, &resourceName);
278 
279     // Asynchronous function call
280     napi_create_async_work(env,
281         nullptr,
282         resourceName,
283         [](napi_env env, void *data) {
284             ANS_LOGD("NapiUnsubscribe work excute.");
285             auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoUnsubscribe *>(data);
286             if (asynccallbackinfo) {
287                 if (asynccallbackinfo->objectInfo == nullptr) {
288                     ANS_LOGE("invalid object info");
289                     asynccallbackinfo->info.errorCode = ERR_ANS_INVALID_PARAM;
290                     return;
291                 }
292 
293                 bool ret = AddDeletingSubscriber(asynccallbackinfo->objectInfo);
294                 if (ret) {
295                     asynccallbackinfo->info.errorCode =
296                         NotificationHelper::UnSubscribeNotification(asynccallbackinfo->objectInfo);
297                     if (asynccallbackinfo->info.errorCode != ERR_OK) {
298                         DelDeletingSubscriber(asynccallbackinfo->objectInfo);
299                     }
300                 } else {
301                     asynccallbackinfo->info.errorCode = ERR_ANS_SUBSCRIBER_IS_DELETING;
302                 }
303             }
304         },
305         [](napi_env env, napi_status status, void *data) {
306             ANS_LOGD("NapiUnsubscribe work complete.");
307             AsyncCallbackInfoUnsubscribe *asynccallbackinfo = static_cast<AsyncCallbackInfoUnsubscribe *>(data);
308             if (asynccallbackinfo) {
309                 Common::CreateReturnValue(env, asynccallbackinfo->info, Common::NapiGetNull(env));
310                 if (asynccallbackinfo->info.callback != nullptr) {
311                     ANS_LOGD("Delete napiUnsubscribe callback reference.");
312                     napi_delete_reference(env, asynccallbackinfo->info.callback);
313                 }
314                 napi_delete_async_work(env, asynccallbackinfo->asyncWork);
315                 delete asynccallbackinfo;
316                 asynccallbackinfo = nullptr;
317             }
318             ANS_LOGD("NapiUnsubscribe work complete end.");
319         },
320         (void *)asynccallbackinfo,
321         &asynccallbackinfo->asyncWork);
322 
323     bool isCallback = asynccallbackinfo->info.isCallback;
324     napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
325 
326     if (isCallback) {
327         ANS_LOGD("null isCallback");
328         return Common::NapiGetNull(env);
329     } else {
330         return promise;
331     }
332 }
333 
AsyncDistributeOperationCall(napi_env env,AsyncOperationCallbackInfo * distributeOperationInfo)334 void AsyncDistributeOperationCall(napi_env env, AsyncOperationCallbackInfo* distributeOperationInfo)
335 {
336     napi_value resourceName = nullptr;
337     napi_create_string_latin1(env, "distributeOperation", NAPI_AUTO_LENGTH, &resourceName);
338 
339     // Asynchronous function call
340     napi_create_async_work(env, nullptr, resourceName, NapiDistributeOperationExecuteCallback,
341         NapiDistributeOperationCompleteCallback, (void *)distributeOperationInfo, &distributeOperationInfo->asyncWork);
342     auto result = napi_queue_async_work_with_qos(env, distributeOperationInfo->asyncWork, napi_qos_user_initiated);
343     if (result != napi_ok) {
344         NapiDistributeOperationCompleteCallback(env, result, distributeOperationInfo);
345         NAPI_CALL_RETURN_VOID(env, result);
346     }
347 }
348 
NapiDistributeOperation(napi_env env,napi_callback_info info)349 napi_value NapiDistributeOperation(napi_env env, napi_callback_info info)
350 {
351     ANS_LOGD("called");
352     std::string hashCode;
353     napi_value thisVar = nullptr;
354     OperationInfo operationInfo;
355     if (ParseParameters(env, info, hashCode, thisVar, operationInfo) == nullptr) {
356         Common::NapiThrow(env, ERROR_PARAM_INVALID);
357         return Common::NapiGetUndefined(env);
358     }
359 
360     napi_value ret = nullptr;
361     napi_deferred deferred;
362     napi_create_promise(env, &deferred, &ret);
363     auto distributeOperationInfo = new (std::nothrow) AsyncOperationCallbackInfo {.env = env,
364         .thisVar = thisVar, .deferred = deferred, .hashCode = hashCode, .operationInfo = operationInfo};
365     if (distributeOperationInfo == nullptr) {
366         Common::NapiThrow(env, ERROR_INTERNAL_ERROR);
367         return Common::NapiGetNull(env);
368     }
369 
370     AsyncDistributeOperationCall(env, distributeOperationInfo);
371     return ret;
372 }
373 }  // namespace NotificationNapi
374 }  // namespace OHOS
375