• 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 
41 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)42 napi_value InterfaceWithManagerWrapper(napi_env env, napi_callback_info info, const std::string &asyncWorkName,
43                                        bool (*Work)(napi_env, napi_value, Context *), AsyncWorkExecutor executor,
44                                        AsyncWorkCallback callback)
45 {
46     NETSTACK_LOGI("js invoke %{public}s", asyncWorkName.c_str());
47     static_assert(std::is_base_of<BaseContext, Context>::value);
48 
49     napi_value thisVal = nullptr;
50     size_t paramsCount = MAX_PARAM_NUM;
51     napi_value params[MAX_PARAM_NUM] = {nullptr};
52     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
53 
54     EventManagerWrapper *wrapper = nullptr;
55     auto napi_ret = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&wrapper));
56     if (napi_ret != napi_ok) {
57         NETSTACK_LOGE("get event manager in napi_unwrap failed, napi_ret is %{public}d", napi_ret);
58         return NapiUtils::GetUndefined(env);
59     }
60 
61     std::shared_ptr<EventManager> sharedManager = nullptr;
62     if (wrapper) {
63         sharedManager = wrapper->sharedManager;
64     }
65     auto context = new (std::nothrow) Context(env, sharedManager);
66     if (!context) {
67         NETSTACK_LOGE("new context is nullptr");
68         return NapiUtils::GetUndefined(env);
69     }
70     context->ParseParams(params, paramsCount);
71     if (context->IsNeedThrowException()) { // only api9 or later need throw exception.
72         napi_throw_error(env, std::to_string(context->GetErrorCode()).c_str(), context->GetErrorMessage().c_str());
73         delete context;
74         context = nullptr;
75         return NapiUtils::GetUndefined(env);
76     }
77     if (Work != nullptr) {
78         if (!Work(env, thisVal, context)) {
79             NETSTACK_LOGE("work failed error code = %{public}d", context->GetErrorCode());
80         }
81     }
82 
83     context->CreateReference(thisVal);
84     context->CreateAsyncWork(asyncWorkName, executor, callback);
85     if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
86         NETSTACK_LOGD("%{public}s create promise", asyncWorkName.c_str());
87         return context->CreatePromise();
88     }
89     return NapiUtils::GetUndefined(env);
90 }
91 
92 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)93 napi_value InterfaceWithSharedManager(napi_env env, napi_callback_info info, const std::string &asyncWorkName,
94                                       bool (*Work)(napi_env, napi_value, Context *), AsyncWorkExecutor executor,
95                                       AsyncWorkCallback callback)
96 {
97     NETSTACK_LOGI("js invoke %{public}s", asyncWorkName.c_str());
98     static_assert(std::is_base_of<BaseContext, Context>::value);
99 
100     napi_value thisVal = nullptr;
101     size_t paramsCount = MAX_PARAM_NUM;
102     napi_value params[MAX_PARAM_NUM] = {nullptr};
103     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
104 
105     std::shared_ptr<EventManager> *sharedManager = nullptr;
106     auto napi_ret = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&sharedManager));
107     if (napi_ret != napi_ok) {
108         NETSTACK_LOGE("get event manager in napi_unwrap failed, napi_ret is %{public}d", napi_ret);
109         return NapiUtils::GetUndefined(env);
110     }
111     std::shared_ptr<EventManager> manager = nullptr;
112     if (sharedManager != nullptr && *sharedManager != nullptr) {
113         manager = *sharedManager;
114     }
115 
116     auto context = new (std::nothrow) Context(env, manager);
117     if (!context) {
118         NETSTACK_LOGE("new context is nullptr");
119         return NapiUtils::GetUndefined(env);
120     }
121     context->ParseParams(params, paramsCount);
122     if (context->IsNeedThrowException()) { // only api9 or later need throw exception.
123         napi_throw_error(env, std::to_string(context->GetErrorCode()).c_str(), context->GetErrorMessage().c_str());
124         delete context;
125         context = nullptr;
126         return NapiUtils::GetUndefined(env);
127     }
128     if (Work != nullptr) {
129         if (!Work(env, thisVal, context)) {
130             NETSTACK_LOGE("work failed error code = %{public}d", context->GetErrorCode());
131         }
132     }
133 
134     context->CreateReference(thisVal);
135     context->CreateAsyncWork(asyncWorkName, executor, callback);
136     if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
137         NETSTACK_LOGD("%{public}s create promise", asyncWorkName.c_str());
138         return context->CreatePromise();
139     }
140     return NapiUtils::GetUndefined(env);
141 }
142 
143 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)144 napi_value InterfaceWithOutAsyncWorkWithManagerWrapper(napi_env env, napi_callback_info info,
145                                                        bool (*Work)(napi_env, napi_value, Context *),
146                                                        const std::string &asyncWorkName, AsyncWorkExecutor executor,
147                                                        AsyncWorkCallback callback)
148 {
149     static_assert(std::is_base_of<BaseContext, Context>::value);
150 
151     napi_value thisVal = nullptr;
152     size_t paramsCount = MAX_PARAM_NUM;
153     napi_value params[MAX_PARAM_NUM] = {nullptr};
154     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
155 
156     EventManagerWrapper *wrapper = nullptr;
157     auto napi_ret = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&wrapper));
158     if (napi_ret != napi_ok) {
159         NETSTACK_LOGE("get event manager in napi_unwrap failed, napi_ret is %{public}d", napi_ret);
160         return NapiUtils::GetUndefined(env);
161     }
162 
163     std::shared_ptr<EventManager> sharedManager = nullptr;
164     if (wrapper) {
165         sharedManager = wrapper->sharedManager;
166     }
167     auto context = new (std::nothrow) Context(env, sharedManager);
168     if (!context) {
169         NETSTACK_LOGE("new context is nullptr");
170         return NapiUtils::GetUndefined(env);
171     }
172     context->ParseParams(params, paramsCount);
173     napi_value ret = NapiUtils::GetUndefined(env);
174     if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
175         NETSTACK_LOGD("%{public}s is invoked in promise mode", asyncWorkName.c_str());
176         ret = context->CreatePromise();
177     } else {
178         NETSTACK_LOGD("%{public}s is invoked in callback mode", asyncWorkName.c_str());
179     }
180     context->CreateReference(thisVal);
181     if (Work != nullptr) {
182         if (!Work(env, thisVal, context)) {
183             NETSTACK_LOGE("work failed error code = %{public}d", context->GetErrorCode());
184         }
185     }
186     if (!context->IsParseOK() || context->IsPermissionDenied() || context->IsNoAllowedHost() ||
187         context->IsCleartextNotPermitted() || context->GetSharedManager()->IsEventDestroy()) {
188         context->CreateAsyncWork(asyncWorkName, executor, callback);
189     }
190     return ret;
191 }
192 
193 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)194 napi_value InterfaceWithOutAsyncWorkWithSharedManager(napi_env env, napi_callback_info info,
195                                                       bool (*Work)(napi_env, napi_value, Context *),
196                                                       const std::string &asyncWorkName, AsyncWorkExecutor executor,
197                                                       AsyncWorkCallback callback)
198 {
199     static_assert(std::is_base_of<BaseContext, Context>::value);
200 
201     napi_value thisVal = nullptr;
202     size_t paramsCount = MAX_PARAM_NUM;
203     napi_value params[MAX_PARAM_NUM] = {nullptr};
204     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
205 
206     std::shared_ptr<EventManager> *sharedManager = nullptr;
207     auto napi_ret = napi_unwrap(env, thisVal, reinterpret_cast<void **>(&sharedManager));
208     if (napi_ret != napi_ok) {
209         NETSTACK_LOGE("get event manager in napi_unwrap failed, napi_ret is %{public}d", napi_ret);
210         return NapiUtils::GetUndefined(env);
211     }
212     std::shared_ptr<EventManager> manager = nullptr;
213     if (sharedManager != nullptr && *sharedManager != nullptr) {
214         manager = *sharedManager;
215     }
216 
217     auto context = new (std::nothrow) Context(env, manager);
218     if (!context) {
219         NETSTACK_LOGE("new context is nullptr");
220         return NapiUtils::GetUndefined(env);
221     }
222     context->ParseParams(params, paramsCount);
223     napi_value ret = NapiUtils::GetUndefined(env);
224     if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
225         NETSTACK_LOGD("%{public}s is invoked in promise mode", asyncWorkName.c_str());
226         ret = context->CreatePromise();
227     } else {
228         NETSTACK_LOGD("%{public}s is invoked in callback mode", asyncWorkName.c_str());
229     }
230     context->CreateReference(thisVal);
231     if (Work != nullptr) {
232         if (!Work(env, thisVal, context)) {
233             NETSTACK_LOGE("work failed error code = %{public}d", context->GetErrorCode());
234         }
235     }
236     if (!context->IsParseOK() || context->IsPermissionDenied() || context->IsNoAllowedHost() ||
237         context->IsCleartextNotPermitted() || context->GetSharedManager()->IsEventDestroy()) {
238         context->CreateAsyncWork(asyncWorkName, executor, callback);
239     }
240     return ret;
241 }
242 
CallbackTemplate(uv_work_t * work,int status)243 template <napi_value (*MakeJsValue)(napi_env, void *)> static void CallbackTemplate(uv_work_t *work, int status)
244 {
245     (void)status;
246 
247     auto workWrapper = static_cast<UvWorkWrapperShared *>(work->data);
248     napi_env env = workWrapper->env;
249     auto closeScope = [env](napi_handle_scope scope) { NapiUtils::CloseScope(env, scope); };
250     std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(NapiUtils::OpenScope(env), closeScope);
251 
252     napi_value obj = MakeJsValue(env, workWrapper->data);
253 
254     std::pair<napi_value, napi_value> arg = {NapiUtils::GetUndefined(workWrapper->env), obj};
255     workWrapper->manager->Emit(workWrapper->type, arg);
256 
257     delete workWrapper;
258     delete work;
259 }
260 
261 template <napi_value (*MakeJsValue)(napi_env, const std::shared_ptr<EventManager> &)>
CallbackTemplateWithSharedManager(uv_work_t * work,int status)262 static void CallbackTemplateWithSharedManager(uv_work_t *work, int status)
263 {
264     (void)status;
265 
266     auto workWrapper = static_cast<UvWorkWrapperShared *>(work->data);
267     napi_env env = workWrapper->env;
268     auto closeScope = [env](napi_handle_scope scope) { NapiUtils::CloseScope(env, scope); };
269     std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(NapiUtils::OpenScope(env), closeScope);
270 
271     napi_value obj = MakeJsValue(env, workWrapper->manager);
272 
273     std::pair<napi_value, napi_value> arg = {NapiUtils::GetUndefined(workWrapper->env), obj};
274     workWrapper->manager->Emit(workWrapper->type, arg);
275 
276     delete workWrapper;
277     delete work;
278 }
279 
280 void CleanUpWithSharedManager(void* data);
281 
282 void DefineClass(napi_env env, napi_value exports, const std::initializer_list<napi_property_descriptor> &properties,
283                  const std::string &className);
284 
285 napi_value NewInstanceNoManager(napi_env env, napi_callback_info info, const std::string &name, Finalizer finalizer);
286 
287 napi_value NewInstanceWithSharedManager(napi_env env, napi_callback_info info, const std::string &className,
288                                         Finalizer finalizer);
289 
290 napi_value NewInstanceWithManagerWrapper(napi_env env, napi_callback_info info, const std::string &className,
291                                          Finalizer finalizer);
292 
293 napi_value OnSharedManager(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
294                            bool asyncCallback);
295 
296 napi_value OnceSharedManager(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
297                              bool asyncCallback);
298 
299 napi_value OffSharedManager(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events);
300 
301 napi_value OnManagerWrapper(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
302                             bool asyncCallback);
303 
304 napi_value OnceManagerWrapper(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
305                               bool asyncCallback);
306 
307 napi_value OffManagerWrapper(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events);
308 } // namespace OHOS::NetStack::ModuleTemplate
309 #endif /* COMMUNICATIONNETSTACK_NETSTACK_MODULE_TEMPLATE_H */
310