Files
ace_engine_lite/frameworks/module_manager/module_manager.cpp
T

348 lines
11 KiB
C++

/*
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "module_manager.h"
#include <stdlib.h>
#include <string.h>
#include "acelite_config.h"
#include "securec.h"
#include "ace_log.h"
#include "internal/jsi_internal.h"
#include "ohos_module_config.h"
namespace OHOS {
namespace ACELite {
// Initialization of static variables
JSIValue ModuleManager::requiredSystemModules = 0;
JSIValue ModuleManager::RequireModule(const char * const moduleName)
{
char* category = nullptr;
char* name = nullptr;
if (!ParseModuleName(moduleName, &category, &name)) {
HILOG_ERROR(HILOG_MODULE_ACE, "ModuleManager::RequireModule: parse module name failed");
return JSI::CreateUndefined();
}
JSIValue moduleObj;
if (!strcmp(category, CATEGORY_SYSTEM) || !strcmp(category, CATEGORY_OHOS)) {
uint16_t moduleCount = sizeof(OHOS_MODULES) / sizeof(Module);
moduleObj = GetModuleObject(name, OHOS_MODULES, moduleCount, requiredSystemModules);
#if (FEATURE_PRODUCT_MODULE == 1)
if ((JSI::ValueIsUndefined(moduleObj)) && (productModulesGetter_ != nullptr)) {
uint16_t prodModCount;
const Module* prodModules = productModulesGetter_(prodModCount);
moduleObj = GetModuleObject(name, prodModules, prodModCount, requiredSystemModules);
}
#endif // FEATURE_PRODUCT_MODULE
#if (FEATURE_PRIVATE_MODULE == 1)
if ((JSI::ValueIsUndefined(moduleObj)) && (privateModulesGetter_ != nullptr)) {
const char * const bundleName = (bundleNameGetter_ != nullptr) ? bundleNameGetter_() : nullptr;
moduleObj = GetModuleObject(name, nullptr, 0, requiredSystemModules, bundleName);
}
#endif // FEATURE_PRIVATE_MODULE
} else {
moduleObj = JSI::CreateUndefined();
HILOG_ERROR(HILOG_MODULE_ACE, "ModuleManager:RequireModule category %{public}s does not exists!", category);
}
ace_free(category);
category = nullptr;
ace_free(name);
name = nullptr;
return moduleObj;
}
void ModuleManager::CleanUpModule()
{
if (requiredSystemModules != 0) {
JSI::ReleaseValue(requiredSystemModules);
requiredSystemModules = 0;
}
InvokeCallbacks(onDestroyHead_);
}
bool ModuleManager::ParseModuleName(const char * const moduleName, char** category, char** name) const
{
if ((moduleName == nullptr) || (category == nullptr) || (name == nullptr)) {
return false;
}
// Get moduleName str
char* str = nullptr;
if (!CreateString(moduleName, &str)) {
return false;
}
// Get category
char* next = nullptr;
char* tokenStr = strtok_s(str, ".", &next);
if (!CreateString(tokenStr, category)) {
ace_free(str);
str = nullptr;
return false;
}
// Get the rest as name
if (!CreateString(next, name)) {
ace_free(str);
str = nullptr;
ace_free(*category);
*category = nullptr;
return false;
}
ace_free(str);
str = nullptr;
tokenStr = nullptr;
next = nullptr;
return true;
}
bool ModuleManager::CreateString(const char * const srcStr, char** resPtr) const
{
if ((srcStr == nullptr) || (resPtr == nullptr)) {
return false;
}
size_t length = strlen(srcStr);
if (length >= UINT16_MAX) {
return false;
}
(*resPtr) = static_cast<char *>(ace_malloc(length + 1));
if ((*resPtr) == nullptr) {
return false;
}
if (memcpy_s((*resPtr), length, srcStr, length) != 0) {
ace_free(*resPtr);
*resPtr = nullptr;
return false;
}
(*resPtr)[length] = '\0';
return true;
}
JSIValue ModuleManager::GetModuleObject(const char * const moduleName, const Module* modules, uint16_t modulesCount,
JSIValue& categoryObj, const char * const bundleName)
{
if (moduleName == nullptr) {
return JSI::CreateUndefined();
}
if (bundleName == nullptr) {
if (modules == nullptr) {
return JSI::CreateUndefined();
}
for (uint16_t i = 0; i < modulesCount; i++) {
const char *regName = modules[i].name;
if ((regName != nullptr) && (strcmp(moduleName, regName) == 0)) {
return InitModuleObject(moduleName, modules[i], categoryObj);
}
}
}
#if (FEATURE_PRIVATE_MODULE == 1)
else {
uint16_t count;
const PrivateModule *privateModules =
(privateModulesGetter_ != nullptr) ? privateModulesGetter_(count) : nullptr;
if (privateModules == nullptr) {
return JSI::CreateUndefined();
}
for (uint16_t i = 0; i < count; i++) {
const char *regBundleName = privateModules[i].bundleName;
const char *regPrivateName = privateModules[i].module.name;
if ((regBundleName != nullptr) && (regPrivateName != nullptr) &&
(strcmp(bundleName, regBundleName) == 0) &&
(strcmp(moduleName, regPrivateName) == 0)) {
return InitModuleObject(moduleName, privateModules[i].module, categoryObj);
}
}
HILOG_WARN(HILOG_MODULE_ACE, "ModuleManager:module %{public}s does not exists!", moduleName);
}
#endif
return JSI::CreateUndefined();
}
JSIValue ModuleManager::InitModuleObject(const char * const name, Module module, JSIValue& categoryObj)
{
if (categoryObj == 0) {
categoryObj = JSI::CreateObject();
}
// Get module object from cached object
JSIValue moduleObj = JSI::GetNamedProperty(categoryObj, name);
if (JSI::ValueIsUndefined(moduleObj)) {
JSIValue exports = JSI::CreateObject();
module.initFunc(exports);
// Get OnDestroy callback from module object
NativeCallback destroy = GetNativeCallback(exports, nullptr);
JsiCallback destroyHandler = GetJsiCallback(exports, ON_DESTROY_HANDLER);
InsertCallback(onDestroyHead_, destroy, destroyHandler);
// Insert OnTerminate callback to callback list
InsertTerminateCallback(name, exports);
// Set module object to cached object
JSI::SetNamedProperty(categoryObj, name, exports);
JSI::ReleaseValue(exports);
moduleObj = JSI::GetNamedProperty(categoryObj, name);
}
return moduleObj;
}
void ModuleManager::InsertTerminateCallback(const char * const name, const JSIValue& moduleObj)
{
if (name == nullptr) {
return;
}
// Determine if this callback has been inserted
CallbackNode *node = onTerminateHead_;
while (node != nullptr) {
if ((node->moduleName != nullptr) && (strcmp(name, node->moduleName) == 0)) {
return;
}
node = node->next;
}
// Get OnTerminate callback from module object
NativeCallback terminate = GetNativeCallback(moduleObj, ON_TERMINATE);
JsiCallback terminateHandler = GetJsiCallback(moduleObj, ON_TERMINATE_HANDLER);
InsertCallback(onTerminateHead_, terminate, terminateHandler, name);
}
void ModuleManager::OnTerminate()
{
InvokeCallbacks(onTerminateHead_);
}
void ModuleManager::InsertCallback(CallbackNode *&head, NativeCallback callback,
JsiCallback callbackHandler, const char * const moduleName) const
{
if ((callback == nullptr) && (callbackHandler == nullptr)) {
return;
}
auto node = new CallbackNode();
if (node == nullptr) {
return;
}
node->callback = callback;
node->callbackHandler = callbackHandler;
if (moduleName != nullptr) {
char *copiedName = nullptr;
if (CreateString(moduleName, &copiedName)) {
node->moduleName = copiedName;
}
}
if (head == nullptr) {
head = node;
} else {
node->next = head;
head = node;
}
}
void ModuleManager::InvokeCallbacks(CallbackNode *&head) const
{
CallbackNode *node = head;
while (node != nullptr) {
NativeCallback callback = node->callback;
JsiCallback callbackHandler = node->callbackHandler;
if (callback != nullptr) {
(*callback)();
}
if (callbackHandler != nullptr) {
(*callbackHandler)(JSI_ERR_OK);
}
head = node->next;
delete node;
node = head;
}
head = nullptr;
}
void* ModuleManager::GetObjectPointer(JSIValue object) const
{
if (!JSI::ValueIsObject(object)) {
return nullptr;
}
void *nativePtr = nullptr;
jerry_value_t jObj = AS_JERRY_VALUE(object);
bool exist = jerry_get_object_native_pointer(jObj, &nativePtr, nullptr);
if (!exist || (nativePtr == nullptr)) {
return nullptr;
}
jerry_delete_object_native_pointer(jObj, nullptr);
return nativePtr;
}
void* ModuleManager::GetObjectNamedPointer(JSIValue object, const char * const name) const
{
if (!JSI::ValueIsObject(object)) {
return nullptr;
}
JSIValue funObj = JSI::GetNamedProperty(object, name);
void *nativePtr = nullptr;
if (JSI::ValueIsObject(funObj)) {
nativePtr = GetObjectPointer(funObj);
DeleteObjectProperty(object, name);
}
JSI::ReleaseValue(funObj);
return nativePtr;
}
void ModuleManager::DeleteObjectProperty(JSIValue object, const char * const name) const
{
if (name == nullptr) {
return;
}
jerry_value_t jName = jerry_create_string(reinterpret_cast<const jerry_char_t *>(name));
jerry_delete_property(AS_JERRY_VALUE(object), jName);
jerry_release_value(jName);
}
NativeCallback ModuleManager::GetNativeCallback(JSIValue object, const char * const name) const
{
void *callback = nullptr;
if (name == nullptr) {
callback = GetObjectPointer(object);
} else {
callback = GetObjectNamedPointer(object, name);
}
return reinterpret_cast<NativeCallback>(callback);
}
JsiCallback ModuleManager::GetJsiCallback(JSIValue object, const char * const name) const
{
void *callback = GetObjectNamedPointer(object, name);
return reinterpret_cast<JsiCallback>(callback);
}
void ModuleManager::SetProductModulesGetter(ProductModulesGetter getter)
{
productModulesGetter_ = getter;
}
void ModuleManager::SetPrivateModulesGetter(PrivateModulesGetter getter)
{
privateModulesGetter_ = getter;
}
void ModuleManager::SetBundleNameGetter(BundleNameGetter getter)
{
bundleNameGetter_ = getter;
}
} // namespace ACELite
} // namespace OHOS