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