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 "js_print_extension.h"
17
18 #include "ability_info.h"
19 #include "iprint_extension_callback.h"
20 #include "js_print_callback.h"
21 #include "js_print_extension_context.h"
22 #include "js_runtime.h"
23 #include "js_runtime_utils.h"
24 #include "napi/native_api.h"
25 #include "napi/native_node_api.h"
26 #include "napi_common_util.h"
27 #include "napi_common_want.h"
28 #include "napi_print_utils.h"
29 #include "napi_remote_object.h"
30 #include "print_log.h"
31 #include "print_manager_client.h"
32 #include "printer_capability.h"
33 #include "print_job_helper.h"
34 #include "print_utils.h"
35
36 namespace OHOS {
37 namespace AbilityRuntime {
38 JsPrintExtension *JsPrintExtension::jsExtension_ = nullptr;
39 using namespace OHOS::AppExecFwk;
40 using namespace OHOS::Print;
41
Create(const std::unique_ptr<Runtime> & runtime)42 JsPrintExtension *JsPrintExtension::Create(const std::unique_ptr<Runtime> &runtime)
43 {
44 PRINT_HILOGD("jws JsPrintExtension begin Create");
45 jsExtension_ = new JsPrintExtension(static_cast<JsRuntime &>(*runtime));
46 return jsExtension_;
47 }
48
JsPrintExtension(JsRuntime & jsRuntime)49 JsPrintExtension::JsPrintExtension(JsRuntime &jsRuntime) : jsRuntime_(jsRuntime),
50 extensionId_(""), hasDestroyed_(false) {}
51 JsPrintExtension::~JsPrintExtension() = default;
52
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)53 void JsPrintExtension::Init(const std::shared_ptr<AbilityLocalRecord> &record,
54 const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
55 const sptr<IRemoteObject> &token)
56 {
57 PRINT_HILOGD("jws JsPrintExtension begin Init");
58 PrintExtension::Init(record, application, handler, token);
59
60 if (!InitExtensionObj(jsRuntime_)) {
61 PRINT_HILOGE("Failed to init extension object");
62 return;
63 }
64
65 PRINT_HILOGD("JsPrintExtension::Init ConvertNativeValueTo.");
66 NativeObject *obj = ConvertNativeValueTo<NativeObject>(jsObj_->Get());
67 if (obj == nullptr) {
68 PRINT_HILOGE("Failed to get JsPrintExtension object");
69 return;
70 }
71
72 if (!InitContextObj(jsRuntime_, obj, extensionId_)) {
73 PRINT_HILOGE("Failed to init extension context object");
74 return;
75 }
76 PRINT_HILOGD("JsPrintExtension::Init end.");
77 }
78
InitExtensionObj(JsRuntime & jsRuntime)79 bool JsPrintExtension::InitExtensionObj(JsRuntime &jsRuntime)
80 {
81 std::string srcPath = "";
82 GetSrcPath(srcPath);
83 if (srcPath.empty()) {
84 PRINT_HILOGE("Failed to get srcPath");
85 return false;
86 }
87
88 std::string moduleName(abilityInfo_->moduleName);
89 moduleName.append("::").append(abilityInfo_->name);
90 PRINT_HILOGD("Init module:%{public}s,srcPath:%{public}s.", moduleName.c_str(), srcPath.c_str());
91 HandleScope handleScope(jsRuntime_);
92
93 jsObj_ = jsRuntime.LoadModule(moduleName, srcPath, abilityInfo_->hapPath,
94 abilityInfo_->compileMode == CompileMode::ES_MODULE);
95 if (jsObj_ == nullptr) {
96 PRINT_HILOGE("Failed to get jsObj_");
97 return false;
98 }
99 return true;
100 }
101
InitContextObj(JsRuntime & jsRuntime,NativeObject * & extObj,std::string & extensionId)102 bool JsPrintExtension::InitContextObj(JsRuntime &jsRuntime, NativeObject *&extObj, std::string &extensionId)
103 {
104 auto context = GetContext();
105 if (context == nullptr) {
106 PRINT_HILOGE("Failed to get context");
107 return false;
108 }
109 PRINT_HILOGD("CreateJsPrintExtensionContext.");
110 auto &engine = jsRuntime.GetNativeEngine();
111 NativeValue *contextObj = CreateJsPrintExtensionContext(engine, context, extensionId);
112 auto shellContextRef = jsRuntime.LoadSystemModule("PrintExtensionContext", &contextObj, NapiPrintUtils::ARGC_ONE);
113 contextObj = shellContextRef->Get();
114 PRINT_HILOGD("JsPrintExtension::Init Bind.");
115 context->Bind(jsRuntime, shellContextRef.release());
116 PRINT_HILOGD("JsPrintExtension::SetProperty.");
117 extObj->SetProperty("context", contextObj);
118
119 auto nativeObj = ConvertNativeValueTo<NativeObject>(contextObj);
120 if (nativeObj == nullptr) {
121 PRINT_HILOGE("Failed to get Print extension native object");
122 return false;
123 }
124
125 nativeObj->SetNativePointer(
126 new std::weak_ptr<AbilityRuntime::Context>(context),
127 [](NativeEngine *, void *data, void *) {
128 PRINT_HILOGD("Finalizer for weak_ptr Print extension context is called");
129 delete static_cast<std::weak_ptr<AbilityRuntime::Context> *>(data);
130 },
131 nullptr);
132 return true;
133 }
134
OnStart(const AAFwk::Want & want)135 void JsPrintExtension::OnStart(const AAFwk::Want &want)
136 {
137 Extension::OnStart(want);
138 PRINT_HILOGD("jws JsPrintExtension OnStart begin..");
139 HandleScope handleScope(jsRuntime_);
140 NativeEngine *nativeEngine = &jsRuntime_.GetNativeEngine();
141 napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
142 NativeValue *nativeWant = reinterpret_cast<NativeValue *>(napiWant);
143 NativeValue *argv[] = { nativeWant };
144 CallObjectMethod("onCreate", argv, NapiPrintUtils::ARGC_ONE);
145 RegisterCb();
146 PrintManagerClient::GetInstance()->LoadExtSuccess(extensionId_);
147 PRINT_HILOGD("%{public}s end.", __func__);
148 }
149
RegisterCb()150 void JsPrintExtension::RegisterCb()
151 {
152 RegisterDiscoveryCb();
153 RegisterConnectionCb();
154 RegisterPrintJobCb();
155 RegisterPreviewCb();
156 RegisterQueryCapCb();
157 RegisterExtensionCb();
158 }
159
OnStop()160 void JsPrintExtension::OnStop()
161 {
162 PrintExtension::OnStop();
163 PRINT_HILOGD("jws JsPrintExtension OnStop begin.");
164 if (!hasDestroyed_) {
165 CallObjectMethod("onDestroy");
166 }
167 bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken());
168 if (ret) {
169 PRINT_HILOGD("The Print extension connection is not disconnected.");
170 }
171 PRINT_HILOGD("%{public}s end.", __func__);
172 }
173
OnConnect(const AAFwk::Want & want)174 sptr<IRemoteObject> JsPrintExtension::OnConnect(const AAFwk::Want &want)
175 {
176 PRINT_HILOGD("jws JsPrintExtension OnConnect begin.");
177 Extension::OnConnect(want);
178 PRINT_HILOGD("%{public}s begin.", __func__);
179 HandleScope handleScope(jsRuntime_);
180 NativeEngine *nativeEngine = &jsRuntime_.GetNativeEngine();
181 napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
182 NativeValue *nativeWant = reinterpret_cast<NativeValue *>(napiWant);
183 NativeValue *argv[] = { nativeWant };
184 if (!jsObj_) {
185 PRINT_HILOGW("Not found PrintExtension.js");
186 return nullptr;
187 }
188
189 NativeValue *value = jsObj_->Get();
190 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
191 if (obj == nullptr) {
192 PRINT_HILOGE("Failed to get PrintExtension object");
193 return nullptr;
194 }
195
196 NativeValue *method = obj->GetProperty("onConnect");
197 if (method == nullptr) {
198 PRINT_HILOGE("Failed to get onConnect from PrintExtension object");
199 return nullptr;
200 }
201 PRINT_HILOGD("JsPrintExtension::CallFunction onConnect, success");
202 NativeValue *remoteNative = nativeEngine->CallFunction(value, method, argv, NapiPrintUtils::ARGC_ONE);
203 if (remoteNative == nullptr) {
204 PRINT_HILOGE("remoteNative nullptr.");
205 }
206 auto remoteObj = NAPI_ohos_rpc_getNativeRemoteObject(
207 reinterpret_cast<napi_env>(nativeEngine), reinterpret_cast<napi_value>(remoteNative));
208 if (remoteObj == nullptr) {
209 PRINT_HILOGE("remoteObj nullptr.");
210 }
211 return remoteObj;
212 }
213
OnDisconnect(const AAFwk::Want & want)214 void JsPrintExtension::OnDisconnect(const AAFwk::Want &want)
215 {
216 PRINT_HILOGD("jws JsPrintExtension OnDisconnect begin.");
217 Extension::OnDisconnect(want);
218 PRINT_HILOGD("%{public}s begin.", __func__);
219 HandleScope handleScope(jsRuntime_);
220 NativeEngine *nativeEngine = &jsRuntime_.GetNativeEngine();
221 napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
222 NativeValue *nativeWant = reinterpret_cast<NativeValue *>(napiWant);
223 NativeValue *argv[] = { nativeWant };
224 if (!jsObj_) {
225 PRINT_HILOGW("Not found PrintExtension.js");
226 return;
227 }
228
229 NativeValue *value = jsObj_->Get();
230 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
231 if (obj == nullptr) {
232 PRINT_HILOGE("Failed to get PrintExtension object");
233 return;
234 }
235
236 NativeValue *method = obj->GetProperty("onDisconnect");
237 if (method == nullptr) {
238 PRINT_HILOGE("Failed to get onDisconnect from PrintExtension object");
239 return;
240 }
241 nativeEngine->CallFunction(value, method, argv, NapiPrintUtils::ARGC_ONE);
242 PRINT_HILOGD("%{public}s end.", __func__);
243 }
244
OnCommand(const AAFwk::Want & want,bool restart,int startId)245 void JsPrintExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId)
246 {
247 PRINT_HILOGD("jws JsPrintExtension OnCommand begin.");
248 Extension::OnCommand(want, restart, startId);
249 PRINT_HILOGD("begin restart=%{public}s,startId=%{public}d.", restart ? "true" : "false", startId);
250 if (startId <= 1) {
251 PRINT_HILOGD("%{public}s ignore.", __func__);
252 return;
253 }
254 PrintManagerClient::GetInstance()->LoadExtSuccess(extensionId_);
255 RegisterCb();
256 PRINT_HILOGD("%{public}s end.", __func__);
257 }
258
CallObjectMethod(const char * name,NativeValue * const * argv,size_t argc)259 NativeValue *JsPrintExtension::CallObjectMethod(const char *name, NativeValue *const *argv, size_t argc)
260 {
261 PRINT_HILOGD("jws JsPrintExtension::CallObjectMethod(%{public}s), begin", name);
262
263 if (!jsObj_) {
264 PRINT_HILOGW("Not found PrintExtension.js");
265 return nullptr;
266 }
267
268 HandleScope handleScope(jsRuntime_);
269 auto &nativeEngine = jsRuntime_.GetNativeEngine();
270
271 NativeValue *value = jsObj_->Get();
272 NativeObject *obj = ConvertNativeValueTo<NativeObject>(value);
273 if (obj == nullptr) {
274 PRINT_HILOGE("Failed to get PrintExtension object");
275 return nullptr;
276 }
277
278 NativeValue *method = obj->GetProperty(name);
279 if (method == nullptr) {
280 PRINT_HILOGE("Failed to get '%{public}s' from PrintExtension object", name);
281 return nullptr;
282 }
283 PRINT_HILOGD("JsPrintExtension::CallFunction(%{public}s), success", name);
284 return nativeEngine.CallFunction(value, method, argv, argc);
285 }
286
GetSrcPath(std::string & srcPath)287 void JsPrintExtension::GetSrcPath(std::string &srcPath)
288 {
289 PRINT_HILOGD("jws JsPrintExtension GetSrcPath begin.");
290 if (!Extension::abilityInfo_->isModuleJson) {
291 /* temporary compatibility api8 + config.json */
292 srcPath.append(Extension::abilityInfo_->package);
293 srcPath.append("/assets/js/");
294 if (!Extension::abilityInfo_->srcPath.empty()) {
295 srcPath.append(Extension::abilityInfo_->srcPath);
296 }
297 srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
298 return;
299 }
300
301 if (!Extension::abilityInfo_->srcEntrance.empty()) {
302 srcPath.append(Extension::abilityInfo_->moduleName + "/");
303 srcPath.append(Extension::abilityInfo_->srcEntrance);
304 srcPath.erase(srcPath.rfind('.'));
305 srcPath.append(".abc");
306 }
307 }
308
RegisterDiscoveryCb()309 void JsPrintExtension::RegisterDiscoveryCb()
310 {
311 PRINT_HILOGD("Register Print Extension Callback");
312 PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_START_DISCOVERY,
313 []() -> bool {
314 PRINT_HILOGD("Start Print Discovery");
315 HandleScope handleScope(jsExtension_->jsRuntime_);
316 auto callback = std::make_shared<JsPrintCallback>(jsExtension_->jsRuntime_);
317 NativeValue *value = jsExtension_->jsObj_->Get();
318 callback->Exec(value, "onStartDiscoverPrinter");
319 return true;
320 });
321 PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_STOP_DISCOVERY,
322 []() -> bool {
323 PRINT_HILOGD("Stop Print Discovery");
324 HandleScope handleScope(jsExtension_->jsRuntime_);
325 auto callback = std::make_shared<JsPrintCallback>(jsExtension_->jsRuntime_);
326 NativeValue *value = jsExtension_->jsObj_->Get();
327 callback->Exec(value, "onStopDiscoverPrinter");
328 return true;
329 });
330 }
331
RegisterConnectionCb()332 void JsPrintExtension::RegisterConnectionCb()
333 {
334 PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_CONNECT_PRINTER,
335 [](const std::string &printId) -> bool {
336 PRINT_HILOGD("Connect Printer");
337 std::string realPrinterId = PrintUtils::GetLocalId(printId, jsExtension_->extensionId_);
338 HandleScope handleScope(jsExtension_->jsRuntime_);
339 NativeEngine *nativeEng = &(jsExtension_->jsRuntime_).GetNativeEngine();
340 napi_value jsPrintId =
341 OHOS::AppExecFwk::WrapStringToJS(reinterpret_cast<napi_env>(nativeEng), realPrinterId);
342 NativeValue *nativePrintId = reinterpret_cast<NativeValue *>(jsPrintId);
343 NativeValue *arg[] = { nativePrintId };
344 auto callback = std::make_shared<JsPrintCallback>(jsExtension_->jsRuntime_);
345 NativeValue *value = jsExtension_->jsObj_->Get();
346 callback->Exec(value, "onConnectPrinter", arg, NapiPrintUtils::ARGC_ONE);
347 return true;
348 });
349 PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_DISCONNECT_PRINTER,
350 [](const std::string &printId) -> bool {
351 PRINT_HILOGD("Disconnect Printer");
352 std::string realPrinterId = PrintUtils::GetLocalId(printId, jsExtension_->extensionId_);
353 HandleScope handleScope(jsExtension_->jsRuntime_);
354 NativeEngine *nativeEng = &(jsExtension_->jsRuntime_).GetNativeEngine();
355 napi_value jsPrintId =
356 OHOS::AppExecFwk::WrapStringToJS(reinterpret_cast<napi_env>(nativeEng), realPrinterId);
357 NativeValue *nativePrintId = reinterpret_cast<NativeValue *>(jsPrintId);
358 NativeValue *arg[] = { nativePrintId };
359 auto callback = std::make_shared<JsPrintCallback>(jsExtension_->jsRuntime_);
360 NativeValue *value = jsExtension_->jsObj_->Get();
361 callback->Exec(value, "onDisconnectPrinter", arg, NapiPrintUtils::ARGC_ONE);
362 return true;
363 });
364 }
365
RegisterPrintJobCb()366 void JsPrintExtension::RegisterPrintJobCb()
367 {
368 PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_START_PRINT,
369 [](const PrintJob &job) -> bool {
370 PRINT_HILOGD("Start Print Job");
371 HandleScope handleScope(jsExtension_->jsRuntime_);
372 NativeEngine *nativeEng = &(jsExtension_->jsRuntime_).GetNativeEngine();
373 napi_value jobObject = PrintJobHelper::MakeJsObject(reinterpret_cast<napi_env>(nativeEng), job);
374 NativeValue *nativeJob = reinterpret_cast<NativeValue *>(jobObject);
375 NativeValue *arg[] = { nativeJob };
376
377 auto callback = std::make_shared<JsPrintCallback>(jsExtension_->jsRuntime_);
378 NativeValue *value = jsExtension_->jsObj_->Get();
379 callback->Exec(value, "onStartPrintJob", arg, NapiPrintUtils::ARGC_ONE);
380 return true;
381 });
382 PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_CANCEL_PRINT,
383 [](const PrintJob &job) -> bool {
384 PRINT_HILOGD("Cancel Print Job");
385 HandleScope handleScope(jsExtension_->jsRuntime_);
386 NativeEngine *nativeEng = &(jsExtension_->jsRuntime_).GetNativeEngine();
387 napi_value jobObject = PrintJobHelper::MakeJsObject(reinterpret_cast<napi_env>(nativeEng), job);
388 NativeValue *nativeJob = reinterpret_cast<NativeValue *>(jobObject);
389 NativeValue *arg[] = { nativeJob };
390
391 auto callback = std::make_shared<JsPrintCallback>(jsExtension_->jsRuntime_);
392 NativeValue *value = jsExtension_->jsObj_->Get();
393 callback->Exec(value, "onCancelPrintJob", arg, NapiPrintUtils::ARGC_ONE);
394 return true;
395 });
396 }
397
RegisterPreviewCb()398 void JsPrintExtension::RegisterPreviewCb()
399 {
400 PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_REQUEST_PREVIEW,
401 [](const PrintJob &job) -> bool {
402 PRINT_HILOGD("Requet preview");
403 HandleScope handleScope(jsExtension_->jsRuntime_);
404 NativeEngine *nativeEng = &(jsExtension_->jsRuntime_).GetNativeEngine();
405 napi_value jobObject = PrintJobHelper::MakeJsObject(reinterpret_cast<napi_env>(nativeEng), job);
406 NativeValue *nativeJob = reinterpret_cast<NativeValue *>(jobObject);
407 NativeValue *arg[] = { nativeJob };
408
409 auto callback = std::make_shared<JsPrintCallback>(jsExtension_->jsRuntime_);
410 NativeValue *value = jsExtension_->jsObj_->Get();
411 callback->Exec(value, "onRequestPreview", arg, NapiPrintUtils::ARGC_ONE);
412 return true;
413 });
414 }
415
RegisterQueryCapCb()416 void JsPrintExtension::RegisterQueryCapCb()
417 {
418 PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_REQUEST_CAP,
419 [](const std::string &printId) -> bool {
420 PRINT_HILOGD("Request Capability");
421 std::string realPrinterId = PrintUtils::GetLocalId(printId, jsExtension_->extensionId_);
422 HandleScope handleScope(jsExtension_->jsRuntime_);
423 NativeEngine *nativeEng = &(jsExtension_->jsRuntime_).GetNativeEngine();
424 napi_value jsPrintId =
425 OHOS::AppExecFwk::WrapStringToJS(reinterpret_cast<napi_env>(nativeEng), realPrinterId);
426 NativeValue *nativePrintId = reinterpret_cast<NativeValue *>(jsPrintId);
427 NativeValue *arg[] = { nativePrintId };
428 auto callback = std::make_shared<JsPrintCallback>(jsExtension_->jsRuntime_);
429 NativeValue *value = jsExtension_->jsObj_->Get();
430 callback->Exec(value, "onRequestPrinterCapability", arg, NapiPrintUtils::ARGC_ONE);
431 PRINT_HILOGD("Request Capability Success");
432 return true;
433 });
434 }
435
RegisterExtensionCb()436 void JsPrintExtension::RegisterExtensionCb()
437 {
438 PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_DESTROY_EXTENSION,
439 []() -> bool {
440 PRINT_HILOGD("Stop Extension");
441 HandleScope handleScope(jsExtension_->jsRuntime_);
442 NativeValue *arg[] = { };
443 auto callback = std::make_shared<JsPrintCallback>(jsExtension_->jsRuntime_);
444 NativeValue *value = jsExtension_->jsObj_->Get();
445 callback->Exec(value, "onDestroy", arg, NapiPrintUtils::ARGC_ZERO);
446 jsExtension_->hasDestroyed_ = true;
447 PRINT_HILOGD("Destroy Extension Success");
448 return true;
449 });
450 }
451 } // namespace AbilityRuntime
452 } // namespace OHOS
453