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 Param *param = new (std::nothrow) Param;
42 if (param == nullptr) {
43 return;
44 }
45 param->env = env_;
46 param->callbackRef = ref_;
47 auto task = [param]() {
48 if (param == nullptr) {
49 PRINT_HILOGE("param is a nullptr");
50 return;
51 }
52 napi_handle_scope scope = nullptr;
53 napi_open_handle_scope(param->env, &scope);
54 if (scope == nullptr) {
55 PRINT_HILOGE("scope is a nullptr");
56 delete param;
57 return;
58 }
59 napi_ref callbackRef_ = param->callbackRef;
60 NapiPrintUtils::DeleteReference(param->env, callbackRef_);
61 napi_close_handle_scope(param->env, scope);
62 delete param;
63 };
64 napi_status ret = napi_send_event(env_, task, napi_eprio_immediate);
65 if (ret != napi_ok) {
66 PRINT_HILOGE("napi_send_event fail");
67 delete param;
68 }
69 }
70 }
71
NapiCallFunction(CallbackParam * cbParam,size_t argcCount,napi_value * callbackValues)72 static void NapiCallFunction(CallbackParam* cbParam, size_t argcCount, napi_value* callbackValues)
73 {
74 if (cbParam == nullptr) {
75 PRINT_HILOGE("cbParam is nullptr");
76 return;
77 }
78 napi_handle_scope scope = nullptr;
79 napi_open_handle_scope(cbParam->env, &scope);
80 if (scope == nullptr) {
81 PRINT_HILOGE("fail to open scope");
82 return;
83 }
84
85 napi_value callbackFunc = NapiPrintUtils::GetReference(cbParam->env, cbParam->ref);
86 if (callbackFunc != nullptr) {
87 napi_call_function(cbParam->env, nullptr, callbackFunc, argcCount,
88 callbackValues, nullptr);
89 PRINT_HILOGI("NapiCallFunction run napi_call_function success");
90 } else {
91 PRINT_HILOGE("NapiCallFunction get reference failed");
92 }
93 napi_close_handle_scope(cbParam->env, scope);
94 }
95
PrintAdapterWorkCb(CallbackParam * cbParam)96 static void PrintAdapterWorkCb(CallbackParam *cbParam)
97 {
98 PRINT_HILOGI("OnCallback start run PrintAdapterWorkCb");
99 if (cbParam == nullptr) {
100 PRINT_HILOGE("cbParam is nullptr");
101 return;
102 }
103 napi_handle_scope scope = nullptr;
104 napi_open_handle_scope(cbParam->env, &scope);
105 if (scope == nullptr) {
106 PRINT_HILOGE("fail to open scope");
107 close(cbParam->fd);
108 return;
109 }
110 napi_value adapterObj = NapiPrintUtils::GetReference(cbParam->env, cbParam->ref);
111 if (adapterObj != nullptr) {
112 napi_value layoutWriteFunc =
113 NapiPrintUtils::GetNamedProperty(cbParam->env, adapterObj, "onStartLayoutWrite");
114 auto successCallback = [](napi_env env, napi_callback_info info) -> napi_value {
115 PRINT_HILOGI("parse from js callback data start");
116 size_t argc = NapiPrintUtils::ARGC_TWO;
117 napi_value args[NapiPrintUtils::ARGC_TWO] = {nullptr};
118
119 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
120 std::string jobId = NapiPrintUtils::GetStringFromValueUtf8(env, args[0]);
121 uint32_t replyState = NapiPrintUtils::GetUint32FromValue(env, args[1]);
122
123 PrintManagerClient::GetInstance()->UpdatePrintJobStateForNormalApp(
124 jobId, PRINT_JOB_CREATE_FILE_COMPLETED, replyState);
125 PRINT_HILOGI("from js return jobId:%{public}s, replyState:%{public}d", jobId.c_str(), replyState);
126 return nullptr;
127 };
128 napi_value callbackResult = nullptr;
129 napi_value callbackValues[NapiPrintUtils::ARGC_FIVE] = { 0 };
130 callbackValues[0] = NapiPrintUtils::CreateStringUtf8(cbParam->env, cbParam->jobId);
131 callbackValues[1] = PrintAttributesHelper::MakeJsObject(cbParam->env, cbParam->oldAttrs);
132 callbackValues[NapiPrintUtils::ARGC_TWO] =
133 PrintAttributesHelper::MakeJsObject(cbParam->env, cbParam->newAttrs);
134 callbackValues[NapiPrintUtils::ARGC_THREE] =
135 NapiPrintUtils::CreateUint32(cbParam->env, cbParam->fd);
136 callbackValues[NapiPrintUtils::ARGC_FOUR] =
137 NapiPrintUtils::CreateFunction(cbParam->env, "writeResultCallback", successCallback, nullptr);
138
139 napi_call_function(cbParam->env, adapterObj, layoutWriteFunc, NapiPrintUtils::ARGC_FIVE,
140 callbackValues, &callbackResult);
141 PRINT_HILOGI("OnCallback end run PrintAdapterWorkCb success");
142 }
143 if (napi_close_handle_scope(cbParam->env, scope) != napi_ok) {
144 close(cbParam->fd);
145 }
146 }
147
OnBaseCallback(std::function<void (CallbackParam *)> paramFun,std::function<void (CallbackParam *)> workCb)148 bool PrintCallback::OnBaseCallback(std::function<void(CallbackParam*)> paramFun,
149 std::function<void(CallbackParam*)> workCb)
150 {
151 CallbackParam *param = new (std::nothrow) CallbackParam;
152 if (param == nullptr) {
153 PRINT_HILOGE("Failed to create callback parameter");
154 return false;
155 }
156
157 {
158 std::lock_guard<std::mutex> lock(mutex_);
159 param->env = env_;
160 param->ref = ref_;
161 param->mutexPtr = &mutex_;
162 paramFun(param);
163 }
164
165 auto task = [param, workCb]() {
166 if (param == nullptr) {
167 PRINT_HILOGE("param is a nullptr");
168 return;
169 }
170 std::lock_guard<std::mutex> autoLock(*param->mutexPtr);
171 workCb(param);
172 delete param;
173 };
174
175 napi_status ret = napi_send_event(env_, task, napi_eprio_immediate);
176 if (ret != napi_ok) {
177 PRINT_HILOGE("napi_send_event fail");
178 delete param;
179 return false;
180 }
181 return true;
182 }
183
OnCallback()184 bool PrintCallback::OnCallback()
185 {
186 PRINT_HILOGI("PrintTask Notification in");
187 return OnBaseCallback([](CallbackParam* param) {},
188 [](CallbackParam *cbParam) {
189 PRINT_HILOGI("OnCallback start run OnCallback");
190 napi_value callbackValues[NapiPrintUtils::ARGC_ONE] = { 0 };
191 callbackValues[0] = NapiPrintUtils::GetUndefined(cbParam->env);
192 NapiCallFunction(cbParam, NapiPrintUtils::ARGC_ZERO, callbackValues);
193 });
194 }
195
OnCallback(uint32_t state,const PrinterInfo & info)196 bool PrintCallback::OnCallback(uint32_t state, const PrinterInfo &info)
197 {
198 PRINT_HILOGI("Printer Notification in");
199 if (nativePrinterChange_cb != nullptr) {
200 return nativePrinterChange_cb(state, info);
201 }
202 return OnBaseCallback(
203 [state, info](CallbackParam* param) {
204 param->state = state;
205 param->printerInfo = info;
206 },
207 [](CallbackParam *cbParam) {
208 PRINT_HILOGI("OnCallback start run PrinterInfoWorkCb");
209 napi_value callbackValues[NapiPrintUtils::ARGC_TWO] = { 0 };
210 callbackValues[0] = NapiPrintUtils::CreateUint32(cbParam->env, cbParam->state);
211 callbackValues[1] = PrinterInfoHelper::MakeJsObject(cbParam->env, cbParam->printerInfo);
212 NapiCallFunction(cbParam, NapiPrintUtils::ARGC_TWO, callbackValues);
213 });
214 }
215
OnCallback(uint32_t state,const PrintJob & info)216 bool PrintCallback::OnCallback(uint32_t state, const PrintJob &info)
217 {
218 PRINT_HILOGI("PrintJob Notification in");
219 return OnBaseCallback(
220 [state, info](CallbackParam* param) {
221 param->state = state;
222 param->jobInfo = info;
223 },
224 [](CallbackParam *cbParam) {
225 PRINT_HILOGI("OnCallback start run PrinterInfoWorkCb");
226 napi_value callbackValues[NapiPrintUtils::ARGC_TWO] = { 0 };
227 callbackValues[0] = NapiPrintUtils::CreateUint32(cbParam->env, cbParam->state);
228 callbackValues[1] = cbParam->jobInfo.GetPrinterId().length() == 0
229 ? PrintJobHelper::MakeJsSimpleObject(cbParam->env, cbParam->jobInfo)
230 : PrintJobHelper::MakeJsObject(cbParam->env, cbParam->jobInfo);
231 NapiCallFunction(cbParam, NapiPrintUtils::ARGC_TWO, callbackValues);
232 });
233 }
234
OnCallback(const std::string & extensionId,const std::string & info)235 bool PrintCallback::OnCallback(const std::string &extensionId, const std::string &info)
236 {
237 PRINT_HILOGI("ExtensionInfo Notification in");
238 return OnBaseCallback(
239 [extensionId, info](CallbackParam* param) {
240 param->extensionId = extensionId;
241 param->info = info;
242 },
243 [](CallbackParam *cbParam) {
244 PRINT_HILOGI("OnCallback start run PrinterInfoWorkCb");
245 napi_value callbackValues[NapiPrintUtils::ARGC_TWO] = { 0 };
246 callbackValues[0] =
247 NapiPrintUtils::CreateStringUtf8(cbParam->env, cbParam->extensionId);
248 callbackValues[1] =
249 NapiPrintUtils::CreateStringUtf8(cbParam->env, cbParam->info);
250 NapiCallFunction(cbParam, NapiPrintUtils::ARGC_TWO, callbackValues);
251 });
252 }
253
OnCallbackAdapterLayout(const std::string & jobId,const PrintAttributes & oldAttrs,const PrintAttributes & newAttrs,uint32_t fd)254 bool PrintCallback::OnCallbackAdapterLayout(
255 const std::string &jobId, const PrintAttributes &oldAttrs, const PrintAttributes &newAttrs, uint32_t fd)
256 {
257 PRINT_HILOGI("PrintCallback OnCallbackAdapterLayout Notification in, jobId:%{public}s newAttrs copyNum:%{public}d",
258 jobId.c_str(),
259 newAttrs.GetCopyNumber());
260 if (adapter_ != nullptr) {
261 PRINT_HILOGI("OnCallbackAdapterLayout run c++");
262 adapter_->onStartLayoutWrite(jobId, oldAttrs, newAttrs, fd, [](std::string jobId, uint32_t state) {
263 PRINT_HILOGI("onStartLayoutWrite write over, jobId:%{public}s state: %{public}d", jobId.c_str(), state);
264 PrintManagerClient::GetInstance()->UpdatePrintJobStateForNormalApp(
265 jobId, PRINT_JOB_CREATE_FILE_COMPLETED, state);
266 });
267 return true;
268 } else {
269 PRINT_HILOGI("OnCallbackAdapterLayout run ets");
270 return OnBaseCallback(
271 [jobId, oldAttrs, newAttrs, fd](CallbackParam *param) {
272 param->jobId = jobId;
273 param->oldAttrs = oldAttrs;
274 param->newAttrs = newAttrs;
275 param->fd = fd;
276 },
277 PrintAdapterWorkCb);
278 }
279 }
280
OnCallbackAdapterJobStateChanged(const std::string jobId,const uint32_t state,const uint32_t subState)281 bool PrintCallback::OnCallbackAdapterJobStateChanged(const std::string jobId, const uint32_t state,
282 const uint32_t subState)
283 {
284 PRINT_HILOGI("PrintCallback OnCallbackAdapterJobStateChanged Notification in, jobId:%{public}s subState:%{public}d",
285 jobId.c_str(), subState);
286 if (adapter_ != nullptr) {
287 PRINT_HILOGI("OnCallbackAdapterJobStateChanged run c++");
288 adapter_->onJobStateChanged(jobId, subState);
289 return true;
290 } else {
291 PRINT_HILOGI("OnCallbackAdapterJobStateChanged run ets");
292 return OnBaseCallback(
293 [jobId, subState](CallbackParam* param) {
294 param->jobId = jobId;
295 param->state = subState;
296 },
297 [](CallbackParam *cbParam) {
298 PRINT_HILOGI("OnCallback start run PrinterInfoWorkCb");
299 napi_value callbackValues[NapiPrintUtils::ARGC_TWO] = { 0 };
300 callbackValues[0] = NapiPrintUtils::CreateStringUtf8(cbParam->env, cbParam->jobId);
301 callbackValues[1] = NapiPrintUtils::CreateUint32(cbParam->env, cbParam->state);
302 NapiCallFunction(cbParam, NapiPrintUtils::ARGC_TWO, callbackValues);
303 });
304 }
305 }
306
OnCallbackAdapterGetFile(uint32_t state)307 bool PrintCallback::OnCallbackAdapterGetFile(uint32_t state)
308 {
309 PRINT_HILOGI("OnCallbackAdapterGetFile in");
310 return OnBaseCallback(
311 [state](CallbackParam* param) {
312 param->state = state;
313 },
314 [](CallbackParam *cbParam) {
315 PRINT_HILOGI("OnCallback start run PrinterInfoWorkCb");
316 napi_value callbackValues[1] = { 0 };
317 callbackValues[0] = NapiPrintUtils::CreateUint32(cbParam->env, cbParam->state);
318 NapiCallFunction(cbParam, NapiPrintUtils::ARGC_TWO, callbackValues);
319 });
320 }
321 } // namespace OHOS::Print