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