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