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