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