• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 std::mutex JsPrintExtension::mtx;
40 using namespace OHOS::AppExecFwk;
41 using namespace OHOS::Print;
42 
Create(const std::unique_ptr<Runtime> & runtime)43 JsPrintExtension *JsPrintExtension::Create(const std::unique_ptr<Runtime> &runtime)
44 {
45     PRINT_HILOGD("jws JsPrintExtension begin Create");
46     jsExtension_ = new JsPrintExtension(static_cast<JsRuntime &>(*runtime));
47     return jsExtension_;
48 }
49 
JsPrintExtension(JsRuntime & jsRuntime)50 JsPrintExtension::JsPrintExtension(JsRuntime &jsRuntime) : jsRuntime_(jsRuntime),
51     extensionId_("") {}
52 JsPrintExtension::~JsPrintExtension() = default;
53 
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)54 void JsPrintExtension::Init(const std::shared_ptr<AbilityLocalRecord> &record,
55     const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
56     const sptr<IRemoteObject> &token)
57 {
58     PRINT_HILOGD("jws JsPrintExtension begin Init");
59     PrintExtension::Init(record, application, handler, token);
60 
61     if (!InitExtensionObj(jsRuntime_)) {
62         PRINT_HILOGE("Failed to init extension object");
63         return;
64     }
65 
66     napi_value obj = jsObj_->GetNapiValue();
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,napi_value & extObj,std::string & extensionId)102 bool JsPrintExtension::InitContextObj(JsRuntime &jsRuntime, napi_value &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     napi_env engine = jsRuntime.GetNapiEnv();
111     napi_value contextObj = CreateJsPrintExtensionContext(engine, context, extensionId);
112     auto shellContextRef = jsRuntime.LoadSystemModule("PrintExtensionContext", &contextObj, NapiPrintUtils::ARGC_ONE);
113     contextObj = shellContextRef->GetNapiValue();
114     PRINT_HILOGD("JsPrintExtension::Init Bind.");
115     context->Bind(jsRuntime, shellContextRef.release());
116     PRINT_HILOGD("JsPrintExtension::napi_set_named_property.");
117     napi_set_named_property(engine, extObj, "context", contextObj);
118     if (contextObj == nullptr) {
119         PRINT_HILOGE("Failed to get Print extension native object");
120         return false;
121     }
122 
123     napi_wrap(engine, contextObj, new std::weak_ptr<AbilityRuntime::Context>(context),
124         [](napi_env, void *data, void *) {
125             PRINT_HILOGD("Finalizer for weak_ptr Print extension context is called");
126             delete static_cast<std::weak_ptr<AbilityRuntime::Context> *>(data);
127         },
128         nullptr, nullptr);
129     return true;
130 }
131 
OnStart(const AAFwk::Want & want)132 void JsPrintExtension::OnStart(const AAFwk::Want &want)
133 {
134     Extension::OnStart(want);
135     PRINT_HILOGD("jws JsPrintExtension OnStart begin..");
136     HandleScope handleScope(jsRuntime_);
137     napi_env nativeEngine = jsRuntime_.GetNapiEnv();
138     napi_value nativeWant = OHOS::AppExecFwk::WrapWant(nativeEngine, want);
139     napi_value argv[] = { nativeWant };
140     CallObjectMethod("onCreate", argv, NapiPrintUtils::ARGC_ONE);
141     RegisterCb();
142     PrintManagerClient::GetInstance()->LoadExtSuccess(extensionId_);
143     PRINT_HILOGD("%{public}s end.", __func__);
144 }
145 
RegisterCb()146 void JsPrintExtension::RegisterCb()
147 {
148     RegisterDiscoveryCb();
149     RegisterConnectionCb();
150     RegisterPrintJobCb();
151     RegisterPreviewCb();
152     RegisterQueryCapCb();
153     RegisterExtensionCb();
154 }
155 
OnStop()156 void JsPrintExtension::OnStop()
157 {
158     PrintExtension::OnStop();
159     PRINT_HILOGD("jws JsPrintExtension OnStop begin.");
160     bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken());
161     if (ret) {
162         PRINT_HILOGD("The Print extension connection is not disconnected.");
163     }
164     PRINT_HILOGD("%{public}s end.", __func__);
165 }
166 
OnConnect(const AAFwk::Want & want)167 sptr<IRemoteObject> JsPrintExtension::OnConnect(const AAFwk::Want &want)
168 {
169     PRINT_HILOGD("jws JsPrintExtension OnConnect begin.");
170     Extension::OnConnect(want);
171     PRINT_HILOGD("%{public}s begin.", __func__);
172     HandleScope handleScope(jsRuntime_);
173     napi_env nativeEngine = jsRuntime_.GetNapiEnv();
174     napi_value nativeWant = OHOS::AppExecFwk::WrapWant(nativeEngine, want);
175     napi_value argv[] = { nativeWant };
176     if (!jsObj_) {
177         PRINT_HILOGW("Not found PrintExtension.js");
178         return nullptr;
179     }
180 
181     napi_value obj = jsObj_->GetNapiValue();
182     if (obj == nullptr) {
183         PRINT_HILOGE("Failed to get PrintExtension object");
184         return nullptr;
185     }
186 
187     napi_value method = nullptr;
188     napi_get_named_property(nativeEngine, obj, "onConnect", &method);
189     if (method == nullptr) {
190         PRINT_HILOGE("Failed to get onConnect from PrintExtension object");
191         return nullptr;
192     }
193     PRINT_HILOGD("JsPrintExtension::napi_call_function onConnect, success");
194     napi_value remoteNative = nullptr;
195     napi_call_function(nativeEngine, obj, method, NapiPrintUtils::ARGC_ONE, argv, &remoteNative);
196     if (remoteNative == nullptr) {
197         PRINT_HILOGE("remoteNative nullptr.");
198     }
199     auto remoteObj = NAPI_ohos_rpc_getNativeRemoteObject(nativeEngine, remoteNative);
200     if (remoteObj == nullptr) {
201         PRINT_HILOGE("remoteObj nullptr.");
202     }
203     return remoteObj;
204 }
205 
OnDisconnect(const AAFwk::Want & want)206 void JsPrintExtension::OnDisconnect(const AAFwk::Want &want)
207 {
208     PRINT_HILOGD("jws JsPrintExtension OnDisconnect begin.");
209     Extension::OnDisconnect(want);
210     PRINT_HILOGD("%{public}s begin.", __func__);
211     HandleScope handleScope(jsRuntime_);
212     napi_env nativeEngine = jsRuntime_.GetNapiEnv();
213     napi_value nativeWant = OHOS::AppExecFwk::WrapWant(nativeEngine, want);
214     napi_value argv[] = { nativeWant };
215     if (!jsObj_) {
216         PRINT_HILOGW("Not found PrintExtension.js");
217         return;
218     }
219 
220     napi_value obj = jsObj_->GetNapiValue();
221     if (obj == nullptr) {
222         PRINT_HILOGE("Failed to get PrintExtension object");
223         return;
224     }
225 
226     napi_value method = nullptr;
227     napi_get_named_property(nativeEngine, obj, "onDisconnect", &method);
228     if (method == nullptr) {
229         PRINT_HILOGE("Failed to get onDisconnect from PrintExtension object");
230         return;
231     }
232     napi_value callResult = nullptr;
233     napi_call_function(nativeEngine, obj, method, NapiPrintUtils::ARGC_ONE, argv, &callResult);
234     PRINT_HILOGD("%{public}s end.", __func__);
235 }
236 
OnCommand(const AAFwk::Want & want,bool restart,int startId)237 void JsPrintExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId)
238 {
239     PRINT_HILOGD("jws JsPrintExtension OnCommand begin.");
240     Extension::OnCommand(want, restart, startId);
241     PRINT_HILOGD("begin restart=%{public}s,startId=%{public}d.", restart ? "true" : "false", startId);
242     if (startId <= 1) {
243         PRINT_HILOGD("%{public}s ignore.", __func__);
244         return;
245     }
246     HandleScope handleScope(jsRuntime_);
247     napi_env nativeEngine = jsRuntime_.GetNapiEnv();
248     napi_value nativeWant = OHOS::AppExecFwk::WrapWant(nativeEngine, want);
249     napi_value argv[] = { nativeWant };
250     CallObjectMethod("onCreate", argv, NapiPrintUtils::ARGC_ONE);
251     RegisterCb();
252     PrintManagerClient::GetInstance()->LoadExtSuccess(extensionId_);
253     PRINT_HILOGD("%{public}s end.", __func__);
254 }
255 
CallObjectMethod(const char * name,napi_value const * argv,size_t argc)256 napi_value JsPrintExtension::CallObjectMethod(const char *name, napi_value const *argv, size_t argc)
257 {
258     PRINT_HILOGD("jws JsPrintExtension::CallObjectMethod(%{public}s), begin", name);
259 
260     if (!jsObj_) {
261         PRINT_HILOGW("Not found PrintExtension.js");
262         return nullptr;
263     }
264 
265     HandleScope handleScope(jsRuntime_);
266     napi_env nativeEngine = jsRuntime_.GetNapiEnv();
267 
268     napi_value obj = jsObj_->GetNapiValue();
269     if (obj == nullptr) {
270         PRINT_HILOGE("Failed to get PrintExtension object");
271         return nullptr;
272     }
273 
274     napi_value method = nullptr;
275     napi_get_named_property(nativeEngine, obj, name, &method);
276     if (method == nullptr) {
277         PRINT_HILOGE("Failed to get '%{public}s' from PrintExtension object", name);
278         return nullptr;
279     }
280     PRINT_HILOGD("JsPrintExtension::napi_call_function(%{public}s), success", name);
281     napi_value callResult = nullptr;
282     napi_call_function(nativeEngine, obj, method, argc, argv, &callResult);
283     return callResult;
284 }
285 
GetSrcPath(std::string & srcPath)286 void JsPrintExtension::GetSrcPath(std::string &srcPath)
287 {
288     PRINT_HILOGD("jws JsPrintExtension GetSrcPath begin.");
289     if (!Extension::abilityInfo_->isModuleJson) {
290         /* temporary compatibility api8 + config.json */
291         srcPath.append(Extension::abilityInfo_->package);
292         srcPath.append("/assets/js/");
293         if (!Extension::abilityInfo_->srcPath.empty()) {
294             srcPath.append(Extension::abilityInfo_->srcPath);
295         }
296         srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
297         return;
298     }
299 
300     if (!Extension::abilityInfo_->srcEntrance.empty()) {
301         srcPath.append(Extension::abilityInfo_->moduleName + "/");
302         srcPath.append(Extension::abilityInfo_->srcEntrance);
303         srcPath.erase(srcPath.rfind('.'));
304         srcPath.append(".abc");
305     }
306 }
307 
Callback(std::string funcName)308 bool JsPrintExtension::Callback(std::string funcName)
309 {
310     PRINT_HILOGD("call %{public}s", funcName.c_str());
311     std::lock_guard<std::mutex> lock(mtx);
312     if (JsPrintExtension::jsExtension_ == nullptr) {
313         return false;
314     }
315     napi_env env = (JsPrintExtension::jsExtension_->jsRuntime_).GetNapiEnv();
316     WorkParam *workParam = new (std::nothrow) WorkParam(env, funcName);
317     if (workParam == nullptr) {
318         return false;
319     }
320     uv_after_work_cb afterCallback = [](uv_work_t *work, int32_t status) {
321         WorkParam *param = reinterpret_cast<WorkParam *>(work->data);
322         if (param == nullptr) {
323             delete work;
324             return;
325         }
326         napi_handle_scope scope = nullptr;
327         napi_open_handle_scope(param->env, &scope);
328         if (scope == nullptr) {
329             delete param;
330             delete work;
331             return;
332         }
333         napi_value arg[] = { 0 };
334         std::lock_guard<std::mutex> lock(mtx);
335         if (JsPrintExtension::jsExtension_ != nullptr) {
336             JsPrintExtension::jsExtension_->CallObjectMethod(param->funcName.c_str(), arg, NapiPrintUtils::ARGC_ZERO);
337         }
338         napi_close_handle_scope(param->env, scope);
339         delete param;
340         delete work;
341     };
342     bool ret = JsPrintCallback::Call(env, workParam, afterCallback);
343     if (!ret) {
344         delete workParam;
345         workParam = nullptr;
346         PRINT_HILOGE("Callback fail, delete param");
347         return false;
348     }
349     return true;
350 }
351 
Callback(const std::string funcName,const std::string & printerId)352 bool JsPrintExtension::Callback(const std::string funcName, const std::string &printerId)
353 {
354     PRINT_HILOGD("call %{public}s", funcName.c_str());
355     std::lock_guard<std::mutex> lock(mtx);
356     if (JsPrintExtension::jsExtension_ == nullptr) {
357         return false;
358     }
359     napi_env env = (JsPrintExtension::jsExtension_->jsRuntime_).GetNapiEnv();
360     WorkParam *workParam = new (std::nothrow) WorkParam(env, funcName);
361     if (workParam == nullptr) {
362         return false;
363     }
364     workParam->printerId = printerId;
365     uv_after_work_cb afterCallback = [](uv_work_t *work, int32_t status) {
366         WorkParam *param = reinterpret_cast<WorkParam *>(work->data);
367         if (param == nullptr) {
368             delete work;
369             return;
370         }
371         napi_handle_scope scope = nullptr;
372         napi_open_handle_scope(param->env, &scope);
373         if (scope == nullptr) {
374             delete param;
375             delete work;
376             return;
377         }
378         napi_value id = OHOS::AppExecFwk::WrapStringToJS(param->env, param->printerId);
379         napi_value arg[] = { id };
380         std::lock_guard<std::mutex> lock(mtx);
381         if (JsPrintExtension::jsExtension_ != nullptr) {
382             JsPrintExtension::jsExtension_->CallObjectMethod(param->funcName.c_str(), arg, NapiPrintUtils::ARGC_ONE);
383         }
384         napi_close_handle_scope(param->env, scope);
385         delete param;
386         delete work;
387     };
388     bool ret = JsPrintCallback::Call(env, workParam, afterCallback);
389     if (!ret) {
390         delete workParam;
391         workParam = nullptr;
392         PRINT_HILOGE("Callback fail, delete param");
393         return false;
394     }
395     return true;
396 }
397 
Callback(const std::string funcName,const Print::PrintJob & job)398 bool JsPrintExtension::Callback(const std::string funcName, const Print::PrintJob &job)
399 {
400     PRINT_HILOGD("call %{public}s", funcName.c_str());
401     std::lock_guard<std::mutex> lock(mtx);
402     if (JsPrintExtension::jsExtension_ == nullptr) {
403         return false;
404     }
405     napi_env env = (JsPrintExtension::jsExtension_->jsRuntime_).GetNapiEnv();
406     WorkParam *workParam = new (std::nothrow) WorkParam(env, funcName);
407     if (workParam == nullptr) {
408         return false;
409     }
410     workParam->job = job;
411     uv_after_work_cb afterCallback = [](uv_work_t *work, int32_t status) {
412         WorkParam *param = reinterpret_cast<WorkParam *>(work->data);
413         if (param == nullptr) {
414             delete work;
415             return;
416         }
417         napi_handle_scope scope = nullptr;
418         napi_open_handle_scope(param->env, &scope);
419         if (scope == nullptr) {
420             delete param;
421             delete work;
422             return;
423         }
424         napi_value jobObject = PrintJobHelper::MakeJsObject(param->env, param->job);
425         napi_value arg[] = { jobObject };
426         std::lock_guard<std::mutex> lock(mtx);
427         if (JsPrintExtension::jsExtension_ != nullptr) {
428             JsPrintExtension::jsExtension_->CallObjectMethod(param->funcName.c_str(), arg, NapiPrintUtils::ARGC_ONE);
429         }
430         napi_close_handle_scope(param->env, scope);
431         delete param;
432         delete work;
433     };
434     bool ret = JsPrintCallback::Call(env, workParam, afterCallback);
435     if (!ret) {
436         delete workParam;
437         workParam = nullptr;
438         PRINT_HILOGE("Callback fail, delete param");
439         return false;
440     }
441     return true;
442 }
443 
RegisterDiscoveryCb()444 void JsPrintExtension::RegisterDiscoveryCb()
445 {
446     PRINT_HILOGD("Register Print Extension Callback");
447     PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_START_DISCOVERY,
448         []() -> bool {
449             if (JsPrintExtension::jsExtension_ == nullptr) {
450                 return false;
451             }
452             return JsPrintExtension::jsExtension_->Callback("onStartDiscoverPrinter");
453     });
454     PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_STOP_DISCOVERY,
455         []() -> bool {
456             if (JsPrintExtension::jsExtension_ == nullptr) {
457                 return false;
458             }
459             return JsPrintExtension::jsExtension_->Callback("onStopDiscoverPrinter");
460     });
461 }
462 
RegisterConnectionCb()463 void JsPrintExtension::RegisterConnectionCb()
464 {
465     PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_CONNECT_PRINTER,
466         [](const std::string &printId) -> bool {
467             if (JsPrintExtension::jsExtension_ == nullptr) {
468                 return false;
469             }
470             std::string realPrinterId = PrintUtils::GetLocalId(printId, jsExtension_->extensionId_);
471             return JsPrintExtension::jsExtension_->Callback("onConnectPrinter", realPrinterId);
472     });
473     PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_DISCONNECT_PRINTER,
474         [](const std::string &printId) -> bool {
475             if (JsPrintExtension::jsExtension_ == nullptr) {
476                 return false;
477             }
478             std::string realPrinterId = PrintUtils::GetLocalId(printId, jsExtension_->extensionId_);
479             return JsPrintExtension::jsExtension_->Callback("onDisconnectPrinter", realPrinterId);
480     });
481 }
482 
RegisterPrintJobCb()483 void JsPrintExtension::RegisterPrintJobCb()
484 {
485     PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_START_PRINT,
486         [](const PrintJob &job) -> bool {
487             if (JsPrintExtension::jsExtension_ == nullptr) {
488                 return false;
489             }
490             return JsPrintExtension::jsExtension_->Callback("onStartPrintJob", job);
491     });
492     PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_CANCEL_PRINT,
493         [](const PrintJob &job) -> bool {
494             if (JsPrintExtension::jsExtension_ == nullptr) {
495                 return false;
496             }
497             return JsPrintExtension::jsExtension_->Callback("onCancelPrintJob", job);
498     });
499 }
500 
RegisterPreviewCb()501 void JsPrintExtension::RegisterPreviewCb()
502 {
503     PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_REQUEST_PREVIEW,
504         [](const PrintJob &job) -> bool {
505             if (JsPrintExtension::jsExtension_ == nullptr) {
506                 return false;
507             }
508             return JsPrintExtension::jsExtension_->Callback("onRequestPreview", job);
509     });
510 }
511 
RegisterQueryCapCb()512 void JsPrintExtension::RegisterQueryCapCb()
513 {
514     PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_REQUEST_CAP,
515         [](const std::string &printId) -> bool {
516             if (JsPrintExtension::jsExtension_ == nullptr) {
517                 return false;
518             }
519             std::string realPrinterId = PrintUtils::GetLocalId(printId, jsExtension_->extensionId_);
520             return JsPrintExtension::jsExtension_->Callback("onRequestPrinterCapability", realPrinterId);
521     });
522 }
523 
RegisterExtensionCb()524 void JsPrintExtension::RegisterExtensionCb()
525 {
526     PrintManagerClient::GetInstance()->RegisterExtCallback(extensionId_, PRINT_EXTCB_DESTROY_EXTENSION,
527         []() -> bool {
528             if (JsPrintExtension::jsExtension_ == nullptr) {
529                 return false;
530             }
531             JsPrintExtension::jsExtension_->OnStop();
532             return JsPrintExtension::jsExtension_->Callback("onDestroy");
533     });
534 }
535 } // namespace AbilityRuntime
536 } // namespace OHOS
537