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