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 #include "print_job_helper.h"
16 #include "napi_print_utils.h"
17 #include "print_constant.h"
18 #include "print_log.h"
19 #include "print_margin_helper.h"
20 #include "print_preview_attribute_helper.h"
21 #include "print_page_size_helper.h"
22 #include "print_range_helper.h"
23 
24 namespace OHOS::Print {
25 static constexpr const char *PARAM_JOB_FDLIST = "fdList";
26 static constexpr const char *PARAM_JOB_JOBID = "jobId";
27 static constexpr const char *PARAM_JOB_PRINTERID = "printerId";
28 static constexpr const char *PARAM_JOB_JOBSTATE = "jobState";
29 static constexpr const char *PARAM_JOB_SUBSTATE = "jobSubstate";
30 static constexpr const char *PARAM_JOB_COPYNUMBER = "copyNumber";
31 static constexpr const char *PARAM_JOB_PAGERANGE = "pageRange";
32 static constexpr const char *PARAM_JOB_ISSEQUENTIAL = "isSequential";
33 static constexpr const char *PARAM_JOB_PAGESIZE = "pageSize";
34 static constexpr const char *PARAM_JOB_ISLANDSCAPE = "isLandscape";
35 static constexpr const char *PARAM_JOB_COLORMODE = "colorMode";
36 static constexpr const char *PARAM_JOB_DUPLEXMODE = "duplexMode";
37 static constexpr const char *PARAM_JOB_MARGIN = "margin";
38 static constexpr const char *PARAM_JOB_PREVIEW = "preview";
39 static constexpr const char *PARAM_JOB_OPTION = "options";
40 
MakeJsSimpleObject(napi_env env,const PrintJob & job)41 napi_value PrintJobHelper::MakeJsSimpleObject(napi_env env, const PrintJob &job)
42 {
43     napi_value jsObj = nullptr;
44     PRINT_CALL(env, napi_create_object(env, &jsObj));
45     NapiPrintUtils::SetStringPropertyUtf8(env, jsObj, PARAM_JOB_JOBID, job.GetJobId());
46     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_JOB_JOBSTATE, job.GetJobState());
47     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_JOB_SUBSTATE, job.GetSubState());
48     return jsObj;
49 }
50 
MakeJsObject(napi_env env,const PrintJob & job)51 napi_value PrintJobHelper::MakeJsObject(napi_env env, const PrintJob &job)
52 {
53     napi_value jsObj = nullptr;
54     PRINT_CALL(env, napi_create_object(env, &jsObj));
55     if (!CreateFdList(env, jsObj, job)) {
56         PRINT_HILOGE("Failed to create files property of print job");
57         return nullptr;
58     }
59     NapiPrintUtils::SetStringPropertyUtf8(env, jsObj, PARAM_JOB_JOBID, job.GetJobId());
60     NapiPrintUtils::SetStringPropertyUtf8(env, jsObj, PARAM_JOB_PRINTERID, job.GetPrinterId());
61     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_JOB_JOBSTATE, job.GetJobState());
62     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_JOB_SUBSTATE, job.GetSubState());
63     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_JOB_COPYNUMBER, job.GetCopyNumber());
64 
65     if (!CreatePageRange(env, jsObj, job)) {
66         PRINT_HILOGE("Failed to create page range property of print job");
67         return nullptr;
68     }
69 
70     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_JOB_ISSEQUENTIAL, job.GetIsSequential());
71 
72     if (!CreatePageSize(env, jsObj, job)) {
73         PRINT_HILOGE("Failed to create page size property of print job");
74         return nullptr;
75     }
76 
77     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_JOB_ISLANDSCAPE, job.GetIsLandscape());
78     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_JOB_COLORMODE, job.GetColorMode());
79     NapiPrintUtils::SetUint32Property(env, jsObj, PARAM_JOB_DUPLEXMODE, job.GetDuplexMode());
80 
81     if (job.HasMargin() && !CreateMargin(env, jsObj, job)) {
82         PRINT_HILOGE("Failed to create margin property of print job");
83         return nullptr;
84     }
85 
86     if (job.HasPreview() && !CreatePreview(env, jsObj, job)) {
87         PRINT_HILOGE("Failed to create preview property of print job");
88         return nullptr;
89     }
90 
91     if (job.HasOption()) {
92         NapiPrintUtils::SetStringPropertyUtf8(env, jsObj, PARAM_JOB_OPTION, job.GetOption());
93     }
94     return jsObj;
95 }
96 
BuildFromJs(napi_env env,napi_value jsValue)97 std::shared_ptr<PrintJob> PrintJobHelper::BuildFromJs(napi_env env, napi_value jsValue)
98 {
99     auto nativeObj = std::make_shared<PrintJob>();
100 
101     if (!ValidateProperty(env, jsValue)) {
102         PRINT_HILOGE("Invalid property of print job");
103         return nullptr;
104     }
105 
106     napi_value jsFdList = NapiPrintUtils::GetNamedProperty(env, jsValue, PARAM_JOB_FDLIST);
107     bool isFileArray = false;
108     napi_is_array(env, jsFdList, &isFileArray);
109     if (!isFileArray) {
110         PRINT_HILOGE("Invalid file list of print job");
111         return nullptr;
112     }
113     std::vector<uint32_t> printFdList;
114     uint32_t arrayReLength = 0;
115     napi_get_array_length(env, jsFdList, &arrayReLength);
116     for (uint32_t index = 0; index < arrayReLength; index++) {
117         napi_value filesValue;
118         napi_get_element(env, jsFdList, index, &filesValue);
119         uint32_t fd = NapiPrintUtils::GetUint32FromValue(env, filesValue);
120         PRINT_HILOGD("printJob_value fd %{public}d", fd);
121         printFdList.emplace_back(fd);
122     }
123     nativeObj->SetFdList(printFdList);
124 
125     std::string jobId = NapiPrintUtils::GetStringPropertyUtf8(env, jsValue, PARAM_JOB_JOBID);
126     std::string printerId = NapiPrintUtils::GetStringPropertyUtf8(env, jsValue, PARAM_JOB_PRINTERID);
127     uint32_t jobState = NapiPrintUtils::GetUint32Property(env, jsValue, PARAM_JOB_JOBSTATE);
128     uint32_t subState = NapiPrintUtils::GetUint32Property(env, jsValue, PARAM_JOB_SUBSTATE);
129     uint32_t copyNumber = NapiPrintUtils::GetUint32Property(env, jsValue, PARAM_JOB_COPYNUMBER);
130     bool isSequential = NapiPrintUtils::GetBooleanProperty(env, jsValue, PARAM_JOB_ISSEQUENTIAL);
131     bool isLandscape = NapiPrintUtils::GetBooleanProperty(env, jsValue, PARAM_JOB_ISLANDSCAPE);
132     uint32_t colorMode = NapiPrintUtils::GetUint32Property(env, jsValue, PARAM_JOB_COLORMODE);
133     uint32_t duplexMode = NapiPrintUtils::GetUint32Property(env, jsValue, PARAM_JOB_DUPLEXMODE);
134     nativeObj->SetJobId(jobId);
135     nativeObj->SetPrinterId(printerId);
136     nativeObj->SetJobState(jobState);
137     nativeObj->SetSubState(subState);
138     nativeObj->SetCopyNumber(copyNumber);
139     nativeObj->SetIsSequential(isSequential);
140     nativeObj->SetIsLandscape(isLandscape);
141     nativeObj->SetColorMode(colorMode);
142     nativeObj->SetDuplexMode(duplexMode);
143 
144     BuildJsWorkerIsLegal(env, jsValue, jobId, jobState, subState, nativeObj);
145     nativeObj->Dump();
146     return nativeObj;
147 }
148 
BuildJsWorkerIsLegal(napi_env env,napi_value jsValue,std::string jobId,uint32_t jobState,uint32_t subState,std::shared_ptr<PrintJob> & nativeObj)149 std::shared_ptr<PrintJob> PrintJobHelper::BuildJsWorkerIsLegal(napi_env env, napi_value jsValue, std::string jobId,
150     uint32_t jobState, uint32_t subState, std::shared_ptr<PrintJob> &nativeObj)
151 {
152     if (jobState >= PRINT_JOB_UNKNOWN || subState > PRINT_JOB_BLOCKED_UNKNOWN) {
153         PRINT_HILOGE("Invalid job state[%{public}d] or sub state [%{public}d]", jobState, subState);
154         return nullptr;
155     }
156 
157     napi_value jsPageRange = NapiPrintUtils::GetNamedProperty(env, jsValue, PARAM_JOB_PAGERANGE);
158     auto pageRangePtr = PrintRangeHelper::BuildFromJs(env, jsPageRange);
159     if (pageRangePtr == nullptr) {
160         PRINT_HILOGE("Failed to build print job object from js");
161         return nullptr;
162     }
163     nativeObj->SetPageRange(*pageRangePtr);
164 
165     napi_value jsPageSize = NapiPrintUtils::GetNamedProperty(env, jsValue, PARAM_JOB_PAGESIZE);
166     auto pageSizePtr = PrintPageSizeHelper::BuildFromJs(env, jsPageSize);
167     if (pageSizePtr == nullptr) {
168         PRINT_HILOGE("Failed to build print job object from js");
169         return nullptr;
170     }
171     nativeObj->SetPageSize(*pageSizePtr);
172 
173     napi_value jsMargin = NapiPrintUtils::GetNamedProperty(env, jsValue, PARAM_JOB_MARGIN);
174     if (jsMargin != nullptr) {
175         auto marginPtr = PrintMarginHelper::BuildFromJs(env, jsMargin);
176         if (marginPtr == nullptr) {
177             PRINT_HILOGE("Failed to build print job object from js");
178             return nullptr;
179         }
180         nativeObj->SetMargin(*marginPtr);
181     }
182 
183     napi_value jsPreview = NapiPrintUtils::GetNamedProperty(env, jsValue, PARAM_JOB_PREVIEW);
184     if (jsPreview != nullptr) {
185         auto previewPtr = PrintPreviewAttributeHelper::BuildFromJs(env, jsPreview);
186         if (previewPtr == nullptr) {
187             PRINT_HILOGE("Failed to build print job object from js");
188             return nullptr;
189         }
190         nativeObj->SetPreview(*previewPtr);
191     }
192 
193     napi_value jsOption = NapiPrintUtils::GetNamedProperty(env, jsValue, PARAM_JOB_OPTION);
194     if (jsOption != nullptr) {
195         nativeObj->SetOption(NapiPrintUtils::GetStringPropertyUtf8(env, jsValue, PARAM_JOB_OPTION));
196     }
197     return nativeObj;
198 }
199 
CreateFdList(napi_env env,napi_value & jsPrintJob,const PrintJob & job)200 bool PrintJobHelper::CreateFdList(napi_env env, napi_value &jsPrintJob, const PrintJob &job)
201 {
202     napi_value arrFiles = nullptr;
203     PRINT_CALL_BASE(env, napi_create_array(env, &arrFiles), false);
204     std::vector<uint32_t> fdList;
205     job.GetFdList(fdList);
206     uint32_t arrFilesLength = fdList.size();
207 
208     for (uint32_t i = 0; i < arrFilesLength; i++) {
209         napi_value value;
210         PRINT_CALL_BASE(env, napi_create_uint32(env, fdList[i], &value), false);
211         PRINT_CALL_BASE(env, napi_set_element(env, arrFiles, i, value), false);
212     }
213     PRINT_CALL_BASE(env, napi_set_named_property(env, jsPrintJob, PARAM_JOB_FDLIST, arrFiles), false);
214     return true;
215 }
216 
CreatePageRange(napi_env env,napi_value & jsPrintJob,const PrintJob & job)217 bool PrintJobHelper::CreatePageRange(napi_env env, napi_value &jsPrintJob, const PrintJob &job)
218 {
219     PrintRange range;
220     job.GetPageRange(range);
221     napi_value jsPageRange = PrintRangeHelper::MakeJsObject(env, range);
222     PRINT_CALL_BASE(env, napi_set_named_property(env, jsPrintJob, PARAM_JOB_PAGERANGE, jsPageRange), false);
223     return true;
224 }
225 
CreatePageSize(napi_env env,napi_value & jsPrintJob,const PrintJob & job)226 bool PrintJobHelper::CreatePageSize(napi_env env, napi_value &jsPrintJob, const PrintJob &job)
227 {
228     PrintPageSize pageSize;
229     job.GetPageSize(pageSize);
230     napi_value jsPageSize = PrintPageSizeHelper::MakeJsObject(env, pageSize);
231     PRINT_CALL_BASE(env, napi_set_named_property(env, jsPrintJob, PARAM_JOB_PAGESIZE, jsPageSize), false);
232     return true;
233 }
234 
CreateMargin(napi_env env,napi_value & jsPrintJob,const PrintJob & job)235 bool PrintJobHelper::CreateMargin(napi_env env, napi_value &jsPrintJob, const PrintJob &job)
236 {
237     PrintMargin margin;
238     job.GetMargin(margin);
239     napi_value jsMargin = PrintMarginHelper::MakeJsObject(env, margin);
240     PRINT_CALL_BASE(env, napi_set_named_property(env, jsPrintJob, PARAM_JOB_MARGIN, jsMargin), false);
241     return true;
242 }
243 
CreatePreview(napi_env env,napi_value & jsPrintJob,const PrintJob & job)244 bool PrintJobHelper::CreatePreview(napi_env env, napi_value &jsPrintJob, const PrintJob &job)
245 {
246     PrintPreviewAttribute preview;
247     job.GetPreview(preview);
248     napi_value jsPreview = PrintPreviewAttributeHelper::MakeJsObject(env, preview);
249     PRINT_CALL_BASE(env, napi_set_named_property(env, jsPrintJob, PARAM_JOB_PREVIEW, jsPreview), false);
250     return true;
251 }
252 
ValidateProperty(napi_env env,napi_value object)253 bool PrintJobHelper::ValidateProperty(napi_env env, napi_value object)
254 {
255     std::map<std::string, PrintParamStatus> propertyList = {
256         {PARAM_JOB_FDLIST, PRINT_PARAM_NOT_SET},
257         {PARAM_JOB_JOBID, PRINT_PARAM_NOT_SET},
258         {PARAM_JOB_PRINTERID, PRINT_PARAM_NOT_SET},
259         {PARAM_JOB_JOBSTATE, PRINT_PARAM_OPT},
260         {PARAM_JOB_SUBSTATE, PRINT_PARAM_OPT},
261         {PARAM_JOB_COPYNUMBER, PRINT_PARAM_NOT_SET},
262         {PARAM_JOB_PAGERANGE, PRINT_PARAM_NOT_SET},
263         {PARAM_JOB_ISSEQUENTIAL, PRINT_PARAM_NOT_SET},
264         {PARAM_JOB_PAGESIZE, PRINT_PARAM_NOT_SET},
265         {PARAM_JOB_ISLANDSCAPE, PRINT_PARAM_NOT_SET},
266         {PARAM_JOB_COLORMODE, PRINT_PARAM_NOT_SET},
267         {PARAM_JOB_DUPLEXMODE, PRINT_PARAM_NOT_SET},
268         {PARAM_JOB_MARGIN, PRINT_PARAM_OPT},
269         {PARAM_JOB_PREVIEW, PRINT_PARAM_OPT},
270         {PARAM_JOB_OPTION, PRINT_PARAM_OPT},
271     };
272 
273     auto names = NapiPrintUtils::GetPropertyNames(env, object);
274     return NapiPrintUtils::VerifyProperty(names, propertyList);
275 }
276 }
277