1 /*
2  * Copyright (c) 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 COMMUNICATIONNETMANAGER_BASE_NETMANAGER_BASE_BASE_ASYNC_WORK_H
17 #define COMMUNICATIONNETMANAGER_BASE_NETMANAGER_BASE_BASE_ASYNC_WORK_H
18 
19 #include <limits>
20 #include <memory>
21 
22 #include <napi/native_api.h>
23 #include <napi/native_common.h>
24 
25 #include "base_context.h"
26 #include "napi_constant.h"
27 #include "napi_utils.h"
28 #include "netmanager_base_log.h"
29 #include "nocopyable.h"
30 
31 namespace OHOS {
32 namespace NetManagerStandard {
33 class BaseAsyncWork final {
34 public:
35     DISALLOW_COPY_AND_MOVE(BaseAsyncWork);
36 
37     BaseAsyncWork() = delete;
38 
ExecAsyncWork(napi_env env,void * data)39     template <class Context, bool (*Executor)(Context *)> static void ExecAsyncWork(napi_env env, void *data)
40     {
41         static_assert(std::is_base_of<BaseContext, Context>::value);
42 
43         (void)env;
44 
45         auto context = reinterpret_cast<Context *>(data);
46         if (context == nullptr || Executor == nullptr) {
47             NETMANAGER_BASE_LOGE("context or Executor is nullptr");
48             return;
49         }
50         context->SetExecOK(Executor(context));
51         /* do not have async executor, execOK should be set in sync work */
52     }
53 
54     template <class Context, napi_value (*Callback)(Context *)>
AsyncWorkCallback(napi_env env,napi_status status,void * data)55     static void AsyncWorkCallback(napi_env env, napi_status status, void *data)
56     {
57         static_assert(std::is_base_of<BaseContext, Context>::value);
58 
59         if ((status != napi_ok) || (data == nullptr)) {
60             return;
61         }
62         auto deleter = [](Context *context) { delete context; };
63         std::unique_ptr<Context, decltype(deleter)> context(static_cast<Context *>(data), deleter);
64         size_t argc = 2;
65         napi_value argv[2] = {nullptr};
66         if (context->IsExecOK()) {
67             argv[0] = NapiUtils::GetUndefined(env);
68 
69             if (Callback != nullptr) {
70                 argv[1] = Callback(context.get());
71             } else {
72                 argv[1] = NapiUtils::GetUndefined(env);
73             }
74             if (argv[1] == nullptr) {
75                 NETMANAGER_BASE_LOGE("AsyncWorkName %{public}s createData fail", context->GetAsyncWorkName().c_str());
76                 return;
77             }
78         } else {
79             argv[0] = NapiUtils::CreateErrorMessage(env, context->GetErrorCode(), context->GetErrorMessage());
80             if (argv[0] == nullptr) {
81                 NETMANAGER_BASE_LOGE("AsyncWorkName %{public}s createErrorMessage fail",
82                                      context->GetAsyncWorkName().c_str());
83                 return;
84             }
85 
86             argv[1] = NapiUtils::GetUndefined(env);
87         }
88 
89         if (context->GetDeferred() != nullptr) {
90             if (context->IsExecOK()) {
91                 napi_resolve_deferred(env, context->GetDeferred(), argv[1]);
92             } else {
93                 napi_reject_deferred(env, context->GetDeferred(), argv[0]);
94             }
95             return;
96         }
97 
98         napi_value func = context->GetCallback();
99         napi_value undefined = NapiUtils::GetUndefined(env);
100         (void)NapiUtils::CallFunction(env, undefined, func, argc, argv);
101     }
102 
103     template <class Context, napi_value (*Callback)(Context *)>
AsyncWorkCallbackForSystem(napi_env env,napi_status status,void * data)104     static void AsyncWorkCallbackForSystem(napi_env env, napi_status status, void *data)
105     {
106         static_assert(std::is_base_of<BaseContext, Context>::value);
107 
108         if ((status != napi_ok) || (data == nullptr)) {
109             return;
110         }
111         auto deleter = [](Context *context) { delete context; };
112         std::unique_ptr<Context, decltype(deleter)> context(static_cast<Context *>(data), deleter);
113         if (Callback != nullptr) {
114             (void)Callback(context.get());
115         }
116     }
117 };
118 } // namespace NetManagerStandard
119 } // namespace OHOS
120 
121 #endif // COMMUNICATIONNETMANAGER_BASE_NETMANAGER_BASE_BASE_ASYNC_WORK_H
122