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