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, ¤t_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, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
344 dlns_inherit(¤t_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
345 dlns_inherit(&ns, ¤t_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, ¤t_ns, sharedLibsSonames_);
354 if (strlen(ndk_ns.name) > 0) {
355 dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
356 dlns_inherit(&ndk_ns, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
357 dlns_inherit(¤t_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