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 "napi_print_utils.h"
17
18 #include "ability.h"
19 #include "accesstoken_kit.h"
20 #include "napi_base_context.h"
21 #include "print_constant.h"
22 #include "print_log.h"
23 #include "securec.h"
24 #include "tokenid_kit.h"
25
26 namespace OHOS::Print {
27 static constexpr const int MAX_STRING_LENGTH = 65536;
28 const std::map<int32_t, std::string> ERROR_CODE_CONVERT_MESSAGE_MAP = {
29 {E_PRINT_NO_PERMISSION, "the application does not have permission to call this function."},
30 {E_PRINT_ILLEGAL_USE_OF_SYSTEM_API, "not system application."},
31 {E_PRINT_INVALID_PARAMETER,
32 "Parameter error. Possible causes: 1.Mandatory parameters are left unspecified; 2.Incorrect parameter types."},
33 {E_PRINT_GENERIC_FAILURE, "Generic failure of print."},
34 {E_PRINT_RPC_FAILURE, "RPC failure."},
35 {E_PRINT_SERVER_FAILURE, "Failure of print service."},
36 {E_PRINT_INVALID_EXTENSION, "Invalid print extension."},
37 {E_PRINT_INVALID_PRINTER, "Invalid printer."},
38 {E_PRINT_INVALID_PRINTJOB, "Invalid print job."},
39 {E_PRINT_FILE_IO, "File i/o error."},
40 {E_PRINT_INVALID_TOKEN, "Invalid token."},
41 {E_PRINT_INVALID_USERID, "Invalid user id."},
42 {E_PRINT_TOO_MANY_FILES, "Number of files exceeding the upper limit."},
43 };
44 static const std::string ERROR_MESSAGE_OUT_OF_DEFINITION = "error is out of definition.";
45
GetValueType(napi_env env,napi_value value)46 napi_valuetype NapiPrintUtils::GetValueType(napi_env env, napi_value value)
47 {
48 if (value == nullptr) {
49 return napi_undefined;
50 }
51
52 napi_valuetype valueType = napi_undefined;
53 PRINT_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
54 return valueType;
55 }
56
57 /* named property */
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)58 bool NapiPrintUtils::HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
59 {
60 bool hasProperty = false;
61 PRINT_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false);
62 return hasProperty;
63 }
64
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)65 napi_value NapiPrintUtils::GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
66 {
67 napi_value value = nullptr;
68 bool hasProperty = false;
69 PRINT_CALL(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty));
70 if (!hasProperty) {
71 return value;
72 }
73 PRINT_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value));
74 return value;
75 }
76
SetNamedProperty(napi_env env,napi_value object,const std::string & name,napi_value value)77 void NapiPrintUtils::SetNamedProperty(napi_env env, napi_value object, const std::string &name, napi_value value)
78 {
79 (void)napi_set_named_property(env, object, name.c_str(), value);
80 }
81
GetPropertyNames(napi_env env,napi_value object)82 std::vector<std::string> NapiPrintUtils::GetPropertyNames(napi_env env, napi_value object)
83 {
84 std::vector<std::string> ret;
85 napi_value names = nullptr;
86 PRINT_CALL_BASE(env, napi_get_property_names(env, object, &names), ret);
87 uint32_t length = 0;
88 PRINT_CALL_BASE(env, napi_get_array_length(env, names, &length), ret);
89 for (uint32_t index = 0; index < length; ++index) {
90 napi_value name = nullptr;
91 if (napi_get_element(env, names, index, &name) != napi_ok) {
92 continue;
93 }
94 if (GetValueType(env, name) != napi_string) {
95 continue;
96 }
97 ret.emplace_back(GetStringFromValueUtf8(env, name));
98 }
99 return ret;
100 }
101
102 /* UINT32 */
CreateUint32(napi_env env,uint32_t code)103 napi_value NapiPrintUtils::CreateUint32(napi_env env, uint32_t code)
104 {
105 napi_value value = nullptr;
106 if (napi_create_uint32(env, code, &value) != napi_ok) {
107 return nullptr;
108 }
109 return value;
110 }
111
GetUint32FromValue(napi_env env,napi_value value)112 uint32_t NapiPrintUtils::GetUint32FromValue(napi_env env, napi_value value)
113 {
114 uint32_t ret = 0;
115 PRINT_CALL_BASE(env, napi_get_value_uint32(env, value, &ret), 0);
116 return ret;
117 }
118
GetUint32Property(napi_env env,napi_value object,const std::string & propertyName)119 uint32_t NapiPrintUtils::GetUint32Property(napi_env env, napi_value object, const std::string &propertyName)
120 {
121 if (!HasNamedProperty(env, object, propertyName)) {
122 return 0;
123 }
124 napi_value value = GetNamedProperty(env, object, propertyName);
125 return GetUint32FromValue(env, value);
126 }
127
SetUint32Property(napi_env env,napi_value object,const std::string & name,uint32_t value)128 void NapiPrintUtils::SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value)
129 {
130 napi_value jsValue = CreateUint32(env, value);
131 if (GetValueType(env, jsValue) != napi_number) {
132 return;
133 }
134
135 napi_set_named_property(env, object, name.c_str(), jsValue);
136 }
137
138 /* INT32 */
CreateInt32(napi_env env,int32_t code)139 napi_value NapiPrintUtils::CreateInt32(napi_env env, int32_t code)
140 {
141 napi_value value = nullptr;
142 if (napi_create_int32(env, code, &value) != napi_ok) {
143 return nullptr;
144 }
145 return value;
146 }
147
GetInt32FromValue(napi_env env,napi_value value)148 int32_t NapiPrintUtils::GetInt32FromValue(napi_env env, napi_value value)
149 {
150 int32_t ret = 0;
151 PRINT_CALL_BASE(env, napi_get_value_int32(env, value, &ret), 0);
152 return ret;
153 }
154
GetInt32Property(napi_env env,napi_value object,const std::string & propertyName)155 int32_t NapiPrintUtils::GetInt32Property(napi_env env, napi_value object, const std::string &propertyName)
156 {
157 if (!HasNamedProperty(env, object, propertyName)) {
158 return 0;
159 }
160 napi_value value = GetNamedProperty(env, object, propertyName);
161 return GetInt32FromValue(env, value);
162 }
163
SetInt32Property(napi_env env,napi_value object,const std::string & name,int32_t value)164 void NapiPrintUtils::SetInt32Property(napi_env env, napi_value object, const std::string &name, int32_t value)
165 {
166 napi_value jsValue = CreateInt32(env, value);
167 if (GetValueType(env, jsValue) != napi_number) {
168 return;
169 }
170
171 napi_set_named_property(env, object, name.c_str(), jsValue);
172 }
173
174 /* String UTF8 */
CreateStringUtf8(napi_env env,const std::string & str)175 napi_value NapiPrintUtils::CreateStringUtf8(napi_env env, const std::string &str)
176 {
177 napi_value value = nullptr;
178 if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) {
179 return nullptr;
180 }
181 return value;
182 }
183
GetStringFromValueUtf8(napi_env env,napi_value value)184 std::string NapiPrintUtils::GetStringFromValueUtf8(napi_env env, napi_value value)
185 {
186 std::string result;
187 std::vector<char> str(MAX_STRING_LENGTH + 1, '\0');
188 size_t length = 0;
189 PRINT_CALL_BASE(env, napi_get_value_string_utf8(env, value, &str[0], MAX_STRING_LENGTH, &length), result);
190 if (length > 0) {
191 return result.append(&str[0], length);
192 }
193 return result;
194 }
195
GetStringPropertyUtf8(napi_env env,napi_value object,const std::string & propertyName)196 std::string NapiPrintUtils::GetStringPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName)
197 {
198 if (!HasNamedProperty(env, object, propertyName)) {
199 return "";
200 }
201 napi_value value = GetNamedProperty(env, object, propertyName);
202 return GetStringFromValueUtf8(env, value);
203 }
204
SetStringPropertyUtf8(napi_env env,napi_value object,const std::string & name,const std::string & value)205 void NapiPrintUtils::SetStringPropertyUtf8(
206 napi_env env, napi_value object, const std::string &name, const std::string &value)
207 {
208 napi_value jsValue = CreateStringUtf8(env, value);
209 if (GetValueType(env, jsValue) != napi_string) {
210 return;
211 }
212 napi_set_named_property(env, object, name.c_str(), jsValue);
213 }
214
215 /* array buffer */
216
CreateArrayBuffer(napi_env env,size_t length,void ** data)217 napi_value NapiPrintUtils::CreateArrayBuffer(napi_env env, size_t length, void **data)
218 {
219 napi_value object = nullptr;
220 PRINT_CALL(env, napi_create_arraybuffer(env, length, data, &object));
221 return object;
222 }
223
ValueIsArrayBuffer(napi_env env,napi_value value)224 bool NapiPrintUtils::ValueIsArrayBuffer(napi_env env, napi_value value)
225 {
226 bool isArrayBuffer = false;
227 PRINT_CALL_BASE(env, napi_is_arraybuffer(env, value, &isArrayBuffer), false);
228 return isArrayBuffer;
229 }
230
GetInfoFromArrayBufferValue(napi_env env,napi_value value,size_t * length)231 void *NapiPrintUtils::GetInfoFromArrayBufferValue(napi_env env, napi_value value, size_t *length)
232 {
233 if (length == nullptr) {
234 return nullptr;
235 }
236
237 void *data = nullptr;
238 PRINT_CALL(env, napi_get_arraybuffer_info(env, value, &data, length));
239 return data;
240 }
241
242 /* object */
CreateObject(napi_env env)243 napi_value NapiPrintUtils::CreateObject(napi_env env)
244 {
245 napi_value object = nullptr;
246 PRINT_CALL(env, napi_create_object(env, &object));
247 return object;
248 }
249
250 /* undefined */
GetUndefined(napi_env env)251 napi_value NapiPrintUtils::GetUndefined(napi_env env)
252 {
253 napi_value undefined = nullptr;
254 PRINT_CALL(env, napi_get_undefined(env, &undefined));
255 return undefined;
256 }
257
258 /* function */
CallFunction(napi_env env,napi_value recv,napi_value func,size_t argc,const napi_value * argv)259 napi_value NapiPrintUtils::CallFunction(
260 napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv)
261 {
262 napi_value res = nullptr;
263 PRINT_CALL(env, napi_call_function(env, recv, func, argc, argv, &res));
264 return res;
265 }
266
CreateFunction(napi_env env,const std::string & name,napi_callback func,void * arg)267 napi_value NapiPrintUtils::CreateFunction
268 (napi_env env, const std::string &name, napi_callback func, void *arg)
269 {
270 napi_value res = nullptr;
271 PRINT_CALL(env, napi_create_function(env, name.c_str(), NAPI_AUTO_LENGTH, func, arg, &res));
272 return res;
273 }
274
275 /* reference */
CreateReference(napi_env env,napi_value callback)276 napi_ref NapiPrintUtils::CreateReference(napi_env env, napi_value callback)
277 {
278 napi_ref callbackRef = nullptr;
279 PRINT_CALL(env, napi_create_reference(env, callback, 1, &callbackRef));
280 return callbackRef;
281 }
282
GetReference(napi_env env,napi_ref callbackRef)283 napi_value NapiPrintUtils::GetReference(napi_env env, napi_ref callbackRef)
284 {
285 napi_value callback = nullptr;
286 PRINT_CALL(env, napi_get_reference_value(env, callbackRef, &callback));
287 return callback;
288 }
289
DeleteReference(napi_env env,napi_ref callbackRef)290 void NapiPrintUtils::DeleteReference(napi_env env, napi_ref callbackRef)
291 {
292 (void)napi_delete_reference(env, callbackRef);
293 }
294
295 /* boolean */
GetBooleanProperty(napi_env env,napi_value object,const std::string & propertyName)296 bool NapiPrintUtils::GetBooleanProperty(napi_env env, napi_value object, const std::string &propertyName)
297 {
298 if (!HasNamedProperty(env, object, propertyName)) {
299 return false;
300 }
301 napi_value value = GetNamedProperty(env, object, propertyName);
302 bool ret = false;
303 PRINT_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false);
304 return ret;
305 }
306
SetBooleanProperty(napi_env env,napi_value object,const std::string & name,bool value)307 void NapiPrintUtils::SetBooleanProperty(napi_env env, napi_value object, const std::string &name, bool value)
308 {
309 napi_value jsValue = nullptr;
310 PRINT_CALL_RETURN_VOID(env, napi_get_boolean(env, value, &jsValue));
311 if (GetValueType(env, jsValue) != napi_boolean) {
312 return;
313 }
314
315 napi_set_named_property(env, object, name.c_str(), jsValue);
316 }
317
318 /* define properties */
DefineProperties(napi_env env,napi_value object,const std::initializer_list<napi_property_descriptor> & properties)319 void NapiPrintUtils::DefineProperties(
320 napi_env env, napi_value object, const std::initializer_list<napi_property_descriptor> &properties)
321 {
322 std::vector<napi_property_descriptor> descriptors(properties.begin(), properties.end());
323
324 (void)napi_define_properties(env, object, properties.size(), descriptors.data());
325 }
326
GetValueString(napi_env env,napi_value value)327 std::string NapiPrintUtils::GetValueString(napi_env env, napi_value value)
328 {
329 std::string resultValue = "";
330 char value_string[256] = { 0 };
331 size_t value_size = 256;
332 size_t result = 0;
333 napi_status status = napi_get_value_string_utf8(env, value, value_string, value_size, &result);
334 if (status == napi_ok && result > 0) {
335 resultValue = value_string;
336 }
337 return resultValue;
338 }
339
GetJsVal(napi_env env,napi_callback_info info,napi_value argv[],size_t length)340 size_t NapiPrintUtils::GetJsVal(napi_env env, napi_callback_info info, napi_value argv[], size_t length)
341 {
342 size_t argc = length;
343 napi_value thisVal = nullptr;
344 void *data = nullptr;
345 napi_get_cb_info(env, info, &argc, argv, &thisVal, &data);
346 return argc;
347 }
348
VerifyProperty(std::vector<std::string> & names,std::map<std::string,PrintParamStatus> & propertyList)349 bool NapiPrintUtils::VerifyProperty(
350 std::vector<std::string> &names, std::map<std::string, PrintParamStatus> &propertyList)
351 {
352 for (const auto& name : names) {
353 if (propertyList.find(name) == propertyList.end()) {
354 PRINT_HILOGE("Invalid property: %{public}s", name.c_str());
355 return false;
356 }
357 propertyList[name] = PRINT_PARAM_SET;
358 }
359
360 for (const auto& propertyItem : propertyList) {
361 if (propertyItem.second == PRINT_PARAM_NOT_SET) {
362 PRINT_HILOGE("Missing Property: %{public}s", propertyItem.first.c_str());
363 return false;
364 }
365 }
366 return true;
367 }
368
GetPrintErrorMsg(int32_t errorCode)369 std::string NapiPrintUtils::GetPrintErrorMsg(int32_t errorCode)
370 {
371 auto msg = PRINT_ERROR_MSG_MAP.find(static_cast<PrintErrorCode>(errorCode));
372 if (msg != PRINT_ERROR_MSG_MAP.end()) {
373 return msg->second;
374 }
375 return "";
376 }
377
CheckCallerIsSystemApp()378 bool NapiPrintUtils::CheckCallerIsSystemApp()
379 {
380 auto callerToken = IPCSkeleton::GetCallingTokenID();
381 auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
382 if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE ||
383 tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL) {
384 PRINT_HILOGD("tokenType check passed.");
385 return true;
386 }
387 auto accessTokenId = IPCSkeleton::GetCallingFullTokenID();
388 return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(accessTokenId);
389 }
390
GetErrorMsgByErrorCode(int32_t code)391 const std::string NapiPrintUtils::GetErrorMsgByErrorCode(int32_t code)
392 {
393 PRINT_HILOGD("GetErrorMsgByErrorCode start");
394 auto iter = ERROR_CODE_CONVERT_MESSAGE_MAP.find(code);
395 if (iter == ERROR_CODE_CONVERT_MESSAGE_MAP.end()) {
396 PRINT_HILOGE("error is out of definition.");
397 return ERROR_MESSAGE_OUT_OF_DEFINITION;
398 }
399 PRINT_HILOGD("ErrorMessage: %{public}s", (iter->second).c_str());
400 return iter->second;
401 }
402
CreateJsError(napi_env env,int32_t errCode)403 napi_value NapiPrintUtils::CreateJsError(napi_env env, int32_t errCode)
404 {
405 std::string errMsg = GetErrorMsgByErrorCode(errCode);
406 PRINT_HILOGD("CreateJsError errCode: %{public}d, errMsg: %{public}s", errCode, errMsg.c_str());
407
408 napi_value code = nullptr;
409 napi_status status = napi_create_int32(env, errCode, &code);
410 if (status != napi_ok) {
411 PRINT_HILOGE("napi create error code failed");
412 return nullptr;
413 }
414
415 napi_value message = nullptr;
416 status = napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
417 if (status != napi_ok) {
418 PRINT_HILOGE("napi create error message failed");
419 return nullptr;
420 }
421
422 napi_value errorObj = nullptr;
423 status = napi_create_error(env, code, message, &errorObj);
424 if (status != napi_ok) {
425 PRINT_HILOGE("napi create js error failed");
426 return nullptr;
427 }
428
429 return errorObj;
430 }
431 } // namespace OHOS::Print
432