mirror of
https://github.com/openharmony/ace_napi.git
synced 2026-07-22 09:15:27 -04:00
1782f29b01
Signed-off-by: zhongjianfei <zhongjianfei@huawei.com> Change-Id: I66daa8e153c20f4edad03808ce0d96cb9bc275f3
218 lines
6.7 KiB
C++
218 lines
6.7 KiB
C++
/*
|
|
* Copyright (c) 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 "native_module_manager.h"
|
|
|
|
#include "native_engine/native_engine.h"
|
|
|
|
#include "securec.h"
|
|
#include "utils/log.h"
|
|
|
|
#include <dirent.h>
|
|
#include <dlfcn.h>
|
|
|
|
NativeModuleManager NativeModuleManager::instance_;
|
|
|
|
NativeModuleManager::NativeModuleManager()
|
|
{
|
|
firstNativeModule_ = nullptr;
|
|
lastNativeModule_ = nullptr;
|
|
|
|
pthread_mutex_init(&mutex_, nullptr);
|
|
}
|
|
|
|
NativeModuleManager::~NativeModuleManager()
|
|
{
|
|
NativeModule* nativeModule = firstNativeModule_;
|
|
while (nativeModule != nullptr) {
|
|
nativeModule = nativeModule->next;
|
|
delete firstNativeModule_;
|
|
firstNativeModule_ = nativeModule;
|
|
}
|
|
firstNativeModule_ = lastNativeModule_ = nullptr;
|
|
|
|
pthread_mutex_destroy(&mutex_);
|
|
}
|
|
|
|
NativeModuleManager* NativeModuleManager::GetInstance()
|
|
{
|
|
return &instance_;
|
|
}
|
|
|
|
void NativeModuleManager::Register(NativeModule* nativeModule)
|
|
{
|
|
if (nativeModule == nullptr) {
|
|
HILOG_ERROR("nativeModule value is null");
|
|
return;
|
|
}
|
|
|
|
if (firstNativeModule_ == lastNativeModule_ && lastNativeModule_ == nullptr) {
|
|
firstNativeModule_ = new NativeModule();
|
|
if (firstNativeModule_ == nullptr) {
|
|
HILOG_ERROR("first NativeModule create failed");
|
|
return;
|
|
}
|
|
lastNativeModule_ = firstNativeModule_;
|
|
} else {
|
|
auto next = new NativeModule();
|
|
if (next == nullptr) {
|
|
HILOG_ERROR("next NativeModule create failed");
|
|
return;
|
|
}
|
|
lastNativeModule_->next = next;
|
|
lastNativeModule_ = lastNativeModule_->next;
|
|
}
|
|
|
|
lastNativeModule_->version = nativeModule->version;
|
|
lastNativeModule_->fileName = nativeModule->fileName;
|
|
lastNativeModule_->name = nativeModule->name;
|
|
lastNativeModule_->refCount = nativeModule->refCount;
|
|
lastNativeModule_->registerCallback = nativeModule->registerCallback;
|
|
lastNativeModule_->next = nullptr;
|
|
}
|
|
|
|
NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName, bool internal)
|
|
{
|
|
if (moduleName == nullptr) {
|
|
HILOG_ERROR("moduleName value is null");
|
|
return nullptr;
|
|
}
|
|
|
|
if (pthread_mutex_lock(&mutex_) != 0) {
|
|
HILOG_ERROR("pthread_mutex_lock is failed");
|
|
return nullptr;
|
|
}
|
|
|
|
NativeModule* nativeModule = FindNativeModuleByCache(moduleName);
|
|
if (nativeModule == nullptr) {
|
|
HILOG_INFO("not in cache: moduleName: %{public}s", moduleName);
|
|
nativeModule = FindNativeModuleByDisk(moduleName, internal);
|
|
}
|
|
|
|
if (pthread_mutex_unlock(&mutex_) != 0) {
|
|
HILOG_ERROR("pthread_mutex_unlock is failed");
|
|
return nullptr;
|
|
}
|
|
|
|
return nativeModule;
|
|
}
|
|
|
|
bool NativeModuleManager::GetNativeModulePath(const char* moduleName, char* nativeModulePath, int32_t pathLength)
|
|
{
|
|
const char* soPostfix = ".so";
|
|
#ifdef _ARM64_
|
|
const char* prefix = "/system/lib64/module";
|
|
#else
|
|
const char* prefix = "/system/lib/module";
|
|
#endif
|
|
|
|
int32_t lengthOfModuleName = strlen(moduleName);
|
|
char dupModuleName[PATH_MAX] = { 0 };
|
|
if (strcpy_s(dupModuleName, PATH_MAX, moduleName) != 0) {
|
|
HILOG_ERROR("strcpy moduleName failed");
|
|
return false;
|
|
}
|
|
|
|
for (int32_t i = 0; i < lengthOfModuleName; i++) {
|
|
dupModuleName[i] = tolower(dupModuleName[i]);
|
|
}
|
|
|
|
int32_t lengthOfPostfix = strlen(soPostfix);
|
|
if ((lengthOfModuleName > lengthOfPostfix) &&
|
|
(strcmp(dupModuleName + lengthOfModuleName - lengthOfPostfix, soPostfix) == 0)) {
|
|
if (sprintf_s(nativeModulePath, pathLength, "%s/%s", prefix, dupModuleName) == -1) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
char* lastDot = strrchr(dupModuleName, '.');
|
|
if (lastDot == nullptr) {
|
|
if (sprintf_s(nativeModulePath, pathLength, "%s/lib%s.z.so", prefix, dupModuleName) == -1) {
|
|
return false;
|
|
}
|
|
} else {
|
|
char* afterDot = lastDot + 1;
|
|
if (*afterDot == '\0') {
|
|
return false;
|
|
}
|
|
*lastDot = '\0';
|
|
lengthOfModuleName = strlen(dupModuleName);
|
|
for (int32_t i = 0; i < lengthOfModuleName; i++) {
|
|
if (*(dupModuleName + i) == '.') {
|
|
*(dupModuleName + i) = '/';
|
|
}
|
|
}
|
|
if (sprintf_s(nativeModulePath, pathLength, "%s/%s/lib%s.z.so", prefix, dupModuleName, afterDot) == -1) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
using NAPIGetJSCode = void (*)(const char** buf, int* bufLen);
|
|
NativeModule* NativeModuleManager::FindNativeModuleByDisk(const char* moduleName, bool internal)
|
|
{
|
|
char nativeModulePath[PATH_MAX] = { 0 };
|
|
if (!GetNativeModulePath(moduleName, nativeModulePath, sizeof(nativeModulePath))) {
|
|
HILOG_ERROR("get module filed");
|
|
return nullptr;
|
|
}
|
|
|
|
HILOG_INFO("get module path: %{public}s", nativeModulePath);
|
|
if (strlen(nativeModulePath) == 0) {
|
|
return nullptr;
|
|
}
|
|
void* lib = dlopen(nativeModulePath, RTLD_LAZY);
|
|
if (lib == nullptr) {
|
|
HILOG_ERROR("dlopen failed: %{public}s", dlerror());
|
|
return nullptr;
|
|
}
|
|
|
|
if (!internal) {
|
|
char symbol[PATH_MAX] = { 0 };
|
|
if (sprintf_s(symbol, sizeof(symbol), "NAPI_%s_GetJSCode", moduleName) == -1) {
|
|
return nullptr;
|
|
}
|
|
auto getJSCode = reinterpret_cast<NAPIGetJSCode>(dlsym(lib, symbol));
|
|
if (getJSCode != nullptr) {
|
|
const char* buf = nullptr;
|
|
int bufLen = 0;
|
|
getJSCode(&buf, &bufLen);
|
|
if (lastNativeModule_ != nullptr) {
|
|
HILOG_INFO("get js code from module: bufLen: %{public}d", bufLen);
|
|
lastNativeModule_->jsCode = buf;
|
|
lastNativeModule_->jsCodeLen = bufLen;
|
|
}
|
|
} else {
|
|
HILOG_INFO("no %{public}s in %{public}s", symbol, nativeModulePath);
|
|
}
|
|
}
|
|
|
|
return lastNativeModule_;
|
|
}
|
|
|
|
NativeModule* NativeModuleManager::FindNativeModuleByCache(const char* moduleName)
|
|
{
|
|
NativeModule* result = nullptr;
|
|
for (NativeModule* temp = firstNativeModule_; temp != nullptr; temp = temp->next) {
|
|
if (!strcmp(temp->name, moduleName)) {
|
|
result = temp;
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|