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