• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     if (filePath != nullptr) {
521         ace_free(dirPath);
522         filePath = nullptr;
523     }
524     // second splice root path with res file path
525     char *realPath = nullptr;
526     if (filePath != nullptr) {
527         realPath = RelocateFilePath(appRootPath, SRC_SUB_FOLDER_NAME, filePath);
528         ace_free(filePath);
529     }
530     return realPath;
531 }
532 
533 // relocate file name to appRootPath/common/fileName
534 // e.x. /system/app/73709738-2d9d-4947-ac63-9858dcae7ccb/common/right.png
RelocateResourceFilePath(const char * const appRootPath,const char * const resFileName)535 char *RelocateResourceFilePath(const char * const appRootPath, const char * const resFileName)
536 {
537     if (PathIsRelative(resFileName)) {
538         // deal with relative path
539         return RelocateFilePathRelative(appRootPath, resFileName);
540     }
541 
542     // deal with absolute path
543     return RelocateFilePath(appRootPath, SRC_SUB_FOLDER_NAME, resFileName);
544 }
545 
546 // relocate file name to appRootPath/src/fileName
547 // e.x. /system/app/73709738-2d9d-4947-ac63-9858dcae7ccb/src/index.js
548 // NOTE: srcFileName must be the relative path to src folder
RelocateJSSourceFilePath(const char * const appRootPath,const char * const srcFileName)549 char *RelocateJSSourceFilePath(const char * const appRootPath, const char * const srcFileName)
550 {
551     return RelocateFilePath(appRootPath, SRC_SUB_FOLDER_NAME, srcFileName);
552 }
553 
ReadJSFile(const char * const appPath,const char * const jsFileName)554 char *ReadJSFile(const char * const appPath, const char * const jsFileName)
555 {
556     uint32_t contentLength = 0;
557     return ReadJSFile(appPath, jsFileName, contentLength);
558 }
559 
560 /**
561  * Check if the given file exists or not.
562  */
IsFileExisted(const char * const filePath)563 bool IsFileExisted(const char * const filePath)
564 {
565     if (filePath == nullptr) {
566         return false;
567     }
568     struct stat info = {0};
569     if (stat(filePath, &info) != 0) {
570         return false;
571     }
572     return true;
573 }
574 
575 /**
576  * Whether file existed and 0 represents file not existed.
577  */
GetFileSize(const char * const filePath)578 int32_t GetFileSize(const char * const filePath)
579 {
580     if (filePath == nullptr) {
581         return 0;
582     }
583     struct stat info = {0};
584     const int retryCount = 5;
585     for (int i = 0; i < retryCount; i++) {
586         int32_t ret = stat(filePath, &info);
587         if (ret < 0) {
588             HILOG_ERROR(HILOG_MODULE_ACE, "file doesn't exit or it's empty, [%{public}s],\
589                 errno: %{public}d, desc = %{public}s", filePath, errno, strerror(errno) );
590         } else {
591             break;
592         }
593     }
594 
595     return info.st_size;
596 }
597 
OpenFileInternal(const char * const orgFullPath,bool binary=false)598 static int32_t OpenFileInternal(const char * const orgFullPath, bool binary = false)
599 {
600     const char *path = orgFullPath;
601 #if (QT_SIMULATOR != 1)
602 #ifndef __LITEOS_M__ // no path canonicalization on M core
603     char fullPath[PATH_MAX + 1] = {0};
604 #if ((defined(__WIN32)) || (defined(__WIN64)))
605     if (!PathCanonicalize(fullPath, orgFullPath)) {
606         return -1;
607     }
608 #else
609     if (realpath(orgFullPath, fullPath) == nullptr) {
610         HILOG_ERROR(HILOG_MODULE_ACE, "realpath handle failed, [%{public}s]", orgFullPath);
611         return -1;
612     }
613 #endif
614     path = fullPath;
615 #endif
616 #endif // QT_SIMULATOR
617     return open(path, O_RDONLY);
618 }
619 
OutputFileMaxLimitationTrace(const char * const fullPath,size_t limitation)620 static void OutputFileMaxLimitationTrace(const char * const fullPath, size_t limitation)
621 {
622     if (fullPath == nullptr || strlen(fullPath) == 0) {
623         return;
624     }
625     const char *ptr = strrchr(fullPath, PATH_SEPARATOR);
626     const size_t fileNameMaxLen = 32;
627     if (ptr == nullptr || strlen(ptr) > fileNameMaxLen) {
628         HILOG_ERROR(HILOG_MODULE_ACE, "file name too long.");
629         return;
630     }
631     const size_t traceDataLen = 128;
632     char traceData[traceDataLen] = {0};
633     const size_t oneKB = 1024;
634     size_t currentLimitation = limitation / oneKB;
635     if (sprintf_s(traceData, traceDataLen, "%s is bigger than %zu KB.\n", (ptr + 1), currentLimitation) < 0) {
636         HILOG_ERROR(HILOG_MODULE_ACE, "splice trace data failed.");
637         return;
638     }
639 
640     LogOutLevel(LogLevel::LOG_LEVEL_ERR);
641     LogString(LogLevel::LOG_LEVEL_ERR, traceData);
642 }
643 
644 /**
645  * Check if the file length is under MAX limitation.
646  */
CheckFileLength(const char * const fullPath,int32_t & outFileSize)647 static bool CheckFileLength(const char * const fullPath, int32_t &outFileSize)
648 {
649     outFileSize = 0;
650     int32_t fileSize = GetFileSize(fullPath);
651     if (fileSize <= 0) {
652         HILOG_ERROR(HILOG_MODULE_ACE, "open file[%{public}s] failed for reading.", fullPath);
653         return false;
654     }
655     if (fileSize > FILE_CONTENT_LENGTH_MAX) {
656         OutputFileMaxLimitationTrace(fullPath, FILE_CONTENT_LENGTH_MAX);
657         ACE_ERROR_CODE_PRINT(EXCE_ACE_ROUTER_REPLACE_FAILED, EXCE_ACE_PAGE_FILE_TOO_HUGE);
658         return false;
659     }
660     outFileSize = fileSize;
661     return true;
662 }
663 
664 /**
665  * Read file content from one give full file path.
666  * Return value must be freed by caller.
667  */
ReadFile(const char * const fullPath,uint32_t & fileSize,const bool binary)668 char *ReadFile(const char * const fullPath, uint32_t &fileSize, const bool binary)
669 {
670     UNUSED(binary);
671     char *scriptBuffer = nullptr;
672     int32_t fd = -1;
673     bool success = false;
674 
675     do {
676         int32_t scriptLength = 0;
677         if (!CheckFileLength(fullPath, scriptLength)) {
678             break;
679         }
680 
681         fileSize = 0;
682         fd = OpenFileInternal(fullPath, O_RDONLY);
683         if (fd < 0) {
684             HILOG_ERROR(HILOG_MODULE_ACE, "open file[fd: %{public}d] failed for reading", fd);
685             HILOG_ERROR(HILOG_MODULE_ACE, "open file[path: %{public}s] failed for reading", fullPath);
686             break;
687         }
688         scriptBuffer = static_cast<char *>(ace_malloc(scriptLength + 1));
689         if (scriptBuffer == nullptr) {
690             HILOG_ERROR(HILOG_MODULE_ACE, "malloc buffer for file content failed, file length[%{public}d]",
691                         scriptLength);
692             break;
693         }
694         if (EOK != memset_s(scriptBuffer, (scriptLength + 1), 0, (scriptLength + 1))) {
695             break;
696         }
697         int32_t count = read(fd, scriptBuffer, scriptLength);
698         if ((count <= 0) || (count > scriptLength)) {
699             HILOG_ERROR(HILOG_MODULE_ACE, "read fail, count(%{public}d), length(%{public}u), path(%{public}s)", count,
700                         scriptLength, fullPath);
701             break;
702         }
703         scriptBuffer[count] = '\0';
704         fileSize = count;
705         success = true;
706     } while (0);
707 
708     if (fd >= 0) {
709         close(fd);
710     }
711     if (!success) {
712         // failed, free buffer if it's already malloced out
713         ACE_FREE(scriptBuffer);
714         return nullptr;
715     }
716     return scriptBuffer;
717 }
718 
719 /*
720  * give app path, such as /system/app/uuid/, read script string from /system/app/uuid/src/index.js,
721  * return value must be freed by caller.
722  */
ReadJSFile(const char * const appPath,const char * const jsFileName,uint32_t & fileSize)723 char *ReadJSFile(const char * const appPath, const char * const jsFileName, uint32_t &fileSize)
724 {
725     fileSize = 0;
726     // RelocateFilePath() will check the input parameters
727     char *fullPath = RelocateJSSourceFilePath(appPath, jsFileName);
728     if (fullPath == nullptr) {
729         HILOG_ERROR(HILOG_MODULE_ACE, "error index.js file path after locate");
730         return nullptr;
731     }
732 
733     if (strlen(fullPath) == 0) {
734         HILOG_ERROR(HILOG_MODULE_ACE, "empty index.js file path after locate");
735         ace_free(fullPath);
736         fullPath = nullptr;
737         return nullptr;
738     }
739 
740     char *fileBuffer = ReadFile(fullPath, fileSize, JsAppEnvironment::GetInstance()->IsSnapshotMode());
741     if (fileBuffer == nullptr) {
742         HILOG_ERROR(HILOG_MODULE_ACE, "Failed to read JS file from path: %{public}s", fullPath);
743     }
744     ace_free(fullPath);
745     fullPath = nullptr;
746     return fileBuffer;
747 }
748 
CalculatePathPosFromUri(const char * const url,const size_t length,size_t * start,size_t * pathLength)749 static void CalculatePathPosFromUri(const char * const url, const size_t length, size_t *start, size_t *pathLength)
750 {
751     const uint8_t minLength = 4;
752     if ((url == nullptr) || (length <= minLength)) {
753         return;
754     }
755 
756     if (strstr(url, "url") != url) {
757         // just the path itself
758         *start = 0;
759         *pathLength = length;
760         return;
761     }
762 
763     // consider this is the url pattern
764     const uint8_t index = 3;
765     const char *pathP = strstr((url + index), "(");
766     if (pathP == nullptr) {
767         return;
768     }
769     *start = (pathP - url) + 1;
770     if (*start >= (length - 1)) {
771         return; // '(' is at the last, not meet the pattern
772     }
773 
774     // path end url(common)
775     const char *pathPE = strstr((pathP + 1), ")");
776     if (pathPE == nullptr) {
777         return;
778     }
779     *pathLength = pathPE - (pathP + 1);
780 }
781 
782 /**
783  * @brief give out the path string from an url pattern, "url(common/logo.png)".
784  *
785  * @param url the given url
786  *
787  * @return the url itself, "common/logo.png"
788  */
CreatePathStrFromUrl(const char * const url)789 char *CreatePathStrFromUrl(const char * const url)
790 {
791     if (url == nullptr) {
792         return nullptr;
793     }
794     size_t length = strlen(url);
795     if (length >= PATH_LENGTH_MAX) {
796         return nullptr;
797     }
798     size_t start = 0;
799     size_t pathLength = 0;
800     CalculatePathPosFromUri(url, length, &start, &pathLength);
801     if ((pathLength == 0) || (pathLength > (length - start))) {
802         return nullptr;
803     }
804     char *filePath = static_cast<char *>(ace_malloc(pathLength + 1));
805     if (filePath == nullptr) {
806         HILOG_ERROR(HILOG_MODULE_ACE, "malloc buffer for file path calculating from url, file length[%{public}d]",
807                     pathLength);
808         return nullptr;
809     }
810     if (memcpy_s(filePath, pathLength, (url + start), pathLength) != 0) {
811         HILOG_ERROR(HILOG_MODULE_ACE, "append path error when calculating from url");
812         ace_free(filePath);
813         filePath = nullptr;
814         return nullptr;
815     }
816     filePath[pathLength] = '\0';
817     return filePath;
818 }
819 
ReleaseJerryValue(jerry_value_t value,...)820 void ReleaseJerryValue(jerry_value_t value, ...)
821 {
822     va_list args;
823     va_start(args, value);
824 
825     jerry_value_t member = value;
826     do {
827         jerry_release_value(member);
828         member = va_arg(args, jerry_value_t);
829     } while (member != (jerry_value_t)VA_ARG_END_FLAG);
830 
831     va_end(args);
832 }
833 
InsertWatcherCommon(Watcher * & head,const jerry_value_t watcher)834 void InsertWatcherCommon(Watcher *&head, const jerry_value_t watcher)
835 {
836     if (IS_UNDEFINED(watcher)) {
837         HILOG_ERROR(HILOG_MODULE_ACE, "watcher is undefined when inserting a watcher.");
838         return;
839     }
840     Watcher *node = new Watcher();
841     if (node == nullptr) {
842         jerry_value_t unsubscribe = jerryx_get_property_str(watcher, "unsubscribe");
843         ReleaseJerryValue(CallJSFunction(unsubscribe, watcher, nullptr, 0), unsubscribe, watcher, VA_ARG_END_FLAG);
844         HILOG_ERROR(HILOG_MODULE_ACE, "malloc memory watcher failed.");
845         return;
846     }
847     node->watcher = watcher;
848     if (head == nullptr) {
849         head = node;
850     } else {
851         node->next = head;
852         head = node;
853     }
854 }
855 
ClearWatchersCommon(Watcher * & head)856 void ClearWatchersCommon(Watcher *&head)
857 {
858     Watcher *node = head;
859     while (node) {
860         head = node->next;
861         // avoid allocating any JS objects when JS runtime broken
862         if (!(FatalHandler::GetInstance().IsJSRuntimeFatal())) {
863             // call js watcher.unsubscribe to release watcher
864             jerry_value_t watcher = node->watcher;
865             jerry_value_t unsubscribe = jerryx_get_property_str(watcher, "unsubscribe");
866             ReleaseJerryValue(CallJSFunction(unsubscribe, watcher, nullptr, 0), unsubscribe, watcher, VA_ARG_END_FLAG);
867         }
868         delete node;
869         node = head;
870     }
871     head = nullptr;
872 }
873 
874 /**
875  * @brief Call jerry_has_property and return the result
876  *
877  * @param container the target JS object to check
878  * @param property the property string value
879  */
JerryHasProperty(const jerry_value_t container,const jerry_value_t property)880 bool JerryHasProperty(const jerry_value_t container, const jerry_value_t property)
881 {
882     if (IS_UNDEFINED(container) || IS_UNDEFINED(property)) {
883         return false;
884     }
885 
886     jerry_value_t result = jerry_has_property(container, property);
887     bool res = jerry_value_to_boolean(result);
888     jerry_release_value(result);
889     return res;
890 }
891 
892 /**
893  * @brief Call jerry_has_own_property and return the result
894  *
895  * @param container the target JS object to check
896  * @param property the property string value
897  */
HasOwnProperty(const jerry_value_t container,const jerry_value_t property)898 bool HasOwnProperty(const jerry_value_t container, const jerry_value_t property)
899 {
900     if (IS_UNDEFINED(container) || IS_UNDEFINED(property)) {
901         return false;
902     }
903 
904     jerry_value_t result = jerry_has_own_property(container, property);
905     bool res = jerry_value_to_boolean(result);
906     jerry_release_value(result);
907     return res;
908 }
909 
910 // this callback is triggered by two conditions:
911 // 1. the array's length changed.(ie. array.push(value))
912 // 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)913 jerry_value_t ListForWatcherCallbackFunc(const jerry_value_t func,
914                                          const jerry_value_t context,
915                                          const jerry_value_t *args,
916                                          const jerry_length_t argsLength)
917 {
918     if (argsLength != ARG_LENGTH_WATCHER_CALLBACK) {
919         return UNDEFINED;
920     }
921     // args[0]==>new changed data watchered
922     // args[1]==>original data watchered, the data here had been updated
923     // args[2]==>new changed children of this component
924     START_TRACING(FOR_WATCHER_CALLBACK_FUNC);
925     const int argsNum = 2;
926     jerry_value_t options = args[argsNum];
927     jerry_value_t nativeElement = jerryx_get_property_str(options, ARG_WATCH_EL);
928     Component *component = ComponentUtils::GetComponentFromBindingObject(nativeElement);
929     if (component) {
930         bool updateResult = component->UpdateForView();
931         if (updateResult) {
932             component->Invalidate();
933         }
934     } else {
935         HILOG_ERROR(HILOG_MODULE_ACE, "No component binds element.");
936     }
937     STOP_TRACING();
938     jerry_release_value(nativeElement);
939     return UNDEFINED;
940 }
StartWith(const char * sequence,const char * prefix)941 bool StartWith(const char *sequence, const char *prefix)
942 {
943     while (*prefix) {
944         if (*prefix++ != *sequence++) {
945             return false;
946         }
947     }
948     return true;
949 }
950 
IsHexColor(const char * const target)951 bool IsHexColor(const char * const target)
952 {
953     return StartWith(target, PREFIX_HEX_COLOR);
954 }
IsRgbColor(const char * const target)955 bool IsRgbColor(const char * const target)
956 {
957     return StartWith(target, PREFIX_RGB_COLOR);
958 }
IsRgbaColor(const char * const target)959 bool IsRgbaColor(const char * const target)
960 {
961     return StartWith(target, PREFIX_RGBA_COLOR);
962 }
963 
964 constexpr uint8_t LENGTH_RGB = 3;
965 constexpr uint8_t LENGTH_RRGGBB = 6;
966 constexpr uint8_t LENGTH_ARGB = 8;
967 constexpr uint8_t IDX_RGB_RED = 1;
968 constexpr uint8_t IDX_RGB_GREEN = 2;
969 constexpr uint8_t IDX_RGB_BLUE = 3;
970 constexpr uint8_t LENGTH_ALPHA = 2;
971 constexpr uint8_t IDX_ARGB_ALPHA_BEGIN = 1;
972 constexpr uint8_t IDX_ARGB_ALPHA_END = 2;
973 constexpr uint8_t IDX_ARGB_COLOR_BEGIN = 3;
974 constexpr uint8_t BITS_PER_BYTE = 8;
975 
ParseHexColor(const char * const source,uint32_t & color,uint8_t & alpha)976 bool ParseHexColor(const char * const source, uint32_t &color, uint8_t &alpha)
977 {
978     if ((source == nullptr) || (strlen(source) <= 1)) {
979         return false;
980     }
981     uint8_t length = strlen(source + 1);
982     // Parse HEX color like #ABC
983     if (length == LENGTH_RGB) {
984         // #ABC equals to #AABBCC
985         char buffer[LENGTH_RRGGBB + 1] = {source[IDX_RGB_RED],
986                                           source[IDX_RGB_RED],
987                                           source[IDX_RGB_GREEN],
988                                           source[IDX_RGB_GREEN],
989                                           source[IDX_RGB_BLUE],
990                                           source[IDX_RGB_BLUE],
991                                           0};
992         color = strtol(buffer, nullptr, HEX);
993         alpha = ALPHA_MAX;
994         return true;
995     }
996 
997     // Parse HEX color like #AABBCC
998     if (length == LENGTH_RRGGBB) {
999         color = strtol(source + 1, nullptr, HEX);
1000         alpha = ALPHA_MAX;
1001         return true;
1002     }
1003 
1004     // Parse HEX color like #FFAABBCC
1005     if (length == LENGTH_ARGB) {
1006         char buffer[LENGTH_ALPHA + 1] = {source[IDX_ARGB_ALPHA_BEGIN], source[IDX_ARGB_ALPHA_END], 0};
1007         alpha = strtol(buffer, nullptr, HEX);
1008         color = strtol(source + IDX_ARGB_COLOR_BEGIN, nullptr, HEX);
1009         return true;
1010     }
1011 
1012     return false;
1013 }
1014 
ParseRgbaColor(const char * const source,uint32_t & color,uint8_t & alpha)1015 bool ParseRgbaColor(const char * const source, uint32_t &color, uint8_t &alpha)
1016 {
1017     uint8_t idxOpenBrace = 0;
1018     uint8_t idxCloseBrace = 0;
1019     if (source == nullptr) {
1020         return false;
1021     }
1022     size_t size = strlen(source);
1023     if (size >= UINT8_MAX) {
1024         return false;
1025     }
1026     for (uint8_t idx = 0; idx < size; ++idx) {
1027         if (source[idx] == BRACE_OPEN) {
1028             idxOpenBrace = idx;
1029             continue;
1030         }
1031         if (source[idx] == BRACE_CLOSE) {
1032             idxCloseBrace = idx;
1033             continue;
1034         }
1035     }
1036 
1037     if (idxOpenBrace == 0 || idxCloseBrace == 0 || idxCloseBrace <= idxOpenBrace) {
1038         return false;
1039     }
1040 
1041     uint8_t bufSize = idxCloseBrace - idxOpenBrace - 1;
1042     char *buffer = static_cast<char *>(ace_malloc(sizeof(char) * (bufSize + 1)));
1043     if (buffer == nullptr) {
1044         return false;
1045     }
1046     if (memcpy_s(buffer, bufSize, source + idxOpenBrace + 1, bufSize) != 0) {
1047         ace_free(buffer);
1048         buffer = nullptr;
1049         return false;
1050     }
1051     buffer[bufSize] = 0;
1052     char *token;
1053     // BITS_PER_BYTE is unsigned, result always equals to 16, can't overflow
1054     int8_t move = BITS_PER_BYTE << 1;
1055     char *next = nullptr;
1056     token = strtok_s(buffer, DELIMITER, &next);
1057     color = 0;
1058     while ((token != nullptr) && (move >= 0)) {
1059         long value = strtol(token, nullptr, DEC);
1060         if ((value < 0) || (value > UINT8_MAX)) {
1061             ace_free(buffer);
1062             buffer = nullptr;
1063             color = 0;
1064             return false;
1065         }
1066         color += ((uint8_t)value << (uint8_t)move);
1067         token = strtok_s(nullptr, DELIMITER, &next);
1068         move -= BITS_PER_BYTE;
1069     }
1070     if (token != nullptr) {
1071         alpha = (uint8_t)(strtod(token, nullptr) * ALPHA_MAX);
1072     } else {
1073         alpha = ALPHA_MAX;
1074     }
1075     ace_free(buffer);
1076     buffer = nullptr;
1077     return true;
1078 }
1079 
ParseColor(const char * const source,uint32_t & color,uint8_t & alpha)1080 bool ParseColor(const char * const source, uint32_t &color, uint8_t &alpha)
1081 {
1082     if (source == nullptr) {
1083         return false;
1084     }
1085 
1086     if (IsHexColor(source)) {
1087         return ParseHexColor(source, color, alpha);
1088     }
1089 
1090     if (IsRgbaColor(source) || IsRgbColor(source)) {
1091         return ParseRgbaColor(source, color, alpha);
1092     }
1093 
1094     return false;
1095 }
1096 
1097 #if JS_PAGE_SPECIFIC
1098 struct JSPageSpecific jsPageSpecific;
1099 #endif // JS_PAGE_SPECIFIC
1100 
GetHorizontalResolution()1101 uint16_t GetHorizontalResolution()
1102 {
1103 // SCREENSIZE_SPECIFIED is temporarily set, when ui and graphic unifid, this can be removed
1104 #if ((defined __LITEOS__) || (defined __linux__) || (SCREENSIZE_SPECIFIED == 1))
1105     return Screen::GetInstance().GetWidth();
1106 #else
1107     constexpr uint16_t resConst = 454;
1108     uint16_t horizontalResolution = resConst;
1109     uint16_t verticalResolution = resConst;
1110     ProductAdapter::GetScreenSize(horizontalResolution, verticalResolution);
1111     return horizontalResolution;
1112 #endif // OHOS_ACELITE_PRODUCT_WATCH
1113 }
1114 
GetVerticalResolution()1115 uint16_t GetVerticalResolution()
1116 {
1117 #if ((defined __LITEOS__) || (defined __linux__) || (SCREENSIZE_SPECIFIED == 1))
1118     return Screen::GetInstance().GetHeight();
1119 #else
1120     constexpr uint16_t resConst = 454;
1121     uint16_t horizontalResolution = resConst;
1122     uint16_t verticalResolution = resConst;
1123     ProductAdapter::GetScreenSize(horizontalResolution, verticalResolution);
1124     return verticalResolution;
1125 #endif // OHOS_ACELITE_PRODUCT_WATCH
1126 }
1127 
GetRootAbilitySlice()1128 JSValue GetRootAbilitySlice()
1129 {
1130     return JSGlobal::Get(ATTR_ROOT);
1131 }
1132 
CallWithRootAbilitySlice(JSValue func,JSValue args[],JSSize size)1133 JSValue CallWithRootAbilitySlice(JSValue func, JSValue args[], JSSize size)
1134 {
1135     JSValue abilitySlice = GetRootAbilitySlice();
1136     JSValue result = JSFunction::Call(func, abilitySlice, args, size);
1137     JSRelease(abilitySlice);
1138     return result;
1139 }
1140 
CallWithRootAbilitySlice(JSValue func)1141 JSValue CallWithRootAbilitySlice(JSValue func)
1142 {
1143     return CallWithRootAbilitySlice(func, nullptr, 0);
1144 }
1145 
CreateWatcher(JSValue getter,JSHandler handler,JSValue options)1146 JSValue CreateWatcher(JSValue getter, JSHandler handler, JSValue options)
1147 {
1148     JSValue abilitySlice = GetRootAbilitySlice();
1149     JSValue callback = JSFunction::Create(handler);
1150     JSValue args[ARG_LENGTH_WATCHER] = {getter, callback, options};
1151     JSValue watcher = JSObject::Call(abilitySlice, ATTR_WATCH, args, ARG_LENGTH_WATCHER);
1152     JSRelease(callback);
1153     JSRelease(abilitySlice);
1154     return watcher;
1155 }
1156 
ExpandImagePathMem(char * & imagePath,const int16_t dotPos,const int16_t suffixLen,const int16_t imagePathLen)1157 void ExpandImagePathMem(char *&imagePath, const int16_t dotPos, const int16_t suffixLen, const int16_t imagePathLen)
1158 {
1159     if (dotPos < 0 || suffixLen < 0 || imagePathLen < 0) {
1160         return;
1161     }
1162     int16_t len = dotPos + 1 + suffixLen + 1;
1163     if (len <= 0) {
1164         return;
1165     }
1166     char *newImagePath = static_cast<char *>(ace_malloc(len));
1167     if (newImagePath == nullptr) {
1168         HILOG_ERROR(HILOG_MODULE_ACE, "malloc buffer for path failed, needed length[%{public}u]",
1169                     (dotPos + 1 + suffixLen + 1));
1170         ACE_FREE(imagePath);
1171         return;
1172     }
1173 
1174     errno_t err = strcpy_s(newImagePath, len, imagePath);
1175     if (err != 0) {
1176         HILOG_ERROR(HILOG_MODULE_ACE, "use strcpy_s secure function [errro:%{public}d]", err);
1177         ace_free(newImagePath);
1178         newImagePath = nullptr;
1179         ACE_FREE(imagePath);
1180         return;
1181     }
1182 
1183     ace_free(imagePath);
1184     imagePath = newImagePath;
1185 }
1186 
ParseImageSrc(jerry_value_t source)1187 const char *ParseImageSrc(jerry_value_t source)
1188 {
1189     uint16_t length = 0;
1190     char *rawSrc = MallocStringOf(source, &length);
1191     if (rawSrc == nullptr) {
1192         HILOG_ERROR(HILOG_MODULE_ACE, "Failed to parse image src cause by empty source.");
1193         return nullptr;
1194     }
1195     if (length == 0) {
1196         HILOG_ERROR(HILOG_MODULE_ACE, "Failed to parse image src cause by empty source.");
1197         ace_free(rawSrc);
1198         rawSrc = nullptr;
1199         return nullptr;
1200     }
1201 
1202     if ((strstr(rawSrc, PATH_RELATIVE_WHOLE) != nullptr) || (strstr(rawSrc, PATH_RELATIVE_PART) != nullptr)) {
1203         HILOG_ERROR(HILOG_MODULE_ACE, "Relative path is not allowed in image src.");
1204         ace_free(rawSrc);
1205         rawSrc = nullptr;
1206         return nullptr;
1207     }
1208 
1209     char *imageSrc = JsAppContext::GetInstance()->GetResourcePath(rawSrc);
1210     ace_free(rawSrc);
1211     rawSrc = nullptr;
1212     return imageSrc;
1213 }
1214 
CopyFontFamily(char * & destination,const char * const fontFamily,uint32_t fontFamilyNameLen)1215 bool CopyFontFamily(char *&destination, const char * const fontFamily, uint32_t fontFamilyNameLen)
1216 {
1217     // unused parameter for now, added for clean up warning
1218     UNUSED(fontFamilyNameLen);
1219     ACE_FREE(destination);
1220     if (fontFamily == nullptr) {
1221         return true; // the destination is already nullptr
1222     }
1223     size_t fontFamilyLen = strlen(fontFamily);
1224     if (fontFamilyLen >= UINT8_MAX) {
1225         HILOG_ERROR(HILOG_MODULE_ACE, "the fontFamily is too long");
1226         return false;
1227     }
1228     size_t len = fontFamilyLen + 1;
1229     destination = static_cast<char *>(ace_malloc(len));
1230     if (destination == nullptr) {
1231         HILOG_ERROR(HILOG_MODULE_ACE, "malloc string failed");
1232         return false;
1233     }
1234     if (strcpy_s(destination, len, fontFamily) != 0) {
1235         HILOG_ERROR(HILOG_MODULE_ACE, "copy fontFamily failed");
1236         ace_free(destination);
1237         destination = nullptr;
1238         return false;
1239     }
1240     return true;
1241 }
1242 
ParseKeyIdFromJSString(const jerry_value_t str)1243 uint16_t ParseKeyIdFromJSString(const jerry_value_t str)
1244 {
1245     // calculate key ID
1246     uint16_t keyId = K_UNKNOWN;
1247     uint16_t strLength = 0;
1248     char *keyStr = MallocStringOf(str, &strLength);
1249     if (keyStr != nullptr) {
1250         if (strLength != 0) {
1251             keyId = KeyParser::ParseKeyId(keyStr, strLength);
1252         }
1253         ace_free(keyStr);
1254         keyStr = nullptr;
1255     }
1256     return keyId;
1257 }
ParseLineCap(const char * lineCap)1258 int8_t ParseLineCap(const char *lineCap)
1259 {
1260     if (lineCap == nullptr) {
1261         return -1;
1262     }
1263     if (strcasecmp(lineCap, LINECAP_BUTT) == 0) {
1264         return BUTT_VALUE;
1265     }
1266     if (strcasecmp(lineCap, LINECAP_SQUARE) == 0) {
1267         return SQUARE_VALUE;
1268     }
1269     if (strcasecmp(lineCap, LINECAP_ROUND) == 0) {
1270         return ROUND_VALUE;
1271     }
1272     return -1;
1273 }
1274 
ParseLineJoin(const char * lineJoin)1275 int8_t ParseLineJoin(const char *lineJoin)
1276 {
1277     if (lineJoin == nullptr) {
1278         return -1;
1279     }
1280     if (strcasecmp(lineJoin, LINEJOIN_MITER) == 0) {
1281         return LINEJOIN_MITER_VALUE;
1282     }
1283     if (strcasecmp(lineJoin, LINEJOIN_ROUND) == 0) {
1284         return LINEJOIN_ROUND_VALUE;
1285     }
1286     if (strcasecmp(lineJoin, LINEJOIN_BEVEL) == 0) {
1287         return LINEJOIN_BEVEL_VALUE;
1288     }
1289     return -1;
1290 }
1291 } // namespace ACELite
1292 } // namespace OHOS
1293