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