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;
GetValueType(napi_env env,napi_value value)28 napi_valuetype NapiPrintUtils::GetValueType(napi_env env, napi_value value)
29 {
30     if (value == nullptr) {
31         return napi_undefined;
32     }
33 
34     napi_valuetype valueType = napi_undefined;
35     PRINT_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
36     return valueType;
37 }
38 
39 /* named property */
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)40 bool NapiPrintUtils::HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
41 {
42     bool hasProperty = false;
43     PRINT_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false);
44     return hasProperty;
45 }
46 
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)47 napi_value NapiPrintUtils::GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
48 {
49     napi_value value = nullptr;
50     bool hasProperty = false;
51     PRINT_CALL(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty));
52     if (!hasProperty) {
53         return value;
54     }
55     PRINT_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value));
56     return value;
57 }
58 
SetNamedProperty(napi_env env,napi_value object,const std::string & name,napi_value value)59 void NapiPrintUtils::SetNamedProperty(napi_env env, napi_value object, const std::string &name, napi_value value)
60 {
61     (void)napi_set_named_property(env, object, name.c_str(), value);
62 }
63 
GetPropertyNames(napi_env env,napi_value object)64 std::vector<std::string> NapiPrintUtils::GetPropertyNames(napi_env env, napi_value object)
65 {
66     std::vector<std::string> ret;
67     napi_value names = nullptr;
68     PRINT_CALL_BASE(env, napi_get_property_names(env, object, &names), ret);
69     uint32_t length = 0;
70     PRINT_CALL_BASE(env, napi_get_array_length(env, names, &length), ret);
71     for (uint32_t index = 0; index < length; ++index) {
72         napi_value name = nullptr;
73         if (napi_get_element(env, names, index, &name) != napi_ok) {
74             continue;
75         }
76         if (GetValueType(env, name) != napi_string) {
77             continue;
78         }
79         ret.emplace_back(GetStringFromValueUtf8(env, name));
80     }
81     return ret;
82 }
83 
84 /* UINT32 */
CreateUint32(napi_env env,uint32_t code)85 napi_value NapiPrintUtils::CreateUint32(napi_env env, uint32_t code)
86 {
87     napi_value value = nullptr;
88     if (napi_create_uint32(env, code, &value) != napi_ok) {
89         return nullptr;
90     }
91     return value;
92 }
93 
GetUint32FromValue(napi_env env,napi_value value)94 uint32_t NapiPrintUtils::GetUint32FromValue(napi_env env, napi_value value)
95 {
96     uint32_t ret = 0;
97     PRINT_CALL_BASE(env, napi_get_value_uint32(env, value, &ret), 0);
98     return ret;
99 }
100 
GetUint32Property(napi_env env,napi_value object,const std::string & propertyName)101 uint32_t NapiPrintUtils::GetUint32Property(napi_env env, napi_value object, const std::string &propertyName)
102 {
103     if (!HasNamedProperty(env, object, propertyName)) {
104         return 0;
105     }
106     napi_value value = GetNamedProperty(env, object, propertyName);
107     return GetUint32FromValue(env, value);
108 }
109 
SetUint32Property(napi_env env,napi_value object,const std::string & name,uint32_t value)110 void NapiPrintUtils::SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value)
111 {
112     napi_value jsValue = CreateUint32(env, value);
113     if (GetValueType(env, jsValue) != napi_number) {
114         return;
115     }
116 
117     napi_set_named_property(env, object, name.c_str(), jsValue);
118 }
119 
120 /* INT32 */
CreateInt32(napi_env env,int32_t code)121 napi_value NapiPrintUtils::CreateInt32(napi_env env, int32_t code)
122 {
123     napi_value value = nullptr;
124     if (napi_create_int32(env, code, &value) != napi_ok) {
125         return nullptr;
126     }
127     return value;
128 }
129 
GetInt32FromValue(napi_env env,napi_value value)130 int32_t NapiPrintUtils::GetInt32FromValue(napi_env env, napi_value value)
131 {
132     int32_t ret = 0;
133     PRINT_CALL_BASE(env, napi_get_value_int32(env, value, &ret), 0);
134     return ret;
135 }
136 
GetInt32Property(napi_env env,napi_value object,const std::string & propertyName)137 int32_t NapiPrintUtils::GetInt32Property(napi_env env, napi_value object, const std::string &propertyName)
138 {
139     if (!HasNamedProperty(env, object, propertyName)) {
140         return 0;
141     }
142     napi_value value = GetNamedProperty(env, object, propertyName);
143     return GetInt32FromValue(env, value);
144 }
145 
SetInt32Property(napi_env env,napi_value object,const std::string & name,int32_t value)146 void NapiPrintUtils::SetInt32Property(napi_env env, napi_value object, const std::string &name, int32_t value)
147 {
148     napi_value jsValue = CreateInt32(env, value);
149     if (GetValueType(env, jsValue) != napi_number) {
150         return;
151     }
152 
153     napi_set_named_property(env, object, name.c_str(), jsValue);
154 }
155 
156 /* String UTF8 */
CreateStringUtf8(napi_env env,const std::string & str)157 napi_value NapiPrintUtils::CreateStringUtf8(napi_env env, const std::string &str)
158 {
159     napi_value value = nullptr;
160     if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) {
161         return nullptr;
162     }
163     return value;
164 }
165 
GetStringFromValueUtf8(napi_env env,napi_value value)166 std::string NapiPrintUtils::GetStringFromValueUtf8(napi_env env, napi_value value)
167 {
168     std::string result;
169     std::vector<char> str(MAX_STRING_LENGTH + 1, '\0');
170     size_t length = 0;
171     PRINT_CALL_BASE(env, napi_get_value_string_utf8(env, value, &str[0], MAX_STRING_LENGTH, &length), result);
172     if (length > 0) {
173         return result.append(&str[0], length);
174     }
175     return result;
176 }
177 
GetStringPropertyUtf8(napi_env env,napi_value object,const std::string & propertyName)178 std::string NapiPrintUtils::GetStringPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName)
179 {
180     if (!HasNamedProperty(env, object, propertyName)) {
181         return "";
182     }
183     napi_value value = GetNamedProperty(env, object, propertyName);
184     return GetStringFromValueUtf8(env, value);
185 }
186 
SetStringPropertyUtf8(napi_env env,napi_value object,const std::string & name,const std::string & value)187 void NapiPrintUtils::SetStringPropertyUtf8(
188     napi_env env, napi_value object, const std::string &name, const std::string &value)
189 {
190     napi_value jsValue = CreateStringUtf8(env, value);
191     if (GetValueType(env, jsValue) != napi_string) {
192         return;
193     }
194     napi_set_named_property(env, object, name.c_str(), jsValue);
195 }
196 
197 /* array buffer */
198 
CreateArrayBuffer(napi_env env,size_t length,void ** data)199 napi_value NapiPrintUtils::CreateArrayBuffer(napi_env env, size_t length, void **data)
200 {
201     napi_value object = nullptr;
202     PRINT_CALL(env, napi_create_arraybuffer(env, length, data, &object));
203     return object;
204 }
205 
ValueIsArrayBuffer(napi_env env,napi_value value)206 bool NapiPrintUtils::ValueIsArrayBuffer(napi_env env, napi_value value)
207 {
208     bool isArrayBuffer = false;
209     PRINT_CALL_BASE(env, napi_is_arraybuffer(env, value, &isArrayBuffer), false);
210     return isArrayBuffer;
211 }
212 
GetInfoFromArrayBufferValue(napi_env env,napi_value value,size_t * length)213 void *NapiPrintUtils::GetInfoFromArrayBufferValue(napi_env env, napi_value value, size_t *length)
214 {
215     if (length == nullptr) {
216         return nullptr;
217     }
218 
219     void *data = nullptr;
220     PRINT_CALL(env, napi_get_arraybuffer_info(env, value, &data, length));
221     return data;
222 }
223 
224 /* object */
CreateObject(napi_env env)225 napi_value NapiPrintUtils::CreateObject(napi_env env)
226 {
227     napi_value object = nullptr;
228     PRINT_CALL(env, napi_create_object(env, &object));
229     return object;
230 }
231 
232 /* undefined */
GetUndefined(napi_env env)233 napi_value NapiPrintUtils::GetUndefined(napi_env env)
234 {
235     napi_value undefined = nullptr;
236     PRINT_CALL(env, napi_get_undefined(env, &undefined));
237     return undefined;
238 }
239 
240 /* function */
CallFunction(napi_env env,napi_value recv,napi_value func,size_t argc,const napi_value * argv)241 napi_value NapiPrintUtils::CallFunction(
242     napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv)
243 {
244     napi_value res = nullptr;
245     PRINT_CALL(env, napi_call_function(env, recv, func, argc, argv, &res));
246     return res;
247 }
248 
CreateFunction(napi_env env,const std::string & name,napi_callback func,void * arg)249 napi_value NapiPrintUtils::CreateFunction
250     (napi_env env, const std::string &name, napi_callback func, void *arg)
251 {
252     napi_value res = nullptr;
253     PRINT_CALL(env, napi_create_function(env, name.c_str(), NAPI_AUTO_LENGTH, func, arg, &res));
254     return res;
255 }
256 
257 /* reference */
CreateReference(napi_env env,napi_value callback)258 napi_ref NapiPrintUtils::CreateReference(napi_env env, napi_value callback)
259 {
260     napi_ref callbackRef = nullptr;
261     PRINT_CALL(env, napi_create_reference(env, callback, 1, &callbackRef));
262     return callbackRef;
263 }
264 
GetReference(napi_env env,napi_ref callbackRef)265 napi_value NapiPrintUtils::GetReference(napi_env env, napi_ref callbackRef)
266 {
267     napi_value callback = nullptr;
268     PRINT_CALL(env, napi_get_reference_value(env, callbackRef, &callback));
269     return callback;
270 }
271 
DeleteReference(napi_env env,napi_ref callbackRef)272 void NapiPrintUtils::DeleteReference(napi_env env, napi_ref callbackRef)
273 {
274     (void)napi_delete_reference(env, callbackRef);
275 }
276 
277 /* boolean */
GetBooleanProperty(napi_env env,napi_value object,const std::string & propertyName)278 bool NapiPrintUtils::GetBooleanProperty(napi_env env, napi_value object, const std::string &propertyName)
279 {
280     if (!HasNamedProperty(env, object, propertyName)) {
281         return false;
282     }
283     napi_value value = GetNamedProperty(env, object, propertyName);
284     bool ret = false;
285     PRINT_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false);
286     return ret;
287 }
288 
SetBooleanProperty(napi_env env,napi_value object,const std::string & name,bool value)289 void NapiPrintUtils::SetBooleanProperty(napi_env env, napi_value object, const std::string &name, bool value)
290 {
291     napi_value jsValue = nullptr;
292     PRINT_CALL_RETURN_VOID(env, napi_get_boolean(env, value, &jsValue));
293     if (GetValueType(env, jsValue) != napi_boolean) {
294         return;
295     }
296 
297     napi_set_named_property(env, object, name.c_str(), jsValue);
298 }
299 
300 /* define properties */
DefineProperties(napi_env env,napi_value object,const std::initializer_list<napi_property_descriptor> & properties)301 void NapiPrintUtils::DefineProperties(
302     napi_env env, napi_value object, const std::initializer_list<napi_property_descriptor> &properties)
303 {
304     std::vector<napi_property_descriptor> descriptors(properties.begin(), properties.end());
305 
306     (void)napi_define_properties(env, object, properties.size(), descriptors.data());
307 }
308 
GetValueString(napi_env env,napi_value value)309 std::string NapiPrintUtils::GetValueString(napi_env env, napi_value value)
310 {
311     std::string resultValue = "";
312     char value_string[256] = { 0 };
313     size_t value_size = 256;
314     size_t result = 0;
315     napi_status status = napi_get_value_string_utf8(env, value, value_string, value_size, &result);
316     if (status == napi_ok && result > 0) {
317         resultValue = value_string;
318     }
319     return resultValue;
320 }
321 
GetJsVal(napi_env env,napi_callback_info info,napi_value argv[],size_t length)322 size_t NapiPrintUtils::GetJsVal(napi_env env, napi_callback_info info, napi_value argv[], size_t length)
323 {
324     size_t argc = length;
325     napi_value thisVal = nullptr;
326     void *data = nullptr;
327     napi_get_cb_info(env, info, &argc, argv, &thisVal, &data);
328     return argc;
329 }
330 
VerifyProperty(std::vector<std::string> & names,std::map<std::string,PrintParamStatus> & propertyList)331 bool NapiPrintUtils::VerifyProperty(
332     std::vector<std::string> &names, std::map<std::string, PrintParamStatus> &propertyList)
333 {
334     for (const auto& name : names) {
335         if (propertyList.find(name) == propertyList.end()) {
336             PRINT_HILOGE("Invalid property: %{public}s", name.c_str());
337             return false;
338         }
339         propertyList[name] = PRINT_PARAM_SET;
340     }
341 
342     for (const auto& propertyItem : propertyList) {
343         if (propertyItem.second == PRINT_PARAM_NOT_SET) {
344             PRINT_HILOGE("Missing Property: %{public}s", propertyItem.first.c_str());
345             return false;
346         }
347     }
348     return true;
349 }
350 
GetPrintErrorMsg(int32_t errorCode)351 std::string NapiPrintUtils::GetPrintErrorMsg(int32_t errorCode)
352 {
353     auto msg = PRINT_ERROR_MSG_MAP.find(static_cast<PrintErrorCode>(errorCode));
354     if (msg != PRINT_ERROR_MSG_MAP.end()) {
355         return msg->second;
356     }
357     return "";
358 }
359 
CheckCallerIsSystemApp()360 bool NapiPrintUtils::CheckCallerIsSystemApp()
361 {
362     auto callerToken = IPCSkeleton::GetCallingTokenID();
363     auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
364     if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE ||
365         tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL) {
366         PRINT_HILOGD("tokenType check passed.");
367         return true;
368     }
369     auto accessTokenId = IPCSkeleton::GetCallingFullTokenID();
370     return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(accessTokenId);
371 }
372 }  // namespace OHOS::Print
373