• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "nweb_helper.h"
17 
18 #include <dlfcn.h>
19 #include <refbase.h>
20 #include <surface.h>
21 
22 #include <cstdint>
23 #include <memory>
24 #include <thread>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <dirent.h>
28 
29 #include "nweb_adapter_helper.h"
30 #include "nweb_enhance_surface_adapter.h"
31 #include "nweb_log.h"
32 #include "nweb_surface_adapter.h"
33 #include "nweb_window_adapter.h"
34 #include "window.h"
35 
36 namespace {
37 const uint32_t NWEB_SURFACE_MAX_WIDTH = 7680;
38 const uint32_t NWEB_SURFACE_MAX_HEIGHT = 7680;
39 #if defined(webview_arm64)
40 const std::string RELATIVE_PATH_FOR_MOCK = "libs/arm64";
41 const std::string RELATIVE_PATH_FOR_BUNDLE = "nweb/libs/arm64";
42 #elif defined(webview_x86_64)
43 const std::string RELATIVE_PATH_FOR_MOCK = "libs/x86_64";
44 const std::string RELATIVE_PATH_FOR_BUNDLE = "nweb/libs/x86_64";
45 #else
46 const std::string RELATIVE_PATH_FOR_MOCK = "libs/arm";
47 const std::string RELATIVE_PATH_FOR_BUNDLE = "nweb/libs/arm";
48 #endif
49 const std::string LIB_NAME_WEB_ENGINE = "libweb_engine.so";
50 const std::string LIB_NAME_NWEB_ADAPTER = "libnweb_adapter.so";
51 static bool g_isFirstTimeStartUp = false;
52 }
53 
54 namespace OHOS::NWeb {
Instance()55 NWebHelper &NWebHelper::Instance()
56 {
57     static NWebHelper helper;
58     return helper;
59 }
60 
61 #ifdef __MUSL__
LoadLib(bool from_ark)62 bool NWebHelper::LoadLib(bool from_ark)
63 {
64     if (libHandleWebEngine_ != nullptr) {
65         return true;
66     }
67     if (bundlePath_.empty()) {
68         return false;
69     }
70     std::string loadLibPath;
71     if (from_ark) {
72         loadLibPath = bundlePath_ + "/" + RELATIVE_PATH_FOR_BUNDLE;
73     } else {
74         loadLibPath = bundlePath_ + "/" + RELATIVE_PATH_FOR_MOCK;
75     }
76     Dl_namespace dlns;
77     dlns_init(&dlns, "nweb_ns");
78     dlns_create(&dlns, loadLibPath.c_str());
79     void *libHandleWebEngine = dlopen_ns(&dlns, LIB_NAME_WEB_ENGINE.c_str(), RTLD_NOW);
80     if (libHandleWebEngine == nullptr) {
81         WVLOG_E("fail to dlopen %{public}s, errmsg=%{public}s", LIB_NAME_WEB_ENGINE.c_str(), dlerror());
82         return false;
83     }
84     libHandleWebEngine_ = libHandleWebEngine;
85     return true;
86 }
87 #else
LoadLib(bool from_ark)88 bool NWebHelper::LoadLib(bool from_ark)
89 {
90     if (libHandleWebEngine_ != nullptr) {
91         return true;
92     }
93     if (bundlePath_.empty()) {
94         return false;
95     }
96     std::string loadLibPath;
97     if (from_ark) {
98         loadLibPath = bundlePath_ + "/" + RELATIVE_PATH_FOR_BUNDLE;
99     } else {
100         loadLibPath = bundlePath_ + "/" + RELATIVE_PATH_FOR_MOCK;
101     }
102     const std::string libPathWebEngine = loadLibPath + "/" + LIB_NAME_WEB_ENGINE;
103     void *libHandleWebEngine = ::dlopen(libPathWebEngine.c_str(), RTLD_NOW);
104     if (libHandleWebEngine == nullptr) {
105         WVLOG_E("fail to dlopen %{public}s, errmsg=%{public}s", libPathWebEngine.c_str(), dlerror());
106         return false;
107     }
108     libHandleWebEngine_ = libHandleWebEngine;
109     return true;
110 }
111 #endif
112 
UnloadLib()113 void NWebHelper::UnloadLib()
114 {
115     if (libHandleWebEngine_ != nullptr) {
116         ::dlclose(libHandleWebEngine_);
117         libHandleWebEngine_ = nullptr;
118     }
119 }
120 
DoPreReadLib(const std::string & bundlePath)121 static void DoPreReadLib(const std::string &bundlePath)
122 {
123     WVLOG_I("NWebHelper PreReadLib");
124     std::string libPathWebEngine = bundlePath + "/" + RELATIVE_PATH_FOR_BUNDLE + "/" + LIB_NAME_WEB_ENGINE;
125 
126     char tempPath[PATH_MAX] = {0};
127     if (realpath(libPathWebEngine.c_str(), tempPath) == nullptr) {
128         WVLOG_E("path to realpath error");
129         return;
130     }
131 
132     struct stat stats;
133     int ret = stat(tempPath, &stats);
134     if (ret < 0) {
135         WVLOG_E("stat web engine library failed, ret = %{public}d", ret);
136         return;
137     }
138 
139     static const int SINGLE_READ_SIZE = 5 * 1024 * 1024;
140     char *buf = new (std::nothrow) char[SINGLE_READ_SIZE];
141     if (buf == nullptr) {
142         WVLOG_E("malloc buf failed");
143         return;
144     }
145 
146     int fd = open(tempPath, O_RDONLY);
147     if (fd <= 0) {
148         WVLOG_E("open web engine library failed");
149         delete [] buf;
150         return;
151     }
152 
153     int readCnt = stats.st_size / SINGLE_READ_SIZE;
154     if (readCnt * SINGLE_READ_SIZE < stats.st_size) {
155         readCnt += 1;
156     }
157 
158     for (int i = 0; i < readCnt; i++) {
159         (void)read(fd, buf, SINGLE_READ_SIZE);
160     }
161 
162     (void)close(fd);
163     delete [] buf;
164     WVLOG_I("NWebHelper PreReadLib Finish");
165 }
166 
TryPreReadLib(bool isFirstTimeStartUpWeb,const std::string & bundlePath)167 void NWebHelper::TryPreReadLib(bool isFirstTimeStartUpWeb, const std::string &bundlePath)
168 {
169     g_isFirstTimeStartUp = isFirstTimeStartUpWeb;
170     if (isFirstTimeStartUpWeb) {
171         WVLOG_I("first time startup, need to wait until the nweb init stage");
172         return;
173     }
174 
175     DoPreReadLib(bundlePath);
176 }
177 
TryPreReadLibForFirstlyAppStartUp(const std::string & bundlePath)178 static void TryPreReadLibForFirstlyAppStartUp(const std::string &bundlePath)
179 {
180     if (g_isFirstTimeStartUp) {
181         std::thread preReadThread([bundlePath]() {
182             DoPreReadLib(bundlePath);
183         });
184 
185         preReadThread.detach();
186     }
187 }
188 
Init(bool from_ark)189 bool NWebHelper::Init(bool from_ark)
190 {
191     TryPreReadLibForFirstlyAppStartUp(bundlePath_);
192     return LoadLib(from_ark);
193 }
194 
SetBundlePath(const std::string & path)195 void NWebHelper::SetBundlePath(const std::string &path)
196 {
197     bundlePath_ = path;
198 }
199 
~NWebHelper()200 NWebHelper::~NWebHelper()
201 {
202     UnloadLib();
203 }
204 
205 using CreateNWebFuncType = void(*)(const NWebCreateInfo &, std::shared_ptr<NWeb> &);
CreateNWeb(const NWebCreateInfo & create_info)206 std::shared_ptr<NWeb> NWebHelper::CreateNWeb(const NWebCreateInfo &create_info)
207 {
208     if (libHandleWebEngine_ == nullptr) {
209         return nullptr;
210     }
211 
212     const std::string CREATE_NWEB_FUNC_NAME = "CreateNWeb";
213     CreateNWebFuncType funcCreateNWeb =
214         reinterpret_cast<CreateNWebFuncType>(dlsym(libHandleWebEngine_, CREATE_NWEB_FUNC_NAME.c_str()));
215     if (funcCreateNWeb == nullptr) {
216         WVLOG_E("fail to dlsym %{public}s from libohoswebview.so", CREATE_NWEB_FUNC_NAME.c_str());
217         return nullptr;
218     }
219     std::shared_ptr<NWeb> nweb;
220     funcCreateNWeb(create_info, nweb);
221     if (nweb == nullptr) {
222         WVLOG_E("fail to create nweb");
223         return nullptr;
224     }
225 
226     return nweb;
227 }
228 
229 using GetCookieManagerFunc = NWebCookieManager *(*)();
GetCookieManager()230 NWebCookieManager *NWebHelper::GetCookieManager()
231 {
232     if (libHandleWebEngine_ == nullptr) {
233         return nullptr;
234     }
235 
236     const std::string COOKIE_FUNC_NAME = "GetCookieManager";
237     GetCookieManagerFunc cookieFunc =
238         reinterpret_cast<GetCookieManagerFunc>(dlsym(libHandleWebEngine_, COOKIE_FUNC_NAME.c_str()));
239     if (cookieFunc == nullptr) {
240         WVLOG_E("fail to dlsym %{public}s from libohoswebview.so", COOKIE_FUNC_NAME.c_str());
241         return nullptr;
242     }
243     return cookieFunc();
244 }
245 
246 using GetNWebFunc = void(*)(int32_t, std::weak_ptr<NWeb> &);
GetNWeb(int32_t nweb_id)247 std::weak_ptr<NWeb> NWebHelper::GetNWeb(int32_t nweb_id)
248 {
249     std::weak_ptr<OHOS::NWeb::NWeb> nweb;
250     if (libHandleWebEngine_ == nullptr) {
251         WVLOG_E("libHandleWebEngine_ is nullptr");
252         return nweb;
253     }
254 
255     const std::string GET_NWEB_FUNC_NAME = "GetNWeb";
256     GetNWebFunc getNWebFunc = reinterpret_cast<GetNWebFunc>(dlsym(libHandleWebEngine_, GET_NWEB_FUNC_NAME.c_str()));
257     if (getNWebFunc == nullptr) {
258         WVLOG_E("fail to dlsym %{public}s from libohoswebview.so", GET_NWEB_FUNC_NAME.c_str());
259         return nweb;
260     }
261 
262     getNWebFunc(nweb_id, nweb);
263     return nweb;
264 }
265 
266 using GetDataBaseFunc = NWebDataBase *(*)();
GetDataBase()267 NWebDataBase *NWebHelper::GetDataBase()
268 {
269     if (libHandleWebEngine_ == nullptr) {
270         return nullptr;
271     }
272 
273     const std::string DATA_BASE_FUNC_NAME = "GetDataBase";
274     GetDataBaseFunc dataBaseFunc =
275         reinterpret_cast<GetDataBaseFunc>(dlsym(libHandleWebEngine_, DATA_BASE_FUNC_NAME.c_str()));
276     if (dataBaseFunc == nullptr) {
277         WVLOG_E("fail to dlsym %{public}s from libohoswebview.so", DATA_BASE_FUNC_NAME.c_str());
278         return nullptr;
279     }
280     return dataBaseFunc();
281 }
282 
283 using GetWebStorageFunc = NWebWebStorage *(*)();
GetWebStorage()284 NWebWebStorage *NWebHelper::GetWebStorage()
285 {
286     if (libHandleWebEngine_ == nullptr) {
287         return nullptr;
288     }
289     const std::string STORAGE_FUNC_NAME = "GetWebStorage";
290     GetWebStorageFunc storageFunc =
291         reinterpret_cast<GetWebStorageFunc>(dlsym(libHandleWebEngine_, STORAGE_FUNC_NAME.c_str()));
292     if (storageFunc == nullptr) {
293         WVLOG_E("fail to dlsym %{public}s from libohoswebview.so", STORAGE_FUNC_NAME.c_str());
294         return nullptr;
295     }
296     return storageFunc();
297 }
298 
Instance()299 NWebAdapterHelper &NWebAdapterHelper::Instance()
300 {
301     static NWebAdapterHelper helper;
302     return helper;
303 }
304 
Init(bool from_ark)305 bool NWebAdapterHelper::Init(bool from_ark)
306 {
307     return NWebHelper::Instance().Init(from_ark);
308 }
309 
CreateNWeb(Rosen::Window * window,const NWebInitArgs & initArgs)310 std::shared_ptr<NWeb> NWebAdapterHelper::CreateNWeb(Rosen::Window *window, const NWebInitArgs &initArgs)
311 {
312     if (window == nullptr) {
313         WVLOG_E("fail to create nweb, input window is nullptr");
314         return nullptr;
315     }
316     auto createInfo = NWebWindowAdapter::Instance().GetCreateInfo(window, initArgs);
317     auto nweb = NWebHelper::Instance().CreateNWeb(createInfo);
318     if (nweb == nullptr) {
319         WVLOG_E("fail to create nweb instance");
320         return nullptr;
321     }
322     NWebWindowAdapter::Instance().RegistEventCb(window, nweb);
323     NWebWindowAdapter::Instance().RequestVsync(window, nweb);
324     return nweb;
325 }
326 
CreateNWeb(sptr<Surface> surface,const NWebInitArgs & initArgs,uint32_t width,uint32_t height)327 std::shared_ptr<NWeb> NWebAdapterHelper::CreateNWeb(sptr<Surface> surface, const NWebInitArgs &initArgs, uint32_t width,
328     uint32_t height)
329 {
330     if (surface == nullptr) {
331         WVLOG_E("fail to create nweb, input surface is nullptr");
332         return nullptr;
333     }
334     if (width > NWEB_SURFACE_MAX_WIDTH || height > NWEB_SURFACE_MAX_HEIGHT) {
335         WVLOG_E("input size %{public}u*%{public}u is invalid.", width, height);
336         return nullptr;
337     }
338     auto createInfo = NWebSurfaceAdapter::Instance().GetCreateInfo(surface, initArgs, width, height);
339     auto nweb = NWebHelper::Instance().CreateNWeb(createInfo);
340     if (nweb == nullptr) {
341         WVLOG_E("fail to create nweb instance");
342     }
343     return nweb;
344 }
345 
CreateNWeb(void * enhanceSurfaceInfo,const NWebInitArgs & initArgs,uint32_t width,uint32_t height)346 std::shared_ptr<NWeb> NWebAdapterHelper::CreateNWeb(void *enhanceSurfaceInfo,
347                                                     const NWebInitArgs &initArgs,
348                                                     uint32_t width,
349                                                     uint32_t height)
350 {
351     if (enhanceSurfaceInfo == nullptr) {
352         WVLOG_E("fail to create nweb, input surface is nullptr");
353         return nullptr;
354     }
355     if (width > NWEB_SURFACE_MAX_WIDTH || height > NWEB_SURFACE_MAX_HEIGHT) {
356         WVLOG_E("input size %{public}u*%{public}u is invalid.", width, height);
357         return nullptr;
358     }
359     auto createInfo = NWebEnhanceSurfaceAdapter::Instance().GetCreateInfo(enhanceSurfaceInfo, initArgs, width, height);
360     auto nweb = NWebHelper::Instance().CreateNWeb(createInfo);
361     if (nweb == nullptr) {
362         WVLOG_E("fail to create nweb instance");
363     }
364     return nweb;
365 }
366 } // namespace OHOS::NWeb
367