1 /*
2 * Copyright (c) 2020-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 "js_fwk_common.h"
16 #include <climits>
17 #include <cerrno>
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 #if ((defined(__WIN32)) || (defined(__WIN64)))
23 #include <shlwapi.h>
24 #endif
25 #include "ace_event_error_code.h"
26 #include "ace_log.h"
27 #include "ace_mem_base.h"
28 #include "component.h"
29 #include "component_utils.h"
30 #include "dfx_assist.h"
31 #include "fatal_handler.h"
32 #include "js_app_context.h"
33 #include "js_app_environment.h"
34 #include "js_profiler.h"
35 #if IS_ENABLED(CONSOLE_LOG_OUTPUT)
36 #include "presets/console_module.h"
37 #endif
38 #include "presets/console_log_impl.h"
39 #include "product_adapter.h"
40 #include "securec.h"
41 #include "task_manager.h"
42
43 #if ((defined __LITEOS__) || (defined __linux__) || (SCREENSIZE_SPECIFIED == 1))
44 #include <screen.h>
45 #endif
46
47 #include <stdarg.h>
48 #include <stdlib.h>
49 #include <string.h>
50
51 namespace OHOS {
52 namespace ACELite {
JerrySetNamedProperty(jerry_value_t object,const char * const name,jerry_value_t propValue)53 void JerrySetNamedProperty(jerry_value_t object, const char * const name, jerry_value_t propValue)
54 {
55 jerry_release_value(jerryx_set_property_str(object, name, propValue));
56 }
57
JerrySetNumberProperty(jerry_value_t object,const char * const name,double value)58 void JerrySetNumberProperty(jerry_value_t object, const char * const name, double value)
59 {
60 jerry_value_t numValue = jerry_create_number(value);
61 JerrySetNamedProperty(object, name, numValue);
62 jerry_release_value(numValue);
63 }
64
JerrySetStringProperty(jerry_value_t object,const char * const name,const char * const value)65 void JerrySetStringProperty(jerry_value_t object, const char * const name, const char * const value)
66 {
67 jerry_value_t strValue = jerry_create_string(reinterpret_cast<const jerry_char_t *>(value));
68 JerrySetNamedProperty(object, name, strValue);
69 jerry_release_value(strValue);
70 }
71
JerrySetStringProperty(jerry_value_t object,const char * const name,const char * const value,uint32_t length)72 void JerrySetStringProperty(jerry_value_t object, const char * const name, const char * const value, uint32_t length)
73 {
74 jerry_value_t strValue = jerry_create_string_sz_from_utf8(reinterpret_cast<const jerry_char_t *>(value), length);
75 JerrySetNamedProperty(object, name, strValue);
76 jerry_release_value(strValue);
77 }
78
JerryMallocStringProperty(const jerry_value_t object,const char * const name,uint16_t & length)79 char *JerryMallocStringProperty(const jerry_value_t object, const char * const name, uint16_t &length)
80 {
81 jerry_value_t propValue = jerryx_get_property_str(object, name);
82 char *res = MallocStringOf(propValue, &length);
83 jerry_release_value(propValue);
84 return res;
85 }
86
JerryGetIntegerProperty(jerry_value_t object,const char * const name)87 int16_t JerryGetIntegerProperty(jerry_value_t object, const char * const name)
88 {
89 jerry_value_t value = jerryx_get_property_str(object, name);
90 int16_t result = IntegerOf(value);
91 jerry_release_value(value);
92 return result;
93 }
94
JerryGetBoolProperty(jerry_value_t object,const char * const name,bool & outValue)95 bool JerryGetBoolProperty(jerry_value_t object, const char * const name, bool &outValue)
96 {
97 jerry_value_t value = jerryx_get_property_str(object, name);
98 if (!jerry_value_is_boolean(value)) {
99 jerry_release_value(value);
100 HILOG_ERROR(HILOG_MODULE_ACE, "js value is not bool.");
101 return false;
102 }
103 outValue = jerry_value_to_boolean(value);
104 jerry_release_value(value);
105 return true;
106 }
107
JerrySetFuncProperty(jerry_value_t object,const char * const name,jerry_external_handler_t handler)108 void JerrySetFuncProperty(jerry_value_t object, const char * const name, jerry_external_handler_t handler)
109 {
110 if (name == nullptr || !strlen(name)) {
111 HILOG_ERROR(HILOG_MODULE_ACE, "Failed to set function property cause by empty name.");
112 return;
113 }
114
115 if (handler == nullptr) {
116 HILOG_ERROR(HILOG_MODULE_ACE, "Failed to set function property cause by empty handler.");
117 return;
118 }
119
120 jerry_value_t func = jerry_create_external_function(handler);
121 jerryx_set_property_str(object, name, func);
122 jerry_release_value(func);
123 }
124
125 /* return value must be freed by caller, except the returned value is nullptr */
MallocStringOf(jerry_value_t source)126 char *MallocStringOf(jerry_value_t source)
127 {
128 uint16_t length = 0;
129 return MallocStringOf(source, &length);
130 }
131
MallocStringOf(jerry_value_t source,uint16_t * strLength)132 char *MallocStringOf(jerry_value_t source, uint16_t *strLength)
133 {
134 if ((IS_UNDEFINED(source)) || (strLength == nullptr)) {
135 HILOG_ERROR(HILOG_MODULE_ACE, "Invalid input: source is undefined or strLength is nullptr");
136 return nullptr;
137 }
138
139 *strLength = 0;
140 bool success = false;
141 jerry_value_t target = UNDEFINED;
142 jerry_char_t *buffer = nullptr;
143 jerry_size_t length = 0;
144 do {
145 if (jerry_value_is_symbol(source)) {
146 target = jerry_get_symbol_descriptive_string(source);
147 } else {
148 target = jerry_value_to_string(source);
149 }
150 if (IS_ERROR_VALUE(target)) {
151 HILOG_ERROR(HILOG_MODULE_ACE, "jerry_value_to_string failed, can not continue to generate char buffer");
152 break;
153 }
154
155 jerry_size_t size = jerry_get_string_size(target);
156 if (size >= UINT16_MAX) {
157 HILOG_ERROR(HILOG_MODULE_ACE, "String size exceeds UINT16_MAX, cannot process");
158 break;
159 }
160 buffer = static_cast<jerry_char_t *>(ace_malloc(sizeof(jerry_char_t) * (size + 1)));
161 if (buffer == nullptr) {
162 HILOG_ERROR(HILOG_MODULE_ACE, "malloc buffer for convert jerry string failed");
163 break;
164 }
165 if (size == 0) {
166 // if here got matched, it means the JS string is empty itself
167 success = true;
168 break;
169 }
170
171 length = jerry_string_to_char_buffer(target, buffer, size);
172 if ((length == 0) || (length >= UINT16_MAX) || (length > size)) {
173 HILOG_ERROR(HILOG_MODULE_ACE, "jerry string to char buffer failed, target size[%{public}d]", size);
174 break;
175 }
176 success = true;
177 } while (0);
178
179 jerry_release_value(target);
180 if (!success) {
181 ACE_FREE(buffer);
182 return nullptr;
183 }
184 // successful scenario, add end character
185 buffer[length] = '\0';
186 *strLength = length;
187 return reinterpret_cast<char *>(buffer);
188 }
189
BoolOf(jerry_value_t source)190 bool BoolOf(jerry_value_t source)
191 {
192 if (!jerry_value_is_boolean(source)) {
193 HILOG_ERROR(HILOG_MODULE_ACE, "js value is not bool.");
194 }
195 return jerry_value_to_boolean(source);
196 }
197
IntegerOf(jerry_value_t source)198 int16_t IntegerOf(jerry_value_t source)
199 {
200 if (!jerry_value_is_number(source)) {
201 char *strValue = MallocStringOf(source);
202 if (strValue == nullptr) {
203 return 0;
204 }
205 int16_t intValue = static_cast<int16_t>(strtol(strValue, nullptr, DEC));
206 ace_free(strValue);
207 return intValue;
208 }
209 int number = (int)jerry_get_number_value(source);
210 if (number >= INT16_MAX) {
211 HILOG_DEBUG(HILOG_MODULE_ACE, "js number value is out of range.");
212 return INT16_MAX;
213 }
214 if (number <= INT16_MIN) {
215 HILOG_DEBUG(HILOG_MODULE_ACE, "js number value is out of range.");
216 return INT16_MIN;
217 }
218 return static_cast<int16_t>(number);
219 }
220
FloatOf(jerry_value_t source)221 float FloatOf(jerry_value_t source)
222 {
223 float value = 0;
224 if (jerry_value_is_number(source)) {
225 value = static_cast<float>(jerry_get_number_value(source));
226 } else {
227 char* cstr = MallocStringOf(source);
228 if (cstr == nullptr) {
229 HILOG_ERROR(HILOG_MODULE_ACE, "cstr is nullptr.");
230 return 0;
231 }
232 value = static_cast<float>(atof(cstr));
233 ACE_FREE(cstr);
234 }
235 return value;
236 }
237
WatcherCallbackFunc(const jerry_value_t func,const jerry_value_t context,const jerry_value_t * args,const jerry_length_t argsLength)238 jerry_value_t WatcherCallbackFunc(const jerry_value_t func,
239 const jerry_value_t context,
240 const jerry_value_t *args,
241 const jerry_length_t argsLength)
242 {
243 if (argsLength != ARG_LENGTH_WATCHER_CALLBACK) {
244 return UNDEFINED;
245 }
246
247 START_TRACING(WATCHER_CALLBACK_FUNC);
248 jerry_value_t value = args[0];
249 const uint8_t optionIndex = 2;
250 jerry_value_t options = args[optionIndex];
251 jerry_value_t nativeElement = jerryx_get_property_str(options, ARG_WATCH_EL);
252 jerry_value_t attrKey = jerryx_get_property_str(options, ARG_WATCH_ATTR);
253
254 Component *component = ComponentUtils::GetComponentFromBindingObject(nativeElement);
255 if (component != nullptr) {
256 uint16_t attrKeyStrLen = 0;
257 char *attrKeyStr = MallocStringOf(attrKey, &attrKeyStrLen);
258 if (attrKeyStr != nullptr) {
259 uint16_t attrKeyId = KeyParser::ParseKeyId(attrKeyStr, attrKeyStrLen);
260 bool updateResult = component->UpdateView(attrKeyId, value);
261 if (updateResult) {
262 component->Invalidate();
263 }
264 ace_free(attrKeyStr);
265 attrKeyStr = nullptr;
266 }
267 }
268 STOP_TRACING();
269 ReleaseJerryValue(attrKey, nativeElement, VA_ARG_END_FLAG);
270 return UNDEFINED;
271 }
272
273 // print out error information from jerry value
PrintErrorMessage(const jerry_value_t errorValue)274 void PrintErrorMessage(const jerry_value_t errorValue)
275 {
276 DfxAssist dfxAssist;
277 dfxAssist.DumpErrorCode(errorValue);
278 dfxAssist.DumpErrorMessage(errorValue);
279 #if IS_ENABLED(ENGINE_DEBUGGER)
280 FlushOutput();
281 #endif
282 }
283
284 // wrapper function for jerry_call_function
CallJSFunction(const jerry_value_t func,const jerry_value_t context,const jerry_value_t args[],jerry_size_t argsCount)285 jerry_value_t CallJSFunction(const jerry_value_t func,
286 const jerry_value_t context,
287 const jerry_value_t args[],
288 jerry_size_t argsCount)
289 {
290 jerry_value_t ret = jerry_call_function(func, context, args, argsCount);
291 // trace out error information if the result contains error
292 if (jerry_value_is_error(ret)) {
293 PrintErrorMessage(ret);
294 }
295 return ret;
296 }
297
CallJSFunctionAutoRelease(const jerry_value_t funcObj,const jerry_value_t thisVal,const jerry_value_t args[],const jerry_size_t argc)298 void CallJSFunctionAutoRelease(const jerry_value_t funcObj,
299 const jerry_value_t thisVal,
300 const jerry_value_t args[],
301 const jerry_size_t argc)
302 {
303 jerry_release_value(CallJSFunction(funcObj, thisVal, args, argc));
304 }
305
CallJSFunctionOnRoot(const jerry_value_t funcObj,const jerry_value_t args[],const jerry_size_t argc)306 jerry_value_t CallJSFunctionOnRoot(const jerry_value_t funcObj, /* function object to call */
307 const jerry_value_t args[], /* function's call arguments */
308 const jerry_size_t argc) /* number of the arguments */
309 {
310 jerry_value_t globalObject = jerry_get_global_object();
311 jerry_value_t pageViewModel = jerryx_get_property_str(globalObject, ATTR_ROOT);
312 jerry_value_t ret = CallJSFunction(funcObj, pageViewModel, args, argc);
313 ReleaseJerryValue(globalObject, pageViewModel, VA_ARG_END_FLAG);
314 return ret;
315 }
316
317 // arg1:target object watched, arg2:watcher callback, arg3:other argument
CallJSWatcher(jerry_value_t arg1,jerry_value_t (* watcherCB)(const jerry_value_t func,const jerry_value_t context,const jerry_value_t * args,const jerry_length_t argsLength),jerry_value_t arg3)318 jerry_value_t CallJSWatcher(jerry_value_t arg1,
319 jerry_value_t (*watcherCB)(const jerry_value_t func,
320 const jerry_value_t context,
321 const jerry_value_t *args,
322 const jerry_length_t argsLength),
323 jerry_value_t arg3)
324 {
325 jerry_value_t globalObject = jerry_get_global_object();
326 jerry_value_t appViewModel = jerryx_get_property_str(globalObject, ATTR_ROOT);
327 const char * const attrWatch = "$watch";
328 jerry_value_t watchFunction = jerryx_get_property_str(appViewModel, attrWatch);
329 jerry_value_t callbackFunc = jerry_create_external_function(watcherCB);
330 jerry_value_t args[ARG_LENGTH_WATCHER] = {arg1, callbackFunc, arg3};
331 jerry_value_t watcher = CallJSFunction(watchFunction, appViewModel, args, ARG_LENGTH_WATCHER);
332 ReleaseJerryValue(callbackFunc, watchFunction, appViewModel, globalObject, VA_ARG_END_FLAG);
333 return watcher;
334 }
335
336 #ifdef JS_EXTRA_EVENT_SUPPORT
CallBaseEvent(const jerry_value_t func,const Event & event,const uint16_t id)337 bool CallBaseEvent(const jerry_value_t func, const Event &event, const uint16_t id)
338 {
339 if (!jerry_value_is_function(func)) {
340 return false;
341 }
342
343 jerry_value_t *args = ConvertBaseEventInfo(event, id);
344 jerry_release_value(CallJSFunctionOnRoot(func, args, 1));
345 ClearEventListener(args, 1);
346 return true;
347 }
348
ConvertBaseEventInfo(const Event & event,const uint16_t id)349 jerry_value_t *ConvertBaseEventInfo(const Event &event, const uint16_t id)
350 {
351 const uint8_t argsNum = 1;
352 jerry_value_t *args = new jerry_value_t[argsNum];
353 args[0] = jerry_create_object();
354 JerrySetStringProperty(args[0], "type", KeyParser::GetKeyById(id));
355 JerrySetNumberProperty(args[0], "timestamp", event.GetTimeStamp());
356 jerry_value_t point = jerry_create_object();
357 JerrySetNumberProperty(point, "x", event.GetCurrentPos().x);
358 JerrySetNumberProperty(point, "y", event.GetCurrentPos().y);
359 JerrySetNamedProperty(args[0], "point", point);
360 jerry_release_value(point);
361 return args;
362 }
363
ConvertKeyEventInfo(const KeyEvent & event)364 jerry_value_t *ConvertKeyEventInfo(const KeyEvent &event)
365 {
366 const uint8_t argsNum = 1;
367 jerry_value_t *args = new jerry_value_t[argsNum];
368 args[0] = jerry_create_object();
369 JerrySetNumberProperty(args[0], "code", event.GetState());
370 JerrySetNumberProperty(args[0], "action", event.GetKeyId());
371 JerrySetNumberProperty(args[0], "repeatCount", 0);
372 JerrySetNumberProperty(args[0], "timeStampStart", event.GetTimeStamp());
373 return args;
374 }
375
ClearEventListener(const jerry_value_t args[],const uint8_t argc)376 void ClearEventListener(const jerry_value_t args[], const uint8_t argc)
377 {
378 for (uint8_t i = 0; i < argc; i++) {
379 jerry_release_value(args[i]);
380 }
381 delete[] args;
382 args = nullptr;
383 }
384 #endif
385
386 /**
387 * only used in this file, caller must make sure the target buffer is big enough.
388 * return the copied byte count.
389 */
AppendTwoPath(char * const first,uint8_t startIndex,const char * const sec,const uint16_t destSize)390 static size_t AppendTwoPath(char * const first, uint8_t startIndex, const char * const sec, const uint16_t destSize)
391 {
392 if ((first == nullptr) || (sec == nullptr) || (strlen(sec) == 0)) {
393 return 0;
394 }
395
396 size_t secLength = strlen(sec);
397 if ((secLength >= PATH_LENGTH_MAX) || (destSize - startIndex < 0) ||
398 (secLength > (size_t)(destSize - startIndex))) {
399 HILOG_ERROR(HILOG_MODULE_ACE, "secLength is too long.");
400 return 0;
401 }
402 if (startIndex == 0) {
403 // this is the first
404 if (memcpy_s(first, destSize, sec, secLength) != 0) {
405 return 0;
406 }
407 first[secLength] = 0;
408 return secLength;
409 }
410
411 size_t copiedLength = 0;
412 // we dont append '/' at the first index
413 bool sepNeeded = (first[startIndex - 1] != PATH_SEPARATOR);
414 if (sepNeeded) {
415 first[startIndex] = PATH_SEPARATOR;
416 copiedLength++;
417 startIndex++;
418 }
419
420 if (sec[0] == PATH_SEPARATOR) {
421 if (secLength > 1) {
422 if (memcpy_s(first + startIndex, (destSize - startIndex), (sec + 1), (secLength - 1)) != 0) {
423 HILOG_ERROR(HILOG_MODULE_ACE, "append path error");
424 return 0;
425 }
426
427 copiedLength = copiedLength + (secLength - 1);
428 startIndex = startIndex + (secLength - 1);
429 }
430 } else {
431 // sec string do not have '/'
432 if (memcpy_s(first + startIndex, (destSize - startIndex), sec, secLength) != 0) {
433 HILOG_ERROR(HILOG_MODULE_ACE, "error happen when append path");
434 return 0;
435 }
436 copiedLength = copiedLength + secLength;
437 startIndex = startIndex + secLength;
438 }
439 first[startIndex] = 0;
440
441 return copiedLength;
442 }
443
RelocateFilePath(const char * appRootPath,const char * subPath,const char * fileName)444 char *RelocateFilePath(const char *appRootPath, const char *subPath, const char *fileName)
445 {
446 size_t appRootPathLength = 0;
447 size_t fileNameLength = 0;
448 if ((appRootPath == nullptr) || ((appRootPathLength = strlen(appRootPath)) == 0) || (fileName == nullptr) ||
449 ((fileNameLength = strlen(fileName)) == 0)) {
450 HILOG_ERROR(HILOG_MODULE_ACE, "input path or fileName is invalid");
451 return nullptr;
452 }
453
454 size_t subPathLength = (subPath == nullptr) ? 0 : strlen(subPath);
455 if ((appRootPathLength >= PATH_LENGTH_MAX) || (subPathLength >= PATH_LENGTH_MAX) ||
456 (fileNameLength >= NAME_LENGTH_MAX)) {
457 HILOG_ERROR(HILOG_MODULE_ACE, "input path or fileName is too long");
458 return nullptr;
459 }
460 // always consume subPath does not have '/'
461 const uint8_t addedLength = 2;
462 size_t totalLength = appRootPathLength + subPathLength + fileNameLength + addedLength;
463 char *fullPath = static_cast<char *>(ace_malloc(totalLength + 1));
464 if (fullPath == nullptr) {
465 HILOG_ERROR(HILOG_MODULE_ACE, "malloc buffer for path failed, needed length[%{public}u]", (totalLength + 1));
466 return nullptr;
467 }
468 fullPath[0] = '\0';
469 // copy root path
470 size_t copiedLength = AppendTwoPath(fullPath, 0, appRootPath, totalLength);
471 size_t index = copiedLength;
472 // copy sub folder name if it's given
473 if (subPathLength > 0) {
474 copiedLength = AppendTwoPath(fullPath, index, subPath, totalLength);
475 index += copiedLength;
476 }
477 // copy filename part
478 index += AppendTwoPath(fullPath, index, fileName, totalLength);
479 fullPath[index] = '\0';
480 return fullPath;
481 }
482
483 // judge absolute path or relative path (start with . is absolute otherwise relative)
PathIsRelative(const char * const resPath)484 static bool PathIsRelative(const char * const resPath)
485 {
486 return strncmp(PATH_PREFIX, resPath, strlen(PATH_PREFIX)) == 0;
487 }
488
RelocateFilePathRelative(const char * const appRootPath,const char * const resFileName)489 char *RelocateFilePathRelative(const char * const appRootPath, const char * const resFileName)
490 {
491 const char * const jsPath = JsAppContext::GetInstance()->GetCurrentJsPath();
492 if (jsPath == nullptr) {
493 return nullptr;
494 }
495 const char * const ret = strrchr(jsPath, RESOURCE_SEPARATOR);
496 if (ret == nullptr) {
497 return nullptr;
498 }
499 size_t jsPathLen = strlen(jsPath);
500 if (jsPathLen >= PATH_LENGTH_MAX) {
501 return nullptr;
502 }
503 int len = jsPathLen - strlen(ret);
504 if (len <= 0) {
505 return nullptr;
506 }
507 char *dirPath = static_cast<char *>(ace_malloc(len + 1));
508 if (dirPath == nullptr) {
509 HILOG_ERROR(HILOG_MODULE_ACE, "malloc dirPath memory heap failed.");
510 return nullptr;
511 }
512 if (memcpy_s(dirPath, len, jsPath, len) != 0) {
513 ace_free(dirPath);
514 dirPath = nullptr;
515 return nullptr;
516 }
517 dirPath[len] = '\0';
518 // first splice resFileName with directory path
519 char *filePath = RelocateFilePath(dirPath, SRC_SUB_FOLDER_NAME, resFileName);
520 ACE_FREE(dirPath);
521 // second splice root path with res file path
522 char *realPath = nullptr;
523 if (filePath != nullptr) {
524 realPath = RelocateFilePath(appRootPath, SRC_SUB_FOLDER_NAME, filePath);
525 ACE_FREE(filePath);
526 }
527 return realPath;
528 }
529
530 // relocate file name to appRootPath/common/fileName
531 // e.x. /system/app/73709738-2d9d-4947-ac63-9858dcae7ccb/common/right.png
RelocateResourceFilePath(const char * const appRootPath,const char * const resFileName)532 char *RelocateResourceFilePath(const char * const appRootPath, const char * const resFileName)
533 {
534 if (PathIsRelative(resFileName)) {
535 // deal with relative path
536 return RelocateFilePathRelative(appRootPath, resFileName);
537 }
538
539 // deal with absolute path
540 return RelocateFilePath(appRootPath, SRC_SUB_FOLDER_NAME, resFileName);
541 }
542
543 // relocate file name to appRootPath/src/fileName
544 // e.x. /system/app/73709738-2d9d-4947-ac63-9858dcae7ccb/src/index.js
545 // NOTE: srcFileName must be the relative path to src folder
RelocateJSSourceFilePath(const char * const appRootPath,const char * const srcFileName)546 char *RelocateJSSourceFilePath(const char * const appRootPath, const char * const srcFileName)
547 {
548 return RelocateFilePath(appRootPath, SRC_SUB_FOLDER_NAME, srcFileName);
549 }
550
ReadJSFile(const char * const appPath,const char * const jsFileName)551 char *ReadJSFile(const char * const appPath, const char * const jsFileName)
552 {
553 uint32_t contentLength = 0;
554 return ReadJSFile(appPath, jsFileName, contentLength);
555 }
556
557 /**
558 * Check if the given file exists or not.
559 */
IsFileExisted(const char * const filePath)560 bool IsFileExisted(const char * const filePath)
561 {
562 if (filePath == nullptr) {
563 return false;
564 }
565 struct stat info = {0};
566 if (stat(filePath, &info) != 0) {
567 return false;
568 }
569 return true;
570 }
571
572 /**
573 * Whether file existed and 0 represents file not existed.
574 */
GetFileSize(const char * const filePath)575 int32_t GetFileSize(const char * const filePath)
576 {
577 if (filePath == nullptr) {
578 return 0;
579 }
580 struct stat info = {0};
581 const int retryCount = 5;
582 for (int i = 0; i < retryCount; i++) {
583 int32_t ret = stat(filePath, &info);
584 if (ret < 0) {
585 HILOG_ERROR(HILOG_MODULE_ACE, "file doesn't exit or it's empty, [%{public}s],\
586 errno: %{public}d, desc = %{public}s", filePath, errno, strerror(errno) );
587 } else {
588 break;
589 }
590 }
591
592 return info.st_size;
593 }
594
OpenFileInternal(const char * const orgFullPath,bool binary=false)595 static int32_t OpenFileInternal(const char * const orgFullPath, bool binary = false)
596 {
597 const char *path = orgFullPath;
598 #if (QT_SIMULATOR != 1)
599 #ifndef __LITEOS_M__ // no path canonicalization on M core
600 char fullPath[PATH_MAX + 1] = {0};
601 #if ((defined(__WIN32)) || (defined(__WIN64)))
602 if (!PathCanonicalize(fullPath, orgFullPath)) {
603 return -1;
604 }
605 #else
606 if (realpath(orgFullPath, fullPath) == nullptr) {
607 HILOG_ERROR(HILOG_MODULE_ACE, "realpath handle failed, [%{public}s]", orgFullPath);
608 return -1;
609 }
610 #endif
611 path = fullPath;
612 #endif
613 #endif // QT_SIMULATOR
614 return open(path, O_RDONLY);
615 }
616
OutputFileMaxLimitationTrace(const char * const fullPath,size_t limitation)617 static void OutputFileMaxLimitationTrace(const char * const fullPath, size_t limitation)
618 {
619 if (fullPath == nullptr || strlen(fullPath) == 0) {
620 return;
621 }
622 const char *ptr = strrchr(fullPath, PATH_SEPARATOR);
623 const size_t fileNameMaxLen = 32;
624 if (ptr == nullptr || strlen(ptr) > fileNameMaxLen) {
625 HILOG_ERROR(HILOG_MODULE_ACE, "file name too long.");
626 return;
627 }
628 const size_t traceDataLen = 128;
629 char traceData[traceDataLen] = {0};
630 const size_t oneKB = 1024;
631 size_t currentLimitation = limitation / oneKB;
632 if (sprintf_s(traceData, traceDataLen, "%s is bigger than %zu KB.\n", (ptr + 1), currentLimitation) < 0) {
633 HILOG_ERROR(HILOG_MODULE_ACE, "splice trace data failed.");
634 return;
635 }
636
637 LogOutLevel(LogLevel::LOG_LEVEL_ERR);
638 LogString(LogLevel::LOG_LEVEL_ERR, traceData);
639 }
640
641 /**
642 * Check if the file length is under MAX limitation.
643 */
CheckFileLength(const char * const fullPath,int32_t & outFileSize)644 static bool CheckFileLength(const char * const fullPath, int32_t &outFileSize)
645 {
646 outFileSize = 0;
647 int32_t fileSize = GetFileSize(fullPath);
648 if (fileSize <= 0) {
649 HILOG_ERROR(HILOG_MODULE_ACE, "open file[%{public}s] failed for reading.", fullPath);
650 return false;
651 }
652 if (fileSize > static_cast<int32_t>(FILE_CONTENT_LENGTH_MAX)) {
653 OutputFileMaxLimitationTrace(fullPath, FILE_CONTENT_LENGTH_MAX);
654 ACE_ERROR_CODE_PRINT(EXCE_ACE_ROUTER_REPLACE_FAILED, EXCE_ACE_PAGE_FILE_TOO_HUGE);
655 return false;
656 }
657 outFileSize = fileSize;
658 return true;
659 }
660
661 /**
662 * Read file content from one give full file path.
663 * Return value must be freed by caller.
664 */
ReadFile(const char * const fullPath,uint32_t & fileSize,const bool binary)665 char *ReadFile(const char * const fullPath, uint32_t &fileSize, const bool binary)
666 {
667 UNUSED(binary);
668 char *scriptBuffer = nullptr;
669 int32_t fd = -1;
670 bool success = false;
671
672 do {
673 int32_t scriptLength = 0;
674 if (!CheckFileLength(fullPath, scriptLength)) {
675 break;
676 }
677
678 fileSize = 0;
679 fd = OpenFileInternal(fullPath, O_RDONLY);
680 if (fd < 0) {
681 HILOG_ERROR(HILOG_MODULE_ACE, "open file[fd: %{public}d] failed for reading", fd);
682 HILOG_ERROR(HILOG_MODULE_ACE, "open file[path: %{public}s] failed for reading", fullPath);
683 break;
684 }
685 scriptBuffer = static_cast<char *>(ace_malloc(scriptLength + 1));
686 if (scriptBuffer == nullptr) {
687 HILOG_ERROR(HILOG_MODULE_ACE, "malloc buffer for file content failed, file length[%{public}d]",
688 scriptLength);
689 break;
690 }
691 if (EOK != memset_s(scriptBuffer, (scriptLength + 1), 0, (scriptLength + 1))) {
692 break;
693 }
694 int32_t count = read(fd, scriptBuffer, scriptLength);
695 if ((count <= 0) || (count > scriptLength)) {
696 HILOG_ERROR(HILOG_MODULE_ACE, "read fail, count(%{public}d), length(%{public}u), path(%{public}s)", count,
697 scriptLength, fullPath);
698 break;
699 }
700 scriptBuffer[count] = '\0';
701 fileSize = count;
702 success = true;
703 } while (0);
704
705 if (fd >= 0) {
706 close(fd);
707 }
708 if (!success) {
709 // failed, free buffer if it's already malloced out
710 ACE_FREE(scriptBuffer);
711 return nullptr;
712 }
713 return scriptBuffer;
714 }
715
716 /*
717 * give app path, such as /system/app/uuid/, read script string from /system/app/uuid/src/index.js,
718 * return value must be freed by caller.
719 */
ReadJSFile(const char * const appPath,const char * const jsFileName,uint32_t & fileSize)720 char *ReadJSFile(const char * const appPath, const char * const jsFileName, uint32_t &fileSize)
721 {
722 fileSize = 0;
723 // RelocateFilePath() will check the input parameters
724 char *fullPath = RelocateJSSourceFilePath(appPath, jsFileName);
725 if (fullPath == nullptr) {
726 HILOG_ERROR(HILOG_MODULE_ACE, "error index.js file path after locate");
727 return nullptr;
728 }
729
730 if (strlen(fullPath) == 0) {
731 HILOG_ERROR(HILOG_MODULE_ACE, "empty index.js file path after locate");
732 ace_free(fullPath);
733 fullPath = nullptr;
734 return nullptr;
735 }
736
737 char *fileBuffer = ReadFile(fullPath, fileSize, JsAppEnvironment::GetInstance()->IsSnapshotMode());
738 if (fileBuffer == nullptr) {
739 HILOG_ERROR(HILOG_MODULE_ACE, "Failed to read JS file from path: %{public}s", fullPath);
740 }
741 ace_free(fullPath);
742 fullPath = nullptr;
743 return fileBuffer;
744 }
745
CalculatePathPosFromUri(const char * const url,const size_t length,size_t * start,size_t * pathLength)746 static void CalculatePathPosFromUri(const char * const url, const size_t length, size_t *start, size_t *pathLength)
747 {
748 const uint8_t minLength = 4;
749 if ((url == nullptr) || (length <= minLength)) {
750 return;
751 }
752
753 if (strstr(url, "url") != url) {
754 // just the path itself
755 *start = 0;
756 *pathLength = length;
757 return;
758 }
759
760 // consider this is the url pattern
761 const uint8_t index = 3;
762 const char *pathP = strstr((url + index), "(");
763 if (pathP == nullptr) {
764 return;
765 }
766 *start = (pathP - url) + 1;
767 if (*start >= (length - 1)) {
768 return; // '(' is at the last, not meet the pattern
769 }
770
771 // path end url(common)
772 const char *pathPE = strstr((pathP + 1), ")");
773 if (pathPE == nullptr) {
774 return;
775 }
776 *pathLength = pathPE - (pathP + 1);
777 }
778
779 /**
780 * @brief give out the path string from an url pattern, "url(common/logo.png)".
781 *
782 * @param url the given url
783 *
784 * @return the url itself, "common/logo.png"
785 */
CreatePathStrFromUrl(const char * const url)786 char *CreatePathStrFromUrl(const char * const url)
787 {
788 if (url == nullptr) {
789 return nullptr;
790 }
791 size_t length = strlen(url);
792 if (length >= PATH_LENGTH_MAX) {
793 return nullptr;
794 }
795 size_t start = 0;
796 size_t pathLength = 0;
797 CalculatePathPosFromUri(url, length, &start, &pathLength);
798 if ((pathLength == 0) || (pathLength > (length - start))) {
799 return nullptr;
800 }
801 char *filePath = static_cast<char *>(ace_malloc(pathLength + 1));
802 if (filePath == nullptr) {
803 HILOG_ERROR(HILOG_MODULE_ACE, "malloc buffer for file path calculating from url, file length[%{public}d]",
804 pathLength);
805 return nullptr;
806 }
807 if (memcpy_s(filePath, pathLength, (url + start), pathLength) != 0) {
808 HILOG_ERROR(HILOG_MODULE_ACE, "append path error when calculating from url");
809 ace_free(filePath);
810 filePath = nullptr;
811 return nullptr;
812 }
813 filePath[pathLength] = '\0';
814 return filePath;
815 }
816
ReleaseJerryValue(jerry_value_t value,...)817 void ReleaseJerryValue(jerry_value_t value, ...)
818 {
819 va_list args;
820 va_start(args, value);
821
822 jerry_value_t member = value;
823 do {
824 jerry_release_value(member);
825 member = va_arg(args, jerry_value_t);
826 } while (member != (jerry_value_t)VA_ARG_END_FLAG);
827
828 va_end(args);
829 }
830
InsertWatcherCommon(Watcher * & head,const jerry_value_t watcher)831 void InsertWatcherCommon(Watcher *&head, const jerry_value_t watcher)
832 {
833 if (IS_UNDEFINED(watcher)) {
834 HILOG_ERROR(HILOG_MODULE_ACE, "watcher is undefined when inserting a watcher.");
835 return;
836 }
837 Watcher *node = new Watcher();
838 if (node == nullptr) {
839 jerry_value_t unsubscribe = jerryx_get_property_str(watcher, "unsubscribe");
840 ReleaseJerryValue(CallJSFunction(unsubscribe, watcher, nullptr, 0), unsubscribe, watcher, VA_ARG_END_FLAG);
841 HILOG_ERROR(HILOG_MODULE_ACE, "malloc memory watcher failed.");
842 return;
843 }
844 node->watcher = watcher;
845 if (head == nullptr) {
846 head = node;
847 } else {
848 node->next = head;
849 head = node;
850 }
851 }
852
ClearWatchersCommon(Watcher * & head)853 void ClearWatchersCommon(Watcher *&head)
854 {
855 Watcher *node = head;
856 while (node) {
857 head = node->next;
858 // avoid allocating any JS objects when JS runtime broken
859 if (!(FatalHandler::GetInstance().IsJSRuntimeFatal())) {
860 // call js watcher.unsubscribe to release watcher
861 jerry_value_t watcher = node->watcher;
862 jerry_value_t unsubscribe = jerryx_get_property_str(watcher, "unsubscribe");
863 ReleaseJerryValue(CallJSFunction(unsubscribe, watcher, nullptr, 0), unsubscribe, watcher, VA_ARG_END_FLAG);
864 }
865 delete node;
866 node = head;
867 }
868 head = nullptr;
869 }
870
871 /**
872 * @brief Call jerry_has_property and return the result
873 *
874 * @param container the target JS object to check
875 * @param property the property string value
876 */
JerryHasProperty(const jerry_value_t container,const jerry_value_t property)877 bool JerryHasProperty(const jerry_value_t container, const jerry_value_t property)
878 {
879 if (IS_UNDEFINED(container) || IS_UNDEFINED(property)) {
880 return false;
881 }
882
883 jerry_value_t result = jerry_has_property(container, property);
884 bool res = jerry_value_to_boolean(result);
885 jerry_release_value(result);
886 return res;
887 }
888
889 /**
890 * @brief Call jerry_has_own_property and return the result
891 *
892 * @param container the target JS object to check
893 * @param property the property string value
894 */
HasOwnProperty(const jerry_value_t container,const jerry_value_t property)895 bool HasOwnProperty(const jerry_value_t container, const jerry_value_t property)
896 {
897 if (IS_UNDEFINED(container) || IS_UNDEFINED(property)) {
898 return false;
899 }
900
901 jerry_value_t result = jerry_has_own_property(container, property);
902 bool res = jerry_value_to_boolean(result);
903 jerry_release_value(result);
904 return res;
905 }
906
907 // this callback is triggered by two conditions:
908 // 1. the array's length changed.(ie. array.push(value))
909 // 2. the array replaced by another new array but length is the same.(ie. array1 = array2)
ListForWatcherCallbackFunc(const jerry_value_t func,const jerry_value_t context,const jerry_value_t * args,const jerry_length_t argsLength)910 jerry_value_t ListForWatcherCallbackFunc(const jerry_value_t func,
911 const jerry_value_t context,
912 const jerry_value_t *args,
913 const jerry_length_t argsLength)
914 {
915 if (argsLength != ARG_LENGTH_WATCHER_CALLBACK) {
916 return UNDEFINED;
917 }
918 // args[0]==>new changed data watchered
919 // args[1]==>original data watchered, the data here had been updated
920 // args[2]==>new changed children of this component
921 START_TRACING(FOR_WATCHER_CALLBACK_FUNC);
922 const int argsNum = 2;
923 jerry_value_t options = args[argsNum];
924 jerry_value_t nativeElement = jerryx_get_property_str(options, ARG_WATCH_EL);
925 Component *component = ComponentUtils::GetComponentFromBindingObject(nativeElement);
926 if (component) {
927 bool updateResult = component->UpdateForView();
928 if (updateResult) {
929 component->Invalidate();
930 }
931 } else {
932 HILOG_ERROR(HILOG_MODULE_ACE, "No component binds element.");
933 }
934 STOP_TRACING();
935 jerry_release_value(nativeElement);
936 return UNDEFINED;
937 }
StartWith(const char * sequence,const char * prefix)938 bool StartWith(const char *sequence, const char *prefix)
939 {
940 while (*prefix) {
941 if (*prefix++ != *sequence++) {
942 return false;
943 }
944 }
945 return true;
946 }
947
IsHexColor(const char * const target)948 bool IsHexColor(const char * const target)
949 {
950 return StartWith(target, PREFIX_HEX_COLOR);
951 }
IsRgbColor(const char * const target)952 bool IsRgbColor(const char * const target)
953 {
954 return StartWith(target, PREFIX_RGB_COLOR);
955 }
IsRgbaColor(const char * const target)956 bool IsRgbaColor(const char * const target)
957 {
958 return StartWith(target, PREFIX_RGBA_COLOR);
959 }
960
961 constexpr uint8_t LENGTH_RGB = 3;
962 constexpr uint8_t LENGTH_RRGGBB = 6;
963 constexpr uint8_t LENGTH_ARGB = 8;
964 constexpr uint8_t IDX_RGB_RED = 1;
965 constexpr uint8_t IDX_RGB_GREEN = 2;
966 constexpr uint8_t IDX_RGB_BLUE = 3;
967 constexpr uint8_t LENGTH_ALPHA = 2;
968 constexpr uint8_t IDX_ARGB_ALPHA_BEGIN = 1;
969 constexpr uint8_t IDX_ARGB_ALPHA_END = 2;
970 constexpr uint8_t IDX_ARGB_COLOR_BEGIN = 3;
971 constexpr uint8_t BITS_PER_BYTE = 8;
972
ParseHexColor(const char * const source,uint32_t & color,uint8_t & alpha)973 bool ParseHexColor(const char * const source, uint32_t &color, uint8_t &alpha)
974 {
975 if ((source == nullptr) || (strlen(source) <= 1)) {
976 return false;
977 }
978 uint8_t length = strlen(source + 1);
979 // Parse HEX color like #ABC
980 if (length == LENGTH_RGB) {
981 // #ABC equals to #AABBCC
982 char buffer[LENGTH_RRGGBB + 1] = {source[IDX_RGB_RED],
983 source[IDX_RGB_RED],
984 source[IDX_RGB_GREEN],
985 source[IDX_RGB_GREEN],
986 source[IDX_RGB_BLUE],
987 source[IDX_RGB_BLUE],
988 0};
989 color = strtol(buffer, nullptr, HEX);
990 alpha = ALPHA_MAX;
991 return true;
992 }
993
994 // Parse HEX color like #AABBCC
995 if (length == LENGTH_RRGGBB) {
996 color = strtol(source + 1, nullptr, HEX);
997 alpha = ALPHA_MAX;
998 return true;
999 }
1000
1001 // Parse HEX color like #FFAABBCC
1002 if (length == LENGTH_ARGB) {
1003 char buffer[LENGTH_ALPHA + 1] = {source[IDX_ARGB_ALPHA_BEGIN], source[IDX_ARGB_ALPHA_END], 0};
1004 alpha = strtol(buffer, nullptr, HEX);
1005 color = strtol(source + IDX_ARGB_COLOR_BEGIN, nullptr, HEX);
1006 return true;
1007 }
1008
1009 return false;
1010 }
1011
ParseRgbaColor(const char * const source,uint32_t & color,uint8_t & alpha)1012 bool ParseRgbaColor(const char * const source, uint32_t &color, uint8_t &alpha)
1013 {
1014 uint8_t idxOpenBrace = 0;
1015 uint8_t idxCloseBrace = 0;
1016 if (source == nullptr) {
1017 return false;
1018 }
1019 size_t size = strlen(source);
1020 if (size >= UINT8_MAX) {
1021 return false;
1022 }
1023 for (uint8_t idx = 0; idx < size; ++idx) {
1024 if (source[idx] == BRACE_OPEN) {
1025 idxOpenBrace = idx;
1026 continue;
1027 }
1028 if (source[idx] == BRACE_CLOSE) {
1029 idxCloseBrace = idx;
1030 continue;
1031 }
1032 }
1033
1034 if (idxOpenBrace == 0 || idxCloseBrace == 0 || idxCloseBrace <= idxOpenBrace) {
1035 return false;
1036 }
1037
1038 uint8_t bufSize = idxCloseBrace - idxOpenBrace - 1;
1039 char *buffer = static_cast<char *>(ace_malloc(sizeof(char) * (bufSize + 1)));
1040 if (buffer == nullptr) {
1041 return false;
1042 }
1043 if (memcpy_s(buffer, bufSize, source + idxOpenBrace + 1, bufSize) != 0) {
1044 ace_free(buffer);
1045 buffer = nullptr;
1046 return false;
1047 }
1048 buffer[bufSize] = 0;
1049 char *token;
1050 // BITS_PER_BYTE is unsigned, result always equals to 16, can't overflow
1051 int8_t move = BITS_PER_BYTE << 1;
1052 char *next = nullptr;
1053 token = strtok_s(buffer, DELIMITER, &next);
1054 color = 0;
1055 while ((token != nullptr) && (move >= 0)) {
1056 long value = strtol(token, nullptr, DEC);
1057 if ((value < 0) || (value > UINT8_MAX)) {
1058 ace_free(buffer);
1059 buffer = nullptr;
1060 color = 0;
1061 return false;
1062 }
1063 color += ((uint8_t)value << (uint8_t)move);
1064 token = strtok_s(nullptr, DELIMITER, &next);
1065 move -= BITS_PER_BYTE;
1066 }
1067 if (token != nullptr) {
1068 alpha = (uint8_t)(strtod(token, nullptr) * ALPHA_MAX);
1069 } else {
1070 alpha = ALPHA_MAX;
1071 }
1072 ace_free(buffer);
1073 buffer = nullptr;
1074 return true;
1075 }
1076
ParseColor(const char * const source,uint32_t & color,uint8_t & alpha)1077 bool ParseColor(const char * const source, uint32_t &color, uint8_t &alpha)
1078 {
1079 if (source == nullptr) {
1080 return false;
1081 }
1082
1083 if (IsHexColor(source)) {
1084 return ParseHexColor(source, color, alpha);
1085 }
1086
1087 if (IsRgbaColor(source) || IsRgbColor(source)) {
1088 return ParseRgbaColor(source, color, alpha);
1089 }
1090
1091 return false;
1092 }
1093
1094 #if JS_PAGE_SPECIFIC
1095 struct JSPageSpecific jsPageSpecific;
1096 #endif // JS_PAGE_SPECIFIC
1097
GetHorizontalResolution()1098 uint16_t GetHorizontalResolution()
1099 {
1100 // SCREENSIZE_SPECIFIED is temporarily set, when ui and graphic unifid, this can be removed
1101 #if ((defined __LITEOS__) || (defined __linux__) || (SCREENSIZE_SPECIFIED == 1))
1102 return Screen::GetInstance().GetWidth();
1103 #else
1104 constexpr uint16_t resConst = 454;
1105 uint16_t horizontalResolution = resConst;
1106 uint16_t verticalResolution = resConst;
1107 ProductAdapter::GetScreenSize(horizontalResolution, verticalResolution);
1108 return horizontalResolution;
1109 #endif // OHOS_ACELITE_PRODUCT_WATCH
1110 }
1111
GetVerticalResolution()1112 uint16_t GetVerticalResolution()
1113 {
1114 #if ((defined __LITEOS__) || (defined __linux__) || (SCREENSIZE_SPECIFIED == 1))
1115 return Screen::GetInstance().GetHeight();
1116 #else
1117 constexpr uint16_t resConst = 454;
1118 uint16_t horizontalResolution = resConst;
1119 uint16_t verticalResolution = resConst;
1120 ProductAdapter::GetScreenSize(horizontalResolution, verticalResolution);
1121 return verticalResolution;
1122 #endif // OHOS_ACELITE_PRODUCT_WATCH
1123 }
1124
GetRootAbilitySlice()1125 JSValue GetRootAbilitySlice()
1126 {
1127 return JSGlobal::Get(ATTR_ROOT);
1128 }
1129
CallWithRootAbilitySlice(JSValue func,JSValue args[],JSSize size)1130 JSValue CallWithRootAbilitySlice(JSValue func, JSValue args[], JSSize size)
1131 {
1132 JSValue abilitySlice = GetRootAbilitySlice();
1133 JSValue result = JSFunction::Call(func, abilitySlice, args, size);
1134 JSRelease(abilitySlice);
1135 return result;
1136 }
1137
CallWithRootAbilitySlice(JSValue func)1138 JSValue CallWithRootAbilitySlice(JSValue func)
1139 {
1140 return CallWithRootAbilitySlice(func, nullptr, 0);
1141 }
1142
CreateWatcher(JSValue getter,JSHandler handler,JSValue options)1143 JSValue CreateWatcher(JSValue getter, JSHandler handler, JSValue options)
1144 {
1145 JSValue abilitySlice = GetRootAbilitySlice();
1146 JSValue callback = JSFunction::Create(handler);
1147 JSValue args[ARG_LENGTH_WATCHER] = {getter, callback, options};
1148 JSValue watcher = JSObject::Call(abilitySlice, ATTR_WATCH, args, ARG_LENGTH_WATCHER);
1149 JSRelease(callback);
1150 JSRelease(abilitySlice);
1151 return watcher;
1152 }
1153
ExpandImagePathMem(char * & imagePath,const int16_t dotPos,const int16_t suffixLen,const int16_t imagePathLen)1154 void ExpandImagePathMem(char *&imagePath, const int16_t dotPos, const int16_t suffixLen, const int16_t imagePathLen)
1155 {
1156 if (dotPos < 0 || suffixLen < 0 || imagePathLen < 0) {
1157 return;
1158 }
1159 int16_t len = dotPos + 1 + suffixLen + 1;
1160 if (len <= 0) {
1161 return;
1162 }
1163 char *newImagePath = static_cast<char *>(ace_malloc(len));
1164 if (newImagePath == nullptr) {
1165 HILOG_ERROR(HILOG_MODULE_ACE, "malloc buffer for path failed, needed length[%{public}u]",
1166 (dotPos + 1 + suffixLen + 1));
1167 ACE_FREE(imagePath);
1168 return;
1169 }
1170
1171 errno_t err = strcpy_s(newImagePath, len, imagePath);
1172 if (err != 0) {
1173 HILOG_ERROR(HILOG_MODULE_ACE, "use strcpy_s secure function [errro:%{public}d]", err);
1174 ace_free(newImagePath);
1175 newImagePath = nullptr;
1176 ACE_FREE(imagePath);
1177 return;
1178 }
1179
1180 ace_free(imagePath);
1181 imagePath = newImagePath;
1182 }
1183
ParseImageSrc(jerry_value_t source)1184 const char *ParseImageSrc(jerry_value_t source)
1185 {
1186 uint16_t length = 0;
1187 char *rawSrc = MallocStringOf(source, &length);
1188 if (rawSrc == nullptr) {
1189 HILOG_ERROR(HILOG_MODULE_ACE, "Failed to parse image src cause by empty source.");
1190 return nullptr;
1191 }
1192 if (length == 0) {
1193 HILOG_ERROR(HILOG_MODULE_ACE, "Failed to parse image src cause by empty source.");
1194 ace_free(rawSrc);
1195 rawSrc = nullptr;
1196 return nullptr;
1197 }
1198
1199 if ((strstr(rawSrc, PATH_RELATIVE_WHOLE) != nullptr) || (strstr(rawSrc, PATH_RELATIVE_PART) != nullptr)) {
1200 HILOG_ERROR(HILOG_MODULE_ACE, "Relative path is not allowed in image src.");
1201 ace_free(rawSrc);
1202 rawSrc = nullptr;
1203 return nullptr;
1204 }
1205
1206 char *imageSrc = JsAppContext::GetInstance()->GetResourcePath(rawSrc);
1207 ace_free(rawSrc);
1208 rawSrc = nullptr;
1209 return imageSrc;
1210 }
1211
CopyFontFamily(char * & destination,const char * const fontFamily,uint32_t fontFamilyNameLen)1212 bool CopyFontFamily(char *&destination, const char * const fontFamily, uint32_t fontFamilyNameLen)
1213 {
1214 // unused parameter for now, added for clean up warning
1215 UNUSED(fontFamilyNameLen);
1216 ACE_FREE(destination);
1217 if (fontFamily == nullptr) {
1218 return true; // the destination is already nullptr
1219 }
1220 size_t fontFamilyLen = strlen(fontFamily);
1221 if (fontFamilyLen >= UINT8_MAX) {
1222 HILOG_ERROR(HILOG_MODULE_ACE, "the fontFamily is too long");
1223 return false;
1224 }
1225 size_t len = fontFamilyLen + 1;
1226 destination = static_cast<char *>(ace_malloc(len));
1227 if (destination == nullptr) {
1228 HILOG_ERROR(HILOG_MODULE_ACE, "malloc string failed");
1229 return false;
1230 }
1231 if (strcpy_s(destination, len, fontFamily) != 0) {
1232 HILOG_ERROR(HILOG_MODULE_ACE, "copy fontFamily failed");
1233 ace_free(destination);
1234 destination = nullptr;
1235 return false;
1236 }
1237 return true;
1238 }
1239
ParseKeyIdFromJSString(const jerry_value_t str)1240 uint16_t ParseKeyIdFromJSString(const jerry_value_t str)
1241 {
1242 // calculate key ID
1243 uint16_t keyId = K_UNKNOWN;
1244 uint16_t strLength = 0;
1245 char *keyStr = MallocStringOf(str, &strLength);
1246 if (keyStr != nullptr) {
1247 if (strLength != 0) {
1248 keyId = KeyParser::ParseKeyId(keyStr, strLength);
1249 }
1250 ace_free(keyStr);
1251 keyStr = nullptr;
1252 }
1253 return keyId;
1254 }
ParseLineCap(const char * lineCap)1255 int8_t ParseLineCap(const char *lineCap)
1256 {
1257 if (lineCap == nullptr) {
1258 return -1;
1259 }
1260 if (strcasecmp(lineCap, LINECAP_BUTT) == 0) {
1261 return BUTT_VALUE;
1262 }
1263 if (strcasecmp(lineCap, LINECAP_SQUARE) == 0) {
1264 return SQUARE_VALUE;
1265 }
1266 if (strcasecmp(lineCap, LINECAP_ROUND) == 0) {
1267 return ROUND_VALUE;
1268 }
1269 return -1;
1270 }
1271
ParseLineJoin(const char * lineJoin)1272 int8_t ParseLineJoin(const char *lineJoin)
1273 {
1274 if (lineJoin == nullptr) {
1275 return -1;
1276 }
1277 if (strcasecmp(lineJoin, LINEJOIN_MITER) == 0) {
1278 return LINEJOIN_MITER_VALUE;
1279 }
1280 if (strcasecmp(lineJoin, LINEJOIN_ROUND) == 0) {
1281 return LINEJOIN_ROUND_VALUE;
1282 }
1283 if (strcasecmp(lineJoin, LINEJOIN_BEVEL) == 0) {
1284 return LINEJOIN_BEVEL_VALUE;
1285 }
1286 return -1;
1287 }
1288 } // namespace ACELite
1289 } // namespace OHOS
1290