• 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                 REQUEST_HILOGE("new ContextNapiHolder null");
44                 return;
45             }
46             // Deletes reference of callback in JS main thread.
47             auto afterCallback = [holder]() {
48                 napi_handle_scope scope = nullptr;
49                 napi_open_handle_scope(holder->env, &scope);
50                 if (scope == nullptr) {
51                     delete holder;
52                     return;
53                 } else if (holder->env == nullptr || holder->work == nullptr || holder->self == nullptr) {
54                     napi_close_handle_scope(holder->env, scope);
55                     delete holder;
56                     return;
57                 }
58                 napi_delete_async_work(holder->env, holder->work);
59                 napi_delete_reference(holder->env, holder->self);
60                 if (holder->callbackRef != nullptr) {
61                     napi_delete_reference(holder->env, holder->callbackRef);
62                 }
63                 napi_close_handle_scope(holder->env, scope);
64                 delete holder;
65             };
66             int32_t ret = napi_send_event(env_, afterCallback, napi_eprio_high);
67             if (ret != napi_ok) {
68                 REQUEST_HILOGE("napi_send_event failed: %{public}d", ret);
69                 delete holder;
70             }
71         };
SetInput(InputAction action)72         inline Context &SetInput(InputAction action)
73         {
74             input_ = std::move(action);
75             return *this;
76         }
SetOutput(OutputAction action)77         inline Context &SetOutput(OutputAction action)
78         {
79             output_ = std::move(action);
80             return *this;
81         }
SetExec(ExecAction action)82         inline Context &SetExec(ExecAction action)
83         {
84             exec_ = std::move(action);
85             return *this;
86         }
CreateErr()87         inline napi_value CreateErr()
88         {
89             ExceptionError error;
90             NapiUtils::ConvertError(innerCode_, error);
91             return NapiUtils::CreateBusinessError(env_, error.code, error.errInfo, withErrCode_);
92         }
93 
94         InputAction input_ = nullptr;
95         OutputAction output_ = nullptr;
96         ExecAction exec_ = nullptr;
97 
98         napi_env env_;
99         napi_ref callbackRef_ = nullptr;
100         napi_ref self_ = nullptr;
101         napi_deferred defer_ = nullptr;
102         napi_async_work work_ = nullptr;
103 
104         int32_t innerCode_;
105         bool withErrCode_;
106         Version version_;
107     };
108 
109     AsyncCall(napi_env env, napi_callback_info info, const std::shared_ptr<Context> &context);
110     ~AsyncCall();
111     napi_value Call(const std::shared_ptr<Context> &context, const std::string &resourceName = "AsyncCall");
112 
SetQosLevel(napi_qos_t napiQosLevel)113     inline void SetQosLevel(napi_qos_t napiQosLevel)
114     {
115         napiQosLevel_ = napiQosLevel;
116     }
117 
118 private:
119     enum { ARG_ERROR, ARG_DATA, ARG_BUTT };
120 
121     struct WorkData {
122         std::shared_ptr<Context> ctx = nullptr;
~WorkDataWorkData123         ~WorkData()
124         {
125             ctx = nullptr;
126         }
127     };
128 
129     struct ContextNapiHolder {
130         napi_env env;
131         napi_ref callbackRef;
132         napi_ref self;
133         napi_async_work work;
134     };
135     static void OnExecute(napi_env env, void *data);
136     static void OnComplete(napi_env env, napi_status status, void *data);
137     napi_qos_t napiQosLevel_ = napi_qos_default;
138 };
139 } // namespace OHOS::Request
140 #endif // ASYNC_CALL_H
141