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 #ifndef FOUNDATION_ACE_NAPI_MODULE_MANAGER_NATIVE_MODULE_MANAGER_H 17 #define FOUNDATION_ACE_NAPI_MODULE_MANAGER_NATIVE_MODULE_MANAGER_H 18 19 #include <cstdint> 20 #include <map> 21 #include <mutex> 22 #include <unordered_map> 23 #include <unordered_set> 24 #include <vector> 25 #include <string> 26 #include <pthread.h> 27 28 #include "module_load_checker.h" 29 #include "utils/macros.h" 30 #include "interfaces/inner_api/napi/native_node_api.h" 31 32 #ifdef WINDOWS_PLATFORM 33 #include <winsock2.h> 34 #include <windows.h> 35 using LIBHANDLE = HMODULE; 36 #define LIBFREE FreeLibrary 37 #define LIBSYM GetProcAddress 38 #else 39 #include <dlfcn.h> 40 using LIBHANDLE = void*; 41 #define LIBFREE dlclose 42 #define LIBSYM dlsym 43 #endif 44 45 #define NAPI_PATH_MAX 4096 46 47 class NativeValue; 48 49 class NativeEngine; 50 51 typedef napi_value (*RegisterCallback)(napi_env, napi_value); 52 53 typedef void (*GetJSCodeCallback)(const char** buf, int* bufLen); 54 55 typedef void (*NapiOnLoadCallback)(); 56 57 struct NativeModule { 58 const char* name = nullptr; /* .nm_modname from native c++ register info */ 59 const char* moduleName = nullptr; /* moduleName required or imported */ 60 const char* fileName = nullptr; 61 const char* systemFilePath = nullptr; 62 RegisterCallback registerCallback = nullptr; 63 GetJSCodeCallback getABCCode = nullptr; 64 GetJSCodeCallback getJSCode = nullptr; 65 int32_t version = 0; 66 uint32_t flags = 0; 67 uint32_t refCount = 0; 68 NativeModule* next = nullptr; 69 const char* jsCode = nullptr; 70 const uint8_t* jsABCCode = nullptr; 71 int32_t jsCodeLen = 0; 72 bool moduleLoaded = false; 73 bool isAppModule = false; 74 std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr; 75 }; 76 77 struct NativeModuleHeadTailStruct { 78 NativeModule* headNativeModule = nullptr; 79 NativeModule* tailNativeModule = nullptr; 80 }; 81 class NAPI_EXPORT NativeModuleManager { 82 public: 83 static NativeModuleManager* GetInstance(); 84 static uint64_t Release(); 85 86 void Register(NativeModule* nativeModule); 87 void SetAppLibPath(const std::string& moduleName, const std::vector<std::string>& appLibPath, 88 const bool& isSystemApp = false); 89 bool GetLdNamespaceName(const std::string &moduleName, std::string &nsName); 90 NativeModule* LoadNativeModule(const char* moduleName, const char* path, bool isAppModule, 91 std::string& errInfo, bool internal = false, const char* relativePath = ""); 92 void SetNativeEngine(std::string moduleName, NativeEngine* nativeEngine); 93 bool UnloadNativeModule(const std::string& moduleKey); 94 std::string GetModuleFileName(const char* moduleName, bool isAppModule); 95 96 /** 97 * @brief Set the path for searching napi dynamic libraries, only for the previewer. 98 * 99 * @param previewSearchPath the path for searching napi dynamic libraries 100 */ 101 void SetPreviewSearchPath(const std::string& previewSearchPath); 102 103 /** 104 * @brief Set the Module Load Checker delegate 105 * 106 * @param moduleCheckerDelegate The Module Load Checker delegate 107 */ 108 void SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate); 109 CheckModuleRestricted(const std::string & moduleName)110 inline bool CheckModuleRestricted(const std::string& moduleName) 111 { 112 const std::string whiteList[] = { 113 "worker", 114 "arkui.uicontext", 115 "arkui.node", 116 "arkui.modifier", 117 "measure", 118 }; 119 120 size_t listLen = sizeof(whiteList) / sizeof(whiteList[0]); 121 for (size_t i = 0; i < listLen; ++i) { 122 if (moduleName == whiteList[i]) { 123 return true; 124 } 125 } 126 127 return false; 128 } 129 130 private: 131 NativeModuleManager(); 132 virtual ~NativeModuleManager(); 133 134 bool GetNativeModulePath(const char* moduleName, const char* path, const char* relativePath, 135 bool isAppModule, char nativeModulePath[][NAPI_PATH_MAX], int32_t pathLength); 136 NativeModule* FindNativeModuleByDisk(const char* moduleName, const char* path, const char* relativePath, 137 bool internal, const bool isAppModule, std::string& errInfo, char nativeModulePath[][NAPI_PATH_MAX], 138 NativeModule* cacheNativeModule); 139 NativeModule* FindNativeModuleByCache(const char* moduleName, 140 char nativeModulePath[][NAPI_PATH_MAX], 141 NativeModule*& cacheNativeModule, 142 NativeModuleHeadTailStruct& cacheHeadTailStruct); 143 bool CheckModuleExist(const char* modulePath); 144 LIBHANDLE LoadModuleLibrary(std::string& moduleKey, const char* path, const char* pathKey, 145 const bool isAppModule, std::string& errInfo, uint32_t& errReason); 146 const uint8_t* GetFileBuffer(const std::string& filePath, const std::string& moduleKey, size_t &len); 147 bool UnloadModuleLibrary(LIBHANDLE handle); 148 bool CloseModuleLibrary(LIBHANDLE handle); 149 void CreateLdNamespace(const std::string moduleName, const char* lib_ld_path, const bool& isSystemApp); 150 bool IsExistedPath(const char* pathKey) const; 151 void EmplaceModuleLib(const std::string moduleKey, LIBHANDLE lib); 152 bool RemoveModuleLib(const std::string moduleKey); 153 void EmplaceModuleBuffer(const std::string moduleKey, const uint8_t* lib); 154 bool RemoveModuleBuffer(const std::string moduleKey); 155 const uint8_t* GetBufferHandle(const std::string& moduleKey) const; 156 void RegisterByBuffer(const std::string& moduleKey, const uint8_t* abcBuffer, size_t len); 157 bool CreateTailNativeModule(); 158 bool CreateHeadNativeModule(); 159 LIBHANDLE GetNativeModuleHandle(const std::string& moduleKey) const; 160 bool RemoveNativeModuleByCache(const std::string& moduleKey); 161 bool RemoveNativeModule(const std::string& moduleKey); 162 bool CheckNativeListChanged(const NativeModule* cacheHeadNativeModule, const NativeModule* cacheTailNativeModule); 163 void MoveApiAllowListCheckerPtr( 164 std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, NativeModule* nativeModule); 165 void Napi_onLoadCallback(LIBHANDLE lib, const char* moduleName); 166 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \ 167 !defined(LINUX_PLATFORM) 168 void CreateSharedLibsSonames(); 169 170 char* sharedLibsSonames_ = nullptr; 171 std::map<std::string, Dl_namespace> nsMap_; 172 #endif 173 174 std::mutex nativeModuleListMutex_; 175 NativeModule* headNativeModule_ = nullptr; 176 NativeModule* tailNativeModule_ = nullptr; 177 178 static NativeModuleManager *instance_; 179 pthread_mutex_t mutex_; 180 std::string prefix_; 181 bool isAppModule_ = false; 182 std::string loadingModuleName_; 183 184 std::mutex nativeEngineListMutex_; 185 std::map<std::string, NativeEngine*> nativeEngineList_; 186 187 mutable std::mutex moduleLibMutex_; 188 std::map<std::string, const LIBHANDLE> moduleLibMap_; 189 190 mutable std::mutex moduleBufMutex_; 191 std::map<std::string, const uint8_t*> moduleBufMap_; 192 193 mutable std::mutex appLibPathMapMutex_; 194 std::map<std::string, char*> appLibPathMap_; 195 std::string previewSearchPath_; 196 std::unique_ptr<ModuleLoadChecker> moduleLoadChecker_ = nullptr; 197 }; 198 199 #endif /* FOUNDATION_ACE_NAPI_MODULE_MANAGER_NATIVE_MODULE_MANAGER_H */ 200