1/*
2 * Copyright (c) 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
16#include "native_module_manager.h"
17
18#include <cstring>
19#include <dirent.h>
20#include <fstream>
21#include <iostream>
22#include <mutex>
23#include <sstream>
24#include <unistd.h>
25
26#ifdef ENABLE_HITRACE
27#include "hitrace_meter.h"
28#endif
29#include "module_load_checker.h"
30#include "native_engine/native_engine.h"
31#include "securec.h"
32#include "utils/log.h"
33
34#define NDK "ndk"
35#define ALLOW_ALL_SHARED_LIBS "allow_all_shared_libs"
36
37namespace {
38constexpr static int32_t NATIVE_PATH_NUMBER = 3;
39constexpr static int32_t IS_APP_MODULE_FLAGS = 100;
40thread_local bool g_isLoadingModule = false;
41enum ModuleLoadFailedReason : uint32_t {
42    MODULE_LOAD_SUCCESS = 0,
43    MODULE_NOT_EXIST    = 1,
44};
45} // namespace
46
47NativeModuleManager* NativeModuleManager::instance_ = NULL;
48std::mutex g_instanceMutex;
49
50NativeModuleManager::NativeModuleManager()
51{
52    HILOG_DEBUG("enter");
53    pthread_mutex_init(&mutex_, nullptr);
54    moduleLoadChecker_ = std::make_unique<ModuleLoadChecker>();
55}
56
57NativeModuleManager::~NativeModuleManager()
58{
59    HILOG_INFO("enter");
60    {
61        std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
62        NativeModule* nativeModule = headNativeModule_;
63        while (nativeModule != nullptr) {
64            nativeModule = nativeModule->next;
65            if (headNativeModule_->name) {
66                delete[] headNativeModule_->name;
67            }
68            if (headNativeModule_->moduleName) {
69                delete[] headNativeModule_->moduleName;
70            }
71            if (headNativeModule_->jsABCCode) {
72                delete[] headNativeModule_->jsABCCode;
73            }
74            delete headNativeModule_;
75            headNativeModule_ = nativeModule;
76        }
77        headNativeModule_ = nullptr;
78        tailNativeModule_ = nullptr;
79    }
80
81#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
82    !defined(LINUX_PLATFORM)
83    if (sharedLibsSonames_) {
84        delete[] sharedLibsSonames_;
85    }
86#endif
87    appLibPathMapMutex_.lock();
88    for (const auto& item : appLibPathMap_) {
89        delete[] item.second;
90    }
91    std::map<std::string, char*>().swap(appLibPathMap_);
92    appLibPathMapMutex_.unlock();
93
94    while (nativeEngineList_.size() > 0) {
95        NativeEngine* wraper = nativeEngineList_.begin()->second;
96        if (wraper != nullptr) {
97            delete wraper;
98            wraper = nullptr;
99        }
100        nativeEngineList_.erase(nativeEngineList_.begin());
101    }
102    pthread_mutex_destroy(&mutex_);
103}
104
105NativeModuleManager* NativeModuleManager::GetInstance()
106{
107    if (instance_ == NULL) {
108        std::lock_guard<std::mutex> lock(g_instanceMutex);
109        if (instance_ == NULL) {
110            instance_ = new NativeModuleManager();
111            HILOG_DEBUG("create native module manager instance");
112        }
113    }
114    return instance_;
115}
116
117void NativeModuleManager::SetNativeEngine(std::string moduleKey, NativeEngine* nativeEngine)
118{
119    HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
120    if (nativeEngine != nullptr) {
121        nativeEngine->SetModuleName(moduleKey);
122    }
123    std::lock_guard<std::mutex> lock(nativeEngineListMutex_);
124    nativeEngineList_.emplace(moduleKey, nativeEngine);
125}
126
127void NativeModuleManager::EmplaceModuleLib(std::string moduleKey, const LIBHANDLE lib)
128{
129    HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
130    std::lock_guard<std::mutex> lock(moduleLibMutex_);
131    if (lib != nullptr) {
132        moduleLibMap_.emplace(moduleKey, lib);
133    }
134}
135
136bool NativeModuleManager::RemoveModuleLib(const std::string moduleKey)
137{
138    HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
139    bool deleted = false;
140    std::lock_guard<std::mutex> lock(moduleLibMutex_);
141    auto it = moduleLibMap_.find(moduleKey);
142    if (it != moduleLibMap_.end()) {
143        moduleLibMap_.erase(it);
144        HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
145        deleted = true;
146    }
147    return deleted;
148}
149
150LIBHANDLE NativeModuleManager::GetNativeModuleHandle(const std::string& moduleKey) const
151{
152    HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
153    std::lock_guard<std::mutex> lock(moduleLibMutex_);
154    auto it = moduleLibMap_.find(moduleKey);
155    if (it == moduleLibMap_.end()) {
156        return nullptr;
157    }
158    return it->second;
159}
160
161void NativeModuleManager::EmplaceModuleBuffer(const std::string moduleKey, const uint8_t* lib)
162{
163    HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
164    std::lock_guard<std::mutex> lock(moduleBufMutex_);
165    if (lib != nullptr) {
166        moduleBufMap_.emplace(moduleKey, lib);
167    }
168}
169
170bool NativeModuleManager::RemoveModuleBuffer(const std::string moduleKey)
171{
172    HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
173    bool deleted = false;
174    std::lock_guard<std::mutex> lock(moduleBufMutex_);
175    auto it = moduleBufMap_.find(moduleKey);
176    if (it != moduleBufMap_.end()) {
177        moduleBufMap_.erase(it);
178        HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
179        deleted = true;
180    }
181    return deleted;
182}
183
184const uint8_t* NativeModuleManager::GetBufferHandle(const std::string& moduleKey) const
185{
186    HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
187    std::lock_guard<std::mutex> lock(moduleBufMutex_);
188    auto it = moduleBufMap_.find(moduleKey);
189    if (it == moduleBufMap_.end()) {
190        return nullptr;
191    }
192    return it->second;
193}
194
195bool NativeModuleManager::RemoveNativeModule(const std::string& moduleKey)
196{
197    bool handleAbcRemoved = RemoveModuleBuffer(moduleKey);
198    bool handleRemoved = RemoveModuleLib(moduleKey);
199    bool moduleRemoved = RemoveNativeModuleByCache(moduleKey);
200
201    HILOG_DEBUG("handleAbcRemoved is %{public}d, handleRemoved is %{public}d, moduleRemoved is %{public}d",
202        handleAbcRemoved, handleRemoved, moduleRemoved);
203    return ((handleRemoved || handleAbcRemoved) && moduleRemoved);
204}
205
206bool NativeModuleManager::UnloadNativeModule(const std::string& moduleKey)
207{
208    HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
209    LIBHANDLE handle = GetNativeModuleHandle(moduleKey);
210    if (handle == nullptr) {
211        HILOG_ERROR("failed to get native module handle.");
212        return false;
213    }
214
215    if (RemoveNativeModule(moduleKey) == false) {
216        HILOG_ERROR("remove native module failed.");
217        return false;
218    }
219
220    return UnloadModuleLibrary(handle);
221}
222
223std::string NativeModuleManager::GetModuleFileName(const char* moduleName, bool isAppModule)
224{
225    if (moduleName == nullptr) {
226        HILOG_ERROR("invalid param. moduleName is nullptr");
227        return "";
228    }
229    HILOG_INFO("moduleName is '%{public}s', isAppModule is %{public}d", moduleName, isAppModule);
230
231    std::string loadPath;
232    std::string name = isAppModule ? (prefix_ + "/" + moduleName) : moduleName;
233    char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
234    const char* pathKey = "default";
235    if (!GetNativeModulePath(moduleName, pathKey, "", isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
236        HILOG_ERROR("get native module path failed");
237        return loadPath;
238    }
239    NativeModule* cacheNativeModule = nullptr;
240    NativeModuleHeadTailStruct cacheHeadTailNativeModule;
241    NativeModule* module =
242        FindNativeModuleByCache(name.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
243    if (module == nullptr) {
244        HILOG_ERROR("get module file name failed");
245        return loadPath;
246    }
247    loadPath = nativeModulePath[0];
248    if (isAppModule && IsExistedPath(pathKey)) {
249        std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
250        loadPath = std::string(appLibPathMap_[pathKey]) + "/" + nativeModulePath[0];
251    }
252    HILOG_ERROR("get module file name failed, moduleName is %{public}s", moduleName);
253    return loadPath;
254}
255
256void NativeModuleManager::Register(NativeModule* nativeModule)
257{
258    if (nativeModule == nullptr) {
259        HILOG_ERROR("nativeModule value is null");
260        return;
261    }
262
263    HILOG_DEBUG("native module name is '%{public}s'", nativeModule->name);
264    std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
265    const char *nativeModuleName = nativeModule->name == nullptr ? "" : nativeModule->name;
266    std::string appName = prefix_ + "/" + nativeModuleName;
267    std::string tmpName = isAppModule_ ? appName : nativeModuleName;
268    if (nativeModule->flags == IS_APP_MODULE_FLAGS) {
269        std::string prefix = "default/";
270        tmpName = prefix + nativeModuleName;
271    }
272    char *moduleName = strdup(tmpName.c_str());
273    if (moduleName == nullptr) {
274        HILOG_ERROR("strdup failed. tmpName is %{public}s", tmpName.c_str());
275        return;
276    }
277
278    if (g_isLoadingModule || !strcmp(loadingModuleName_.c_str(), moduleName)) {
279        if (!CreateTailNativeModule()) {
280            HILOG_ERROR("create tail nativeModule failed");
281            delete moduleName;
282            return;
283        }
284        tailNativeModule_->version = nativeModule->version;
285        tailNativeModule_->fileName = nativeModule->fileName;
286        tailNativeModule_->isAppModule = isAppModule_;
287        tailNativeModule_->name = moduleName;
288        tailNativeModule_->moduleName = nullptr;  /* we update moduleName latter */
289        tailNativeModule_->refCount = nativeModule->refCount;
290        tailNativeModule_->registerCallback = nativeModule->registerCallback;
291        tailNativeModule_->getJSCode = nativeModule->getJSCode;
292        tailNativeModule_->getABCCode = nativeModule->getABCCode;
293        tailNativeModule_->next = nullptr;
294        tailNativeModule_->moduleLoaded = true;
295        tailNativeModule_->systemFilePath = "";
296        HILOG_INFO("At tail register module name is '%{public}s', isAppModule is %{public}d",
297            tailNativeModule_->name, isAppModule_);
298    } else {
299        if (!CreateHeadNativeModule()) {
300            HILOG_ERROR("create head nativeModule failed");
301            return;
302        }
303        headNativeModule_->version = nativeModule->version;
304        headNativeModule_->fileName = nativeModule->fileName;
305        headNativeModule_->isAppModule = isAppModule_;
306        headNativeModule_->name = moduleName;
307        headNativeModule_->refCount = nativeModule->refCount;
308        headNativeModule_->registerCallback = nativeModule->registerCallback;
309        headNativeModule_->getJSCode = nativeModule->getJSCode;
310        headNativeModule_->getABCCode = nativeModule->getABCCode;
311        headNativeModule_->moduleLoaded = true;
312        headNativeModule_->systemFilePath = "";
313        HILOG_INFO("At head register module name is '%{public}s', isAppModule is %{public}d",
314            headNativeModule_->name, isAppModule_);
315    }
316}
317
318bool NativeModuleManager::CreateHeadNativeModule()
319{
320    if (headNativeModule_ == tailNativeModule_ && tailNativeModule_ == nullptr) {
321        headNativeModule_ = new NativeModule();
322        if (headNativeModule_ == nullptr) {
323            HILOG_ERROR("first NativeModule create failed");
324            return false;
325        }
326        tailNativeModule_ = headNativeModule_;
327    } else {
328        auto head = new NativeModule();
329        if (head == nullptr) {
330            HILOG_ERROR("head NativeModule create failed");
331            return false;
332        }
333        if (headNativeModule_) {
334            head->next = headNativeModule_;
335            headNativeModule_ = head;
336        }
337    }
338    return true;
339}
340
341bool NativeModuleManager::CreateTailNativeModule()
342{
343    if (headNativeModule_ == tailNativeModule_ && tailNativeModule_ == nullptr) {
344        headNativeModule_ = new NativeModule();
345        if (headNativeModule_ == nullptr) {
346            HILOG_ERROR("first NativeModule create failed");
347            return false;
348        }
349        tailNativeModule_ = headNativeModule_;
350    } else {
351        auto tail = new NativeModule();
352        if (tail == nullptr) {
353            HILOG_ERROR("tail NativeModule create failed");
354            return false;
355        }
356        if (tailNativeModule_) {
357            tailNativeModule_->next = tail;
358            tailNativeModule_ = tailNativeModule_->next;
359        }
360    }
361    return true;
362}
363
364#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
365    !defined(LINUX_PLATFORM)
366void NativeModuleManager::CreateSharedLibsSonames()
367{
368    HILOG_DEBUG("enter");
369    const char* allowList[] = {
370        // bionic library
371        "libc.so",
372        "libdl.so",
373        "libm.so",
374        "libz.so",
375        "libclang_rt.asan.so",
376        "libclang_rt.tsan.so",
377        "libclang_rt.ubsan_standalone.so",
378        "libclang_rt.ubsan_minimal.so",
379        "libclang_rt.hwasan.so",
380        // z library
381        "libace_napi.z.so",
382        "libace_ndk.z.so",
383        "libcj_environment.z.so",
384        "libbundle_ndk.z.so",
385        "libdeviceinfo_ndk.z.so",
386        "libEGL.so",
387        "libGLESv3.so",
388        "libhiappevent_ndk.z.so",
389        "libhuks_ndk.z.so",
390        "libhukssdk.z.so",
391        "libnative_drawing.so",
392        "libnative_window.so",
393        "libnative_buffer.so",
394        "libnative_vsync.so",
395        "libOpenSLES.so",
396        "libpixelmap_ndk.z.so",
397        "libimage_ndk.z.so",
398        "libimage_receiver_ndk.z.so",
399        "libimage_source_ndk.z.so",
400        "librawfile.z.so",
401        "libuv.so",
402        "libhilog.so",
403        "libnative_image.so",
404        "libnative_media_adec.so",
405        "libnative_media_aenc.so",
406        "libnative_media_codecbase.so",
407        "libnative_media_core.so",
408        "libnative_media_vdec.so",
409        "libnative_media_venc.so",
410        "libnative_media_avmuxer.so",
411        "libnative_media_avdemuxer.so",
412        "libnative_media_avsource.so",
413        "libnative_avscreen_capture.so",
414        "libavplayer.so",
415        // adaptor library
416        "libohosadaptor.so",
417        "libusb_ndk.z.so",
418        "libvulkan.so",
419    };
420
421    size_t allowListLength = sizeof(allowList) / sizeof(char*);
422    int32_t sharedLibsSonamesLength = 1;
423    for (size_t i = 0; i < allowListLength; i++) {
424        sharedLibsSonamesLength += strlen(allowList[i]) + 1;
425    }
426    sharedLibsSonames_ = new char[sharedLibsSonamesLength];
427    int32_t cursor = 0;
428    for (size_t i = 0; i < allowListLength; i++) {
429        if (sprintf_s(sharedLibsSonames_ + cursor, sharedLibsSonamesLength - cursor, "%s:", allowList[i]) == -1) {
430            delete[] sharedLibsSonames_;
431            sharedLibsSonames_ = nullptr;
432            return;
433        }
434        cursor += strlen(allowList[i]) + 1;
435    }
436    sharedLibsSonames_[cursor] = '\0';
437}
438#endif
439
440void NativeModuleManager::CreateLdNamespace(const std::string moduleName, const char* lib_ld_path,
441                                            [[maybe_unused]] const bool& isSystemApp)
442{
443#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
444    !defined(LINUX_PLATFORM)
445    Dl_namespace current_ns;
446    Dl_namespace ns;
447
448    // Create module ns.
449    std::string nsName = "moduleNs_" + moduleName;
450    dlns_init(&ns, nsName.c_str());
451    dlns_get(nullptr, &current_ns);
452
453    Dl_namespace ndk_ns;
454    dlns_get(NDK, &ndk_ns);
455
456    if (isSystemApp) {
457        /*
458         * The app's so may have the same name as the system library, LOCAL_NS_PREFERED means linker will check
459         * and use the app's so first.
460         */
461        dlns_create2(&ns, lib_ld_path, LOCAL_NS_PREFERED);
462        // Performs a namespace check on the full path passed directly or the full path converted after setting rpath.
463        dlns_set_namespace_separated(nsName.c_str(), true);
464        // Allows access to subdirectories of this directory for shared objects (so).
465        dlns_set_namespace_permitted_paths(nsName.c_str(), lib_ld_path);
466        // System app can visit all ndk and default ns libs.
467        if (strlen(ndk_ns.name) > 0) {
468            dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
469            dlns_inherit(&ndk_ns, &current_ns, ALLOW_ALL_SHARED_LIBS);
470            dlns_inherit(&current_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
471            dlns_inherit(&ns, &current_ns, ALLOW_ALL_SHARED_LIBS);
472        }
473    } else {
474        dlns_create2(&ns, lib_ld_path, 0);
475        // Performs a namespace check on the full path passed directly or the full path converted after setting rpath.
476        dlns_set_namespace_separated(nsName.c_str(), true);
477        // Allows access to subdirectories of this directory for shared objects (so).
478        dlns_set_namespace_permitted_paths(nsName.c_str(), lib_ld_path);
479        // Non-system app can visit all ndk ns libs and default ns shared libs.
480        if (!sharedLibsSonames_) {
481            CreateSharedLibsSonames();
482        }
483        dlns_inherit(&ns, &current_ns, sharedLibsSonames_);
484        if (strlen(ndk_ns.name) > 0) {
485            dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
486            dlns_inherit(&ndk_ns, &current_ns, ALLOW_ALL_SHARED_LIBS);
487            dlns_inherit(&current_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
488        }
489    }
490
491    nsMap_[moduleName] = ns;
492
493    HILOG_DEBUG("end. moduleName: %{public}s, path: %{public}s", moduleName.c_str(), lib_ld_path);
494#endif
495}
496
497void NativeModuleManager::SetAppLibPath(const std::string& moduleName, const std::vector<std::string>& appLibPath,
498                                        const bool& isSystemApp)
499{
500    HILOG_DEBUG("moduleName is %{public}s, isisSystemApp is %{public}d", moduleName.c_str(), isSystemApp);
501
502    std::string tmpPath = "";
503    for (size_t i = 0; i < appLibPath.size(); i++) {
504        if (appLibPath[i].empty()) {
505            continue;
506        }
507        tmpPath += appLibPath[i];
508        tmpPath += ":";
509    }
510    if (tmpPath.back() == ':') {
511        tmpPath.pop_back();
512    }
513
514    char *tmp = strdup(tmpPath.c_str());
515    if (tmp == nullptr) {
516        HILOG_ERROR("strdup failed. tmpPath is %{public}s", tmpPath.c_str());
517        return;
518    }
519
520    std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
521    if (appLibPathMap_[moduleName] != nullptr) {
522        delete[] appLibPathMap_[moduleName];
523    }
524    appLibPathMap_[moduleName] = tmp;
525    CreateLdNamespace(moduleName, tmp, isSystemApp);
526    HILOG_DEBUG("path: %{public}s", appLibPathMap_[moduleName]);
527}
528
529void NativeModuleManager::MoveApiAllowListCheckerPtr(
530    std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, NativeModule* nativeModule)
531{
532    if (apiAllowListChecker != nullptr) {
533        nativeModule->apiAllowListChecker.reset(apiAllowListChecker.release());
534    }
535}
536
537NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName, const char* path, bool isAppModule,
538    std::string& errInfo, bool internal, const char* relativePath)
539{
540    if (moduleName == nullptr) {
541        errInfo = "load native module failed. moduleName is nullptr";
542        HILOG_ERROR("%{public}s", errInfo.c_str());
543        return nullptr;
544    }
545
546    if (relativePath == nullptr) {
547        errInfo = "load native module failed. relativePath is nullptr";
548        HILOG_ERROR("%{public}s", errInfo.c_str());
549        return nullptr;
550    }
551
552    HILOG_DEBUG("moduleName is %{public}s, path is %{public}s, relativePath is %{public}s",
553        moduleName, path, relativePath);
554
555    std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
556    if (moduleLoadChecker_ && !moduleLoadChecker_->DiskCheckOnly() &&
557        !moduleLoadChecker_->CheckModuleLoadable(moduleName, apiAllowListChecker)) {
558        errInfo = "module " + std::string(moduleName) + " is in blocklist, loading prohibited";
559        HILOG_ERROR("%{public}s", errInfo.c_str());
560        return nullptr;
561    }
562    std::string prefixTmp;
563#ifdef ANDROID_PLATFORM
564    std::string strModule(moduleName);
565    std::string strCutName = strModule;
566    if (path != nullptr) {
567        if (IsExistedPath(path)) {
568            strModule = path;
569        }
570        prefixTmp = "default";
571        strModule = prefixTmp + '/' + moduleName;
572    } else {
573        path = "default";
574        if (strModule.find(".") != std::string::npos) {
575            char* temp = const_cast<char*>(strCutName.c_str());
576            for (char* p = strchr(temp, '.'); p != nullptr; p = strchr(p + 1, '.')) {
577                *p = '_';
578            }
579        }
580    }
581#endif
582
583    char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
584    nativeModulePath[0][0] = 0;
585    nativeModulePath[1][0] = 0;
586    nativeModulePath[2][0] = 0; // 2 : Element index value
587    NativeModule* cacheNativeModule = nullptr;
588    NativeModuleHeadTailStruct cacheHeadTailNativeModule;
589#ifdef ANDROID_PLATFORM
590    if (!GetNativeModulePath(strCutName.c_str(), path, relativePath, isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
591        errInfo = "failed to get native file path of module " + std::string(moduleName);
592        HILOG_WARN("%{public}s", errInfo.c_str());
593        return nullptr;
594    }
595    NativeModule* nativeModule =
596        FindNativeModuleByCache(strModule.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
597#else
598    std::string key(moduleName);
599    if (isAppModule) {
600        prefixTmp = "default";
601        if (path && IsExistedPath(path)) {
602            prefixTmp = path;
603        }
604        key = prefixTmp + '/' + moduleName;
605        HILOG_INFO("key is %{public}s", key.c_str());
606    }
607    if (!GetNativeModulePath(moduleName, prefixTmp.c_str(), relativePath, isAppModule, nativeModulePath,
608                             NAPI_PATH_MAX)) {
609        errInfo = "failed to get native file path of module " + std::string(moduleName);
610        HILOG_WARN("%{public}s", errInfo.c_str());
611        return nullptr;
612    }
613#ifdef ENABLE_HITRACE
614    StartTrace(HITRACE_TAG_ACE, moduleName);
615#endif
616    NativeModule* nativeModule =
617        FindNativeModuleByCache(key.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
618#endif
619    if (nativeModule == nullptr) {
620        (void)pthread_mutex_lock(&mutex_);
621#ifndef IOS_PLATFORM
622        if (CheckNativeListChanged(cacheHeadTailNativeModule.headNativeModule,
623                                   cacheHeadTailNativeModule.tailNativeModule)) {
624#ifdef ANDROID_PLATFORM
625            nativeModule = FindNativeModuleByCache(strModule.c_str(), nativeModulePath, cacheNativeModule,
626                                                   cacheHeadTailNativeModule);
627#else
628            nativeModule =
629                FindNativeModuleByCache(key.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
630#endif
631        }
632#else
633#endif
634        if (nativeModule == nullptr) {
635            prefix_ = prefixTmp;
636            isAppModule_ = isAppModule;
637            g_isLoadingModule = true;
638#ifndef IOS_PLATFORM
639
640#ifdef ANDROID_PLATFORM
641            HILOG_DEBUG("module '%{public}s' does not in cache", strCutName.c_str());
642            nativeModule = FindNativeModuleByDisk(strCutName.c_str(), path, relativePath, internal, isAppModule,
643                                                  errInfo, nativeModulePath, cacheNativeModule);
644#else
645            HILOG_DEBUG("module '%{public}s' does not in cache", moduleName);
646            nativeModule = FindNativeModuleByDisk(moduleName, prefix_.c_str(), relativePath, internal, isAppModule,
647                                                  errInfo, nativeModulePath, cacheNativeModule);
648#endif
649
650#else
651            nativeModule =
652                FindNativeModuleByCache(moduleName, nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
653#endif
654            g_isLoadingModule = false;
655        }
656
657        (void)pthread_mutex_unlock(&mutex_);
658    }
659    MoveApiAllowListCheckerPtr(apiAllowListChecker, nativeModule);
660#ifdef ENABLE_HITRACE
661    FinishTrace(HITRACE_TAG_ACE);
662#endif
663    HILOG_DEBUG("load native module %{public}s", (nativeModule == nullptr) ? "failed" : "success");
664    return nativeModule;
665}
666
667bool NativeModuleManager::CheckNativeListChanged(
668    const NativeModule* cacheHeadNativeModule, const NativeModule* cacheTailNativeModule)
669{
670    std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
671    if (!cacheHeadNativeModule || !cacheTailNativeModule || !headNativeModule_ || !tailNativeModule_) {
672        return true;
673    }
674    if (strcmp(cacheHeadNativeModule->name, headNativeModule_->name) != 0 ||
675        strcmp(cacheTailNativeModule->name, tailNativeModule_->name) != 0) {
676        return true;
677    }
678
679    return false;
680}
681bool NativeModuleManager::GetNativeModulePath(const char* moduleName, const char* path,
682    const char* relativePath, bool isAppModule, char nativeModulePath[][NAPI_PATH_MAX], int32_t pathLength)
683{
684#ifdef WINDOWS_PLATFORM
685    const char* soPostfix = ".dll";
686    const char* zfix = "";
687    std::string sysPrefix("./module");
688    const char* abcfix = ".abc";
689    std::string sysAbcPrefix("./module");
690#elif defined(MAC_PLATFORM)
691    const char* soPostfix = ".dylib";
692    const char* zfix = "";
693    std::string sysPrefix("./module");
694    const char* abcfix = ".abc";
695    std::string sysAbcPrefix("./module");
696#elif defined(_ARM64_) || defined(SIMULATOR)
697    const char* soPostfix = ".so";
698    const char* zfix = ".z";
699    std::string sysPrefix("/system/lib64/module");
700    const char* abcfix = ".abc";
701    std::string sysAbcPrefix("/system/etc/abc");
702#elif defined(LINUX_PLATFORM)
703    const char* soPostfix = ".so";
704    const char* zfix = "";
705    std::string sysPrefix("./module");
706    const char* abcfix = ".abc";
707    std::string sysAbcPrefix("./module");
708#else
709    const char* soPostfix = ".so";
710    const char* zfix = ".z";
711    std::string sysPrefix("/system/lib/module");
712    const char* abcfix = ".abc";
713    std::string sysAbcPrefix("/system/etc/abc");
714#endif
715
716#ifdef ANDROID_PLATFORM
717    isAppModule = true;
718#endif
719    int32_t lengthOfModuleName = strlen(moduleName);
720    char dupModuleName[NAPI_PATH_MAX] = { 0 };
721    if (strcpy_s(dupModuleName, NAPI_PATH_MAX, moduleName) != 0) {
722        HILOG_ERROR("strcpy_s moduleName '%{public}s' failed", moduleName);
723        return false;
724    }
725
726    const char* prefix = nullptr;
727    if (isAppModule && IsExistedPath(path)) {
728        appLibPathMapMutex_.lock();
729        prefix = appLibPathMap_[path];
730        appLibPathMapMutex_.unlock();
731#ifdef ANDROID_PLATFORM
732        for (int32_t i = 0; i < lengthOfModuleName; i++) {
733            dupModuleName[i] = tolower(dupModuleName[i]);
734        }
735#endif
736    } else {
737        if (relativePath[0]) {
738            if (previewSearchPath_.empty()) {
739                sysPrefix = sysPrefix + "/" + relativePath;
740            } else {
741                sysPrefix = previewSearchPath_ + "/module";
742            }
743        }
744        prefix = sysPrefix.c_str();
745        for (int32_t i = 0; i < lengthOfModuleName; i++) {
746            dupModuleName[i] = tolower(dupModuleName[i]);
747        }
748    }
749
750    int32_t lengthOfPostfix = strlen(soPostfix);
751    if ((lengthOfModuleName > lengthOfPostfix) &&
752        (strcmp(dupModuleName + lengthOfModuleName - lengthOfPostfix, soPostfix) == 0)) {
753        if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s", prefix, dupModuleName) == -1) {
754            return false;
755        }
756        return true;
757    }
758
759    char* lastDot = strrchr(dupModuleName, '.');
760    if (lastDot == nullptr) {
761        if (!isAppModule || !IsExistedPath(path)) {
762#ifdef ANDROID_PLATFORM
763            if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
764                return false;
765            }
766#else
767            if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s%s",
768                prefix, dupModuleName, zfix, soPostfix) == -1) {
769                return false;
770            }
771#endif
772            if (sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s_napi%s%s",
773                prefix, dupModuleName, zfix, soPostfix) == -1) {
774                return false;
775            }
776
777            if (sprintf_s(nativeModulePath[2], pathLength, "%s/%s%s", // 2 : Element index value
778                sysAbcPrefix.c_str(), dupModuleName, abcfix) == -1) {
779                return false;
780            }
781        } else {
782#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
783    !defined(LINUX_PLATFORM)
784            if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
785                return false;
786            }
787#elif defined(ANDROID_PLATFORM)
788            std::string libPath;
789            int sprintfResult = 0;
790            std::string prefixStr = std::string(prefix);
791            std::size_t pos = prefixStr.find(':');
792            if (pos != std::string::npos) {
793                sprintfResult = sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s",
794                    prefixStr.substr(0, pos).c_str(), dupModuleName, soPostfix);
795                libPath = prefixStr.substr(pos + 1);
796            } else {
797                sprintfResult = sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix);
798                libPath = prefixStr;
799            }
800            if (sprintfResult == -1) {
801                return false;
802            }
803#else
804            if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s", prefix, dupModuleName, soPostfix) == -1) {
805                return false;
806            }
807#endif
808#ifdef ANDROID_PLATFORM
809            if (sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s%s", libPath.c_str(),
810                dupModuleName, soPostfix) == -1) {
811                return false;
812            }
813#endif
814        }
815    } else {
816        char* afterDot = lastDot + 1;
817        if (*afterDot == '\0') {
818            return false;
819        }
820        *lastDot = '\0';
821        lengthOfModuleName = strlen(dupModuleName);
822        for (int32_t i = 0; i < lengthOfModuleName; i++) {
823            if (*(dupModuleName + i) == '.') {
824                *(dupModuleName + i) = '/';
825            }
826        }
827        if (!isAppModule || !IsExistedPath(path)) {
828            if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s%s",
829                prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
830                return false;
831            }
832            if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s_napi%s%s",
833                prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
834                return false;
835            }
836            if (sprintf_s(nativeModulePath[2], pathLength, "%s/%s/%s%s", // 2 : Element index value
837                sysAbcPrefix.c_str(), dupModuleName, afterDot, abcfix) == -1) {
838                return false;
839            }
840        } else {
841#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
842    !defined(LINUX_PLATFORM)
843            if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", afterDot, soPostfix) == -1) {
844                return false;
845            }
846#else
847            if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s",
848                prefix, dupModuleName, afterDot, soPostfix) == -1) {
849                return false;
850            }
851#endif
852#ifdef ANDROID_PLATFORM
853            if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s%s",
854                prefix, moduleName, afterDot, soPostfix) == -1) {
855                return false;
856            }
857#endif
858        }
859    }
860    return true;
861}
862
863LIBHANDLE NativeModuleManager::LoadModuleLibrary(std::string& moduleKey, const char* path,
864    const char* pathKey, const bool isAppModule, std::string& errInfo, uint32_t& errReason)
865{
866    if (strlen(path) == 0) {
867        errInfo += "load module " + moduleKey  + " failed. module path is empty";
868        HILOG_ERROR("%{public}s", errInfo.c_str());
869        return nullptr;
870    }
871
872    LIBHANDLE lib = nullptr;
873
874    HILOG_DEBUG("path: %{public}s, pathKey: %{public}s, isAppModule: %{public}d", path, pathKey, isAppModule);
875#ifdef ENABLE_HITRACE
876    StartTrace(HITRACE_TAG_ACE, path);
877#endif
878#if defined(WINDOWS_PLATFORM)
879    if (CheckModuleExist(path) == false) {
880        errReason = MODULE_NOT_EXIST;
881        return nullptr;
882    }
883    lib = LoadLibrary(path);
884    if (lib == nullptr) {
885        errInfo += "load module failed. " + std::to_string(GetLastError());
886        HILOG_WARN("%{public}s", errInfo.c_str());
887    }
888#elif defined(MAC_PLATFORM) || defined(__BIONIC__) || defined(LINUX_PLATFORM)
889#ifndef ANDROID_PLATFORM
890    if (CheckModuleExist(path) == false) {
891        errReason = MODULE_NOT_EXIST;
892        return nullptr;
893    }
894#endif
895    lib = dlopen(path, RTLD_LAZY);
896    if (lib == nullptr) {
897        char* dlerr = dlerror();
898        auto dlerrMsg = dlerr != nullptr ? dlerr : "dlerror msg is empty";
899        errInfo += "load module failed. " +  std::string(dlerrMsg);
900    }
901
902#elif defined(IOS_PLATFORM)
903    lib = nullptr;
904#else
905    if (isAppModule && IsExistedPath(pathKey)) {
906        Dl_namespace ns = nsMap_[pathKey];
907        lib = dlopen_ns(&ns, path, RTLD_LAZY);
908    } else if (access(path, F_OK) == 0) {
909        lib = dlopen(path, RTLD_LAZY);
910    }
911    if (lib == nullptr) {
912        char* dlerr = dlerror();
913        auto dlerrMsg = dlerr != nullptr ? dlerr :
914            "Error loading path " + std::string(path) + ":No such file or directory";
915        errInfo += "load app module failed. " +  std::string(dlerrMsg);
916    }
917#endif
918#ifdef ENABLE_HITRACE
919    FinishTrace(HITRACE_TAG_ACE);
920#endif
921    EmplaceModuleLib(moduleKey, lib);
922
923    return lib;
924}
925
926const uint8_t* NativeModuleManager::GetFileBuffer(const std::string& filePath,
927    const std::string& moduleKey, size_t &len)
928{
929    const uint8_t* lib = nullptr;
930    std::ifstream inFile(filePath, std::ios::ate | std::ios::binary);
931    if (!inFile.is_open()) {
932        HILOG_ERROR("%{public}s is not existed.", filePath.c_str());
933        return lib;
934    }
935    len = static_cast<size_t>(inFile.tellg());
936    std::string abcModuleKey = moduleKey;
937    lib = GetBufferHandle(abcModuleKey);
938    if (lib != nullptr) {
939        HILOG_DEBUG("get native abc handle success. moduleKey is %{public}s", moduleKey.c_str());
940        inFile.close();
941        return lib;
942    }
943
944    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(len);
945    inFile.seekg(0);
946    inFile.read(reinterpret_cast<char*>(buffer.get()), len);
947    inFile.close();
948    lib = buffer.release();
949    EmplaceModuleBuffer(abcModuleKey, lib);
950    return lib;
951}
952
953bool NativeModuleManager::UnloadModuleLibrary(LIBHANDLE handle)
954{
955    if (handle == nullptr) {
956        HILOG_WARN("handle is nullptr");
957        return false;
958    }
959#if !defined(WINDOWS_PLATFORM) && !defined(IOS_PLATFORM)
960    if (!dlclose(handle)) {
961        return true;
962    }
963    char* dlerr = dlerror();
964    auto dlerrMsg = dlerr != nullptr ? dlerr : "dlerror msg is empty";
965    HILOG_WARN("dlclose failed: %{public}s", dlerrMsg);
966#endif
967    return false;
968}
969
970bool NativeModuleManager::CheckModuleExist(const char* modulePath)
971{
972    if (modulePath) {
973        std::ifstream inFile(modulePath, std::ios::ate | std::ios::binary);
974        if (inFile.is_open()) {
975            inFile.close();
976            return true;
977        }
978    }
979    return false;
980}
981
982NativeModule* NativeModuleManager::FindNativeModuleByDisk(const char* moduleName, const char* path,
983    const char* relativePath, bool internal, const bool isAppModule, std::string& errInfo,
984    char nativeModulePath[][NAPI_PATH_MAX], NativeModule* cacheNativeModule)
985{
986    std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
987    if (moduleLoadChecker_ && !moduleLoadChecker_->CheckModuleLoadable(moduleName, apiAllowListChecker)) {
988        errInfo = "module " + std::string(moduleName) + " is in blocklist, loading prohibited";
989        HILOG_WARN("%{public}s", errInfo.c_str());
990        return nullptr;
991    }
992
993    std::string moduleKey(moduleName);
994    if (isAppModule) {
995        moduleKey = path;
996        moduleKey = moduleKey + '/' + moduleName;
997    }
998    loadingModuleName_ = moduleKey;
999
1000    // load primary module path first
1001    char* loadPath = nativeModulePath[0];
1002    HILOG_DEBUG("moduleName is %{public}s. get primary module path is %{public}s", moduleName, loadPath);
1003    uint32_t errReason0 = MODULE_LOAD_SUCCESS;
1004    errInfo = "First attempt: ";
1005    LIBHANDLE lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule, errInfo, errReason0);
1006    if (lib == nullptr) {
1007        errInfo += "\nSecond attempt: ";
1008        loadPath = nativeModulePath[1];
1009        HILOG_DEBUG("try to load secondary module path: %{public}s", loadPath);
1010        uint32_t errReason1 = MODULE_LOAD_SUCCESS;
1011        lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule, errInfo, errReason1);
1012        if (lib == nullptr && errReason0 == MODULE_NOT_EXIST && errReason1 == MODULE_NOT_EXIST) {
1013            HILOG_ERROR("%{public}s does not exist, errMsg %{public}s", nativeModulePath[0], errInfo.c_str());
1014        }
1015    }
1016
1017    //Maintain compatibility
1018    if (lib == nullptr && cacheNativeModule != nullptr) {
1019        HILOG_DEBUG("Maintain compatibility.");
1020        return cacheNativeModule;
1021    }
1022
1023    const uint8_t* abcBuffer = nullptr;
1024    size_t len = 0;
1025    if (lib == nullptr) {
1026        loadPath = nativeModulePath[2]; // 2 : Element index value
1027        HILOG_DEBUG("try to load abc module path: %{public}s", loadPath);
1028        abcBuffer = GetFileBuffer(loadPath, moduleKey, len);
1029        if (!abcBuffer) {
1030            errInfo += "\ntry to load abc file from " + std::string(loadPath) + " failed";
1031            HILOG_ERROR("%{public}s", errInfo.c_str());
1032            return nullptr;
1033        }
1034    }
1035
1036    std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1037    if (tailNativeModule_ && !abcBuffer) {
1038        const char* moduleName = strdup(moduleKey.c_str());
1039        if (moduleName == nullptr) {
1040            HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleKey.c_str());
1041            return nullptr;
1042        }
1043
1044        tailNativeModule_->moduleName = moduleName;
1045        tailNativeModule_->systemFilePath = strdup(loadPath);
1046        if (strcmp(tailNativeModule_->moduleName, tailNativeModule_->name)) {
1047            HILOG_WARN("mismatch: moduleName is %{public}s, name is %{public}s",
1048                tailNativeModule_->moduleName, tailNativeModule_->name);
1049            HILOG_WARN("suggestion: keep .nm_modname the same as moduleName imported or required");
1050        }
1051    }
1052
1053    if (!internal) {
1054        char symbol[NAPI_PATH_MAX] = { 0 };
1055        if (sprintf_s(symbol, sizeof(symbol), "NAPI_%s_GetABCCode", moduleKey.c_str()) == -1) {
1056            if (lib != nullptr) {
1057                LIBFREE(lib);
1058            }
1059            errInfo = "sprintf symbol NAPI_" + moduleKey + "_GetABCCode failed";
1060            HILOG_ERROR("%{public}s", errInfo.c_str());
1061            return nullptr;
1062        }
1063
1064        // replace '.' and '/' with '_'
1065        for (char* p = strchr(symbol, '.'); p != nullptr; p = strchr(p + 1, '.')) {
1066            *p = '_';
1067        }
1068        for (char* p = strchr(symbol, '/'); p != nullptr; p = strchr(p + 1, '/')) {
1069            *p = '_';
1070        }
1071
1072        if (lib != nullptr) {
1073            auto getJSCode = reinterpret_cast<GetJSCodeCallback>(LIBSYM(lib, symbol));
1074            if (getJSCode == nullptr) {
1075                HILOG_DEBUG("ignore: no %{public}s in %{public}s", symbol, loadPath);
1076                MoveApiAllowListCheckerPtr(apiAllowListChecker, tailNativeModule_);
1077                return tailNativeModule_;
1078            }
1079            const char* buf = nullptr;
1080            int bufLen = 0;
1081            getJSCode(&buf, &bufLen);
1082            if (tailNativeModule_) {
1083                HILOG_DEBUG("get js code from module: bufLen: %{public}d", bufLen);
1084                tailNativeModule_->jsCode = buf;
1085                tailNativeModule_->jsCodeLen = bufLen;
1086            }
1087        } else {
1088            RegisterByBuffer(moduleKey, abcBuffer, len);
1089            tailNativeModule_->systemFilePath = strdup(loadPath);
1090        }
1091    }
1092    if (tailNativeModule_) {
1093        tailNativeModule_->moduleLoaded = true;
1094        if (tailNativeModule_->name && tailNativeModule_->moduleName) {
1095            HILOG_DEBUG("last native info: name is %{public}s, moduleName is %{public}s",
1096                tailNativeModule_->name, tailNativeModule_->moduleName);
1097        }
1098        MoveApiAllowListCheckerPtr(apiAllowListChecker, tailNativeModule_);
1099    }
1100    return tailNativeModule_;
1101}
1102
1103void NativeModuleManager::RegisterByBuffer(const std::string& moduleKey, const uint8_t* abcBuffer, size_t len)
1104{
1105    HILOG_DEBUG("native module name is '%{public}s'", moduleKey.c_str());
1106    if (!CreateTailNativeModule()) {
1107        HILOG_ERROR("create tail nativeModule failed");
1108        return;
1109    }
1110
1111    char *moduleName = strdup(moduleKey.c_str());
1112    if (moduleName == nullptr) {
1113        HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleKey.c_str());
1114        return;
1115    }
1116    tailNativeModule_->moduleName = moduleName;
1117    tailNativeModule_->name = strdup(moduleName);
1118    if (tailNativeModule_->name == nullptr) {
1119        HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleName);
1120        free(moduleName);
1121        tailNativeModule_->moduleName = nullptr;
1122        return;
1123    }
1124    tailNativeModule_->jsABCCode = abcBuffer;
1125    tailNativeModule_->jsCodeLen = static_cast<int32_t>(len);
1126    tailNativeModule_->next = nullptr;
1127
1128    HILOG_INFO("Register by buffer success. module name is '%{public}s'", tailNativeModule_->moduleName);
1129}
1130
1131bool NativeModuleManager::RemoveNativeModuleByCache(const std::string& moduleKey)
1132{
1133    std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1134
1135    if (headNativeModule_ == nullptr) {
1136        HILOG_WARN("NativeModule list is empty");
1137        return false;
1138    }
1139
1140    NativeModule* nativeModule = headNativeModule_;
1141    if (!strcasecmp(nativeModule->moduleName, moduleKey.c_str())) {
1142        if (headNativeModule_ == tailNativeModule_) {
1143            tailNativeModule_ = nullptr;
1144        }
1145        headNativeModule_ = headNativeModule_->next;
1146        delete[] nativeModule->name;
1147        if (nativeModule->moduleName) {
1148            delete[] nativeModule->moduleName;
1149        }
1150        if (headNativeModule_->jsABCCode) {
1151            delete[] headNativeModule_->jsABCCode;
1152        }
1153        delete nativeModule;
1154        HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
1155        return true;
1156    }
1157
1158    bool moduleDeleted = false;
1159    NativeModule* prev = headNativeModule_;
1160    NativeModule* curr = prev->next;
1161    while (curr != nullptr) {
1162        if (!strcasecmp(curr->moduleName, moduleKey.c_str())) {
1163            if (curr == tailNativeModule_) {
1164                tailNativeModule_ = prev;
1165            }
1166            prev->next = curr->next;
1167            delete[] curr->name;
1168            if (curr->moduleName) {
1169                delete[] curr->moduleName;
1170            }
1171            if (curr->jsABCCode) {
1172                delete[] curr->jsABCCode;
1173            }
1174            delete curr;
1175            HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
1176            moduleDeleted = true;
1177            break;
1178        }
1179        prev = prev->next;
1180        curr = prev->next;
1181    }
1182
1183    return moduleDeleted;
1184}
1185
1186NativeModule* NativeModuleManager::FindNativeModuleByCache(const char* moduleName,
1187                                                           char nativeModulePath[][NAPI_PATH_MAX],
1188                                                           NativeModule*& cacheNativeModule,
1189                                                           NativeModuleHeadTailStruct& cacheHeadTailStruct)
1190{
1191    NativeModule* result = nullptr;
1192
1193    std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1194    cacheNativeModule = nullptr;
1195    for (NativeModule* temp = headNativeModule_; temp != nullptr; temp = temp->next) {
1196        if ((temp->moduleName && !strcmp(temp->moduleName, moduleName))
1197            || !strcasecmp(temp->name, moduleName)) {
1198            if (strcmp(temp->name, moduleName)) {
1199                HILOG_WARN("moduleName '%{public}s' seems not match plugin's name '%{public}s'",
1200                           moduleName, temp->name);
1201            }
1202            int label = 0;
1203#if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
1204            while (label < NATIVE_PATH_NUMBER && strcmp(temp->systemFilePath, nativeModulePath[label])) {
1205                label++;
1206            }
1207#endif
1208            if (label < NATIVE_PATH_NUMBER || !strcmp(temp->systemFilePath, "")) {
1209                result = temp;
1210                break;
1211            } else {
1212                HILOG_WARN("moduleName '%{public}s' is in different path", moduleName);
1213                cacheNativeModule = temp;
1214            }
1215        }
1216    }
1217    cacheHeadTailStruct.headNativeModule = headNativeModule_;
1218    cacheHeadTailStruct.tailNativeModule = tailNativeModule_;
1219
1220    return result;
1221}
1222
1223bool NativeModuleManager::IsExistedPath(const char* pathKey) const
1224{
1225    HILOG_DEBUG("pathKey is '%{public}s'", pathKey);
1226    std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
1227    return pathKey && appLibPathMap_.find(pathKey) != appLibPathMap_.end();
1228}
1229
1230void NativeModuleManager::SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate)
1231{
1232    HILOG_DEBUG("enter");
1233    if (!moduleLoadChecker_) {
1234        HILOG_ERROR("SetModuleLoadChecker failed, moduleLoadChecker_ is nullptr");
1235        return;
1236    }
1237    moduleLoadChecker_->SetDelegate(moduleCheckerDelegate);
1238}
1239
1240void NativeModuleManager::SetPreviewSearchPath(const std::string& previewSearchPath)
1241{
1242    HILOG_DEBUG("previewSearchPath is '%{public}s'", previewSearchPath.c_str());
1243    previewSearchPath_ = previewSearchPath;
1244}
1245