1 /*
2 * Copyright (c) 2024 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 "print_modal_ui_callback.h"
17 #include "napi_print_utils.h"
18
19 #include <uv.h>
20 #include <js_native_api.h>
21 #include "napi/native_api.h"
22 #include "napi/native_common.h"
23 #include "napi_base_context.h"
24 #include "ui_content.h"
25
26 using namespace OHOS::Ace;
27
28 #define PRINT_ERROR_CODE "code"
29 #define PRINT_ERROR_MSG "message"
30
31 namespace OHOS {
32 namespace Print {
33
34 const uint32_t RESULT_LENGTH_TWO = 2;
35
PrintModalUICallback(std::shared_ptr<BaseContext> baseContext)36 PrintModalUICallback::PrintModalUICallback(std::shared_ptr<BaseContext> baseContext)
37 {
38 this->baseContext = baseContext;
39 PRINT_HILOGI("constructor ModalUICallback");
40 }
41
SetSessionId(int32_t sessionId)42 void PrintModalUICallback::SetSessionId(int32_t sessionId)
43 {
44 this->sessionId_ = sessionId;
45 }
46
OnRelease(int32_t releaseCode)47 void PrintModalUICallback::OnRelease(int32_t releaseCode)
48 {
49 PRINT_HILOGE("OnRelease enter. release code is %{public}d", releaseCode);
50 if (this->baseContext == nullptr) {
51 PRINT_HILOGE("OnRelease baseContext is null");
52 return;
53 }
54
55 if (this->isResultForModal) {
56 PRINT_HILOGE("SendMessageBack isResultForModal true.");
57 return;
58 }
59
60 this->isResultForModal = true;
61
62 this->baseContext->errorMessage.code = E_PRINT_SERVER_FAILURE;
63 SendMessageBack();
64 return;
65 }
66
OnReceive(const OHOS::AAFwk::WantParams & request)67 void PrintModalUICallback::OnReceive(const OHOS::AAFwk::WantParams& request)
68 {
69 PRINT_HILOGI("OnReceive enter.");
70 }
71
OnError(int32_t code,const std::string & name,const std::string & message)72 void PrintModalUICallback::OnError(int32_t code, const std::string& name, const std::string& message)
73 {
74 PRINT_HILOGE("OnError enter. errorCode=%{public}d, name=%{public}s, message=%{public}s",
75 code, name.c_str(), message.c_str());
76 if (this->baseContext == nullptr) {
77 PRINT_HILOGE("OnError baseContext is null");
78 return;
79 }
80
81 if (this->isResultForModal) {
82 PRINT_HILOGE("SendMessageBack isResultForModal true.");
83 return;
84 }
85
86 this->isResultForModal = true;
87
88 this->baseContext->errorMessage.code = E_PRINT_SERVER_FAILURE;
89 SendMessageBack();
90 return;
91 }
92
OnResultForModal(int32_t resultCode,const OHOS::AAFwk::Want & result)93 void PrintModalUICallback::OnResultForModal(int32_t resultCode, const OHOS::AAFwk::Want& result)
94 {
95 PRINT_HILOGI("OnResultForModal enter. resultCode is %{public}d", resultCode);
96 if (this->baseContext == nullptr) {
97 PRINT_HILOGE("OnResultForModal baseContext is null");
98 return;
99 }
100
101 if (this->isResultForModal) {
102 PRINT_HILOGI("SendMessageBack isResultForModal true.");
103 return;
104 }
105
106 this->isResultForModal = true;
107
108 this->baseContext->errorMessage.code = resultCode;
109 if (this->baseContext->errorMessage.code != E_PRINT_NONE) {
110 this->baseContext->errorMessage.message = result.GetStringParam("message");
111 PRINT_HILOGI("OnResultForModal errorMessage is %s", this->baseContext->errorMessage.message.c_str());
112 }
113
114 SendMessageBack();
115 return;
116 }
117
SendMessageBack()118 void PrintModalUICallback::SendMessageBack()
119 {
120 PRINT_HILOGI("SendMessageBack enter.");
121 if (this->baseContext == nullptr) {
122 PRINT_HILOGE("baseContext is null");
123 return;
124 }
125
126 auto abilityContext = this->baseContext->context;
127 auto uiExtContext = this->baseContext->uiExtensionContext;
128 OHOS::Ace::UIContent* uiContent = nullptr;
129 if (abilityContext != nullptr) {
130 uiContent = abilityContext->GetUIContent();
131 } else if (uiExtContext != nullptr) {
132 uiContent = uiExtContext->GetUIContent();
133 }
134
135 if (uiContent != nullptr) {
136 PRINT_HILOGE("CloseModalUIExtension");
137 uiContent->CloseModalUIExtension(this->sessionId_);
138 }
139
140 uv_loop_s* loop = nullptr;
141 napi_get_uv_event_loop(this->baseContext->env, &loop);
142 if (loop == nullptr) {
143 PRINT_HILOGE("loop is nullptr");
144 return;
145 }
146 uv_work_t* work = new (std::nothrow) uv_work_t;
147 if (work == nullptr) {
148 PRINT_HILOGE("work is nullptr");
149 return;
150 }
151 BaseContext *printBaseContext = new (std::nothrow) BaseContext(*this->baseContext);
152 if (printBaseContext == nullptr) {
153 PRINT_HILOGE("printBaseContext is nullptr.");
154 delete work;
155 work = nullptr;
156 return;
157 }
158 work->data = reinterpret_cast<void*>(printBaseContext);
159
160 int ret = uv_queue_work(
161 loop, work, [](uv_work_t* work) { (void)work; }, SendMessageBackWork);
162 if (ret != 0) {
163 PRINT_HILOGE("Failed to get uv_queue_work.");
164 delete printBaseContext;
165 delete work;
166 work = nullptr;
167 }
168 }
169
SendMessageBackWork(uv_work_t * work,int statusIn)170 void PrintModalUICallback::SendMessageBackWork(uv_work_t* work, int statusIn)
171 {
172 (void)statusIn;
173 napi_handle_scope scope = nullptr;
174 if (work == nullptr) {
175 PRINT_HILOGE("work is nullptr");
176 return;
177 }
178 BaseContext* context = reinterpret_cast<BaseContext*>(work->data);
179 if (context == nullptr) {
180 PRINT_HILOGE("context is null");
181 delete work;
182 work = nullptr;
183 return;
184 }
185
186 napi_status status;
187 size_t resultLength = RESULT_LENGTH_TWO;
188 size_t errorIndex = NapiPrintUtils::INDEX_ZERO;
189 size_t resultIndex = NapiPrintUtils::INDEX_ONE;
190
191 napi_open_handle_scope(context->env, &scope);
192 if (scope == nullptr) {
193 PRINT_HILOGE("open handle scope failed");
194 }
195
196 napi_value result[2] = { nullptr };
197 CreateResultMessage(context, result, resultLength);
198 if (context->deferred) {
199 if (context->errorMessage.code == E_PRINT_NONE) {
200 status = napi_resolve_deferred(context->env, context->deferred, result[resultIndex]);
201 PRINT_HILOGD("promise SUCCEED status %{public}d", (status == napi_ok));
202 } else {
203 status = napi_reject_deferred(context->env, context->deferred, result[errorIndex]);
204 PRINT_HILOGE("promise FAILD status %{public}d", (status == napi_ok));
205 }
206 } else {
207 napi_value callback = nullptr;
208 status = napi_get_reference_value(context->env, context->callback, &callback);
209 status = napi_call_function(context->env, nullptr, callback, sizeof(result) / sizeof(result[0]), result,
210 nullptr);
211 PRINT_HILOGD("callBack status %{public}d", (status == napi_ok));
212 }
213
214 PRINT_HILOGD("uv_queue_work callback success");
215 napi_close_handle_scope(context->env, scope);
216
217 delete context;
218 context = nullptr;
219
220 delete work;
221 work = nullptr;
222 }
223
CreateResultMessage(BaseContext * context,napi_value * result,uint32_t length)224 napi_status PrintModalUICallback::CreateResultMessage(BaseContext* context, napi_value* result, uint32_t length)
225 {
226 PRINT_HILOGD("CreateResultMessage resultLength %{public}d", length);
227 size_t errorIndex = NapiPrintUtils::INDEX_ZERO;
228 if (length < RESULT_LENGTH_TWO) {
229 PRINT_HILOGE("Result length is less than 2.");
230 return napi_invalid_arg;
231 }
232 size_t resultIndex = NapiPrintUtils::INDEX_ONE;
233 napi_status status;
234
235 if (context == nullptr) {
236 PRINT_HILOGE("context is nullptr");
237 return napi_invalid_arg;
238 }
239 PRINT_HILOGD("errorcode: %{public}d", context->errorMessage.code);
240 if (context->errorMessage.code == E_PRINT_NONE) {
241 if (context->requestType == PrintRequestType::REQUEST_TYPE_START) {
242 PrintContext* printContext = static_cast<PrintContext*>(context);
243 CreatePrintResult(printContext, result[resultIndex]);
244 status = napi_get_undefined(context->env, &result[errorIndex]);
245 return status;
246 }
247 status = napi_get_undefined(context->env, &result[resultIndex]);
248 status = napi_get_undefined(context->env, &result[errorIndex]);
249 return status;
250 } else {
251 result[errorIndex] =
252 CreateBusinessError(context->env, context->errorMessage.code, context->errorMessage.message);
253 status = napi_get_undefined(context->env, &result[resultIndex]);
254 return status;
255 }
256 }
257
CreatePrintResult(PrintContext * printContext,napi_value & result)258 napi_status PrintModalUICallback::CreatePrintResult(PrintContext* printContext, napi_value& result)
259 {
260 if (printContext == nullptr) {
261 PRINT_HILOGE("printContext is nullptr");
262 return napi_invalid_arg;
263 }
264 napi_status status = napi_create_object(printContext->env, &result);
265 if (status != napi_ok) {
266 PRINT_HILOGE("create js object failed");
267 }
268 return status;
269 }
270
CreateBusinessError(const napi_env & env,int32_t errCode,const std::string & errMsg)271 napi_value PrintModalUICallback::CreateBusinessError(const napi_env& env, int32_t errCode, const std::string& errMsg)
272 {
273 PRINT_HILOGD("CreateBusinessError errCode: %{public}d errMsg: %{public}s", errCode, errMsg.c_str());
274
275 napi_value message = nullptr;
276 napi_status status = napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
277 if (status != napi_ok) {
278 PRINT_HILOGE("napi create errorMessage failed");
279 return message;
280 }
281
282 napi_value code = nullptr;
283 status = napi_create_int32(env, errCode, &code);
284 if (status != napi_ok) {
285 PRINT_HILOGE("napi create errorCode failed");
286 return code;
287 }
288
289 napi_value businessError = nullptr;
290 status = napi_create_object(env, &businessError);
291 if (status != napi_ok) {
292 PRINT_HILOGE("napi create businessError failed");
293 return businessError;
294 }
295
296 status = napi_set_named_property(env, businessError, PRINT_ERROR_CODE, code);
297 if (status != napi_ok) {
298 PRINT_HILOGE("napi set errorCode failed");
299 }
300
301 status = napi_set_named_property(env, businessError, PRINT_ERROR_MSG, message);
302 if (status != napi_ok) {
303 PRINT_HILOGE("napi set errorMessage failed");
304 }
305
306 PRINT_HILOGI("CreateBusinessError exit");
307 return businessError;
308 }
309
310 } // namespace Print
311 } // namespace OHOS