• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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