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