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