• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #ifndef REQUEST_ASYNC_CALL_H
16 #define REQUEST_ASYNC_CALL_H
17 
18 #include <functional>
19 #include <memory>
20 #include <new>
21 #include <string>
22 
23 #include "constant.h"
24 #include "log.h"
25 #include "napi/native_node_api.h"
26 #include "napi_utils.h"
27 #include "request_common.h"
28 
29 namespace OHOS::Request {
30 class AsyncCall final {
31 public:
32     class Context {
33     public:
34         using InputAction = std::function<napi_status(size_t, napi_value *, napi_value)>;
35         using OutputAction = std::function<napi_status(napi_value *)>;
36         using ExecAction = std::function<void()>;
37         Context() = default;
~Context()38         virtual ~Context()
39         {
40             ContextNapiHolder *holder = new (std::nothrow)
41                 ContextNapiHolder{ .env = env_, .callbackRef = callbackRef_, .self = self_, .work = work_ };
42             if (holder == nullptr) {
43                 return;
44             }
45             auto afterCallback = [holder]() {
46                 napi_handle_scope scope = nullptr;
47                 napi_open_handle_scope(holder->env, &scope);
48                 if (scope == nullptr) {
49                     delete holder;
50                     return;
51                 } else if (holder->env == nullptr || holder->work == nullptr || holder->self == nullptr) {
52                     napi_close_handle_scope(holder->env, scope);
53                     delete holder;
54                     return;
55                 }
56                 napi_delete_async_work(holder->env, holder->work);
57                 napi_delete_reference(holder->env, holder->self);
58                 if (holder->callbackRef != nullptr) {
59                     napi_delete_reference(holder->env, holder->callbackRef);
60                 }
61                 napi_close_handle_scope(holder->env, scope);
62                 delete holder;
63             };
64             int32_t ret = napi_send_event(env_, afterCallback, napi_eprio_high);
65             if (ret != napi_ok) {
66                 REQUEST_HILOGE("napi_send_event failed: %{public}d", ret);
67                 delete holder;
68             }
69         };
SetInput(InputAction action)70         inline Context &SetInput(InputAction action)
71         {
72             input_ = std::move(action);
73             return *this;
74         }
SetOutput(OutputAction action)75         inline Context &SetOutput(OutputAction action)
76         {
77             output_ = std::move(action);
78             return *this;
79         }
SetExec(ExecAction action)80         inline Context &SetExec(ExecAction action)
81         {
82             exec_ = std::move(action);
83             return *this;
84         }
CreateErr()85         inline napi_value CreateErr()
86         {
87             ExceptionError error;
88             NapiUtils::ConvertError(innerCode_, error);
89             return NapiUtils::CreateBusinessError(env_, error.code, error.errInfo, withErrCode_);
90         }
91 
92         InputAction input_ = nullptr;
93         OutputAction output_ = nullptr;
94         ExecAction exec_ = nullptr;
95 
96         napi_env env_;
97         napi_ref callbackRef_ = nullptr;
98         napi_ref self_ = nullptr;
99         napi_deferred defer_ = nullptr;
100         napi_async_work work_ = nullptr;
101 
102         int32_t innerCode_;
103         bool withErrCode_;
104         Version version_;
105     };
106 
107     AsyncCall(napi_env env, napi_callback_info info, const std::shared_ptr<Context> &context);
108     ~AsyncCall();
109     napi_value Call(const std::shared_ptr<Context> &context, const std::string &resourceName = "AsyncCall");
110 
SetQosLevel(napi_qos_t napiQosLevel)111     inline void SetQosLevel(napi_qos_t napiQosLevel)
112     {
113         napiQosLevel_ = napiQosLevel;
114     }
115 
116 private:
117     enum { ARG_ERROR, ARG_DATA, ARG_BUTT };
118 
119     struct WorkData {
120         std::shared_ptr<Context> ctx = nullptr;
~WorkDataWorkData121         ~WorkData()
122         {
123             ctx = nullptr;
124         }
125     };
126 
127     struct ContextNapiHolder {
128         napi_env env;
129         napi_ref callbackRef;
130         napi_ref self;
131         napi_async_work work;
132     };
133     static void OnExecute(napi_env env, void *data);
134     static void OnComplete(napi_env env, napi_status status, void *data);
135     napi_qos_t napiQosLevel_ = napi_qos_default;
136 };
137 } // namespace OHOS::Request
138 #endif // ASYNC_CALL_H
139