• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "arkweb_utils.h"
16 
17 #include "parameters.h"
18 #include "nweb_log.h"
19 #include "json/json.h"
20 #include <cerrno>
21 #include <cstring>
22 #include <dlfcn.h>
23 #include <fstream>
24 
25 namespace OHOS::ArkWeb {
26 
27 static int g_appEngineVersion = static_cast<int>(ArkWebEngineVersion::SYSTEM_DEFAULT);
28 static bool g_webEngineInitFlag = false;
29 
30 #if defined(webview_arm64)
31 const std::string ARK_WEB_CORE_MOCK_HAP_LIB_PATH =
32     "/data/storage/el1/bundle/libs/arm64";
33 const std::string ARK_WEB_CORE_HAP_LIB_PATH =
34     "/data/storage/el1/bundle/arkwebcore/libs/arm64";
35 const std::string ARK_WEB_CORE_LEGACY_HAP_LIB_PATH =
36     "/data/storage/el1/bundle/arkwebcorelegacy/libs/arm64";
37 const std::string ARK_WEB_CORE_PATH_FOR_MOCK = "libs/arm64";
38 const std::string ARK_WEB_CORE_PATH_FOR_BUNDLE = "arkwebcore/libs/arm64";
39 const std::string ARK_WEB_CORE_LEGACY_PATH_FOR_BUNDLE = "arkwebcorelegacy/libs/arm64";
40 #elif defined(webview_x86_64)
41 const std::string ARK_WEB_CORE_MOCK_HAP_LIB_PATH =
42     "/data/storage/el1/bundle/libs/x86_64";
43 const std::string ARK_WEB_CORE_HAP_LIB_PATH =
44     "/data/storage/el1/bundle/arkwebcore/libs/x86_64";
45 const std::string ARK_WEB_CORE_LEGACY_HAP_LIB_PATH =
46     "/data/storage/el1/bundle/arkwebcorelegacy/libs/x86_64";
47 const std::string ARK_WEB_CORE_PATH_FOR_MOCK = "libs/x86_64";
48 const std::string ARK_WEB_CORE_PATH_FOR_BUNDLE = "arkwebcore/libs/x86_64";
49 const std::string ARK_WEB_CORE_LEGACY_PATH_FOR_BUNDLE = "arkwebcorelegacy/libs/x86_64";
50 #else
51 const std::string ARK_WEB_CORE_MOCK_HAP_LIB_PATH =
52     "/data/storage/el1/bundle/libs/arm";
53 const std::string ARK_WEB_CORE_HAP_LIB_PATH =
54     "/data/storage/el1/bundle/arkwebcore/libs/arm";
55 const std::string ARK_WEB_CORE_LEGACY_HAP_LIB_PATH =
56     "/data/storage/el1/bundle/arkwebcorelegacy/libs/arm";
57 const std::string ARK_WEB_CORE_PATH_FOR_MOCK = "libs/arm";
58 const std::string ARK_WEB_CORE_PATH_FOR_BUNDLE = "arkwebcore/libs/arm";
59 const std::string ARK_WEB_CORE_LEGACY_PATH_FOR_BUNDLE = "arkwebcorelegacy/libs/arm";
60 #endif
61 
62 #if defined(IS_ASAN)
63 #if defined(webview_arm64)
64 const std::string ARK_WEB_CORE_ASAN_PATH_FOR_BUNDLE = "arkwebcore_asan/libs/arm64";
65 const std::string WEBVIEW_RELATIVE_SANDBOX_PATH_FOR_LIBRARY =
66                     "data/storage/el1/bundle/arkwebcore_asan/libs/arm64/libarkweb_engine.so";
67 const std::string ARK_WEB_CORE_HAP_LIB_PATH_ASAN = "/data/storage/el1/bundle/arkwebcore_asan/libs/arm64";
68 #elif defined(webview_x86_64)
69 const std::string ARK_WEB_CORE_ASAN_PATH_FOR_BUNDLE = "arkwebcore_asan/libs/x86_64";
70 #else
71 const std::string ARK_WEB_CORE_ASAN_PATH_FOR_BUNDLE = "arkwebcore_asan/libs/arm";
72 #endif
73 #endif
74 
75 const std::string PRECONFIG_LEGACY_HAP_PATH = "/system/app/ArkWebCoreLegacy/ArkWebCoreLegacy.hap";
76 const std::string  PRECONFIG_EVERGREEN_HAP_PATH =
77     "/system/app/com.ohos.arkwebcore/ArkWebCore.hap";
78 const std::string PRECONFIG_EVERGREEN_WATCH_HAP_PATH =
79     "/system/app/NWeb/NWeb.hap";
80 const std::string SANDBOX_LEGACY_HAP_PATH = "/data/storage/el1/bundle/arkwebcorelegacy/entry.hap";
81 const std::string SANDBOX_EVERGREEN_HAP_PATH = "/data/storage/el1/bundle/arkwebcore/entry.hap";
82 
83 const std::string JSON_CONFIG_PATH =
84     "/data/service/el1/public/update/param_service/install/system/etc/ArkWebSafeBrowsing/generic/ArkWebCoreCfg.json";
85 const std::string WEB_PARAM_PREFIX = "web.engine.";
86 
validateSpecialParams(const std::string & key,int value)87 static bool validateSpecialParams(const std::string& key, int value)
88 {
89     if (key == "web.engine.default") {
90         if (value != static_cast<int>(ArkWebEngineType::EVERGREEN) &&
91             value != static_cast<int>(ArkWebEngineType::LEGACY)) {
92             WVLOG_E("Invalid value for %{public}s: %{public}d, must be EVERGREEN or LEGACY",
93                 key.c_str(), value);
94             return false;
95         }
96     }
97     else if (key == "web.engine.enforce") {
98         if (value != static_cast<int>(ArkWebEngineType::EVERGREEN)) {
99             WVLOG_E("Invalid value for %{public}s: %{public}d, must be EVERGREEN",
100                 key.c_str(), value);
101             return false;
102         }
103     }
104     return true;
105 }
106 
processJsonConfig(const Json::Value & root)107 static void processJsonConfig(const Json::Value& root)
108 {
109     if (!root.isObject()) {
110         WVLOG_E("Not a JSON object");
111         return;
112     }
113 
114     Json::Value::Members keys = root.getMemberNames();
115     for (const auto& key : keys) {
116         const Json::Value& value = root[key];
117         if (!value.isInt() || key.rfind(WEB_PARAM_PREFIX, 0) != 0) {
118             WVLOG_E("Invalid param %{public}s", key.c_str());
119             continue;
120         }
121 
122         int intValue = value.asInt();
123 
124         // 验证特殊参数
125         if (!validateSpecialParams(key, intValue)) {
126             continue;  // 跳过非法值
127         }
128 
129         // 设置有效参数
130         std::string valueStr = std::to_string(intValue);
131         if (OHOS::system::SetParameter(key, valueStr)) {
132             WVLOG_I("Set param %{public}s with %{public}s", key.c_str(), valueStr.c_str());
133         } else {
134             WVLOG_E("Set param %{public}s with %{public}s failed", key.c_str(), valueStr.c_str());
135         }
136     }
137 }
138 
updateCfgToSystemParam()139 static void updateCfgToSystemParam()
140 {
141     std::ifstream jsonFile(JSON_CONFIG_PATH.c_str());
142     if (!jsonFile.is_open()) {
143         WVLOG_E("Failed to open file reason: %{public}s", strerror(errno));
144         return;
145     }
146 
147     Json::Value root;
148     Json::CharReaderBuilder readerBuilder;
149     std::string parseErrors;
150     bool parsingSuccessful = Json::parseFromStream(readerBuilder, jsonFile, &root, &parseErrors);
151 
152     if (!parsingSuccessful) {
153         WVLOG_E("JSON parse failed, parseErrors:%{public}s", parseErrors.c_str());
154         return;
155     }
156 
157     processJsonConfig(root);
158 }
159 
PreloadArkWebLibForBrowser()160 void PreloadArkWebLibForBrowser()
161 {
162     updateCfgToSystemParam();
163     if (!(access(PRECONFIG_LEGACY_HAP_PATH.c_str(), F_OK) == 0)) {
164         if (OHOS::system::SetParameter("web.engine.enforce",
165                 std::to_string(static_cast<int>(ArkWebEngineType::EVERGREEN)))) {
166             WVLOG_I("Set param web.engine.enforce with %{public}d", static_cast<int>(ArkWebEngineType::EVERGREEN));
167         } else {
168             WVLOG_I("Set param web.engine.enforce with %{public}d failed",
169                     static_cast<int>(ArkWebEngineType::EVERGREEN));
170         }
171     }
172     return;
173 }
174 
setActiveWebEngineVersion(ArkWebEngineVersion version)175 void setActiveWebEngineVersion(ArkWebEngineVersion version)
176 {
177     if (g_webEngineInitFlag) {
178         WVLOG_E("library resources have been loaded, can't set appEngineVersion");
179         return;
180     }
181 
182     if (static_cast<int>(version) != static_cast<int>(ArkWebEngineType::LEGACY) &&
183       static_cast<int>(version) != static_cast<int>(ArkWebEngineType::EVERGREEN) &&
184       static_cast<int>(version) != static_cast<int>(ArkWebEngineVersion::SYSTEM_DEFAULT) &&
185       static_cast<int>(version) != static_cast<int>(ArkWebEngineVersion::SYSTEM_EVERGREEN)) {
186         WVLOG_I("set EngineVersion not support, setVersion: %{public}d", static_cast<int>(version));
187         return;
188     }
189     g_appEngineVersion = static_cast<int>(version);
190     WVLOG_I("set appEngineVersion: %{public}d", g_appEngineVersion);
191 }
192 
getAppWebEngineVersion()193 ArkWebEngineVersion getAppWebEngineVersion()
194 {
195     return static_cast<ArkWebEngineVersion>(g_appEngineVersion);
196 }
197 
getActiveWebEngineVersion()198 ArkWebEngineVersion getActiveWebEngineVersion()
199 {
200     int webEngineEnforce = OHOS::system::GetIntParameter("web.engine.enforce", 0);
201     if (webEngineEnforce == static_cast<int>(ArkWebEngineType::EVERGREEN)) {
202         WVLOG_I("WebEngineVersionResult, enforce EVERGREEN");
203         return static_cast<ArkWebEngineVersion>(ArkWebEngineType::EVERGREEN);
204     }
205 
206     if (g_appEngineVersion != static_cast<int>(ArkWebEngineVersion::SYSTEM_DEFAULT)) {
207         WVLOG_I("get appEngineVersion: %{public}d", g_appEngineVersion);
208         if (g_appEngineVersion == static_cast<int>(ArkWebEngineVersion::SYSTEM_EVERGREEN)) {
209             return static_cast<ArkWebEngineVersion>(ArkWebEngineType::EVERGREEN);
210         }
211         return static_cast<ArkWebEngineVersion>(g_appEngineVersion);
212     }
213 
214     int webEngineDefault = OHOS::system::GetIntParameter("web.engine.default",
215         static_cast<int>(ArkWebEngineType::EVERGREEN));
216     if (webEngineDefault != static_cast<int>(ArkWebEngineType::LEGACY) &&
217       webEngineDefault != static_cast<int>(ArkWebEngineType::EVERGREEN)) {
218         WVLOG_E("webEngineDefault is not EVERGREEN or LEGACY: %{public}d", webEngineDefault);
219         return static_cast<ArkWebEngineVersion>(ArkWebEngineType::EVERGREEN);
220     }
221 
222     WVLOG_I("get webEngineDefault: %{public}d", webEngineDefault);
223     return static_cast<ArkWebEngineVersion>(webEngineDefault);
224 }
225 
getActiveWebEngineType()226 ArkWebEngineType getActiveWebEngineType()
227 {
228     return static_cast<ArkWebEngineType>(getActiveWebEngineVersion());
229 }
230 
IsActiveWebEngineEvergreen()231 bool IsActiveWebEngineEvergreen()
232 {
233     if (getActiveWebEngineType() == ArkWebEngineType::EVERGREEN) {
234         return true;
235     }
236     return false;
237 }
238 
LogForUnsupportedFunc(ArkWebEngineVersion version,const char * msg)239 void LogForUnsupportedFunc(ArkWebEngineVersion version, const char* msg)
240 {
241     WVLOG_W("%{public}s unsupported engine version: %{public}d",
242         msg, static_cast<int>(version));
243 }
244 
GetArkwebLibPath()245 std::string GetArkwebLibPath()
246 {
247     std::string path;
248     if (getActiveWebEngineType() == ArkWebEngineType::LEGACY) {
249         path =  ARK_WEB_CORE_LEGACY_HAP_LIB_PATH;
250     } else {
251         path = ARK_WEB_CORE_HAP_LIB_PATH;
252 #if defined(IS_ASAN) && defined(webview_arm64)
253         if ((access(WEBVIEW_RELATIVE_SANDBOX_PATH_FOR_LIBRARY.c_str(), F_OK) == 0)) {
254             path = ARK_WEB_CORE_HAP_LIB_PATH_ASAN;
255         }
256 #endif
257     }
258     WVLOG_I("get arkweb lib path: %{public}s", path.c_str());
259     return path;
260 }
261 
GetArkwebLibPathForMock()262 std::string GetArkwebLibPathForMock()
263 {
264     std::string path =  ARK_WEB_CORE_MOCK_HAP_LIB_PATH;
265     WVLOG_I("get arkweb lib mock path: %{public}s", path.c_str());
266     return path;
267 }
268 
GetArkwebNameSpace()269 std::string GetArkwebNameSpace()
270 {
271     std::string ns;
272     if (getActiveWebEngineType() == ArkWebEngineType::LEGACY) {
273         ns = "nweb_ns_legacy";
274     } else {
275         ns = "nweb_ns";
276     }
277     WVLOG_I("get arkweb name space: %{public}s", ns.c_str());
278     return ns;
279 }
280 
GetArkwebRelativePathForBundle()281 std::string GetArkwebRelativePathForBundle()
282 {
283     std::string path;
284 #if defined(IS_ASAN) && defined(webview_arm64)
285     if (!(access(WEBVIEW_RELATIVE_SANDBOX_PATH_FOR_LIBRARY.c_str(), F_OK) == 0)) {
286         path = "arkwebcore/libs/arm64";
287     } else {
288         path = ARK_WEB_CORE_ASAN_PATH_FOR_BUNDLE;
289     }
290 #else
291     if (getActiveWebEngineType() == ArkWebEngineType::LEGACY) {
292         path = ARK_WEB_CORE_LEGACY_PATH_FOR_BUNDLE;
293     } else {
294         path = ARK_WEB_CORE_PATH_FOR_BUNDLE;
295     }
296 #endif
297     WVLOG_I("get arkweb relative bundle path: %{public}s", path.c_str());
298     return path;
299 }
300 
GetArkwebRelativePathForMock()301 std::string GetArkwebRelativePathForMock()
302 {
303     std::string path = ARK_WEB_CORE_PATH_FOR_MOCK;
304     WVLOG_I("get arkweb mock path: %{public}s", path.c_str());
305     return path;
306 }
307 
GetArkwebInstallPath()308 std::string GetArkwebInstallPath()
309 {
310     std::vector<std::string> legacyPaths = {SANDBOX_LEGACY_HAP_PATH, PRECONFIG_LEGACY_HAP_PATH,};
311     std::vector<std::string> greenPaths = {SANDBOX_EVERGREEN_HAP_PATH, PRECONFIG_EVERGREEN_HAP_PATH,
312         PRECONFIG_EVERGREEN_WATCH_HAP_PATH};
313 
314     std::vector<std::string> workPaths;
315     if (getActiveWebEngineType() == ArkWebEngineType::LEGACY) {
316         workPaths = legacyPaths;
317     } else {
318         workPaths = greenPaths;
319     }
320 
321     std::string installPath = "";
322     for (auto path : workPaths) {
323         if (access(path.c_str(), F_OK) == 0) {
324             installPath = path;
325             break;
326         }
327     }
328     if (installPath == "") {
329         WVLOG_E("failed to find hap path");
330     }
331     WVLOG_I("get arkweb install path: %{public}s", installPath.c_str());
332     return installPath;
333 }
334 
ArkWebBridgeHelperLoadLibFile(int openMode,const std::string & libFilePath,bool isPrintLog=true)335 void* ArkWebBridgeHelperLoadLibFile(int openMode, const std::string& libFilePath,
336     bool isPrintLog = true)
337 {
338     void* libFileHandler = ::dlopen(libFilePath.c_str(), openMode);
339     if (!libFileHandler) {
340         if (isPrintLog) {
341             WVLOG_E("failed to load lib file %{public}s", libFilePath.c_str());
342         }
343         return nullptr;
344     }
345 
346     if (isPrintLog) {
347         WVLOG_I("succeed to load lib file %{public}s", libFilePath.c_str());
348     }
349     return libFileHandler;
350 }
351 
ArkWebBridgeHelperLoadLibFile(int openMode,const std::string & libNsName,const std::string & libDirPath,const std::string & libFileName,bool isPrintLog=true)352 void* ArkWebBridgeHelperLoadLibFile(int openMode, const std::string& libNsName,
353     const std::string& libDirPath, const std::string& libFileName, bool isPrintLog = true)
354 {
355     Dl_namespace dlns;
356 
357     dlns_init(&dlns, libNsName.c_str());
358 
359     int ret = dlns_create(&dlns, libDirPath.c_str());
360     if (ret != 0) {
361         WVLOG_E("dlns_create failed for '%{public}s': %{public}s (errno=%{public}d)",
362                 libDirPath.c_str(), strerror(errno), ret);
363     }
364 
365     Dl_namespace ndkns;
366     ret = dlns_get("ndk", &ndkns);
367     if (ret != 0) {
368         WVLOG_E("dlns_get(ndk) failed: %{public}s (errno=%{public}d)", strerror(errno), ret);
369     }
370 
371     ret = dlns_inherit(&dlns, &ndkns, "allow_all_shared_libs");
372     if (ret != 0) {
373         WVLOG_E("dlns_inherit failed: %{public}s (errno=%{public}d)", strerror(errno), ret);
374     }
375 
376     void* libFileHandler = dlopen_ns(&dlns, libFileName.c_str(), openMode);
377     if (!libFileHandler) {
378         if (isPrintLog) {
379             WVLOG_E(
380                 "failed to load lib file %{public}s/%{public}s", libDirPath.c_str(), libFileName.c_str());
381         }
382         return nullptr;
383     }
384 
385     if (isPrintLog) {
386         WVLOG_I(
387             "succeed to load lib file %{public}s/%{public}s", libDirPath.c_str(), libFileName.c_str());
388     }
389 
390     return libFileHandler;
391 }
392 
ArkWebBridgeHelperSharedInit(bool isPreDlopen,bool runMode)393 void* ArkWebBridgeHelperSharedInit(bool isPreDlopen, bool runMode)
394 {
395     std::string libFileName = "libarkweb_engine.so";
396 
397     std::string libDirPath;
398     if (runMode) {
399         libDirPath = GetArkwebLibPath();
400     } else {
401         libDirPath = GetArkwebLibPathForMock();
402     }
403 
404     std::string libNsName = GetArkwebNameSpace();
405 
406     void* libFileHandler;
407 
408 #ifdef __MUSL__
409     libFileHandler = ArkWebBridgeHelperLoadLibFile(RTLD_NOW | RTLD_GLOBAL, libNsName, libDirPath, libFileName);
410 #else
411     libFileHandler = ArkWebBridgeHelperLoadLibFile(RTLD_NOW, libDirPath + "/" + libFileName)
412 #endif
413 
414     if (!isPreDlopen && libFileHandler != nullptr) {
415         g_webEngineInitFlag = true;
416         WVLOG_I("g_webEngineInitFlag set to true. setActiveWebEngineVersion will be ignored.");
417     }
418 
419     return libFileHandler;
420 }
421 }