• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "base/bridge/ark_web_bridge_helper.h"
17 
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 
22 #include "base/bridge/ark_web_bridge_macros.h"
23 
24 namespace OHOS::ArkWeb {
25 
26 int g_ark_web_init_addr = 1;
27 
~ArkWebBridgeHelper()28 ArkWebBridgeHelper::~ArkWebBridgeHelper()
29 {
30     UnloadLibFile();
31 }
32 
LoadLibFile(int openMode,const std::string & libFilePath,bool isPrintLog)33 bool ArkWebBridgeHelper::LoadLibFile(int openMode, const std::string& libFilePath, bool isPrintLog)
34 {
35     if (libFileHandler_) {
36         return true;
37     }
38 
39     void* libFileHandler = ::dlopen(libFilePath.c_str(), openMode);
40     if (!libFileHandler) {
41         if (isPrintLog) {
42             ARK_WEB_BRIDGE_ERROR_LOG("failed to load lib file %{public}s", libFilePath.c_str());
43         }
44 
45         return false;
46     }
47 
48     if (isPrintLog) {
49         ARK_WEB_BRIDGE_INFO_LOG("succeed to load lib file %{public}s", libFilePath.c_str());
50     }
51 
52     libFileHandler_ = libFileHandler;
53     return true;
54 }
55 
56 #if defined(OHOS_WEBVIEW_GLUE)
LoadLibFile(int openMode,const std::string & libNsName,const std::string & libDirPath,const std::string & libFileName,bool isPrintLog)57 bool ArkWebBridgeHelper::LoadLibFile(int openMode, const std::string& libNsName, const std::string& libDirPath,
58     const std::string& libFileName, bool isPrintLog)
59 {
60     if (libFileHandler_) {
61         return true;
62     }
63 
64     Dl_namespace dlns;
65     dlns_init(&dlns, libNsName.c_str());
66     dlns_create(&dlns, libDirPath.c_str());
67 
68     Dl_namespace ndkns;
69     dlns_get("ndk", &ndkns);
70     dlns_inherit(&dlns, &ndkns, "allow_all_shared_libs");
71 
72     void* libFileHandler = dlopen_ns(&dlns, libFileName.c_str(), openMode);
73     if (!libFileHandler) {
74         if (isPrintLog) {
75             ARK_WEB_BRIDGE_ERROR_LOG(
76                 "failed to load lib file %{public}s/%{public}s", libDirPath.c_str(), libFileName.c_str());
77         }
78 
79         return false;
80     }
81 
82     if (isPrintLog) {
83         ARK_WEB_BRIDGE_INFO_LOG(
84             "succeed to load lib file %{public}s/%{public}s", libDirPath.c_str(), libFileName.c_str());
85     }
86 
87     libFileHandler_ = libFileHandler;
88     return true;
89 }
90 #endif
91 
UnloadLibFile()92 void ArkWebBridgeHelper::UnloadLibFile()
93 {
94     if (libFileHandler_ != nullptr) {
95         ::dlclose(libFileHandler_);
96         libFileHandler_ = nullptr;
97     }
98 }
99 
PrereadLibFile(const std::string & libFilePath,bool isPrintLog)100 void ArkWebBridgeHelper::PrereadLibFile(const std::string& libFilePath, bool isPrintLog)
101 {
102     char realPath[PATH_MAX] = { 0 };
103     if (realpath(libFilePath.c_str(), realPath) == nullptr) {
104         if (isPrintLog) {
105             ARK_WEB_BRIDGE_ERROR_LOG("failed to get real path,lib file is %{public}s,errno is %{public}d(%{public}s)",
106                 libFilePath.c_str(), errno, strerror(errno));
107         }
108         return;
109     }
110 
111     struct stat stats;
112     if (stat(realPath, &stats) < 0) {
113         if (isPrintLog) {
114             ARK_WEB_BRIDGE_ERROR_LOG("failed to stat lib file %{public}s,errno is %{public}d(%{public}s)",
115                 libFilePath.c_str(), errno, strerror(errno));
116         }
117         return;
118     }
119 
120     int fd = open(realPath, O_RDONLY);
121     if (fd <= 0) {
122         if (isPrintLog) {
123             ARK_WEB_BRIDGE_ERROR_LOG("failed to open lib file %{public}s,errno is %{public}d : %{public}s",
124                 libFilePath.c_str(), errno, strerror(errno));
125         }
126         return;
127     }
128 
129     static const int SINGLE_READ_SIZE = 5 * 1024 * 1024;
130     char* buf = new (std::nothrow) char[SINGLE_READ_SIZE];
131     if (buf == nullptr) {
132         (void)close(fd);
133         if (isPrintLog) {
134             ARK_WEB_BRIDGE_ERROR_LOG("failed to malloc buf,lib file is %{public}s", libFilePath.c_str());
135         }
136         return;
137     }
138 
139     int readCnt = stats.st_size / SINGLE_READ_SIZE;
140     if (readCnt * SINGLE_READ_SIZE < stats.st_size) {
141         readCnt += 1;
142     }
143 
144     for (int i = 0; i < readCnt; i++) {
145         (void)read(fd, buf, SINGLE_READ_SIZE);
146     }
147 
148     (void)close(fd);
149     delete[] buf;
150 
151     if (isPrintLog) {
152         ARK_WEB_BRIDGE_INFO_LOG("succeed to preread lib file %{public}s", libFilePath.c_str());
153     }
154 }
155 
LoadFuncSymbol(const char * funcName,bool isPrintLog)156 void* ArkWebBridgeHelper::LoadFuncSymbol(const char* funcName, bool isPrintLog)
157 {
158     if (!libFileHandler_) {
159         if (isPrintLog) {
160             ARK_WEB_BRIDGE_ERROR_LOG("lib file handle is nullptr,func name is %{public}s", funcName);
161         }
162 
163         return nullptr;
164     }
165 
166     if (isPrintLog) {
167         ARK_WEB_BRIDGE_INFO_LOG("load func %{public}s", funcName);
168     }
169 
170     return dlsym(libFileHandler_, funcName);
171 }
172 
InitFuncMemberMaps(ArkWebBridgeType init,ArkWebBridgeType butt,bool isPrintLog)173 void ArkWebBridgeHelper::InitFuncMemberMaps(ArkWebBridgeType init, ArkWebBridgeType butt, bool isPrintLog)
174 {
175     std::map<std::string, void*> funcMemberMap;
176     for (int type = static_cast<int>(init); type < static_cast<int>(butt); type++) {
177         funcMemberMaps_[type] = funcMemberMap;
178     }
179 
180     if (isPrintLog) {
181         ARK_WEB_BRIDGE_DV_LOG("init func member maps,bridge type is %{public}d - %{public}d", init, butt);
182     }
183 }
184 
RegisterFuncMember(ArkWebBridgeType bridgeType,const std::map<std::string,void * > & funcMemberMap)185 void ArkWebBridgeHelper::RegisterFuncMember(
186     ArkWebBridgeType bridgeType, const std::map<std::string, void*>& funcMemberMap)
187 {
188     auto itor = funcMemberMaps_.find(static_cast<int>(bridgeType));
189     if (itor == funcMemberMaps_.end()) {
190         ARK_WEB_BRIDGE_INFO_LOG("func member map isn't exist,bridge type is %{public}d", bridgeType);
191         return;
192     }
193 
194     itor->second = funcMemberMap;
195     ARK_WEB_BRIDGE_DV_LOG("func member map is registered and bridge type is %{public}d", bridgeType);
196 }
197 
CheckFuncMemberForCalled(ArkWebBridgeType bridgeType,const std::string & funcName)198 void* ArkWebBridgeHelper::CheckFuncMemberForCalled(ArkWebBridgeType bridgeType, const std::string& funcName)
199 {
200     if (funcName.empty()) {
201         ARK_WEB_BRIDGE_INFO_LOG("func name is empty,bridge ype is %{public}d", bridgeType);
202         return nullptr;
203     }
204 
205     auto itor0 = funcMemberMaps_.find(static_cast<int>(bridgeType));
206     if (itor0 == funcMemberMaps_.end()) {
207         ARK_WEB_BRIDGE_INFO_LOG("func member map isn't registered,bridge type is %{public}d,func name is %{public}s",
208             bridgeType, funcName.c_str());
209         return nullptr;
210     }
211 
212     auto itor1 = itor0->second.find(funcName);
213     if (itor1 == itor0->second.end()) {
214         ARK_WEB_BRIDGE_INFO_LOG("func member isn't registered,bridge type is %{public}d,func name is %{public}s",
215             bridgeType, funcName.c_str());
216         return nullptr;
217     }
218 
219     return itor1->second;
220 }
221 
CheckFuncMemberForCaller(ArkWebBridgeType bridgeType,const std::string & funcName)222 void* ArkWebBridgeHelper::CheckFuncMemberForCaller(ArkWebBridgeType bridgeType, const std::string& funcName)
223 {
224     if (!memberCheckFunc_) {
225         return ARK_WEB_INIT_ADDR;
226     }
227 
228     ArkWebString stFuncName = ArkWebStringClassToStruct(funcName);
229     void* func = memberCheckFunc_(bridgeType, &stFuncName);
230     ArkWebStringStructRelease(stFuncName);
231     return func;
232 }
233 
234 } // namespace OHOS::ArkWeb
235