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
16 #include "upload/upload_task_napiV5.h"
17
18 #include "ability.h"
19 #include "js_initialize.h"
20 #include "napi_base_context.h"
21 #include "upload/js_util.h"
22
23 namespace OHOS::Request::Upload {
24 constexpr int FIRST_ARGV = 0;
25 constexpr int PARAM_COUNT_ZERO = 0;
26 constexpr int PARAM_COUNT_ONE = 1;
27 constexpr int PARAM_COUNT_TWO = 2;
~UploadTaskNapiV5()28 UploadTaskNapiV5::~UploadTaskNapiV5()
29 {
30 if (env_ == nullptr) {
31 return;
32 }
33
34 RecycleRef *callbackData = new (std::nothrow)
35 RecycleRef{ .env = env_, .successRef = success_, .failRef = fail_, .completeRef = complete_ };
36 if (callbackData == nullptr) {
37 UPLOAD_HILOGE(UPLOAD_MODULE_JS_NAPI, "Failed to create callbackData");
38 return;
39 }
40 auto afterCallback = [callbackData]() {
41 if (callbackData != nullptr) {
42 UPLOAD_HILOGD(UPLOAD_MODULE_JS_NAPI, "~UploadTaskNapiV5 callbackDataPtr delete start");
43 napi_delete_reference(callbackData->env, callbackData->successRef);
44 napi_delete_reference(callbackData->env, callbackData->failRef);
45 napi_delete_reference(callbackData->env, callbackData->completeRef);
46 delete callbackData;
47 }
48 };
49 int32_t ret = napi_send_event(env_, afterCallback, napi_eprio_high);
50 if (ret != napi_ok) {
51 REQUEST_HILOGE("napi_send_event failed: %{public}d", ret);
52 delete callbackData;
53 }
54 }
55
ParseCallback(napi_env env,napi_callback_info info)56 bool UploadTaskNapiV5::ParseCallback(napi_env env, napi_callback_info info)
57 {
58 napi_value self = nullptr;
59 size_t argc = JSUtil::MAX_ARGC;
60 napi_value argv[JSUtil::MAX_ARGC] = { nullptr };
61 NAPI_CALL_BASE(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr), false);
62 bool successCb = JSUtil::ParseFunction(env, argv[FIRST_ARGV], "success", success_);
63 bool failCb = JSUtil::ParseFunction(env, argv[FIRST_ARGV], "fail", fail_);
64 bool completeCb = JSUtil::ParseFunction(env, argv[FIRST_ARGV], "complete", complete_);
65 return successCb || failCb || completeCb;
66 }
67
AddCallbackToConfig(napi_env env,std::shared_ptr<UploadConfig> & config)68 void UploadTaskNapiV5::AddCallbackToConfig(napi_env env, std::shared_ptr<UploadConfig> &config)
69 {
70 config->fsuccess = std::bind(&UploadTaskNapiV5::OnSystemSuccess, env_, success_, std::placeholders::_1);
71 config->ffail =
72 std::bind(&UploadTaskNapiV5::OnSystemFail, env_, fail_, std::placeholders::_1, std::placeholders::_2);
73 config->fcomplete = std::bind(&UploadTaskNapiV5::OnSystemComplete, shared_from_this());
74 }
75
JsUpload(napi_env env,napi_callback_info info)76 napi_value UploadTaskNapiV5::JsUpload(napi_env env, napi_callback_info info)
77 {
78 UPLOAD_HILOGI(UPLOAD_MODULE_JS_NAPI, "Enter JsUploadV5.");
79 napi_value self = nullptr;
80 size_t argc = JSUtil::MAX_ARGC;
81 napi_value argv[JSUtil::MAX_ARGC] = { nullptr };
82 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
83
84 std::shared_ptr<OHOS::AbilityRuntime::Context> context = nullptr;
85 napi_status getStatus = JsInitialize::GetContext(env, argv[FIRST_ARGV], context);
86 if (getStatus != napi_ok) {
87 UPLOAD_HILOGE(UPLOAD_MODULE_JS_NAPI, "GetContext fail.");
88 NAPI_ASSERT(env, false, "GetContext fail");
89 }
90
91 std::shared_ptr<UploadConfig> uploadConfig = JSUtil::ParseUploadConfig(env, argv[FIRST_ARGV], API3);
92 if (uploadConfig == nullptr) {
93 UPLOAD_HILOGE(UPLOAD_MODULE_JS_NAPI, "ParseUploadConfig fail.");
94 NAPI_ASSERT(env, false, "ParseUploadConfig fail");
95 }
96
97 AddCallbackToConfig(env, uploadConfig);
98 uploadTask_ = std::make_shared<Upload::UploadTask>(uploadConfig);
99 uploadTask_->SetContext(context);
100 uploadTask_->SetUploadProxy(shared_from_this());
101 uploadTask_->ExecuteTask();
102 uploadTask_ = nullptr;
103 return nullptr;
104 }
105
OnSystemSuccess(napi_env env,napi_ref ref,Upload::UploadResponse & response)106 void UploadTaskNapiV5::OnSystemSuccess(napi_env env, napi_ref ref, Upload::UploadResponse &response)
107 {
108 UPLOAD_HILOGI(UPLOAD_MODULE_JS_NAPI, "OnSystemSuccess enter");
109
110 SystemSuccessCallback *successCallback = new (std::nothrow)
111 SystemSuccessCallback{ .env = env, .ref = ref, .response = response };
112 if (successCallback == nullptr) {
113 UPLOAD_HILOGE(UPLOAD_MODULE_JS_NAPI, "Failed to create successCallback");
114 return;
115 }
116 auto afterCallback = [successCallback]() {
117 napi_handle_scope scope = nullptr;
118 napi_open_handle_scope(successCallback->env, &scope);
119 napi_value callback = nullptr;
120 napi_value global = nullptr;
121 napi_value result = nullptr;
122 napi_value jsResponse = JSUtil::Convert2JSUploadResponse(successCallback->env, successCallback->response);
123 napi_value args[PARAM_COUNT_ONE] = { jsResponse };
124 napi_get_reference_value(successCallback->env, successCallback->ref, &callback);
125 napi_get_global(successCallback->env, &global);
126 napi_call_function(successCallback->env, global, callback, PARAM_COUNT_ONE, args, &result);
127 napi_close_handle_scope(successCallback->env, scope);
128 delete successCallback;
129 };
130 int32_t ret = napi_send_event(env, afterCallback, napi_eprio_high);
131 if (ret != napi_ok) {
132 REQUEST_HILOGE("napi_send_event failed: %{public}d", ret);
133 delete successCallback;
134 }
135 }
136
OnSystemFail(napi_env env,napi_ref ref,std::string & data,int32_t & code)137 void UploadTaskNapiV5::OnSystemFail(napi_env env, napi_ref ref, std::string &data, int32_t &code)
138 {
139 UPLOAD_HILOGI(UPLOAD_MODULE_JS_NAPI, "OnSystemFail enter");
140 SystemFailCallback *failCallback = new (std::nothrow)
141 SystemFailCallback{ .data = data, .code = code, .env = env, .ref = ref };
142 if (failCallback == nullptr) {
143 UPLOAD_HILOGE(UPLOAD_MODULE_JS_NAPI, "Failed to create failCallback");
144 return;
145 }
146 auto afterCallback = [failCallback]() {
147 napi_handle_scope scope = nullptr;
148 napi_open_handle_scope(failCallback->env, &scope);
149 napi_value callback = nullptr;
150 napi_value global = nullptr;
151 napi_value result = nullptr;
152 napi_value jsData = nullptr;
153 napi_create_string_utf8(failCallback->env, failCallback->data.c_str(), failCallback->data.size(), &jsData);
154 napi_value jsCode = nullptr;
155 napi_create_int32(failCallback->env, failCallback->code, &jsCode);
156 napi_value args[PARAM_COUNT_TWO] = { jsData, jsCode };
157 napi_get_reference_value(failCallback->env, failCallback->ref, &callback);
158 napi_get_global(failCallback->env, &global);
159 napi_call_function(failCallback->env, global, callback, PARAM_COUNT_TWO, args, &result);
160 napi_close_handle_scope(failCallback->env, scope);
161 delete failCallback;
162 };
163 int32_t ret = napi_send_event(env, afterCallback, napi_eprio_high);
164 if (ret != napi_ok) {
165 REQUEST_HILOGE("napi_send_event failed: %{public}d", ret);
166 delete failCallback;
167 }
168 }
169
OnSystemComplete(std::shared_ptr<Upload::UploadTaskNapiV5> proxy)170 void UploadTaskNapiV5::OnSystemComplete(std::shared_ptr<Upload::UploadTaskNapiV5> proxy)
171 {
172 UPLOAD_HILOGI(UPLOAD_MODULE_JS_NAPI, "OnSystemComplete enter");
173 SystemCompleteCallback *completeCallback = new (std::nothrow) SystemCompleteCallback{ .proxy = proxy };
174 if (completeCallback == nullptr) {
175 UPLOAD_HILOGE(UPLOAD_MODULE_JS_NAPI, "Failed to create completeCallback");
176 return;
177 }
178 auto afterCallback = [completeCallback]() {
179 napi_handle_scope scope = nullptr;
180 napi_open_handle_scope(completeCallback->proxy->env_, &scope);
181 napi_value callback = nullptr;
182 napi_value global = nullptr;
183 napi_value result = nullptr;
184
185 napi_status ret =
186 napi_get_reference_value(completeCallback->proxy->env_, completeCallback->proxy->complete_, &callback);
187 if (ret == napi_ok) {
188 napi_get_global(completeCallback->proxy->env_, &global);
189 napi_call_function(completeCallback->proxy->env_, global, callback, PARAM_COUNT_ZERO, nullptr, &result);
190 }
191 UPLOAD_HILOGD(
192 UPLOAD_MODULE_JS_NAPI, "OnSystemComplete NapiV5Proxy: %{public}ld", completeCallback->proxy.use_count());
193 napi_close_handle_scope(completeCallback->proxy->env_, scope);
194 delete completeCallback;
195 };
196 int32_t ret = napi_send_event(completeCallback->proxy->env_, afterCallback, napi_eprio_high);
197 if (ret != napi_ok) {
198 REQUEST_HILOGE("napi_send_event failed: %{public}d", ret);
199 delete completeCallback;
200 }
201 }
202 } // namespace OHOS::Request::Upload