1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "rstate.h"
16 #include "napi/native_api.h"
17 #include "napi/native_node_api.h"
18 #include "native_engine.h"
19 #include "../../../../frameworks/resmgr/include/hilog_wrapper.h"
20
21 namespace OHOS {
22 namespace Global {
23 namespace Resource {
24 #define GET_PARAMS(env, info, num) \
25 size_t argc = num; \
26 napi_value argv[num] = {nullptr}; \
27 napi_value thisVar = nullptr; \
28 void *data = nullptr; \
29 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)
30
IsNapiObject(napi_env env,napi_callback_info info)31 static bool IsNapiObject(napi_env env, napi_callback_info info)
32 {
33 GET_PARAMS(env, info, 1);
34 napi_valuetype valueType = napi_valuetype::napi_undefined;
35 napi_typeof(env, argv[0], &valueType);
36 if (valueType != napi_object) {
37 RESMGR_HILOGW(RESMGR_JS_TAG, "Parameter type is not napi_object");
38 return false;
39 }
40 return true;
41 }
42
NapiThrow(napi_env env,int32_t errCode)43 static void NapiThrow(napi_env env, int32_t errCode)
44 {
45 napi_value code = nullptr;
46 napi_create_string_latin1(env, std::to_string(errCode).c_str(), NAPI_AUTO_LENGTH, &code);
47
48 napi_value message = nullptr;
49 std::string errMsg = "Invalid input parameter";
50 napi_create_string_latin1(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
51 if (message != nullptr) {
52 napi_value error = nullptr;
53 napi_create_error(env, code, message, &error);
54 napi_throw(env, error);
55 }
56 }
57
GetResourceProp(napi_env env,napi_callback_info info,std::vector<napi_value> & props)58 static bool GetResourceProp(napi_env env, napi_callback_info info, std::vector<napi_value> &props)
59 {
60 if (!IsNapiObject(env, info)) {
61 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource object");
62 return false;
63 }
64 GET_PARAMS(env, info, 1);
65 napi_value bundleName = nullptr;
66 napi_valuetype bundleNameType = napi_undefined;
67 if (napi_get_named_property(env, argv[0], "bundleName", &bundleName) != napi_ok ||
68 napi_typeof(env, bundleName, &bundleNameType) != napi_ok || bundleNameType != napi_string) {
69 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource bundleName property");
70 return false;
71 }
72
73 napi_value moduleName = nullptr;
74 napi_valuetype moduleNameType = napi_undefined;
75 if (napi_get_named_property(env, argv[0], "moduleName", &moduleName) != napi_ok ||
76 napi_typeof(env, moduleName, &moduleNameType) != napi_ok || moduleNameType != napi_string) {
77 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource moduleName property");
78 return false;
79 }
80
81 napi_value id = nullptr;
82 napi_valuetype idType = napi_undefined;
83 if (napi_get_named_property(env, argv[0], "id", &id) != napi_ok ||
84 napi_typeof(env, id, &idType) != napi_ok || idType != napi_number) {
85 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource id property");
86 return false;
87 }
88
89 napi_value params = nullptr;
90 if (napi_get_named_property(env, argv[0], "params", ¶ms) != napi_ok) {
91 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource params property");
92 return false;
93 }
94
95 napi_value type = nullptr;
96 if (napi_get_named_property(env, argv[0], "type", &type) != napi_ok) {
97 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource type property");
98 return false;
99 }
100 props.emplace_back(bundleName);
101 props.emplace_back(moduleName);
102 props.emplace_back(id);
103 props.emplace_back(params);
104 props.emplace_back(type);
105 return true;
106 }
107
GetParams(napi_env env,napi_value params,napi_value * newParams,bool isSendable)108 static bool GetParams(napi_env env, napi_value params, napi_value *newParams, bool isSendable)
109 {
110 napi_status status;
111 bool isArray = false;
112 uint32_t len = 0;
113 napi_value length = nullptr;
114 napi_valuetype paramsType = napi_undefined;
115 if (napi_typeof(env, params, ¶msType) != napi_ok) {
116 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get resource params property type");
117 return false;
118 }
119 if (paramsType == napi_undefined) {
120 return true;
121 }
122 if (napi_is_array(env, params, &isArray) != napi_ok || !isArray ||
123 napi_get_named_property(env, params, "length", &length) != napi_ok ||
124 napi_get_value_uint32(env, length, &len) != napi_ok) {
125 RESMGR_HILOGE(RESMGR_JS_TAG, "Resource params property params is error");
126 return false;
127 }
128 if (isSendable) {
129 status = napi_create_sendable_array_with_length(env, len, newParams);
130 } else {
131 status = napi_create_array_with_length(env, len, newParams);
132 }
133 if (status != napi_ok) {
134 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to create array, status = %{public}d", status);
135 return false;
136 }
137 napi_value jsValue = nullptr;
138 for (uint32_t i = 0; i < len; i++) {
139 if (napi_get_element(env, params, i, &jsValue) != napi_ok) {
140 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to get element");
141 return false;
142 }
143 if (napi_set_element(env, *(newParams), i, jsValue) != napi_ok) {
144 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to set element");
145 return false;
146 }
147 }
148 return true;
149 }
150
InstanceResource(napi_env env,napi_callback_info info,bool isSendable)151 static napi_value InstanceResource(napi_env env, napi_callback_info info, bool isSendable)
152 {
153 std::vector<napi_value> props;
154 if (!GetResourceProp(env, info, props)) {
155 return nullptr;
156 }
157 napi_property_descriptor creatorProp[5] = { // array len
158 DECLARE_NAPI_DEFAULT_PROPERTY("bundleName", props[0]),
159 DECLARE_NAPI_DEFAULT_PROPERTY("moduleName", props[1]),
160 DECLARE_NAPI_DEFAULT_PROPERTY("id", props[2]),
161 DECLARE_NAPI_INSTANCE_GENERIC_PROPERTY("params"),
162 DECLARE_NAPI_INSTANCE_GENERIC_PROPERTY("type"),
163 };
164
165 napi_value params = props[3]; // index 3
166 napi_value newParams = nullptr;
167 if (!GetParams(env, params, &newParams, isSendable)) {
168 return nullptr;
169 }
170 if (newParams != nullptr) {
171 creatorProp[3] = DECLARE_NAPI_DEFAULT_PROPERTY("params", newParams); // index 3
172 }
173
174 napi_value type = props[4]; // index 4
175 napi_valuetype valueType = napi_undefined;
176 if (napi_typeof(env, type, &valueType) != napi_ok) {
177 RESMGR_HILOGE(RESMGR_JS_TAG, "Resource type property type is error");
178 return nullptr;
179 }
180 if (valueType != napi_undefined) {
181 if (valueType != napi_number) {
182 RESMGR_HILOGE(RESMGR_JS_TAG, "Resource type property type is not number");
183 return nullptr;
184 }
185 creatorProp[4] = DECLARE_NAPI_DEFAULT_PROPERTY("type", type); // index 4
186 }
187
188 napi_value result = nullptr;
189 napi_status status;
190 if (isSendable) {
191 status = napi_create_sendable_object_with_properties(env, sizeof(creatorProp) / sizeof(creatorProp[0]),
192 creatorProp, &result);
193 } else {
194 status =napi_create_object_with_properties(env, &result, sizeof(creatorProp) / sizeof(creatorProp[0]),
195 creatorProp);
196 }
197 if (status != napi_ok) {
198 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to create object with properties, status = %{public}d", status);
199 return nullptr;
200 }
201 return result;
202 }
203
ResourceToSendableResource(napi_env env,napi_callback_info info)204 static napi_value ResourceToSendableResource(napi_env env, napi_callback_info info)
205 {
206 napi_value result = InstanceResource(env, info, true);
207 if (result == nullptr) {
208 NapiThrow(env, ERROR_CODE_INVALID_INPUT_PARAMETER);
209 return nullptr;
210 }
211 return result;
212 }
213
SendableResourceToResource(napi_env env,napi_callback_info info)214 static napi_value SendableResourceToResource(napi_env env, napi_callback_info info)
215 {
216 napi_value result = InstanceResource(env, info, false);
217 if (result == nullptr) {
218 NapiThrow(env, ERROR_CODE_INVALID_INPUT_PARAMETER);
219 return nullptr;
220 }
221 return result;
222 }
223
SendableResourceManagerInit(napi_env env,napi_value exports)224 static napi_value SendableResourceManagerInit(napi_env env, napi_value exports)
225 {
226 napi_property_descriptor functionProp[] = {
227 DECLARE_NAPI_FUNCTION("resourceToSendableResource", ResourceToSendableResource),
228 DECLARE_NAPI_FUNCTION("sendableResourceToResource", SendableResourceToResource),
229 };
230
231 napi_status status = napi_define_properties(env, exports, sizeof(functionProp) / sizeof(functionProp[0]),
232 functionProp);
233 if (status != napi_ok) {
234 RESMGR_HILOGE(RESMGR_JS_TAG, "Failed to set function at init");
235 return nullptr;
236 }
237
238 return exports;
239 }
240
241 static napi_module g_sendableResourceManagerModule = {
242 .nm_version = 1,
243 .nm_flags = 0,
244 .nm_filename = nullptr,
245 .nm_register_func = SendableResourceManagerInit,
246 .nm_modname = "sendableResourceManager",
247 .nm_priv = ((void*)0),
248 .reserved = {0}
249 };
250
ResMgrRegister()251 extern "C" __attribute__((constructor)) void ResMgrRegister()
252 {
253 napi_module_register(&g_sendableResourceManagerModule);
254 }
255 } // namespace Resource
256 } // namespace Global
257 } // namespace OHOS