• 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,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