• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef COMMUNICATIONNETSTACK_NETSTACK_MODULE_TEMPLATE_H
17 #define COMMUNICATIONNETSTACK_NETSTACK_MODULE_TEMPLATE_H
18 
19 #include <cstddef>
20 #include <initializer_list>
21 #include <iosfwd>
22 #include <type_traits>
23 #include <vector>
24 
25 #include "base_async_work.h"
26 #include "base_context.h"
27 #include "napi/native_api.h"
28 #include "napi/native_common.h"
29 #include "napi_utils.h"
30 #include "netstack_log.h"
31 
32 namespace OHOS::NetStack {
33 class EventManager;
34 struct EventManagerWrapper;
35 } // namespace OHOS::NetStack
36 
37 #define MAX_PARAM_NUM 64
38 
39 namespace OHOS::NetStack::ModuleTemplate {
40 typedef void (*Finalizer)(napi_env, void *data, void *);
41 
42 template <class Context>
InterfaceWithManagerWrapper(napi_env env,napi_callback_info info,const std::string & asyncWorkName,bool (* Work)(napi_env,napi_value,Context *),AsyncWorkExecutor executor,AsyncWorkCallback callback)43 napi_value InterfaceWithManagerWrapper(napi_env env, napi_callback_info info, const std::string &asyncWorkName,
44                                        bool (*Work)(napi_env, napi_value, Context *), AsyncWorkExecutor executor,
45                                        AsyncWorkCallback callback)
46 {
47     NETSTACK_LOGI("js invoke %{public}s", asyncWorkName.c_str());
48     static_assert(std::is_base_of<BaseContext, Context>::value);
49 
50     napi_value thisVal = nullptr;
51     size_t paramsCount = MAX_PARAM_NUM;
52     napi_value params[MAX_PARAM_NUM] = {nullptr};
53     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
54 
55     EventManagerWrapper *wrapper = nullptr;
56     auto napi_ret = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&wrapper));
57     if (napi_ret != napi_ok) {
58         NETSTACK_LOGE("get event manager in napi_unwrap failed, napi_ret is %{public}d", napi_ret);
59         return NapiUtils::GetUndefined(env);
60     }
61 
62     std::shared_ptr<EventManager> sharedManager = nullptr;
63     if (wrapper) {
64         sharedManager = wrapper->sharedManager;
65     }
66     auto context = new (std::nothrow) Context(env, sharedManager);
67     if (!context) {
68         NETSTACK_LOGE("new context is nullptr");
69         return NapiUtils::GetUndefined(env);
70     }
71     context->ParseParams(params, paramsCount);
72     if (context->IsNeedThrowException()) { // only api9 or later need throw exception.
73         napi_throw_error(env, std::to_string(context->GetErrorCode()).c_str(), context->GetErrorMessage().c_str());
74         delete context;
75         context = nullptr;
76         return NapiUtils::GetUndefined(env);
77     }
78     if (Work != nullptr) {
79         if (!Work(env, thisVal, context)) {
80             NETSTACK_LOGE("work failed error code = %{public}d", context->GetErrorCode());
81         }
82     }
83 
84     context->CreateReference(thisVal);
85     context->CreateAsyncWork(asyncWorkName, executor, callback);
86     if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
87         NETSTACK_LOGD("%{public}s create promise", asyncWorkName.c_str());
88         return context->CreatePromise();
89     }
90     return NapiUtils::GetUndefined(env);
91 }
92 
93 template <class Context>
InterfaceWithSharedManager(napi_env env,napi_callback_info info,const std::string & asyncWorkName,bool (* Work)(napi_env,napi_value,Context *),AsyncWorkExecutor executor,AsyncWorkCallback callback)94 napi_value InterfaceWithSharedManager(napi_env env, napi_callback_info info, const std::string &asyncWorkName,
95                                       bool (*Work)(napi_env, napi_value, Context *), AsyncWorkExecutor executor,
96                                       AsyncWorkCallback callback)
97 {
98     NETSTACK_LOGI("js invoke %{public}s", asyncWorkName.c_str());
99     static_assert(std::is_base_of<BaseContext, Context>::value);
100 
101     napi_value thisVal = nullptr;
102     size_t paramsCount = MAX_PARAM_NUM;
103     napi_value params[MAX_PARAM_NUM] = {nullptr};
104     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
105 
106     std::shared_ptr<EventManager> *sharedManager = nullptr;
107     auto napi_ret = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&sharedManager));
108     if (napi_ret != napi_ok) {
109         NETSTACK_LOGE("get event manager in napi_unwrap failed, napi_ret is %{public}d", napi_ret);
110         return NapiUtils::GetUndefined(env);
111     }
112     std::shared_ptr<EventManager> manager = nullptr;
113     if (sharedManager != nullptr && *sharedManager != nullptr) {
114         manager = *sharedManager;
115     }
116 
117     auto context = new (std::nothrow) Context(env, manager);
118     if (!context) {
119         NETSTACK_LOGE("new context is nullptr");
120         return NapiUtils::GetUndefined(env);
121     }
122     context->ParseParams(params, paramsCount);
123     if (context->IsNeedThrowException()) { // only api9 or later need throw exception.
124         napi_throw_error(env, std::to_string(context->GetErrorCode()).c_str(), context->GetErrorMessage().c_str());
125         delete context;
126         context = nullptr;
127         return NapiUtils::GetUndefined(env);
128     }
129     if (Work != nullptr) {
130         if (!Work(env, thisVal, context)) {
131             NETSTACK_LOGE("work failed error code = %{public}d", context->GetErrorCode());
132         }
133     }
134 
135     context->CreateReference(thisVal);
136     context->CreateAsyncWork(asyncWorkName, executor, callback);
137     if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
138         NETSTACK_LOGD("%{public}s create promise", asyncWorkName.c_str());
139         return context->CreatePromise();
140     }
141     return NapiUtils::GetUndefined(env);
142 }
143 
144 template <class Context>
InterfaceWithOutAsyncWorkWithManagerWrapper(napi_env env,napi_callback_info info,bool (* Work)(napi_env,napi_value,Context *),const std::string & asyncWorkName,AsyncWorkExecutor executor,AsyncWorkCallback callback)145 napi_value InterfaceWithOutAsyncWorkWithManagerWrapper(napi_env env, napi_callback_info info,
146                                                        bool (*Work)(napi_env, napi_value, Context *),
147                                                        const std::string &asyncWorkName, AsyncWorkExecutor executor,
148                                                        AsyncWorkCallback callback)
149 {
150     static_assert(std::is_base_of<BaseContext, Context>::value);
151 
152     napi_value thisVal = nullptr;
153     size_t paramsCount = MAX_PARAM_NUM;
154     napi_value params[MAX_PARAM_NUM] = {nullptr};
155     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
156 
157     EventManagerWrapper *wrapper = nullptr;
158     auto napi_ret = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&wrapper));
159     if (napi_ret != napi_ok) {
160         NETSTACK_LOGE("get event manager in napi_unwrap failed, napi_ret is %{public}d", napi_ret);
161         return NapiUtils::GetUndefined(env);
162     }
163 
164     std::shared_ptr<EventManager> sharedManager = nullptr;
165     if (wrapper) {
166         sharedManager = wrapper->sharedManager;
167     }
168     auto context = new (std::nothrow) Context(env, sharedManager);
169     if (!context) {
170         NETSTACK_LOGE("new context is nullptr");
171         return NapiUtils::GetUndefined(env);
172     }
173     context->ParseParams(params, paramsCount);
174     napi_value ret = NapiUtils::GetUndefined(env);
175     if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
176         NETSTACK_LOGD("%{public}s is invoked in promise mode", asyncWorkName.c_str());
177         ret = context->CreatePromise();
178     } else {
179         NETSTACK_LOGD("%{public}s is invoked in callback mode", asyncWorkName.c_str());
180     }
181     context->CreateReference(thisVal);
182     if (Work != nullptr) {
183         if (!Work(env, thisVal, context)) {
184             NETSTACK_LOGE("work failed error code = %{public}d", context->GetErrorCode());
185         }
186     }
187     if (!context->IsParseOK() || context->IsPermissionDenied() || context->IsNoAllowedHost() ||
188         context->IsCleartextNotPermitted() || context->GetSharedManager()->IsEventDestroy()) {
189         context->CreateAsyncWork(asyncWorkName, executor, callback);
190     }
191     return ret;
192 }
193 
194 template <class Context>
InterfaceWithOutAsyncWorkWithSharedManager(napi_env env,napi_callback_info info,bool (* Work)(napi_env,napi_value,Context *),const std::string & asyncWorkName,AsyncWorkExecutor executor,AsyncWorkCallback callback)195 napi_value InterfaceWithOutAsyncWorkWithSharedManager(napi_env env, napi_callback_info info,
196                                                       bool (*Work)(napi_env, napi_value, Context *),
197                                                       const std::string &asyncWorkName, AsyncWorkExecutor executor,
198                                                       AsyncWorkCallback callback)
199 {
200     static_assert(std::is_base_of<BaseContext, Context>::value);
201 
202     napi_value thisVal = nullptr;
203     size_t paramsCount = MAX_PARAM_NUM;
204     napi_value params[MAX_PARAM_NUM] = {nullptr};
205     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
206 
207     std::shared_ptr<EventManager> *sharedManager = nullptr;
208     auto napi_ret = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&sharedManager));
209     if (napi_ret != napi_ok) {
210         NETSTACK_LOGE("get event manager in napi_unwrap failed, napi_ret is %{public}d", napi_ret);
211         return NapiUtils::GetUndefined(env);
212     }
213     std::shared_ptr<EventManager> manager = nullptr;
214     if (sharedManager != nullptr && *sharedManager != nullptr) {
215         manager = *sharedManager;
216     }
217 
218     auto context = new (std::nothrow) Context(env, manager);
219     if (!context) {
220         NETSTACK_LOGE("new context is nullptr");
221         return NapiUtils::GetUndefined(env);
222     }
223     context->ParseParams(params, paramsCount);
224     napi_value ret = NapiUtils::GetUndefined(env);
225     if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
226         NETSTACK_LOGD("%{public}s is invoked in promise mode", asyncWorkName.c_str());
227         ret = context->CreatePromise();
228     } else {
229         NETSTACK_LOGD("%{public}s is invoked in callback mode", asyncWorkName.c_str());
230     }
231     context->CreateReference(thisVal);
232     if (Work != nullptr) {
233         if (!Work(env, thisVal, context)) {
234             NETSTACK_LOGE("work failed error code = %{public}d", context->GetErrorCode());
235         }
236     }
237     if (!context->IsParseOK() || context->IsPermissionDenied() || context->IsNoAllowedHost() ||
238         context->IsCleartextNotPermitted() || context->GetSharedManager()->IsEventDestroy()) {
239         context->CreateAsyncWork(asyncWorkName, executor, callback);
240     }
241     return ret;
242 }
243 
CallbackTemplate(uv_work_t * work,int status)244 template <napi_value (*MakeJsValue)(napi_env, void *)> static void CallbackTemplate(uv_work_t *work, int status)
245 {
246     (void)status;
247 
248     auto workWrapper = static_cast<UvWorkWrapperShared *>(work->data);
249     napi_env env = workWrapper->env;
250     auto closeScope = [env](napi_handle_scope scope) { NapiUtils::CloseScope(env, scope); };
251     std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(NapiUtils::OpenScope(env), closeScope);
252 
253     napi_value obj = MakeJsValue(env, workWrapper->data);
254 
255     std::pair<napi_value, napi_value> arg = {NapiUtils::GetUndefined(workWrapper->env), obj};
256     workWrapper->manager->Emit(workWrapper->type, arg);
257 
258     delete workWrapper;
259     delete work;
260 }
261 
262 template <napi_value (*MakeJsValue)(napi_env, const std::shared_ptr<EventManager> &)>
CallbackTemplateWithSharedManager(uv_work_t * work,int status)263 static void CallbackTemplateWithSharedManager(uv_work_t *work, int status)
264 {
265     (void)status;
266 
267     auto workWrapper = static_cast<UvWorkWrapperShared *>(work->data);
268     napi_env env = workWrapper->env;
269     auto closeScope = [env](napi_handle_scope scope) { NapiUtils::CloseScope(env, scope); };
270     std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(NapiUtils::OpenScope(env), closeScope);
271 
272     napi_value obj = MakeJsValue(env, workWrapper->manager);
273 
274     std::pair<napi_value, napi_value> arg = {NapiUtils::GetUndefined(workWrapper->env), obj};
275     workWrapper->manager->Emit(workWrapper->type, arg);
276 
277     delete workWrapper;
278     delete work;
279 }
280 
281 void DefineClass(napi_env env, napi_value exports, const std::initializer_list<napi_property_descriptor> &properties,
282                  const std::string &className);
283 
284 napi_value NewInstanceNoManager(napi_env env, napi_callback_info info, const std::string &name, Finalizer finalizer);
285 
286 napi_value NewInstanceWithSharedManager(napi_env env, napi_callback_info info, const std::string &className,
287                                         Finalizer finalizer);
288 
289 napi_value NewInstanceWithManagerWrapper(napi_env env, napi_callback_info info, const std::string &className,
290                                          Finalizer finalizer);
291 
292 napi_value OnSharedManager(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
293                            bool asyncCallback);
294 
295 napi_value OnceSharedManager(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
296                              bool asyncCallback);
297 
298 napi_value OffSharedManager(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events);
299 
300 napi_value OnManagerWrapper(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
301                             bool asyncCallback);
302 
303 napi_value OnceManagerWrapper(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
304                               bool asyncCallback);
305 
306 napi_value OffManagerWrapper(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events);
307 } // namespace OHOS::NetStack::ModuleTemplate
308 #endif /* COMMUNICATIONNETSTACK_NETSTACK_MODULE_TEMPLATE_H */
309