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