1 /*
2 * Copyright (c) 2020-2022 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 "module_manager.h"
17 #include <stdlib.h>
18 #include <string.h>
19 #include "acelite_config.h"
20 #include "securec.h"
21 #include "ace_log.h"
22 #include "internal/jsi_internal.h"
23 #include "ohos_module_config.h"
24
25 namespace OHOS {
26 namespace ACELite {
27 // Initialization of static variables
28 JSIValue ModuleManager::requiredSystemModules = 0;
29
RequireModule(const char * const moduleName)30 JSIValue ModuleManager::RequireModule(const char * const moduleName)
31 {
32 char* category = nullptr;
33 char* name = nullptr;
34 if (!ParseModuleName(moduleName, &category, &name)) {
35 HILOG_ERROR(HILOG_MODULE_ACE, "ModuleManager::RequireModule: parse module name failed");
36 return JSI::CreateUndefined();
37 }
38
39 JSIValue moduleObj;
40 if (!strcmp(category, CATEGORY_SYSTEM) || !strcmp(category, CATEGORY_OHOS)) {
41 uint16_t moduleCount = sizeof(OHOS_MODULES) / sizeof(Module);
42 moduleObj = GetModuleObject(name, OHOS_MODULES, moduleCount, requiredSystemModules);
43 #if (FEATURE_PRODUCT_MODULE == 1)
44 if ((JSI::ValueIsUndefined(moduleObj)) && (productModulesGetter_ != nullptr)) {
45 uint16_t prodModCount;
46 const Module* prodModules = productModulesGetter_(prodModCount);
47 moduleObj = GetModuleObject(name, prodModules, prodModCount, requiredSystemModules);
48 }
49 #endif // FEATURE_PRODUCT_MODULE
50 #if (FEATURE_PRIVATE_MODULE == 1)
51 if ((JSI::ValueIsUndefined(moduleObj)) && (privateModulesGetter_ != nullptr)) {
52 const char * const bundleName = (bundleNameGetter_ != nullptr) ? bundleNameGetter_() : nullptr;
53 moduleObj = GetModuleObject(name, nullptr, 0, requiredSystemModules, bundleName);
54 }
55 #endif // FEATURE_PRIVATE_MODULE
56 } else {
57 moduleObj = JSI::CreateUndefined();
58 HILOG_ERROR(HILOG_MODULE_ACE, "ModuleManager:RequireModule category %{public}s does not exists!", category);
59 }
60
61 ace_free(category);
62 category = nullptr;
63 ace_free(name);
64 name = nullptr;
65 return moduleObj;
66 }
67
CleanUpModule()68 void ModuleManager::CleanUpModule()
69 {
70 if (requiredSystemModules != 0) {
71 JSI::ReleaseValue(requiredSystemModules);
72 requiredSystemModules = 0;
73 }
74 InvokeCallbacks(onDestroyHead_);
75 }
76
ParseModuleName(const char * const moduleName,char ** category,char ** name) const77 bool ModuleManager::ParseModuleName(const char * const moduleName, char** category, char** name) const
78 {
79 if ((moduleName == nullptr) || (category == nullptr) || (name == nullptr)) {
80 return false;
81 }
82 // Get moduleName str
83 char* str = nullptr;
84 if (!CreateString(moduleName, &str)) {
85 return false;
86 }
87
88 // Get category
89 char* next = nullptr;
90 char* tokenStr = strtok_s(str, ".", &next);
91 if (!CreateString(tokenStr, category)) {
92 ace_free(str);
93 str = nullptr;
94 return false;
95 }
96
97 // Get the rest as name
98 if (!CreateString(next, name)) {
99 ace_free(str);
100 str = nullptr;
101 ace_free(*category);
102 *category = nullptr;
103 return false;
104 }
105
106 ace_free(str);
107 str = nullptr;
108 tokenStr = nullptr;
109 next = nullptr;
110 return true;
111 }
112
CreateString(const char * const srcStr,char ** resPtr) const113 bool ModuleManager::CreateString(const char * const srcStr, char** resPtr) const
114 {
115 if ((srcStr == nullptr) || (resPtr == nullptr)) {
116 return false;
117 }
118 size_t length = strlen(srcStr);
119 if (length >= UINT16_MAX) {
120 return false;
121 }
122 (*resPtr) = static_cast<char *>(ace_malloc(length + 1));
123 if ((*resPtr) == nullptr) {
124 return false;
125 }
126 if (memcpy_s((*resPtr), length, srcStr, length) != 0) {
127 ace_free(*resPtr);
128 *resPtr = nullptr;
129 return false;
130 }
131
132 (*resPtr)[length] = '\0';
133 return true;
134 }
135
GetModuleObject(const char * const moduleName,const Module * modules,uint16_t modulesCount,JSIValue & categoryObj,const char * const bundleName)136 JSIValue ModuleManager::GetModuleObject(const char * const moduleName, const Module* modules, uint16_t modulesCount,
137 JSIValue& categoryObj, const char * const bundleName)
138 {
139 if (moduleName == nullptr) {
140 return JSI::CreateUndefined();
141 }
142 if (bundleName == nullptr) {
143 if (modules == nullptr) {
144 return JSI::CreateUndefined();
145 }
146 for (uint16_t i = 0; i < modulesCount; i++) {
147 const char *regName = modules[i].name;
148 if ((regName != nullptr) && (strcmp(moduleName, regName) == 0)) {
149 return InitModuleObject(moduleName, modules[i], categoryObj);
150 }
151 }
152 }
153 #if (FEATURE_PRIVATE_MODULE == 1)
154 else {
155 uint16_t count;
156 const PrivateModule *privateModules =
157 (privateModulesGetter_ != nullptr) ? privateModulesGetter_(count) : nullptr;
158 if (privateModules == nullptr) {
159 return JSI::CreateUndefined();
160 }
161 for (uint16_t i = 0; i < count; i++) {
162 const char *regBundleName = privateModules[i].bundleName;
163 const char *regPrivateName = privateModules[i].module.name;
164 if ((regBundleName != nullptr) && (regPrivateName != nullptr) &&
165 (strcmp(bundleName, regBundleName) == 0) &&
166 (strcmp(moduleName, regPrivateName) == 0)) {
167 return InitModuleObject(moduleName, privateModules[i].module, categoryObj);
168 }
169 }
170 HILOG_WARN(HILOG_MODULE_ACE, "ModuleManager:module %{public}s does not exists!", moduleName);
171 }
172 #endif
173 return JSI::CreateUndefined();
174 }
175
InitModuleObject(const char * const name,Module module,JSIValue & categoryObj)176 JSIValue ModuleManager::InitModuleObject(const char * const name, Module module, JSIValue& categoryObj)
177 {
178 if (categoryObj == 0) {
179 categoryObj = JSI::CreateObject();
180 }
181
182 // Get module object from cached object
183 JSIValue moduleObj = JSI::GetNamedProperty(categoryObj, name);
184 if (JSI::ValueIsUndefined(moduleObj)) {
185 JSIValue exports = JSI::CreateObject();
186 module.initFunc(exports);
187
188 // Get OnDestroy callback from module object
189 NativeCallback destroy = GetNativeCallback(exports, nullptr);
190 JsiCallback destroyHandler = GetJsiCallback(exports, ON_DESTROY_HANDLER);
191 InsertCallback(onDestroyHead_, destroy, destroyHandler);
192
193 // Insert OnTerminate callback to callback list
194 InsertTerminateCallback(name, exports);
195
196 // Set module object to cached object
197 JSI::SetNamedProperty(categoryObj, name, exports);
198 JSI::ReleaseValue(exports);
199 moduleObj = JSI::GetNamedProperty(categoryObj, name);
200 }
201 return moduleObj;
202 }
203
InsertTerminateCallback(const char * const name,const JSIValue & moduleObj)204 void ModuleManager::InsertTerminateCallback(const char * const name, const JSIValue& moduleObj)
205 {
206 if (name == nullptr) {
207 return;
208 }
209 // Determine if this callback has been inserted
210 CallbackNode *node = onTerminateHead_;
211 while (node != nullptr) {
212 if ((node->moduleName != nullptr) && (strcmp(name, node->moduleName) == 0)) {
213 return;
214 }
215 node = node->next;
216 }
217 // Get OnTerminate callback from module object
218 NativeCallback terminate = GetNativeCallback(moduleObj, ON_TERMINATE);
219 JsiCallback terminateHandler = GetJsiCallback(moduleObj, ON_TERMINATE_HANDLER);
220 InsertCallback(onTerminateHead_, terminate, terminateHandler, name);
221 }
222
OnTerminate()223 void ModuleManager::OnTerminate()
224 {
225 InvokeCallbacks(onTerminateHead_);
226 }
227
InsertCallback(CallbackNode * & head,NativeCallback callback,JsiCallback callbackHandler,const char * const moduleName) const228 void ModuleManager::InsertCallback(CallbackNode *&head, NativeCallback callback,
229 JsiCallback callbackHandler, const char * const moduleName) const
230 {
231 if ((callback == nullptr) && (callbackHandler == nullptr)) {
232 return;
233 }
234 auto node = new CallbackNode();
235 if (node == nullptr) {
236 return;
237 }
238 node->callback = callback;
239 node->callbackHandler = callbackHandler;
240 if (moduleName != nullptr) {
241 char *copiedName = nullptr;
242 if (CreateString(moduleName, &copiedName)) {
243 node->moduleName = copiedName;
244 }
245 }
246
247 if (head == nullptr) {
248 head = node;
249 } else {
250 node->next = head;
251 head = node;
252 }
253 }
254
InvokeCallbacks(CallbackNode * & head) const255 void ModuleManager::InvokeCallbacks(CallbackNode *&head) const
256 {
257 CallbackNode *node = head;
258 while (node != nullptr) {
259 NativeCallback callback = node->callback;
260 JsiCallback callbackHandler = node->callbackHandler;
261 if (callback != nullptr) {
262 (*callback)();
263 }
264 if (callbackHandler != nullptr) {
265 (*callbackHandler)(JSI_ERR_OK);
266 }
267
268 head = node->next;
269 delete node;
270 node = head;
271 }
272 head = nullptr;
273 }
274
GetObjectPointer(JSIValue object) const275 void* ModuleManager::GetObjectPointer(JSIValue object) const
276 {
277 if (!JSI::ValueIsObject(object)) {
278 return nullptr;
279 }
280 void *nativePtr = nullptr;
281 jerry_value_t jObj = AS_JERRY_VALUE(object);
282 bool exist = jerry_get_object_native_pointer(jObj, &nativePtr, nullptr);
283 if (!exist || (nativePtr == nullptr)) {
284 return nullptr;
285 }
286 jerry_delete_object_native_pointer(jObj, nullptr);
287 return nativePtr;
288 }
289
GetObjectNamedPointer(JSIValue object,const char * const name) const290 void* ModuleManager::GetObjectNamedPointer(JSIValue object, const char * const name) const
291 {
292 if (!JSI::ValueIsObject(object)) {
293 return nullptr;
294 }
295 JSIValue funObj = JSI::GetNamedProperty(object, name);
296 void *nativePtr = nullptr;
297 if (JSI::ValueIsObject(funObj)) {
298 nativePtr = GetObjectPointer(funObj);
299 DeleteObjectProperty(object, name);
300 }
301 JSI::ReleaseValue(funObj);
302 return nativePtr;
303 }
304
DeleteObjectProperty(JSIValue object,const char * const name) const305 void ModuleManager::DeleteObjectProperty(JSIValue object, const char * const name) const
306 {
307 if (name == nullptr) {
308 return;
309 }
310 jerry_value_t jName = jerry_create_string(reinterpret_cast<const jerry_char_t *>(name));
311 jerry_delete_property(AS_JERRY_VALUE(object), jName);
312 jerry_release_value(jName);
313 }
314
GetNativeCallback(JSIValue object,const char * const name) const315 NativeCallback ModuleManager::GetNativeCallback(JSIValue object, const char * const name) const
316 {
317 void *callback = nullptr;
318 if (name == nullptr) {
319 callback = GetObjectPointer(object);
320 } else {
321 callback = GetObjectNamedPointer(object, name);
322 }
323 return reinterpret_cast<NativeCallback>(callback);
324 }
325
GetJsiCallback(JSIValue object,const char * const name) const326 JsiCallback ModuleManager::GetJsiCallback(JSIValue object, const char * const name) const
327 {
328 void *callback = GetObjectNamedPointer(object, name);
329 return reinterpret_cast<JsiCallback>(callback);
330 }
331
332
SetProductModulesGetter(ProductModulesGetter getter)333 void ModuleManager::SetProductModulesGetter(ProductModulesGetter getter)
334 {
335 productModulesGetter_ = getter;
336 }
337
SetPrivateModulesGetter(PrivateModulesGetter getter)338 void ModuleManager::SetPrivateModulesGetter(PrivateModulesGetter getter)
339 {
340 privateModulesGetter_ = getter;
341 }
342
SetBundleNameGetter(BundleNameGetter getter)343 void ModuleManager::SetBundleNameGetter(BundleNameGetter getter)
344 {
345 bundleNameGetter_ = getter;
346 }
347 } // namespace ACELite
348 } // namespace OHOS
349