1 /*
2 * Copyright (c) 2022 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_callback.h"
17 #include "napi_print_utils.h"
18 #include "print_job_helper.h"
19 #include "printer_info_helper.h"
20 #include "print_attributes_helper.h"
21 #include "print_log.h"
22
23 namespace OHOS::Print {
PrintCallback(napi_env env,napi_ref ref)24 PrintCallback::PrintCallback(napi_env env, napi_ref ref) : env_(env), ref_(ref), adapter_(nullptr)
25 {
26 }
27
PrintCallback(PrintDocumentAdapter * adapter)28 PrintCallback::PrintCallback(PrintDocumentAdapter* adapter) : env_(nullptr), ref_(nullptr), adapter_(adapter)
29 {
30 }
31
~PrintCallback()32 PrintCallback::~PrintCallback()
33 {
34 if (adapter_ != nullptr) {
35 delete adapter_;
36 adapter_ = nullptr;
37 } else if (nativePrinterChange_cb != nullptr) {
38 nativePrinterChange_cb = nullptr;
39 } else {
40 std::lock_guard<std::mutex> autoLock(mutex_);
41 PRINT_HILOGD("callback has been destroyed");
42
43 uv_loop_s *loop = nullptr;
44 napi_get_uv_event_loop(env_, &loop);
45 Param *param = new (std::nothrow) Param;
46 if (param == nullptr) {
47 return;
48 }
49 param->env = env_;
50 param->callbackRef = ref_;
51 uv_work_t *work = new (std::nothrow) uv_work_t;
52 if (work == nullptr) {
53 delete param;
54 return;
55 }
56 work->data = reinterpret_cast<void*>(param);
57 int retVal = uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int _status) {
58 PRINT_HILOGD("uv_queue_work PrintCallback DeleteReference");
59 Param *param_ = reinterpret_cast<Param*>(work->data);
60 if (param_ == nullptr) {
61 delete work;
62 return;
63 }
64 napi_handle_scope scope = nullptr;
65 napi_open_handle_scope(param_->env, &scope);
66 if (scope == nullptr) {
67 delete param_;
68 delete work;
69 return;
70 }
71 napi_ref callbackRef_ = param_->callbackRef;
72 NapiPrintUtils::DeleteReference(param_->env, callbackRef_);
73 napi_close_handle_scope(param_->env, scope);
74 delete param_;
75 delete work;
76 });
77 if (retVal != 0) {
78 PRINT_HILOGE("Failed to get uv_queue_work.");
79 delete param;
80 delete work;
81 return;
82 }
83 }
84 }
85
InitUvWorkCallbackEnv(uv_work_t * work,napi_handle_scope & scope)86 static bool InitUvWorkCallbackEnv(uv_work_t *work, napi_handle_scope &scope)
87 {
88 if (work == nullptr) {
89 PRINT_HILOGE("work is nullptr");
90 return false;
91 }
92 if (work->data == nullptr) {
93 PRINT_HILOGE("data is nullptr");
94 delete work;
95 work = nullptr;
96 return false;
97 }
98 CallbackParam *cbParam = reinterpret_cast<CallbackParam *>(work->data);
99 napi_open_handle_scope(cbParam->env, &scope);
100 if (scope == nullptr) {
101 PRINT_HILOGE("fail to open scope");
102 delete cbParam;
103 cbParam = nullptr;
104 delete work;
105 work = nullptr;
106 return false;
107 }
108 return true;
109 }
110
PrintTaskAfterCallFun(uv_work_t * work,int status)111 static void PrintTaskAfterCallFun(uv_work_t *work, int status)
112 {
113 PRINT_HILOGI("OnCallback start run PrintTaskAfterCallFun");
114 napi_handle_scope scope = nullptr;
115 if (!InitUvWorkCallbackEnv(work, scope)) {
116 return;
117 }
118 CallbackParam *cbParam = static_cast<CallbackParam*>(work->data);
119 if (cbParam != nullptr) {
120 std::lock_guard<std::mutex> autoLock(*cbParam->mutexPtr);
121 napi_value callbackFunc = NapiPrintUtils::GetReference(cbParam->env, cbParam->ref);
122 napi_value callbackResult = nullptr;
123 napi_value callbackValues[NapiPrintUtils::ARGC_ONE] = { 0 };
124 callbackValues[0] = NapiPrintUtils::GetUndefined(cbParam->env);
125 napi_call_function(cbParam->env, nullptr, callbackFunc, NapiPrintUtils::ARGC_ZERO,
126 callbackValues, &callbackResult);
127 napi_close_handle_scope(cbParam->env, scope);
128 PRINT_HILOGI("OnCallback end run PrintTaskAfterCallFun success");
129 delete cbParam;
130 cbParam = nullptr;
131 }
132 if (work != nullptr) {
133 delete work;
134 work = nullptr;
135 }
136 }
137
PrinterAfterCallFun(uv_work_t * work,int status)138 static void PrinterAfterCallFun(uv_work_t *work, int status)
139 {
140 PRINT_HILOGI("OnCallback start run PrinterAfterCallFun");
141 napi_handle_scope scope = nullptr;
142 if (!InitUvWorkCallbackEnv(work, scope)) {
143 return;
144 }
145 CallbackParam *cbParam = static_cast<CallbackParam*>(work->data);
146 if (cbParam != nullptr) {
147 std::lock_guard<std::mutex> autoLock(*cbParam->mutexPtr);
148 napi_value callbackFunc = NapiPrintUtils::GetReference(cbParam->env, cbParam->ref);
149 napi_value callbackResult = nullptr;
150 napi_value callbackValues[NapiPrintUtils::ARGC_TWO] = { 0 };
151 callbackValues[0] = NapiPrintUtils::CreateUint32(cbParam->env, cbParam->state);
152 callbackValues[1] = PrinterInfoHelper::MakeJsObject(cbParam->env, cbParam->printerInfo);
153 napi_call_function(cbParam->env, nullptr, callbackFunc, NapiPrintUtils::ARGC_TWO,
154 callbackValues, &callbackResult);
155 napi_close_handle_scope(cbParam->env, scope);
156 PRINT_HILOGI("OnCallback end run PrinterAfterCallFun success");
157 delete cbParam;
158 cbParam = nullptr;
159 }
160 if (work != nullptr) {
161 delete work;
162 work = nullptr;
163 }
164 }
165
PrintJobAfterCallFun(uv_work_t * work,int status)166 static void PrintJobAfterCallFun(uv_work_t *work, int status)
167 {
168 PRINT_HILOGI("OnCallback start run PrintJobAfterCallFun");
169 napi_handle_scope scope = nullptr;
170 if (!InitUvWorkCallbackEnv(work, scope)) {
171 return;
172 }
173 CallbackParam *cbParam = static_cast<CallbackParam*>(work->data);
174 if (cbParam != nullptr) {
175 std::lock_guard<std::mutex> autoLock(*cbParam->mutexPtr);
176 napi_value callbackFunc = NapiPrintUtils::GetReference(cbParam->env, cbParam->ref);
177 napi_value callbackResult = nullptr;
178 napi_value callbackValues[NapiPrintUtils::ARGC_TWO] = { 0 };
179 callbackValues[0] = NapiPrintUtils::CreateUint32(cbParam->env, cbParam->state);
180 callbackValues[1] = cbParam->jobInfo.GetPrinterId().length() == 0
181 ? PrintJobHelper::MakeJsSimpleObject(cbParam->env, cbParam->jobInfo)
182 : PrintJobHelper::MakeJsObject(cbParam->env, cbParam->jobInfo);
183 napi_call_function(cbParam->env, nullptr, callbackFunc, NapiPrintUtils::ARGC_TWO,
184 callbackValues, &callbackResult);
185 napi_close_handle_scope(cbParam->env, scope);
186 PRINT_HILOGI("OnCallback end run PrintJobAfterCallFun success");
187 delete cbParam;
188 cbParam = nullptr;
189 }
190 if (work != nullptr) {
191 delete work;
192 work = nullptr;
193 }
194 }
195
ExtensionAfterCallFun(uv_work_t * work,int status)196 static void ExtensionAfterCallFun(uv_work_t *work, int status)
197 {
198 PRINT_HILOGI("OnCallback start run ExtensionAfterCallFun");
199 napi_handle_scope scope = nullptr;
200 if (!InitUvWorkCallbackEnv(work, scope)) {
201 return;
202 }
203 CallbackParam *cbParam = static_cast<CallbackParam*>(work->data);
204 if (cbParam != nullptr) {
205 std::lock_guard<std::mutex> autoLock(*cbParam->mutexPtr);
206 napi_value callbackFunc = NapiPrintUtils::GetReference(cbParam->env, cbParam->ref);
207 napi_value callbackResult = nullptr;
208 napi_value callbackValues[NapiPrintUtils::ARGC_TWO] = { 0 };
209 callbackValues[0] =
210 NapiPrintUtils::CreateStringUtf8(cbParam->env, cbParam->extensionId);
211 callbackValues[1] =
212 NapiPrintUtils::CreateStringUtf8(cbParam->env, cbParam->info);
213 napi_call_function(cbParam->env, nullptr, callbackFunc, NapiPrintUtils::ARGC_TWO,
214 callbackValues, &callbackResult);
215 napi_close_handle_scope(cbParam->env, scope);
216 PRINT_HILOGI("OnCallback end run ExtensionAfterCallFun success");
217 delete cbParam;
218 cbParam = nullptr;
219 }
220 if (work != nullptr) {
221 delete work;
222 work = nullptr;
223 }
224 }
225
PrintAdapterAfterCallFun(uv_work_t * work,int status)226 static void PrintAdapterAfterCallFun(uv_work_t *work, int status)
227 {
228 PRINT_HILOGI("OnCallback start run PrintAdapterAfterCallFun");
229 napi_handle_scope scope = nullptr;
230 if (!InitUvWorkCallbackEnv(work, scope)) {
231 return;
232 }
233 CallbackParam *cbParam = static_cast<CallbackParam*>(work->data);
234 if (cbParam != nullptr) {
235 std::lock_guard<std::mutex> autoLock(*cbParam->mutexPtr);
236 napi_value adapterObj = NapiPrintUtils::GetReference(cbParam->env, cbParam->ref);
237
238 napi_value layoutWriteFunc = NapiPrintUtils::GetNamedProperty(cbParam->env, adapterObj, "onStartLayoutWrite");
239 auto successCallback = [](napi_env env, napi_callback_info info) -> napi_value {
240 PRINT_HILOGI("parse from js callback data start");
241 size_t argc = NapiPrintUtils::ARGC_TWO;
242 napi_value args[NapiPrintUtils::ARGC_TWO] = {nullptr};
243
244 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
245 std::string jobId = NapiPrintUtils::GetStringFromValueUtf8(env, args[0]);
246 uint32_t replyState = NapiPrintUtils::GetUint32FromValue(env, args[1]);
247
248 PrintManagerClient::GetInstance()->UpdatePrintJobStateForNormalApp(
249 jobId, PRINT_JOB_CREATE_FILE_COMPLETED, replyState);
250 PRINT_HILOGI("from js return jobId:%{public}s, replyState:%{public}d", jobId.c_str(), replyState);
251 return nullptr;
252 };
253
254 napi_value callbackResult = nullptr;
255 napi_value callbackValues[NapiPrintUtils::ARGC_FIVE] = { 0 };
256 callbackValues[0] = NapiPrintUtils::CreateStringUtf8(cbParam->env, cbParam->jobId);
257 callbackValues[1] = PrintAttributesHelper::MakeJsObject(cbParam->env, cbParam->oldAttrs);
258 callbackValues[NapiPrintUtils::ARGC_TWO] =
259 PrintAttributesHelper::MakeJsObject(cbParam->env, cbParam->newAttrs);
260 callbackValues[NapiPrintUtils::ARGC_THREE] =
261 NapiPrintUtils::CreateUint32(cbParam->env, cbParam->fd);
262 callbackValues[NapiPrintUtils::ARGC_FOUR] =
263 NapiPrintUtils::CreateFunction(cbParam->env, "writeResultCallback", successCallback, nullptr);
264
265 napi_call_function(cbParam->env, adapterObj, layoutWriteFunc, NapiPrintUtils::ARGC_FIVE,
266 callbackValues, &callbackResult);
267
268 napi_close_handle_scope(cbParam->env, scope);
269 PRINT_HILOGI("OnCallback end run PrintAdapterAfterCallFun success");
270 delete cbParam;
271 cbParam = nullptr;
272 }
273 if (work != nullptr) {
274 delete work;
275 work = nullptr;
276 }
277 }
278
PrintAdapterJobStateChangedAfterCallFun(uv_work_t * work,int status)279 static void PrintAdapterJobStateChangedAfterCallFun(uv_work_t *work, int status)
280 {
281 PRINT_HILOGI("OnCallback start run PrintAdapterJobStateChangedAfterCallFun");
282 napi_handle_scope scope = nullptr;
283 if (!InitUvWorkCallbackEnv(work, scope)) {
284 return;
285 }
286 CallbackParam *cbParam = static_cast<CallbackParam*>(work->data);
287 if (cbParam != nullptr) {
288 std::lock_guard<std::mutex> autoLock(*cbParam->mutexPtr);
289 napi_value adapterObj = NapiPrintUtils::GetReference(cbParam->env, cbParam->ref);
290
291 napi_value jobStateChangedFunc = NapiPrintUtils::GetNamedProperty(cbParam->env, adapterObj,
292 "onJobStateChanged");
293
294 napi_value callbackResult = nullptr;
295 napi_value callbackValues[NapiPrintUtils::ARGC_TWO] = { 0 };
296 callbackValues[0] = NapiPrintUtils::CreateStringUtf8(cbParam->env, cbParam->jobId);
297 callbackValues[1] = NapiPrintUtils::CreateUint32(cbParam->env, cbParam->state);
298
299 napi_call_function(cbParam->env, adapterObj, jobStateChangedFunc, NapiPrintUtils::ARGC_TWO,
300 callbackValues, &callbackResult);
301
302 napi_close_handle_scope(cbParam->env, scope);
303 PRINT_HILOGI("OnCallback end run PrintAdapterJobStateChangedAfterCallFun success");
304 delete cbParam;
305 cbParam = nullptr;
306 }
307 if (work != nullptr) {
308 delete work;
309 work = nullptr;
310 }
311 }
312
PrintAdapterGetFileAfterCallFun(uv_work_t * work,int status)313 static void PrintAdapterGetFileAfterCallFun(uv_work_t *work, int status)
314 {
315 PRINT_HILOGI("OnCallback start run PrintAdapterGetFileAfterCallFun");
316 napi_handle_scope scope = nullptr;
317 if (!InitUvWorkCallbackEnv(work, scope)) {
318 return;
319 }
320 CallbackParam *cbParam = static_cast<CallbackParam*>(work->data);
321 if (cbParam != nullptr) {
322 std::lock_guard<std::mutex> autoLock(*cbParam->mutexPtr);
323 napi_value callbackFunc = NapiPrintUtils::GetReference(cbParam->env, cbParam->ref);
324 napi_value callbackResult = nullptr;
325 napi_value callbackValues[1] = { 0 };
326 callbackValues[0] = NapiPrintUtils::CreateUint32(cbParam->env, cbParam->state);
327 napi_call_function(cbParam->env, nullptr, callbackFunc, 1,
328 callbackValues, &callbackResult);
329 napi_close_handle_scope(cbParam->env, scope);
330 PRINT_HILOGI("OnCallback end run PrintAdapterGetFileAfterCallFun success");
331 delete cbParam;
332 cbParam = nullptr;
333 }
334 if (work != nullptr) {
335 delete work;
336 work = nullptr;
337 }
338 }
339
onBaseCallback(std::function<void (CallbackParam *)> paramFun,uv_after_work_cb after_work_cb)340 bool PrintCallback::onBaseCallback(std::function<void(CallbackParam*)> paramFun, uv_after_work_cb after_work_cb)
341 {
342 uv_loop_s *loop = nullptr;
343 napi_get_uv_event_loop(env_, &loop);
344 if (loop == nullptr) {
345 PRINT_HILOGE("Failed to get uv event loop");
346 return false;
347 }
348
349 uv_work_t *work = new (std::nothrow) uv_work_t;
350 if (work == nullptr) {
351 PRINT_HILOGE("Failed to create uv work");
352 return false;
353 }
354 CallbackParam *param = new (std::nothrow) CallbackParam;
355 if (param == nullptr) {
356 PRINT_HILOGE("Failed to create callback parameter");
357 delete work;
358 return false;
359 } else {
360 std::lock_guard<std::mutex> lock(mutex_);
361
362 param->env = env_;
363 param->ref = ref_;
364 param->mutexPtr = &mutex_;
365
366 paramFun(param);
367 }
368
369 work->data = param;
370 int retVal = uv_queue_work(loop, work, [](uv_work_t *work) {}, after_work_cb);
371 if (retVal != 0) {
372 PRINT_HILOGE("Failed to get uv_queue_work.");
373 delete param;
374 delete work;
375 return false;
376 }
377 return true;
378 }
379
OnCallback()380 bool PrintCallback::OnCallback()
381 {
382 PRINT_HILOGI("PrintTask Notification in");
383 return onBaseCallback([](CallbackParam* param) {}, PrintTaskAfterCallFun);
384 }
385
OnCallback(uint32_t state,const PrinterInfo & info)386 bool PrintCallback::OnCallback(uint32_t state, const PrinterInfo &info)
387 {
388 PRINT_HILOGI("Printer Notification in");
389 if (nativePrinterChange_cb != nullptr) {
390 return nativePrinterChange_cb(state, info);
391 }
392 return onBaseCallback(
393 [state, info](CallbackParam* param) {
394 param->state = state;
395 param->printerInfo = info;
396 }, PrinterAfterCallFun);
397 }
398
OnCallback(uint32_t state,const PrintJob & info)399 bool PrintCallback::OnCallback(uint32_t state, const PrintJob &info)
400 {
401 PRINT_HILOGI("PrintJob Notification in");
402 return onBaseCallback(
403 [state, info](CallbackParam* param) {
404 param->state = state;
405 param->jobInfo = info;
406 }, PrintJobAfterCallFun);
407 }
408
OnCallback(const std::string & extensionId,const std::string & info)409 bool PrintCallback::OnCallback(const std::string &extensionId, const std::string &info)
410 {
411 PRINT_HILOGI("ExtensionInfo Notification in");
412 return onBaseCallback(
413 [extensionId, info](CallbackParam* param) {
414 param->extensionId = extensionId;
415 param->info = info;
416 }, ExtensionAfterCallFun);
417 }
418
OnCallbackAdapterLayout(const std::string & jobId,const PrintAttributes & oldAttrs,const PrintAttributes & newAttrs,uint32_t fd)419 bool PrintCallback::OnCallbackAdapterLayout(
420 const std::string &jobId, const PrintAttributes &oldAttrs, const PrintAttributes &newAttrs, uint32_t fd)
421 {
422 PRINT_HILOGI("PrintCallback OnCallbackAdapterLayout Notification in, jobId:%{public}s newAttrs copyNum:%{public}d",
423 jobId.c_str(),
424 newAttrs.GetCopyNumber());
425 if (adapter_ != nullptr) {
426 PRINT_HILOGI("OnCallbackAdapterLayout run c++");
427 adapter_->onStartLayoutWrite(jobId, oldAttrs, newAttrs, fd, [](std::string jobId, uint32_t state) {
428 PRINT_HILOGI("onStartLayoutWrite write over, jobId:%{public}s state: %{public}d", jobId.c_str(), state);
429 PrintManagerClient::GetInstance()->UpdatePrintJobStateForNormalApp(
430 jobId, PRINT_JOB_CREATE_FILE_COMPLETED, state);
431 });
432 return true;
433 } else {
434 PRINT_HILOGI("OnCallbackAdapterLayout run ets");
435 return onBaseCallback(
436 [jobId, oldAttrs, newAttrs, fd](CallbackParam *param) {
437 param->jobId = jobId;
438 param->oldAttrs = oldAttrs;
439 param->newAttrs = newAttrs;
440 param->fd = fd;
441 },
442 PrintAdapterAfterCallFun);
443 }
444 }
445
onCallbackAdapterJobStateChanged(const std::string jobId,const uint32_t state,const uint32_t subState)446 bool PrintCallback::onCallbackAdapterJobStateChanged(const std::string jobId, const uint32_t state,
447 const uint32_t subState)
448 {
449 PRINT_HILOGI("PrintCallback onCallbackAdapterJobStateChanged Notification in, jobId:%{public}s subState:%{public}d",
450 jobId.c_str(), subState);
451 if (adapter_ != nullptr) {
452 PRINT_HILOGI("onCallbackAdapterJobStateChanged run c++");
453 adapter_->onJobStateChanged(jobId, subState);
454 return true;
455 } else {
456 PRINT_HILOGI("onCallbackAdapterJobStateChanged run ets");
457 return onBaseCallback(
458 [jobId, subState](CallbackParam* param) {
459 param->jobId = jobId;
460 param->state = subState;
461 }, PrintAdapterJobStateChangedAfterCallFun);
462 }
463 }
464
OnCallbackAdapterGetFile(uint32_t state)465 bool PrintCallback::OnCallbackAdapterGetFile(uint32_t state)
466 {
467 PRINT_HILOGI("OnCallbackAdapterGetFile in");
468 return onBaseCallback(
469 [state](CallbackParam* param) {
470 param->state = state;
471 }, PrintAdapterGetFileAfterCallFun);
472 }
473 } // namespace OHOS::Print
474