• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <dirent.h>
19 #include <mutex>
20 
21 #ifdef ANDROID_PLATFORM
22 #include <fstream>
23 #include <iostream>
24 #include <sstream>
25 #endif
26 
27 #ifdef ENABLE_HITRACE
28 #include "hitrace_meter.h"
29 #endif
30 #include "module_load_checker.h"
31 #include "native_engine/native_engine.h"
32 #include "securec.h"
33 #include "utils/log.h"
34 
35 #define NDK "ndk"
36 #define ALLOW_ALL_SHARED_LIBS "allow_all_shared_libs"
37 
38 namespace {
39 constexpr static int32_t NATIVE_PATH_NUMBER = 2;
40 } // namespace
41 
42 NativeModuleManager* NativeModuleManager::instance_ = NULL;
43 std::mutex g_instanceMutex;
44 
NativeModuleManager()45 NativeModuleManager::NativeModuleManager()
46 {
47     HILOG_DEBUG("enter");
48     pthread_mutex_init(&mutex_, nullptr);
49     moduleLoadChecker_ = std::make_unique<ModuleLoadChecker>();
50 }
51 
~NativeModuleManager()52 NativeModuleManager::~NativeModuleManager()
53 {
54     HILOG_INFO("enter");
55     {
56         std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
57         NativeModule* nativeModule = firstNativeModule_;
58         while (nativeModule != nullptr) {
59             nativeModule = nativeModule->next;
60             delete[] firstNativeModule_->name;
61             delete firstNativeModule_;
62             firstNativeModule_ = nativeModule;
63         }
64         firstNativeModule_ = nullptr;
65         lastNativeModule_ = nullptr;
66     }
67 
68 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
69     !defined(LINUX_PLATFORM)
70     if (sharedLibsSonames_) {
71         delete[] sharedLibsSonames_;
72     }
73 #endif
74 
75     for (const auto& item : appLibPathMap_) {
76         delete[] item.second;
77     }
78     std::map<std::string, char*>().swap(appLibPathMap_);
79 
80     while (nativeEngineList_.size() > 0) {
81         NativeEngine* wraper = nativeEngineList_.begin()->second;
82         if (wraper != nullptr) {
83             delete wraper;
84             wraper = nullptr;
85         }
86         nativeEngineList_.erase(nativeEngineList_.begin());
87     }
88     pthread_mutex_destroy(&mutex_);
89 }
90 
GetInstance()91 NativeModuleManager* NativeModuleManager::GetInstance()
92 {
93     if (instance_ == NULL) {
94         std::lock_guard<std::mutex> lock(g_instanceMutex);
95         if (instance_ == NULL) {
96             instance_ = new NativeModuleManager();
97             HILOG_DEBUG("create native module manager instance");
98         }
99     }
100     return instance_;
101 }
102 
SetNativeEngine(std::string moduleKey,NativeEngine * nativeEngine)103 void NativeModuleManager::SetNativeEngine(std::string moduleKey, NativeEngine* nativeEngine)
104 {
105     HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
106     std::lock_guard<std::mutex> lock(nativeEngineListMutex_);
107     nativeEngineList_.emplace(moduleKey, nativeEngine);
108 }
109 
EmplaceModuleLib(std::string moduleKey,const LIBHANDLE lib)110 void NativeModuleManager::EmplaceModuleLib(std::string moduleKey, const LIBHANDLE lib)
111 {
112     HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
113     std::lock_guard<std::mutex> lock(moduleLibMutex_);
114     if (lib != nullptr) {
115         moduleLibMap_.emplace(moduleKey, lib);
116     }
117 }
118 
RemoveModuleLib(const std::string moduleKey)119 bool NativeModuleManager::RemoveModuleLib(const std::string moduleKey)
120 {
121     HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
122     bool deleted = false;
123     std::lock_guard<std::mutex> lock(moduleLibMutex_);
124     auto it = moduleLibMap_.find(moduleKey);
125     if (it != moduleLibMap_.end()) {
126         moduleLibMap_.erase(it);
127         HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
128         deleted = true;
129     }
130     return deleted;
131 }
132 
GetNativeModuleHandle(const std::string & moduleKey) const133 LIBHANDLE NativeModuleManager::GetNativeModuleHandle(const std::string &moduleKey) const
134 {
135     HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
136     std::lock_guard<std::mutex> lock(moduleLibMutex_);
137     auto it = moduleLibMap_.find(moduleKey);
138     if (it == moduleLibMap_.end()) {
139         return nullptr;
140     }
141     return it->second;
142 }
143 
RemoveNativeModule(const std::string & moduleKey)144 bool NativeModuleManager::RemoveNativeModule(const std::string &moduleKey)
145 {
146     bool handleRemoved = RemoveModuleLib(moduleKey);
147     bool moduleRemoved = RemoveNativeModuleByCache(moduleKey);
148 
149     HILOG_DEBUG("handleRemoved is %{public}d, moduleRemoved is %{public}d", handleRemoved, moduleRemoved);
150     return (handleRemoved && moduleRemoved);
151 }
152 
UnloadNativeModule(const std::string & moduleKey)153 bool NativeModuleManager::UnloadNativeModule(const std::string &moduleKey)
154 {
155     HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
156     LIBHANDLE handle = GetNativeModuleHandle(moduleKey);
157     if (handle == nullptr) {
158         HILOG_ERROR("failed to get native module handle.");
159         return false;
160     }
161 
162     if (RemoveNativeModule(moduleKey) == false) {
163         HILOG_ERROR("remove native module failed.");
164         return false;
165     }
166 
167     return UnloadModuleLibrary(handle);
168 }
169 
GetModuleFileName(const char * moduleName,bool isAppModule)170 const char* NativeModuleManager::GetModuleFileName(const char* moduleName, bool isAppModule)
171 {
172     HILOG_INFO("moduleName is '%{public}s', isAppModule is %{public}d", moduleName, isAppModule);
173 
174     NativeModule* module = FindNativeModuleByCache(moduleName);
175     if (module != nullptr) {
176         char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
177         if (!GetNativeModulePath(moduleName, "default", "", isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
178             HILOG_ERROR("get native module path failed");
179             return nullptr;
180         }
181         const char* loadPath = nativeModulePath[0];
182         return loadPath;
183     }
184     HILOG_ERROR("get module file name failed");
185     return nullptr;
186 }
187 
Register(NativeModule * nativeModule)188 void NativeModuleManager::Register(NativeModule* nativeModule)
189 {
190     if (nativeModule == nullptr) {
191         HILOG_ERROR("nativeModule value is null");
192         return;
193     }
194 
195     HILOG_DEBUG("native module name is '%{public}s'", nativeModule->name);
196     std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
197     if (firstNativeModule_ == lastNativeModule_ && lastNativeModule_ == nullptr) {
198         firstNativeModule_ = new NativeModule();
199         if (firstNativeModule_ == nullptr) {
200             HILOG_ERROR("first NativeModule create failed");
201             return;
202         }
203         lastNativeModule_ = firstNativeModule_;
204     } else {
205         auto next = new NativeModule();
206         if (next == nullptr) {
207             HILOG_ERROR("next NativeModule create failed");
208             return;
209         }
210         if (lastNativeModule_) {
211             lastNativeModule_->next = next;
212             lastNativeModule_ = lastNativeModule_->next;
213         }
214     }
215 
216     const char *nativeModuleName = nativeModule->name == nullptr ? "" : nativeModule->name;
217     std::string appName = prefix_ + "/" + nativeModuleName;
218     const char *tmpName = isAppModule_ ? appName.c_str() : nativeModuleName;
219     char *moduleName = new char[NAPI_PATH_MAX];
220     errno_t err = EOK;
221     err = memset_s(moduleName, NAPI_PATH_MAX, 0, NAPI_PATH_MAX);
222     if (err != EOK) {
223         delete[] moduleName;
224         return;
225     }
226     err = strcpy_s(moduleName, NAPI_PATH_MAX, tmpName);
227     if (err != EOK) {
228         delete[] moduleName;
229         return;
230     }
231 
232     lastNativeModule_->version = nativeModule->version;
233     lastNativeModule_->fileName = nativeModule->fileName;
234     lastNativeModule_->isAppModule = isAppModule_;
235     lastNativeModule_->name = moduleName;
236     lastNativeModule_->refCount = nativeModule->refCount;
237     lastNativeModule_->registerCallback = nativeModule->registerCallback;
238     lastNativeModule_->getJSCode = nativeModule->getJSCode;
239     lastNativeModule_->getABCCode = nativeModule->getABCCode;
240     lastNativeModule_->next = nullptr;
241 #if defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
242     // For iOS and android, force make module loaded
243     lastNativeModule_->moduleLoaded = true;
244 #endif
245     HILOG_INFO("NativeModule Register success. module name is '%{public}s'", lastNativeModule_->name);
246 }
247 
248 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
249     !defined(LINUX_PLATFORM)
CreateSharedLibsSonames()250 void NativeModuleManager::CreateSharedLibsSonames()
251 {
252     HILOG_DEBUG("enter");
253     const char* allowList[] = {
254         // bionic library
255         "libc.so",
256         "libdl.so",
257         "libm.so",
258         "libz.so",
259         "libclang_rt.asan.so",
260         // z library
261         "libace_napi.z.so",
262         "libace_ndk.z.so",
263         "libbundle_ndk.z.so",
264         "libdeviceinfo_ndk.z.so",
265         "libEGL.so",
266         "libGLESv3.so",
267         "libhiappevent_ndk.z.so",
268         "libhuks_ndk.z.so",
269         "libhukssdk.z.so",
270         "libnative_drawing.so",
271         "libnative_window.so",
272         "libnative_buffer.so",
273         "libnative_vsync.so",
274         "libOpenSLES.so",
275         "libpixelmap_ndk.z.so",
276         "libimage_ndk.z.so",
277         "libimage_receiver_ndk.z.so",
278         "libimage_source_ndk.z.so",
279         "librawfile.z.so",
280         "libuv.so",
281         "libhilog.so",
282         "libnative_image.so",
283         "libnative_media_adec.so",
284         "libnative_media_aenc.so",
285         "libnative_media_codecbase.so",
286         "libnative_media_core.so",
287         "libnative_media_vdec.so",
288         "libnative_media_venc.so",
289         "libnative_media_avmuxer.so",
290         "libnative_media_avdemuxer.so",
291         "libnative_media_avsource.so",
292         "libnative_avscreen_capture.so",
293         // adaptor library
294         "libohosadaptor.so",
295         "libusb_ndk.z.so",
296         "libvulkan.so",
297     };
298 
299     size_t allowListLength = sizeof(allowList) / sizeof(char*);
300     int32_t sharedLibsSonamesLength = 1;
301     for (size_t i = 0; i < allowListLength; i++) {
302         sharedLibsSonamesLength += strlen(allowList[i]) + 1;
303     }
304     sharedLibsSonames_ = new char[sharedLibsSonamesLength];
305     int32_t cursor = 0;
306     for (size_t i = 0; i < allowListLength; i++) {
307         if (sprintf_s(sharedLibsSonames_ + cursor, sharedLibsSonamesLength - cursor, "%s:", allowList[i]) == -1) {
308             delete[] sharedLibsSonames_;
309             sharedLibsSonames_ = nullptr;
310             return;
311         }
312         cursor += strlen(allowList[i]) + 1;
313     }
314     sharedLibsSonames_[cursor] = '\0';
315 }
316 #endif
317 
CreateLdNamespace(const std::string moduleName,const char * lib_ld_path,const bool & isSystemApp)318 void NativeModuleManager::CreateLdNamespace(const std::string moduleName, const char* lib_ld_path,
319                                             [[maybe_unused]] const bool& isSystemApp)
320 {
321 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
322     !defined(LINUX_PLATFORM)
323     Dl_namespace current_ns;
324     Dl_namespace ns;
325 
326     // Create module ns.
327     std::string nsName = "moduleNs_" + moduleName;
328     dlns_init(&ns, nsName.c_str());
329     dlns_get(nullptr, &current_ns);
330 
331     Dl_namespace ndk_ns;
332     dlns_get(NDK, &ndk_ns);
333 
334     if (isSystemApp) {
335         /*
336          * The app's so may have the same name as the system library, LOCAL_NS_PREFERED means linker will check
337          * and use the app's so first.
338          */
339         dlns_create2(&ns, lib_ld_path, LOCAL_NS_PREFERED);
340         // System app can visit all ndk and default ns libs.
341         if (strlen(ndk_ns.name) > 0) {
342             dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
343             dlns_inherit(&ndk_ns, &current_ns, ALLOW_ALL_SHARED_LIBS);
344             dlns_inherit(&current_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
345             dlns_inherit(&ns, &current_ns, ALLOW_ALL_SHARED_LIBS);
346         }
347     } else {
348         dlns_create2(&ns, lib_ld_path, 0);
349         // Non-system app can visit all ndk ns libs and default ns shared libs.
350         if (!sharedLibsSonames_) {
351             CreateSharedLibsSonames();
352         }
353         dlns_inherit(&ns, &current_ns, sharedLibsSonames_);
354         if (strlen(ndk_ns.name) > 0) {
355             dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
356             dlns_inherit(&ndk_ns, &current_ns, ALLOW_ALL_SHARED_LIBS);
357             dlns_inherit(&current_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
358         }
359     }
360 
361     nsMap_[moduleName] = ns;
362 
363     HILOG_INFO("CreateLdNamespace success. moduleName: %{public}s, path: %{public}s", moduleName.c_str(), lib_ld_path);
364 #endif
365 }
366 
SetAppLibPath(const std::string & moduleName,const std::vector<std::string> & appLibPath,const bool & isSystemApp)367 void NativeModuleManager::SetAppLibPath(const std::string& moduleName, const std::vector<std::string>& appLibPath,
368                                         const bool& isSystemApp)
369 {
370     HILOG_DEBUG("moduleName is %{public}s, isisSystemApp is %{public}d", moduleName.c_str(), isSystemApp);
371     char* tmp = new char[NAPI_PATH_MAX];
372     errno_t err = EOK;
373     err = memset_s(tmp, NAPI_PATH_MAX, 0, NAPI_PATH_MAX);
374     if (err != EOK) {
375         delete[] tmp;
376         HILOG_ERROR("memset_s failed");
377         return;
378     }
379 
380     std::string tmpPath = "";
381     for (size_t i = 0; i < appLibPath.size(); i++) {
382         if (appLibPath[i].empty()) {
383             continue;
384         }
385         tmpPath += appLibPath[i];
386         tmpPath += ":";
387     }
388     if (tmpPath.back() == ':') {
389         tmpPath.pop_back();
390     }
391 
392     err = strcpy_s(tmp, NAPI_PATH_MAX, tmpPath.c_str());
393     if (err != EOK) {
394         delete[] tmp;
395         return;
396     }
397 
398     if (appLibPathMap_[moduleName] != nullptr) {
399         delete[] appLibPathMap_[moduleName];
400     }
401 
402     appLibPathMap_[moduleName] = tmp;
403     CreateLdNamespace(moduleName, tmp, isSystemApp);
404     HILOG_INFO("create ld namespace, path: %{public}s", appLibPathMap_[moduleName]);
405 }
406 
LoadNativeModule(const char * moduleName,const char * path,bool isAppModule,bool internal,const char * relativePath)407 NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName,
408     const char* path, bool isAppModule, bool internal, const char* relativePath)
409 {
410     if (moduleName == nullptr || relativePath == nullptr) {
411         HILOG_ERROR("moduleName or relativePath is nullptr");
412         return nullptr;
413     }
414 
415     HILOG_DEBUG("moduleName is %{public}s, path is %{public}s", moduleName, path);
416 #ifdef ANDROID_PLATFORM
417     std::string strModule(moduleName);
418     std::string strCutName = strModule;
419     if (path != nullptr) {
420         if (IsExistedPath(path)) {
421             strModule = path;
422         }
423         prefix_ = "default";
424         strModule = prefix_ + '/' + moduleName;
425     } else {
426         path = "default";
427         if (strModule.find(".") != std::string::npos) {
428             char* temp = const_cast<char*>(strCutName.c_str());
429             for (char* p = strchr(temp, '.'); p != nullptr; p = strchr(p + 1, '.')) {
430                 *p = '_';
431             }
432         }
433     }
434 #endif
435 
436     if (pthread_mutex_lock(&mutex_) != 0) {
437         HILOG_ERROR("pthread_mutex_lock is failed");
438         return nullptr;
439     }
440 
441 #ifdef ANDROID_PLATFORM
442     NativeModule* nativeModule = FindNativeModuleByCache(strModule.c_str());
443 #else
444     std::string key(moduleName);
445     isAppModule_ = isAppModule;
446     if (isAppModule) {
447         prefix_ = "default";
448         if (path && IsExistedPath(path)) {
449             prefix_ = path;
450         }
451         key = prefix_ + '/' + moduleName;
452     }
453     NativeModule* nativeModule = FindNativeModuleByCache(key.c_str());
454 #endif
455 
456 #ifndef IOS_PLATFORM
457     if (nativeModule == nullptr) {
458 #ifdef ANDROID_PLATFORM
459         HILOG_WARN("module '%{public}s' does not in cache", strCutName.c_str());
460         nativeModule = FindNativeModuleByDisk(strCutName.c_str(), path, relativePath, internal, isAppModule);
461 #else
462         HILOG_WARN("module '%{public}s' does not in cache", moduleName);
463         nativeModule = FindNativeModuleByDisk(moduleName, prefix_.c_str(), relativePath, internal, isAppModule);
464 #endif
465     }
466 #endif
467 
468     if (pthread_mutex_unlock(&mutex_) != 0) {
469         HILOG_ERROR("pthread_mutex_unlock is failed");
470         return nullptr;
471     }
472 
473     HILOG_DEBUG("load native module %{public}s", (nativeModule == nullptr) ? "failed" : "success");
474     return nativeModule;
475 }
476 
GetNativeModulePath(const char * moduleName,const char * path,const char * relativePath,bool isAppModule,char nativeModulePath[][NAPI_PATH_MAX],int32_t pathLength)477 bool NativeModuleManager::GetNativeModulePath(const char* moduleName, const char* path,
478     const char* relativePath, bool isAppModule, char nativeModulePath[][NAPI_PATH_MAX], int32_t pathLength)
479 {
480 #ifdef WINDOWS_PLATFORM
481     const char* soPostfix = ".dll";
482     const char* zfix = "";
483     std::string sysPrefix("./module");
484 #elif defined(MAC_PLATFORM)
485     const char* soPostfix = ".dylib";
486     const char* zfix = "";
487     std::string sysPrefix("./module");
488 #elif defined(_ARM64_) || defined(SIMULATOR)
489     const char* soPostfix = ".so";
490     const char* zfix = ".z";
491     std::string sysPrefix("/system/lib64/module");
492 #elif defined(LINUX_PLATFORM)
493     const char* soPostfix = ".so";
494     const char* zfix = "";
495     std::string sysPrefix("./module");
496 #else
497     const char* soPostfix = ".so";
498     const char* zfix = ".z";
499     std::string sysPrefix("/system/lib/module");
500 #endif
501 
502 #ifdef ANDROID_PLATFORM
503     isAppModule = true;
504 #endif
505     int32_t lengthOfModuleName = strlen(moduleName);
506     char dupModuleName[NAPI_PATH_MAX] = { 0 };
507     if (strcpy_s(dupModuleName, NAPI_PATH_MAX, moduleName) != 0) {
508         HILOG_ERROR("strcpy_s moduleName '%{public}s' failed", moduleName);
509         return false;
510     }
511 
512     const char* prefix = nullptr;
513     if (isAppModule && IsExistedPath(path)) {
514         prefix = appLibPathMap_[path];
515 #ifdef ANDROID_PLATFORM
516         for (int32_t i = 0; i < lengthOfModuleName; i++) {
517             dupModuleName[i] = tolower(dupModuleName[i]);
518         }
519 #endif
520     } else {
521         if (relativePath[0]) {
522             if (previewSearchPath_.empty()) {
523                 sysPrefix = sysPrefix + "/" + relativePath;
524             } else {
525                 sysPrefix = previewSearchPath_ + "/module";
526             }
527         }
528         prefix = sysPrefix.c_str();
529         for (int32_t i = 0; i < lengthOfModuleName; i++) {
530             dupModuleName[i] = tolower(dupModuleName[i]);
531         }
532     }
533 
534     int32_t lengthOfPostfix = strlen(soPostfix);
535     if ((lengthOfModuleName > lengthOfPostfix) &&
536         (strcmp(dupModuleName + lengthOfModuleName - lengthOfPostfix, soPostfix) == 0)) {
537         if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s", prefix, dupModuleName) == -1) {
538             return false;
539         }
540         return true;
541     }
542 
543     char* lastDot = strrchr(dupModuleName, '.');
544     if (lastDot == nullptr) {
545         if (!isAppModule || !IsExistedPath(path)) {
546 #ifdef ANDROID_PLATFORM
547             if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
548                 return false;
549             }
550 #else
551             if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s%s",
552                 prefix, dupModuleName, zfix, soPostfix) == -1) {
553                 return false;
554             }
555 #endif
556             if (sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s_napi%s%s",
557                 prefix, dupModuleName, zfix, soPostfix) == -1) {
558                 return false;
559             }
560         } else {
561 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
562     !defined(LINUX_PLATFORM)
563             if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
564                 return false;
565             }
566 #elif defined(ANDROID_PLATFORM)
567             std::istringstream iss(prefix);
568             std::string libPath;
569             while (std::getline(iss, libPath, ':')) {
570                 std::ifstream dupModuleFile(libPath + "/lib" + dupModuleName + soPostfix);
571                 std::ifstream moduleFile(libPath + "/lib" + moduleName + soPostfix);
572                 if(dupModuleFile.good() || moduleFile.good()) {
573                     break;
574                 }
575             }
576             if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s", libPath.c_str(),
577                 dupModuleName, soPostfix) == -1) {
578                 return false;
579             }
580 #else
581             if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s", prefix, dupModuleName, soPostfix) == -1) {
582                 return false;
583             }
584 #endif
585 #ifdef ANDROID_PLATFORM
586             if (sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s%s", libPath.c_str(),
587                 moduleName, soPostfix) == -1) {
588                 return false;
589             }
590 #endif
591         }
592     } else {
593         char* afterDot = lastDot + 1;
594         if (*afterDot == '\0') {
595             return false;
596         }
597         *lastDot = '\0';
598         lengthOfModuleName = strlen(dupModuleName);
599         for (int32_t i = 0; i < lengthOfModuleName; i++) {
600             if (*(dupModuleName + i) == '.') {
601                 *(dupModuleName + i) = '/';
602             }
603         }
604         if (!isAppModule || !IsExistedPath(path)) {
605             if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s%s",
606                 prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
607                 return false;
608             }
609             if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s_napi%s%s",
610                 prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
611                 return false;
612             }
613         } else {
614 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
615     !defined(LINUX_PLATFORM)
616             if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", afterDot, soPostfix) == -1) {
617                 return false;
618             }
619 #else
620             if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s",
621                 prefix, dupModuleName, afterDot, soPostfix) == -1) {
622                 return false;
623             }
624 #endif
625 #ifdef ANDROID_PLATFORM
626             if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s%s",
627                 prefix, moduleName, afterDot, soPostfix) == -1) {
628                 return false;
629             }
630 #endif
631         }
632     }
633     return true;
634 }
635 
LoadModuleLibrary(std::string & moduleKey,const char * path,const char * pathKey,const bool isAppModule)636 LIBHANDLE NativeModuleManager::LoadModuleLibrary(std::string &moduleKey, const char* path,
637                                                  const char* pathKey, const bool isAppModule)
638 {
639     if (strlen(path) == 0) {
640         HILOG_ERROR("primary module path is empty");
641         return nullptr;
642     }
643 
644     LIBHANDLE lib = nullptr;
645     lib = GetNativeModuleHandle(moduleKey);
646     if (lib != nullptr) {
647         HILOG_DEBUG("get native module handle success. moduleKey is %{public}s", moduleKey.c_str());
648         return lib;
649     }
650 
651     HILOG_DEBUG("path: %{public}s, pathKey: %{public}s, isAppModule: %{public}d", path, pathKey, isAppModule);
652 #ifdef ENABLE_HITRACE
653     StartTrace(HITRACE_TAG_ACE, path);
654 #endif
655 #if defined(WINDOWS_PLATFORM)
656     lib = LoadLibrary(path);
657     if (lib == nullptr) {
658         HILOG_WARN("LoadLibrary failed, error: %{public}d", GetLastError());
659     }
660 #elif defined(MAC_PLATFORM) || defined(__BIONIC__) || defined(LINUX_PLATFORM)
661     lib = dlopen(path, RTLD_LAZY);
662     if (lib == nullptr) {
663         HILOG_WARN("dlopen failed: %{public}s", dlerror());
664     }
665 
666 #elif defined(IOS_PLATFORM)
667     lib = nullptr;
668 #else
669     if (isAppModule && IsExistedPath(pathKey)) {
670         Dl_namespace ns = nsMap_[pathKey];
671         lib = dlopen_ns(&ns, path, RTLD_LAZY);
672     } else {
673         lib = dlopen(path, RTLD_LAZY);
674     }
675     if (lib == nullptr) {
676         HILOG_WARN("dlopen failed: %{public}s", dlerror());
677     }
678 #endif
679 #ifdef ENABLE_HITRACE
680     FinishTrace(HITRACE_TAG_ACE);
681 #endif
682     EmplaceModuleLib(moduleKey, lib);
683 
684     return lib;
685 }
686 
UnloadModuleLibrary(LIBHANDLE handle)687 bool NativeModuleManager::UnloadModuleLibrary(LIBHANDLE handle)
688 {
689     if (handle == nullptr) {
690         HILOG_WARN("handle is nullptr");
691         return false;
692     }
693 #if !defined(WINDOWS_PLATFORM) && !defined(IOS_PLATFORM)
694     if (!dlclose(handle)) {
695         return true;
696     }
697     HILOG_WARN("dlclose failed: %{public}s", dlerror());
698 #endif
699     return false;
700 }
701 
FindNativeModuleByDisk(const char * moduleName,const char * path,const char * relativePath,bool internal,const bool isAppModule)702 NativeModule* NativeModuleManager::FindNativeModuleByDisk(
703     const char* moduleName, const char* path, const char* relativePath, bool internal,  const bool isAppModule)
704 {
705     char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
706     nativeModulePath[0][0] = 0;
707     nativeModulePath[1][0] = 0;
708     if (!GetNativeModulePath(moduleName, path, relativePath, isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
709         HILOG_WARN("get module '%{public}s' path failed", moduleName);
710         return nullptr;
711     }
712     if (moduleLoadChecker_ && !moduleLoadChecker_->CheckModuleLoadable(moduleName)) {
713         HILOG_ERROR("module '%{public}s' is not allowed to load", moduleName);
714         return nullptr;
715     }
716 
717     std::string moduleKey(moduleName);
718     if (isAppModule) {
719         moduleKey = path;
720         moduleKey = moduleKey + '/' + moduleName;
721     }
722 
723     // load primary module path first
724     char* loadPath = nativeModulePath[0];
725     HILOG_DEBUG("moduleName: %{public}s. get primary module path: %{public}s", moduleName, loadPath);
726     LIBHANDLE lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule);
727     if (lib == nullptr) {
728         loadPath = nativeModulePath[1];
729         HILOG_DEBUG("try to load secondary module path: %{public}s", loadPath);
730         lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule);
731         if (lib == nullptr) {
732             HILOG_ERROR("primary and secondary path load module '%{public}s' failed", moduleName);
733             return nullptr;
734         }
735     }
736 
737     std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
738     if (lastNativeModule_ && strcmp(lastNativeModule_->name, moduleKey.c_str())) {
739         HILOG_WARN("moduleName '%{public}s' seems not match plugin's name '%{public}s'",
740                    moduleKey.c_str(), lastNativeModule_->name);
741     }
742 
743     if (!internal) {
744         char symbol[NAPI_PATH_MAX] = { 0 };
745         if (sprintf_s(symbol, sizeof(symbol), "NAPI_%s_GetABCCode", moduleKey.c_str()) == -1) {
746             LIBFREE(lib);
747             return nullptr;
748         }
749 
750         // replace '.' and '/' with '_'
751         for (char* p = strchr(symbol, '.'); p != nullptr; p = strchr(p + 1, '.')) {
752             *p = '_';
753         }
754         for (char* p = strchr(symbol, '/'); p != nullptr; p = strchr(p + 1, '/')) {
755             *p = '_';
756         }
757 
758         auto getJSCode = reinterpret_cast<GetJSCodeCallback>(LIBSYM(lib, symbol));
759         if (getJSCode != nullptr) {
760             const char* buf = nullptr;
761             int bufLen = 0;
762             getJSCode(&buf, &bufLen);
763             if (lastNativeModule_ != nullptr) {
764                 HILOG_DEBUG("get js code from module: bufLen: %{public}d", bufLen);
765                 lastNativeModule_->jsCode = buf;
766                 lastNativeModule_->jsCodeLen = bufLen;
767             }
768         } else {
769             HILOG_DEBUG("ignore: no %{public}s in %{public}s", symbol, loadPath);
770         }
771     }
772     if (lastNativeModule_) {
773         lastNativeModule_->moduleLoaded = true;
774         HILOG_DEBUG("last native module name is %{public}s", lastNativeModule_->name);
775     }
776     return lastNativeModule_;
777 }
778 
RemoveNativeModuleByCache(const std::string & moduleKey)779 bool NativeModuleManager::RemoveNativeModuleByCache(const std::string &moduleKey)
780 {
781     std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
782 
783     if (firstNativeModule_ == nullptr) {
784         HILOG_WARN("NativeModule list is empty");
785         return false;
786     }
787 
788     NativeModule* nativeModule = firstNativeModule_;
789     if (!strcasecmp(nativeModule->name, moduleKey.c_str())) {
790         firstNativeModule_ = firstNativeModule_->next;
791         delete[] nativeModule->name;
792         delete nativeModule;
793         HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
794         return true;
795     }
796 
797     bool moduleDeleted = false;
798     NativeModule* prev = firstNativeModule_;
799     NativeModule* curr = prev->next;
800     while (curr != nullptr) {
801         if (!strcasecmp(curr->name, moduleKey.c_str())) {
802             prev->next = curr->next;
803             delete[] curr->name;
804             delete curr;
805             HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
806             moduleDeleted = true;
807             break;
808         }
809         prev = prev->next;
810         curr = prev->next;
811     }
812 
813     return moduleDeleted;
814 }
815 
FindNativeModuleByCache(const char * moduleName)816 NativeModule* NativeModuleManager::FindNativeModuleByCache(const char* moduleName)
817 {
818     NativeModule* result = nullptr;
819     NativeModule* preNativeModule = nullptr;
820 
821     std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
822     for (NativeModule* temp = firstNativeModule_; temp != nullptr; temp = temp->next) {
823         if (!strcasecmp(temp->name, moduleName)) {
824             if (strcmp(temp->name, moduleName)) {
825                 HILOG_WARN("moduleName '%{public}s' seems not match plugin's name '%{public}s'",
826                            moduleName, temp->name);
827             }
828             result = temp;
829             break;
830         }
831         preNativeModule = temp;
832     }
833 
834     if (result && !result->moduleLoaded) {
835         if (result == lastNativeModule_) {
836             HILOG_DEBUG("module '%{public}s' does not load", result->name);
837             return nullptr;
838         }
839         if (preNativeModule) {
840             preNativeModule->next = result->next;
841         } else {
842             firstNativeModule_ = firstNativeModule_->next;
843         }
844         result->next = nullptr;
845         lastNativeModule_->next = result;
846         lastNativeModule_ = result;
847         HILOG_DEBUG("module '%{public}s' does not found", moduleName);
848         return nullptr;
849     }
850     HILOG_DEBUG("module '%{public}s' found in cache", moduleName);
851     return result;
852 }
853 
IsExistedPath(const char * pathKey) const854 bool NativeModuleManager::IsExistedPath(const char* pathKey) const
855 {
856     HILOG_DEBUG("pathKey is '%{public}s'", pathKey);
857     return pathKey && appLibPathMap_.find(pathKey) != appLibPathMap_.end();
858 }
859 
SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate> & moduleCheckerDelegate)860 void NativeModuleManager::SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate)
861 {
862     HILOG_DEBUG("enter");
863     if (!moduleLoadChecker_) {
864         HILOG_ERROR("SetModuleLoadChecker failed, moduleLoadChecker_ is nullptr");
865         return;
866     }
867     moduleLoadChecker_->SetDelegate(moduleCheckerDelegate);
868 }
869 
SetPreviewSearchPath(const std::string & previewSearchPath)870 void NativeModuleManager::SetPreviewSearchPath(const std::string& previewSearchPath)
871 {
872     HILOG_DEBUG("previewSearchPath is '%{public}s'", previewSearchPath.c_str());
873     previewSearchPath_ = previewSearchPath;
874 }
875