1 /*
2 * Copyright (c) 2023 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
16 #include "resource_manager_napi_utils.h"
17
18 #include "hilog/log_cpp.h"
19 #include "securec.h"
20 #include "utils/string_utils.h"
21
22 namespace OHOS {
23 namespace Global {
24 namespace Resource {
25 constexpr int ARRAY_SUBCRIPTOR_ZERO = 0;
26 constexpr int PARAMS_NUM_TWO = 2;
27
28 const std::unordered_map<int32_t, std::string> ResourceManagerNapiUtils::ErrorCodeToMsg {
29 {ERROR_CODE_INVALID_INPUT_PARAMETER, "Invalid input parameter"},
30 {ERROR_CODE_RES_ID_NOT_FOUND, "Invalid resource ID: %lu"},
31 {ERROR_CODE_RES_NAME_NOT_FOUND, "Invalid resource name"},
32 {ERROR_CODE_RES_NOT_FOUND_BY_ID, "No matching resource is found based on the resource ID"},
33 {ERROR_CODE_RES_NOT_FOUND_BY_NAME, "No matching resource is found based on the resource name"},
34 {ERROR_CODE_RES_PATH_INVALID, "Invalid relative path"},
35 {ERROR_CODE_RES_REF_TOO_MUCH, "The resource is referenced cyclically"},
36 {ERROR_CODE_RES_ID_FORMAT_ERROR, "Failed to format the resource obtained based on the resource ID"},
37 {ERROR_CODE_RES_NAME_FORMAT_ERROR, "Failed to format the resource obtained based on the resource Name"},
38 {ERROR_CODE_SYSTEM_RES_MANAGER_GET_FAILED, "Failed to access the system resource"},
39 {ERROR_CODE_OVERLAY_RES_PATH_INVALID, "Invalid overlay path"},
40 {ERROR, "Unknow error"}
41 };
42
IsNapiString(napi_env env,napi_callback_info info)43 bool ResourceManagerNapiUtils::IsNapiString(napi_env env, napi_callback_info info)
44 {
45 GET_PARAMS(env, info, PARAMS_NUM_TWO);
46
47 napi_valuetype valueType = napi_valuetype::napi_undefined;
48 napi_typeof(env, argv[ARRAY_SUBCRIPTOR_ZERO], &valueType);
49 if (valueType != napi_string) {
50 RESMGR_HILOGD(RESMGR_JS_TAG, "Parameter type is not napi_string");
51 return false;
52 }
53 return true;
54 }
55
IsNapiNumber(napi_env env,napi_callback_info info)56 bool ResourceManagerNapiUtils::IsNapiNumber(napi_env env, napi_callback_info info)
57 {
58 GET_PARAMS(env, info, PARAMS_NUM_TWO);
59
60 napi_valuetype valueType = napi_valuetype::napi_undefined;
61 napi_typeof(env, argv[ARRAY_SUBCRIPTOR_ZERO], &valueType);
62 if (valueType != napi_number) {
63 return false;
64 }
65 return true;
66 }
67
IsNapiObject(napi_env env,napi_callback_info info)68 bool ResourceManagerNapiUtils::IsNapiObject(napi_env env, napi_callback_info info)
69 {
70 GET_PARAMS(env, info, PARAMS_NUM_TWO);
71
72 napi_valuetype valueType = napi_valuetype::napi_undefined;
73 napi_typeof(env, argv[ARRAY_SUBCRIPTOR_ZERO], &valueType);
74 if (valueType != napi_object) {
75 RESMGR_HILOGI(RESMGR_JS_TAG, "Parameter type is not napi_object");
76 return false;
77 }
78 return true;
79 }
80
GetType(napi_env env,napi_value value)81 napi_valuetype ResourceManagerNapiUtils::GetType(napi_env env, napi_value value)
82 {
83 napi_valuetype valueType = napi_valuetype::napi_undefined;
84 napi_typeof(env, value, &valueType);
85 return valueType;
86 }
87
GetResNameOrPath(napi_env env,size_t argc,napi_value * argv)88 std::string ResourceManagerNapiUtils::GetResNameOrPath(napi_env env, size_t argc, napi_value *argv)
89 {
90 if (argc == 0 || argv == nullptr) {
91 return "";
92 }
93
94 napi_valuetype valuetype;
95 napi_typeof(env, argv[ARRAY_SUBCRIPTOR_ZERO], &valuetype);
96 if (valuetype != napi_string) {
97 RESMGR_HILOGE(RESMGR_JS_TAG, "Invalid param, not string");
98 return "";
99 }
100 size_t len = 0;
101 napi_status status = napi_get_value_string_utf8(env, argv[ARRAY_SUBCRIPTOR_ZERO], nullptr, 0, &len);
102 if (status != napi_ok) {
103 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resName or rawfile path length");
104 return "";
105 }
106 std::vector<char> buf(len + 1);
107 status = napi_get_value_string_utf8(env, argv[ARRAY_SUBCRIPTOR_ZERO], buf.data(), len + 1, &len);
108 if (status != napi_ok) {
109 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resName or raw file path");
110 return "";
111 }
112 return buf.data();
113 }
114
GetResId(napi_env env,size_t argc,napi_value * argv)115 uint32_t ResourceManagerNapiUtils::GetResId(napi_env env, size_t argc, napi_value *argv)
116 {
117 if (argc == 0 || argv == nullptr) {
118 return 0;
119 }
120
121 napi_valuetype valuetype;
122 napi_status status = napi_typeof(env, argv[ARRAY_SUBCRIPTOR_ZERO], &valuetype);
123 if (status != napi_ok) {
124 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get value type");
125 return 0;
126 }
127 if (valuetype != napi_number) {
128 RESMGR_HILOGE(RESMGR_JS_TAG, "Invalid param, not number");
129 return 0;
130 }
131 int64_t resId = 0;
132 status = napi_get_value_int64(env, argv[ARRAY_SUBCRIPTOR_ZERO], &resId);
133 if (status != napi_ok || resId < 0 || resId > UINT32_MAX) {
134 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get id number");
135 return 0;
136 }
137
138 return static_cast<uint32_t>(resId);
139 }
140
FindErrMsg(int32_t errCode)141 std::string ResourceManagerNapiUtils::FindErrMsg(int32_t errCode)
142 {
143 auto iter = ResourceManagerNapiUtils::ErrorCodeToMsg.find(errCode);
144 std::string errMsg = iter != ResourceManagerNapiUtils::ErrorCodeToMsg.end() ? iter->second : "";
145 return errMsg;
146 }
147
NapiThrow(napi_env env,int32_t errCode,...)148 void ResourceManagerNapiUtils::NapiThrow(napi_env env, int32_t errCode, ...)
149 {
150 napi_value code = nullptr;
151 napi_create_string_latin1(env, std::to_string(errCode).c_str(), NAPI_AUTO_LENGTH, &code);
152
153 napi_value message = nullptr;
154 va_list args;
155 va_start(args, errCode);
156 std::string errMsg = FormatString(FindErrMsg(errCode).c_str(), args);
157 va_end(args);
158 napi_create_string_latin1(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
159 if (errMsg != "") {
160 napi_value error = nullptr;
161 napi_create_error(env, code, message, &error);
162 napi_throw(env, error);
163 }
164 }
165
CreateJsArray(napi_env env,ResMgrDataContext & dataContext)166 napi_value ResourceManagerNapiUtils::CreateJsArray(napi_env env, ResMgrDataContext &dataContext)
167 {
168 napi_value result;
169 napi_status status = napi_create_array_with_length(env, dataContext.arrayValue_.size(), &result);
170 if (status != napi_ok) {
171 dataContext.SetErrorMsg("Failed to create array");
172 return nullptr;
173 }
174 for (size_t i = 0; i < dataContext.arrayValue_.size(); i++) {
175 napi_value value;
176 status = napi_create_string_utf8(env, dataContext.arrayValue_[i].c_str(), NAPI_AUTO_LENGTH, &value);
177 if (status != napi_ok) {
178 dataContext.SetErrorMsg("Failed to create string item");
179 return nullptr;
180 }
181 status = napi_set_element(env, result, i, value);
182 if (status != napi_ok) {
183 dataContext.SetErrorMsg("Failed to set array item");
184 return nullptr;
185 }
186 }
187 return result;
188 }
189
CreateJsUint8Array(napi_env env,ResMgrDataContext & context)190 napi_value ResourceManagerNapiUtils::CreateJsUint8Array(napi_env env, ResMgrDataContext &context)
191 {
192 napi_value buffer;
193 uint8_t *data;
194 napi_status status = napi_create_arraybuffer(env, context.len_, reinterpret_cast<void **>(&data), &buffer);
195 if (status != napi_ok) {
196 context.SetErrorMsg("Failed to create media array buffer");
197 return nullptr;
198 }
199
200 napi_value result = nullptr;
201 status = napi_create_typedarray(env, napi_uint8_array, context.len_, buffer, 0, &result);
202 if (status != napi_ok) {
203 context.SetErrorMsg("Failed to create media typed array");
204 return nullptr;
205 }
206
207 if (context.len_ == 0) {
208 return result;
209 }
210
211 uint8_t *tempData = context.mediaData.release();
212 int ret = memcpy_s(data, context.len_, tempData, context.len_);
213 delete[] tempData;
214 if (ret != 0) {
215 context.SetErrorMsg("Failed to copy media to buffer");
216 return result;
217 }
218 return result;
219 }
220
CreateJsRawFd(napi_env env,ResMgrDataContext & context)221 napi_value ResourceManagerNapiUtils::CreateJsRawFd(napi_env env, ResMgrDataContext &context)
222 {
223 napi_value result;
224 napi_status status = napi_create_object(env, &result);
225 if (status != napi_ok) {
226 context.SetErrorMsg("Failed to create result");
227 return result;
228 }
229
230 napi_value fd;
231 status = napi_create_int32(env, context.descriptor_.fd, &fd);
232 if (status != napi_ok) {
233 context.SetErrorMsg("Failed to create fd");
234 return result;
235 }
236 status = napi_set_named_property(env, result, "fd", fd);
237 if (status != napi_ok) {
238 context.SetErrorMsg("Failed to set fd");
239 return result;
240 }
241
242 napi_value offset;
243 status = napi_create_int64(env, context.descriptor_.offset, &offset);
244 if (status != napi_ok) {
245 context.SetErrorMsg("Failed to create offset");
246 return result;
247 }
248 status = napi_set_named_property(env, result, "offset", offset);
249 if (status != napi_ok) {
250 context.SetErrorMsg("Failed to set offset");
251 return result;
252 }
253
254 napi_value length;
255 status = napi_create_int64(env, context.descriptor_.length, &length);
256 if (status != napi_ok) {
257 context.SetErrorMsg("Failed to create length");
258 return result;
259 }
260 status = napi_set_named_property(env, result, "length", length);
261 if (status != napi_ok) {
262 context.SetErrorMsg("Failed to set length");
263 return result;
264 }
265 return result;
266 }
267
CloseJsRawFd(napi_env env,ResMgrDataContext & context)268 napi_value ResourceManagerNapiUtils::CloseJsRawFd(napi_env env, ResMgrDataContext& context)
269 {
270 napi_value undefined;
271 if (napi_get_undefined(env, &undefined) != napi_ok) {
272 return nullptr;
273 }
274 RState state = context.addon_->GetResMgr()->CloseRawFileDescriptor(context.path_);
275 if (state != RState::SUCCESS) {
276 context.SetErrorMsg("CloseRawFileDescriptor failed state", true, state);
277 return nullptr;
278 }
279 return undefined;
280 }
281
CreateJsString(napi_env env,ResMgrDataContext & context)282 napi_value ResourceManagerNapiUtils::CreateJsString(napi_env env, ResMgrDataContext& context)
283 {
284 napi_value result;
285 if (napi_create_string_utf8(env, context.value_.c_str(), NAPI_AUTO_LENGTH, &result) != napi_ok) {
286 context.SetErrorMsg("Failed to create result");
287 return result;
288 }
289 return result;
290 }
291
CreateJsNumber(napi_env env,ResMgrDataContext & context)292 napi_value ResourceManagerNapiUtils::CreateJsNumber(napi_env env, ResMgrDataContext& context)
293 {
294 napi_value jsValue = nullptr;
295 napi_status status;
296 if (context.iValue_) {
297 status = napi_create_int32(env, context.iValue_, &jsValue);
298 } else {
299 status = napi_create_double(env, context.fValue_, &jsValue);
300 }
301 if (status != napi_ok) {
302 context.SetErrorMsg("Failed to create js number", true);
303 }
304 return jsValue;
305 }
306
CreateJsBool(napi_env env,ResMgrDataContext & context)307 napi_value ResourceManagerNapiUtils::CreateJsBool(napi_env env, ResMgrDataContext& context)
308 {
309 napi_value jsValue = nullptr;
310 if (napi_get_boolean(env, context.bValue_, &jsValue) != napi_ok) {
311 context.SetErrorMsg("Failed to create result", true);
312 }
313 return jsValue;
314 }
315
GetResourceObjectName(napi_env env,std::shared_ptr<ResourceManager::Resource> & resourcePtr,napi_value & value,int32_t type)316 bool ResourceManagerNapiUtils::GetResourceObjectName(napi_env env,
317 std::shared_ptr<ResourceManager::Resource> &resourcePtr, napi_value &value, int32_t type)
318 {
319 std::string typeName("moduleName");
320 if (type == 0) {
321 typeName = std::string("bundleName");
322 }
323 napi_value name;
324 napi_status status = napi_get_named_property(env, value, typeName.c_str(), &name);
325 if (status != napi_ok || name == nullptr) {
326 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource name property");
327 return false;
328 }
329 if (ResourceManagerNapiUtils::GetType(env, name) != napi_string) {
330 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource name string");
331 return false;
332 }
333 size_t len = 0;
334 status = napi_get_value_string_utf8(env, name, nullptr, 0, &len);
335 if (status != napi_ok) {
336 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource len");
337 return false;
338 }
339 std::vector<char> buf(len + 1);
340 status = napi_get_value_string_utf8(env, name, buf.data(), len + 1, &len);
341 if (status != napi_ok) {
342 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource name value");
343 return false;
344 }
345 if (type == 0) {
346 resourcePtr->bundleName = buf.data();
347 } else {
348 resourcePtr->moduleName = buf.data();
349 }
350 return true;
351 }
352
GetResourceObjectId(napi_env env,std::shared_ptr<ResourceManager::Resource> & resourcePtr,napi_value & value)353 bool ResourceManagerNapiUtils::GetResourceObjectId(napi_env env,
354 std::shared_ptr<ResourceManager::Resource> &resourcePtr, napi_value &value)
355 {
356 napi_value id;
357 napi_status status = napi_get_named_property(env, value, "id", &id);
358 if (status != napi_ok || id == nullptr) {
359 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource id property");
360 return false;
361 }
362 if (ResourceManagerNapiUtils::GetType(env, id) != napi_number) {
363 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource id number");
364 return false;
365 }
366 int64_t resId = 0;
367 status = napi_get_value_int64(env, id, &resId);
368 if (resId == -1) {
369 resourcePtr->id = 0;
370 return true;
371 }
372 if (status != napi_ok || resId < 0 || resId > UINT32_MAX) {
373 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource id value");
374 return false;
375 }
376 resourcePtr->id = static_cast<uint32_t>(resId);
377 return true;
378 }
379
GetResourceObject(napi_env env,std::shared_ptr<ResourceManager::Resource> & resourcePtr,napi_value & value)380 int32_t ResourceManagerNapiUtils::GetResourceObject(napi_env env,
381 std::shared_ptr<ResourceManager::Resource> &resourcePtr, napi_value &value)
382 {
383 if (resourcePtr == nullptr) {
384 RESMGR_HILOGE(RESMGR_JS_TAG, "resourcePtr == nullptr");
385 return ERROR;
386 }
387 if (!GetResourceObjectName(env, resourcePtr, value, 0)) {
388 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get bundleName");
389 return ERROR_CODE_INVALID_INPUT_PARAMETER;
390 }
391 if (!GetResourceObjectName(env, resourcePtr, value, 1)) {
392 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get moduleName");
393 return ERROR_CODE_INVALID_INPUT_PARAMETER;
394 }
395 if (!GetResourceObjectId(env, resourcePtr, value)) {
396 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get id");
397 return ERROR_CODE_INVALID_INPUT_PARAMETER;
398 }
399
400 return SUCCESS;
401 }
402
GetHapResourceManager(const ResMgrDataContext * dataContext,std::shared_ptr<ResourceManager> & resMgr,uint32_t & resId)403 bool ResourceManagerNapiUtils::GetHapResourceManager(const ResMgrDataContext* dataContext,
404 std::shared_ptr<ResourceManager> &resMgr, uint32_t &resId)
405 {
406 std::shared_ptr<ResourceManager::Resource> resource = dataContext->resource_;
407 // In fa module, resource is null.
408 if (resource == nullptr) {
409 resMgr = dataContext->addon_->GetResMgr();
410 resId = dataContext->resId_;
411 return true;
412 }
413
414 // In stage module and isSystem is true, resId is the resource object id.
415 if (dataContext->addon_->IsSystem()) {
416 resMgr = dataContext->addon_->GetResMgr();
417 resId = resource->id;
418 return true;
419 }
420
421 resId = resource->id;
422 if (dataContext->addon_->isOverrideAddon()) {
423 resMgr = dataContext->addon_->GetResMgr();
424 return true;
425 }
426 auto context = dataContext->addon_->GetContext();
427 if (context == nullptr) {
428 RESMGR_HILOGE(RESMGR_JS_TAG, "GetHapResourceManager context == nullptr");
429 return false;
430 }
431 std::string bundleName(resource->bundleName);
432 if (bundleName.empty()) {
433 auto applicationInfo = context->GetApplicationInfo();
434 if (applicationInfo != nullptr) {
435 bundleName = applicationInfo->name;
436 }
437 }
438 auto moduleContext = context->CreateModuleContext(bundleName, resource->moduleName);
439 if (moduleContext == nullptr) {
440 RESMGR_HILOGE(RESMGR_JS_TAG, "GetHapResourceManager moduleContext == nullptr, bundleName = %{public}s," \
441 "moduleName = %{public}s", bundleName.c_str(), resource->moduleName.c_str());
442 return false;
443 }
444 resMgr = moduleContext->GetResourceManager();
445 return true;
446 }
447
CreateJsDeviceCap(napi_env env,ResMgrDataContext & context)448 napi_value ResourceManagerNapiUtils::CreateJsDeviceCap(napi_env env, ResMgrDataContext& context)
449 {
450 std::unique_ptr<ResConfig> cfg(CreateResConfig());
451 if (!cfg) {
452 context.SetErrorMsg("Failed to create ResConfig object.");
453 return nullptr;
454 }
455 context.addon_->GetResMgr()->GetResConfig(*cfg);
456
457 napi_value result;
458 napi_status status = napi_create_object(env, &result);
459 if (status != napi_ok) {
460 context.SetErrorMsg("Failed to create GetDeviceCapability object");
461 return nullptr;
462 }
463
464 napi_value deviceType;
465 status = napi_create_int32(env, static_cast<int>(cfg->GetDeviceType()), &deviceType);
466 if (status != napi_ok) {
467 context.SetErrorMsg("Failed to create deviceType");
468 return nullptr;
469 }
470 status = napi_set_named_property(env, result, "deviceType", deviceType);
471 if (status != napi_ok) {
472 context.SetErrorMsg("Failed to set deviceType property");
473 return nullptr;
474 }
475
476 napi_value screenDensity;
477 status = napi_create_int32(env, static_cast<int>(cfg->ConvertDensity(cfg->GetScreenDensity())), &screenDensity);
478 if (status != napi_ok) {
479 context.SetErrorMsg("Failed to create screenDensity");
480 return nullptr;
481 }
482 status = napi_set_named_property(env, result, "screenDensity", screenDensity);
483 if (status != napi_ok) {
484 context.SetErrorMsg("Failed to set screenDensity property");
485 return nullptr;
486 }
487 return result;
488 }
489
490
GetLocale(std::unique_ptr<ResConfig> & cfg)491 std::string ResourceManagerNapiUtils::GetLocale(std::unique_ptr<ResConfig> &cfg)
492 {
493 std::string result;
494 #ifdef SUPPORT_GRAPHICS
495 const icu::Locale *localeInfo = cfg->GetLocaleInfo();
496 if (localeInfo == nullptr) {
497 return result;
498 }
499 const char *lang = localeInfo->getLanguage();
500 if (lang == nullptr) {
501 return result;
502 }
503 result = lang;
504
505 const char *script = localeInfo->getScript();
506 if (script != nullptr) {
507 result += std::string("_") + script;
508 }
509
510 const char *region = localeInfo->getCountry();
511 if (region != nullptr) {
512 result += std::string("_") + region;
513 }
514 #endif
515 return result;
516 }
517
CreateJsConfig(napi_env env,ResMgrDataContext & context)518 napi_value ResourceManagerNapiUtils::CreateJsConfig(napi_env env, ResMgrDataContext& context)
519 {
520 std::unique_ptr<ResConfig> cfg(CreateResConfig());
521 if (!cfg) {
522 context.SetErrorMsg("Failed to create ResConfig object.");
523 return nullptr;
524 }
525 context.addon_->GetResMgr()->GetResConfig(*cfg);
526 return CreateConfig(env, context, cfg);
527 }
528
CreateOverrideJsConfig(napi_env env,ResMgrDataContext & context)529 napi_value ResourceManagerNapiUtils::CreateOverrideJsConfig(napi_env env, ResMgrDataContext& context)
530 {
531 std::unique_ptr<ResConfig> cfg(CreateResConfig());
532 if (!cfg) {
533 context.SetErrorMsg("Failed to create ResConfig object.");
534 return nullptr;
535 }
536 context.addon_->GetResMgr()->GetOverrideResConfig(*cfg);
537 return CreateConfig(env, context, cfg);
538 }
539
CreateConfig(napi_env env,ResMgrDataContext & context,std::unique_ptr<ResConfig> & cfg)540 napi_value ResourceManagerNapiUtils::CreateConfig(napi_env env,
541 ResMgrDataContext& context, std::unique_ptr<ResConfig> &cfg)
542 {
543 napi_value result;
544 napi_status status = napi_create_object(env, &result);
545 if (status != napi_ok) {
546 context.SetErrorMsg("Failed to create Configuration object");
547 return nullptr;
548 }
549
550 // write locale
551 napi_value locale;
552 status = napi_create_string_utf8(env, ResourceManagerNapiUtils::GetLocale(cfg).c_str(), NAPI_AUTO_LENGTH, &locale);
553 if (status != napi_ok) {
554 context.SetErrorMsg("Failed to create locale");
555 return nullptr;
556 }
557 status = napi_set_named_property(env, result, "locale", locale);
558 if (status != napi_ok) {
559 context.SetErrorMsg("Failed to set locale property");
560 return nullptr;
561 }
562
563 // write other int properties
564 SetIntProperty(env, context, result, "direction", static_cast<int>(cfg->GetDirection()));
565 SetIntProperty(env, context, result, "deviceType", static_cast<int>(cfg->GetDeviceType()));
566 SetIntProperty(env, context, result, "screenDensity", static_cast<int>(cfg->GetScreenDensityDpi()));
567 SetIntProperty(env, context, result, "colorMode", static_cast<int>(cfg->GetColorMode()));
568 SetIntProperty(env, context, result, "mcc", static_cast<int>(cfg->GetMcc()));
569 SetIntProperty(env, context, result, "mnc", static_cast<int>(cfg->GetMnc()));
570
571 return result;
572 }
573
SetIntProperty(napi_env env,ResMgrDataContext & context,napi_value & object,const std::string & property,const int & value)574 bool ResourceManagerNapiUtils::SetIntProperty(napi_env env,
575 ResMgrDataContext& context, napi_value &object, const std::string &property, const int &value)
576 {
577 napi_value napi_val;
578 napi_status status = napi_create_int32(env, value, &napi_val);
579 if (status != napi_ok) {
580 context.SetErrorMsg("Failed to create %{public}s", property.c_str());
581 return false;
582 }
583 status = napi_set_named_property(env, object, property.c_str(), napi_val);
584 if (status != napi_ok) {
585 context.SetErrorMsg("Failed to set %{public}s property", property.c_str());
586 return false;
587 }
588 return true;
589 }
590
GetConfigObject(napi_env env,napi_value object,std::unique_ptr<ResMgrDataContext> & dataContext)591 RState ResourceManagerNapiUtils::GetConfigObject(napi_env env,
592 napi_value object, std::unique_ptr<ResMgrDataContext> &dataContext)
593 {
594 napi_valuetype valueType;
595 napi_typeof(env, object, &valueType);
596 if (valueType == napi_undefined || valueType == napi_null) {
597 RESMGR_HILOGD(RESMGR_JS_TAG, "GetConfigObject, no config");
598 return SUCCESS;
599 }
600 if (valueType != napi_object) {
601 RESMGR_HILOGE(RESMGR_JS_TAG, "GetConfigObject, param not object");
602 return ERROR_CODE_INVALID_INPUT_PARAMETER;
603 }
604
605 ResConfig *config = CreateDefaultResConfig();
606 if (config == nullptr) {
607 RESMGR_HILOGE(RESMGR_JS_TAG, "GetConfigObject, new config failed");
608 return ERROR_CODE_INVALID_INPUT_PARAMETER;
609 }
610 dataContext->overrideResConfig_.reset(config);
611
612 if (!GetEnumParamOfConfig(env, dataContext->overrideResConfig_, object)) {
613 return ERROR_CODE_INVALID_INPUT_PARAMETER;
614 }
615 if (!GetLocaleOfConfig(env, dataContext->overrideResConfig_, object)) {
616 return ERROR_CODE_INVALID_INPUT_PARAMETER;
617 }
618
619 return SUCCESS;
620 }
621
GetEnumParamOfConfig(napi_env env,std::shared_ptr<ResConfig> configPtr,napi_value & object)622 bool ResourceManagerNapiUtils::GetEnumParamOfConfig(napi_env env,
623 std::shared_ptr<ResConfig> configPtr, napi_value &object)
624 {
625 std::vector<std::string> properties = {"direction", "deviceType", "screenDensity", "colorMode", "mcc", "mnc"};
626 for (const auto& property : properties) {
627 napi_value napi_val;
628 napi_status status = napi_get_named_property(env, object, property.c_str(), &napi_val);
629 if (status != napi_ok) {
630 RESMGR_HILOGE(RESMGR_JS_TAG, "GetEnumParamOfConfig failed to get property %{public}s", property.c_str());
631 return false;
632 }
633 if (napi_val == nullptr) {
634 RESMGR_HILOGD(RESMGR_JS_TAG, "GetEnumParamOfConfig property %{public}s not set", property.c_str());
635 continue;
636 }
637 if (ResourceManagerNapiUtils::GetType(env, napi_val) != napi_number) {
638 RESMGR_HILOGE(RESMGR_JS_TAG,
639 "GetEnumParamOfConfig type of property %{public}s is not number", property.c_str());
640 return false;
641 }
642 int value;
643 status = napi_get_value_int32(env, napi_val, &value);
644 if (status != napi_ok) {
645 RESMGR_HILOGE(RESMGR_JS_TAG,
646 "GetEnumParamOfConfig failed to get value of property %{public}s", property.c_str());
647 return false;
648 }
649
650 RESMGR_HILOGD(RESMGR_JS_TAG, "GetEnumParamOfConfig, %{public}s = %{public}d", property.c_str(), value);
651 if (property == "direction") {
652 configPtr->SetDirection(static_cast<Direction>(value));
653 } else if (property == "deviceType") {
654 configPtr->SetDeviceType(static_cast<DeviceType>(value));
655 } else if (property == "screenDensity") {
656 configPtr->SetScreenDensityDpi(static_cast<ScreenDensity>(value));
657 } else if (property == "colorMode") {
658 configPtr->SetColorMode(static_cast<ColorMode>(value));
659 } else if (property == "mcc") {
660 configPtr->SetMcc(value);
661 } else if (property == "mnc") {
662 configPtr->SetMnc(value);
663 }
664 }
665 return true;
666 }
667
GetLocaleOfConfig(napi_env env,std::shared_ptr<ResConfig> configPtr,napi_value & object)668 bool ResourceManagerNapiUtils::GetLocaleOfConfig(
669 napi_env env, std::shared_ptr<ResConfig> configPtr, napi_value &object)
670 {
671 #ifdef SUPPORT_GRAPHICS
672 napi_value locale;
673 napi_status status = napi_get_named_property(env, object, "locale", &locale);
674 if (status != napi_ok) {
675 RESMGR_HILOGE(RESMGR_JS_TAG, "GetLocaleOfConfig failed to get property locale");
676 return false;
677 }
678 if (locale == nullptr) {
679 RESMGR_HILOGD(RESMGR_JS_TAG, "GetLocaleOfConfig property locale not set");
680 return true;
681 }
682 if (ResourceManagerNapiUtils::GetType(env, locale) != napi_string) {
683 RESMGR_HILOGE(RESMGR_JS_TAG, "GetLocaleOfConfig type of property locale is not string");
684 return false;
685 }
686
687 size_t len = 0;
688 status = napi_get_value_string_utf8(env, locale, nullptr, 0, &len);
689 if (status != napi_ok) {
690 RESMGR_HILOGE(RESMGR_JS_TAG, "GetLocaleOfConfig failed to get locale len");
691 return false;
692 }
693 if (len == 0) {
694 RESMGR_HILOGD(RESMGR_JS_TAG, "GetLocaleOfConfig locale not set or empty");
695 return true;
696 }
697
698 std::vector<char> buf(len + 1);
699 status = napi_get_value_string_utf8(env, locale, buf.data(), len + 1, &len);
700 if (status != napi_ok) {
701 RESMGR_HILOGE(RESMGR_JS_TAG, "GetLocaleOfConfig failed to get locale value");
702 return false;
703 }
704
705 if (configPtr->SetLocaleInfo(buf.data()) != SUCCESS) {
706 RESMGR_HILOGE(RESMGR_JS_TAG, "GetLocaleOfConfig failed to SetLocaleInfo");
707 return false;
708 }
709 #endif
710 return true;
711 }
712
CreateJsColor(napi_env env,ResMgrDataContext & context)713 napi_value ResourceManagerNapiUtils::CreateJsColor(napi_env env, ResMgrDataContext& context)
714 {
715 napi_value jsColorValue;
716 if (napi_create_uint32(env, context.colorValue_, &jsColorValue) != napi_ok) {
717 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get density");
718 return nullptr;
719 }
720 return jsColorValue;
721 }
722
CreateJsSymbol(napi_env env,ResMgrDataContext & context)723 napi_value ResourceManagerNapiUtils::CreateJsSymbol(napi_env env, ResMgrDataContext& context)
724 {
725 napi_value jsSymbolValue;
726 if (napi_create_uint32(env, context.symbolValue_, &jsSymbolValue) != napi_ok) {
727 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get symbol");
728 return nullptr;
729 }
730 return jsSymbolValue;
731 }
732
GetDataType(napi_env env,napi_value value,uint32_t & density)733 RState ResourceManagerNapiUtils::GetDataType(napi_env env, napi_value value, uint32_t& density)
734 {
735 napi_valuetype valuetype;
736 napi_typeof(env, value, &valuetype);
737 if (valuetype == napi_undefined || valuetype == napi_null) {
738 return SUCCESS;
739 }
740 if (valuetype != napi_number) {
741 RESMGR_HILOGE(RESMGR_JS_TAG, "Invalid param, not number");
742 return ERROR_CODE_INVALID_INPUT_PARAMETER;
743 }
744
745 if (napi_get_value_uint32(env, value, &density) != napi_ok) {
746 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get density");
747 return NOT_FOUND;
748 }
749 return SUCCESS;
750 }
751
GetIncludeSystem(napi_env env,napi_value value,bool & includeSystem)752 RState ResourceManagerNapiUtils::GetIncludeSystem(napi_env env, napi_value value, bool &includeSystem)
753 {
754 napi_valuetype valuetype;
755 napi_typeof(env, value, &valuetype);
756 if (valuetype == napi_undefined || valuetype == napi_null) {
757 return SUCCESS;
758 }
759 if (valuetype != napi_boolean) {
760 RESMGR_HILOGE(RESMGR_JS_TAG, "Invalid param, not boolean");
761 return ERROR_CODE_INVALID_INPUT_PARAMETER;
762 }
763
764 if (napi_get_value_bool(env, value, &includeSystem) != napi_ok) {
765 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get includeSystem");
766 return NOT_FOUND;
767 }
768 return SUCCESS;
769 }
770 } // namespace Resource
771 } // namespace Global
772 } // namespace OHOS