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