* Copyright (c) 2022-2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstdint>
#include <dirent.h>
#include <dlfcn.h>
#include <memory>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <thread>
#include <unistd.h>
#include <fcntl.h>
#include "arkweb_utils.h"
#include "application_context.h"
#include "bundle_mgr_interface.h"
#include "config_policy_utils.h"
#include "iservice_registry.h"
#include "nweb_config_helper.h"
#include "nweb_log.h"
#include "parameters.h"
#include "system_ability_definition.h"
namespace {
const std::string WEB_CONFIG_PATH = "etc/web/web_config.xml";
const std::string INIT_CONFIG = "initConfig";
const std::string DELETE_CONFIG = "deleteArgsConfig";
const std::string PERFORMANCE_CONFIG = "performanceConfig";
const std::string BASE_WEB_CONFIG = "baseWebConfig";
const std::string WEB_ANIMATION_DYNAMIC_SETTING_CONFIG = "property_animation_dynamic_settings";
const std::string WEB_ANIMATION_DYNAMIC_APP = "dynamic_apps";
const std::string WEB_LTPO_STRATEGY = "ltpo_strategy";
const std::string WEB_LOAD_URL_CONFIG = "load_url_config";
const std::string WEB_LOAD_URL_STRATEGY = "load_url_strategy";
const std::string WEB_DVSYNC_CONFIG = "dvsync_config";
const std::string WEB_DVSYNC_SWITCH = "dvsync_switch";
const std::string WEB_WINDOW_ORIENTATION_CONFIG = "window_orientation_config";
const std::string WEB_NATIVE_MESSAGING_EXTENSION_CONFIG = "webNativeMessagingExtensionConfig";
const std::string WEB_ALL_BUNDLE_NAME = "*";
const std::string WEB_THROTTLE_STRATEGY = "throttle_strategy";
const std::string WEB_THROTTLE_TIMEOUT = "throttle_timeout";
const std::string WEB_THROTTLE_RATIO = "throttle_ratio";
const auto XML_ATTR_NAME = "name";
const auto XML_ATTR_MIN = "min";
const auto XML_ATTR_MAX = "max";
const auto XML_ATTR_FPS = "preferred_fps";
const auto XML_BUNDLE_NAME = "bundle_name";
const auto XML_ENABLE_WINDOW_ORIENTATION = "enable_window_orientation";
const std::unordered_map<std::string_view, std::function<std::string(std::string&)>> configMap = {
{ "renderConfig/renderProcessCount",
[](std::string& contentStr) { return std::string("--renderer-process-limit=") + contentStr; } },
{ "mediaConfig/backgroundMediaShouldSuspend",
[](std::string& contentStr) {
return contentStr == "false" ? std::string("--disable-background-media-suspend") : std::string();
} },
{ "loadurlSocPerfConfig/loadurlSocPerfParam",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-loadurl-soc-perf") : std::string();
} },
{ "mouseWheelSocPerfConfig/mouseWheelSocPerfParam",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-mousewheel-soc-perf") : std::string();
} },
{ "touchEventConfig/touchEventShouldRegister",
[](std::string& contentStr) {
return contentStr == "false" ? std::string("--disable-touch-event-register") : std::string();
} },
{ "settingConfig/enableWaitForUsername",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-wait-for-username") : std::string();
} },
{ "settingConfig/enableMaxNumberOfSavedFrames",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-max-number-of-saved-frames") : std::string();
} },
{ "settingConfig/enableNumRasterThreads",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-num-raster-threads") : std::string();
} },
{ "settingConfig/enableSingleRenderProcess",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-single-render-process") : std::string();
} },
{ "userAgentConfig/userAgentValue",
[](std::string& contentStr) { return std::string("--ohos-user-agent-value=") + contentStr; } },
{ "settingConfig/enableSimpleBackendIsDefault",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-simple-backend-is-default") : std::string();
} },
{ "settingConfig/enableEmbedMode",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-embed-mode") : std::string();
} },
{ "settingConfig/enableWebViewImplForLargeScreen",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-web-view-impl-for-large-screen") : std::string();
} },
{ "settingConfig/enableDeleteUnusedResourcesDelay",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-delete-unused-resources-delay") : std::string();
} },
{ "settingConfig/enableSetHttpCacheMaxSize",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-set-http-cache-max-size") : std::string();
} },
{ "settingConfig/enableCookieConfigPersistSession",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-cookie-config-persist-session") : std::string();
} },
{ "settingConfig/enableDoubleTapForPlatform",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-double-tap-for-platform") : std::string();
} },
{ "settingConfig/enableIgnoreLockdownMode",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-Ignore-lockdown-mode") : std::string();
} },
{ "settingConfig/enablePrinting",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-printing") : std::string();
} },
{ "settingConfig/enableHttpCacheSimple",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-http-cache-simple") : std::string();
} },
{ "settingConfig/enableCalcTabletMode",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-calc-tablet-mode") : std::string();
} },
{ "settingConfig/enableReportCookieMonsterClient",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-report-cookie-monster-client") : std::string();
} },
{ "settingConfig/enableReportThreadPoolForeg",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-report-thread-pool-foreg") : std::string();
} },
{ "settingConfig/enableJsFlagOptimizeForSize",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--js-flags=--optimize_for_size") : std::string();
} },
{ "settingConfig/disableMobileStyleSheet",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-disable-mobile-style-sheet") : std::string();
} },
{ "outOfProcessGPUConfig/enableOopGpu",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--in-process-gpu") : std::string();
} },
{ "enableVulkanConfig/enableVulkan",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-vulkan") : std::string();
} },
{ "disableDrdcConfig/disableDrdc",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-enable-drdc") : std::string();
} },
{ "settingConfig/disableNextPreviousFlag",
[](std::string& contentStr) {
return contentStr == "true" ? std::string("--ohos-disable-next-previous-flag") : std::string();
} }
};
}
namespace OHOS::NWeb {
NWebConfigHelper::NWebConfigHelper()
{
auto saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
bool hasPlayGround = false;
bool isDebugApp = false;
bool isDeveloperMode = IsDeveloperModeEnabled();
dvsyncSwitch_ = false;
if (saManager == nullptr) {
WVLOG_E("webPlayGround get saManager fail");
return;
}
sptr<IRemoteObject> remoteObject =
saManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
sptr<OHOS::AppExecFwk::IBundleMgr> bundleMgrProxy =
OHOS::iface_cast<OHOS::AppExecFwk::IBundleMgr>(remoteObject);
if (bundleMgrProxy == nullptr) {
WVLOG_E("webPlayGround get bundleMgrProxy fail");
return;
}
OHOS::AppExecFwk::BundleInfo bundleInfo;
bundleMgrProxy->GetBundleInfoForSelf(
OHOS::AppExecFwk::BundleFlag::GET_BUNDLE_WITH_ABILITIES, bundleInfo);
isDebugApp = (bundleInfo.applicationInfo.appProvisionType ==
AppExecFwk::Constants::APP_PROVISION_TYPE_DEBUG);
for (auto appEnv : bundleInfo.applicationInfo.appEnvironments) {
if (appEnv.name == PLAYGROUND && appEnv.value == "true") {
hasPlayGround = true;
break;
}
}
web_play_ground_enabled_ = isDebugApp && hasPlayGround && isDeveloperMode;
if (web_play_ground_enabled_) {
#define XPM_KICKER (0x6a6974)
prctl(XPM_KICKER, 0, 0);
WVLOG_I("webPlayGround opened");
} else {
if (hasPlayGround) {
WVLOG_I("webPlayGround not opened for isDebugApp %{public}d"
" hasPlayGround %{public}d isDeveloperMode %{public}d",
isDebugApp, hasPlayGround, isDeveloperMode);
}
}
}
bool NWebConfigHelper::IsWebPlayGroundEnable()
{
return web_play_ground_enabled_;
}
const std::string& NWebConfigHelper::GetWebPlayGroundInitArg()
{
return web_play_ground_enabled_ ? SINGLE_PROCESS : NULL_STR;
}
const std::string& NWebConfigHelper::GetWebPlayGroundHapPath()
{
return web_play_ground_enabled_ ? PLAY_GROUND_HAP_PATH : NULL_STR;
}
bool NWebConfigHelper::IsDeveloperModeEnabled()
{
return OHOS::system::GetBoolParameter("const.security.developermode.state", false);
}
NWebConfigHelper &NWebConfigHelper::Instance()
{
static NWebConfigHelper helper;
return helper;
}
bool NWebConfigHelper::IsPerfConfigEmpty()
{
std::lock_guard<std::mutex> lock(lock_);
return perfConfig_.empty();
}
void NWebConfigHelper::ReadConfigIfNeeded()
{
if (IsPerfConfigEmpty()) {
std::shared_ptr<NWebEngineInitArgsImpl> initArgs = std::make_shared<NWebEngineInitArgsImpl>();
NWebConfigHelper::Instance().ParseConfig(initArgs);
}
}
std::string NWebConfigHelper::GetConfigPath(const std::string &configFileName)
{
char buf[PATH_MAX + 1];
char *configPath = GetOneCfgFile(configFileName.c_str(), buf, PATH_MAX + 1);
char tmpPath[PATH_MAX + 1] = { 0 };
if (!configPath || strlen(configPath) == 0 || strlen(configPath) > PATH_MAX || !realpath(configPath, tmpPath)) {
WVLOG_I("can not get customization config file");
return "/system/" + configFileName;
}
return std::string(tmpPath);
}
void NWebConfigHelper::ReadConfig(const xmlNodePtr &rootPtr, std::shared_ptr<NWebEngineInitArgsImpl> initArgs)
{
for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) {
if (curNodePtr->name == nullptr || curNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
std::string nodeName = reinterpret_cast<const char *>(curNodePtr->name);
for (xmlNodePtr curChildNodePtr = curNodePtr->xmlChildrenNode; curChildNodePtr != nullptr;
curChildNodePtr = curChildNodePtr->next) {
if (curChildNodePtr->name == nullptr || curChildNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
std::string childNodeName = reinterpret_cast<const char *>(curChildNodePtr->name);
xmlChar *content = xmlNodeGetContent(curChildNodePtr);
if (content == nullptr) {
WVLOG_E("read xml node error: nodeName:(%{public}s)", curChildNodePtr->name);
continue;
}
std::string contentStr = reinterpret_cast<const char *>(content);
xmlFree(content);
auto it = configMap.find(nodeName + "/" + childNodeName);
if (it == configMap.end()) {
WVLOG_W("not found for web_config: %{public}s/%{public}s", nodeName.c_str(), childNodeName.c_str());
continue;
}
std::string param = it->second(contentStr);
if (!param.empty()) {
initArgs->AddArg(param);
}
}
}
}
xmlNodePtr NWebConfigHelper::GetChildrenNode(xmlNodePtr NodePtr, const std::string &childrenNodeName)
{
WVLOG_D("GetChildrenNode:(%{public}s)", childrenNodeName.c_str());
for (xmlNodePtr curNodePtr = NodePtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) {
if (curNodePtr->name == nullptr || curNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
if (!xmlStrcmp(curNodePtr->name, reinterpret_cast<const xmlChar*>(childrenNodeName.c_str()))) {
return curNodePtr;
}
}
return nullptr;
}
void NWebConfigHelper::ParseConfig(std::shared_ptr<NWebEngineInitArgsImpl> initArgs)
{
CfgFiles* cfgFiles = GetCfgFiles(WEB_CONFIG_PATH.c_str());
std::string defaultConfigPath = "/system/" + WEB_CONFIG_PATH;
if (cfgFiles == nullptr) {
WVLOG_E("Not found webConfigxml,read system config");
ParseWebConfigXml(defaultConfigPath, initArgs);
std::lock_guard<std::mutex> lock(lock_);
isConfigParsed_ = true;
return;
}
for (int32_t i = 1; i < MAX_CFG_POLICY_DIRS_CNT; i++) {
auto cfgFilePath = cfgFiles->paths[i];
if (!cfgFilePath || *(cfgFilePath) == '\0') {
break;
}
WVLOG_D("web config file path:%{public}s", cfgFilePath);
if (!cfgFilePath || strlen(cfgFilePath) == 0 || strlen(cfgFilePath) > PATH_MAX) {
WVLOG_W("can not get customization config file");
ParseWebConfigXml(defaultConfigPath, initArgs);
continue;
}
ParseWebConfigXml(cfgFiles->paths[i], initArgs);
}
FreeCfgFiles(cfgFiles);
{
std::lock_guard<std::mutex> lock(lock_);
isConfigParsed_ = true;
}
}
void NWebConfigHelper::ParseWebConfigXml(const std::string& configFilePath,
std::shared_ptr<NWebEngineInitArgsImpl> initArgs)
{
xmlDocPtr docPtr = xmlReadFile(configFilePath.c_str(), nullptr, XML_PARSE_NOBLANKS);
if (docPtr == nullptr) {
WVLOG_E("load xml error!");
return;
}
xmlNodePtr rootPtr = xmlDocGetRootElement(docPtr);
if (rootPtr == nullptr || rootPtr->name == nullptr ||
xmlStrcmp(rootPtr->name, reinterpret_cast<const xmlChar *>("WEB"))) {
WVLOG_E("get root element failed!");
xmlFreeDoc(docPtr);
return;
}
xmlNodePtr initNodePtr = GetChildrenNode(rootPtr, INIT_CONFIG);
if (initNodePtr != nullptr) {
WVLOG_D("read config from init node");
ReadConfig(initNodePtr, initArgs);
} else {
WVLOG_D("read config from root node");
ReadConfig(rootPtr, initArgs);
}
xmlNodePtr deleteNodePtr = GetChildrenNode(rootPtr, DELETE_CONFIG);
if (deleteNodePtr != nullptr) {
WVLOG_D("read config from delete node");
ParseDeleteConfig(deleteNodePtr, initArgs);
}
xmlNodePtr perfNodePtr = GetChildrenNode(rootPtr, PERFORMANCE_CONFIG);
if (perfNodePtr != nullptr) {
ParsePerfConfig(perfNodePtr);
}
xmlNodePtr adapterNodePtr = GetChildrenNode(rootPtr, BASE_WEB_CONFIG);
if (adapterNodePtr != nullptr) {
ParsePerfConfig(adapterNodePtr);
}
if (ltpoConfig_.empty() && ltpoStrategy_ == 0) {
xmlNodePtr ltpoConfigNodePtr = GetChildrenNode(rootPtr, WEB_ANIMATION_DYNAMIC_SETTING_CONFIG);
if (ltpoConfigNodePtr != nullptr) {
ParseNWebLTPOConfig(ltpoConfigNodePtr);
}
}
if (!dvsyncSwitch_) {
xmlNodePtr dvsyncConfigNodePtr = GetChildrenNode(rootPtr, WEB_DVSYNC_CONFIG);
if (dvsyncConfigNodePtr != nullptr) {
ParseNWebDvsync(dvsyncConfigNodePtr);
}
}
xmlNodePtr loadUrlConfigNodePtr = GetChildrenNode(rootPtr, WEB_LOAD_URL_CONFIG);
if (loadUrlConfigNodePtr != nullptr) {
ParseNWebLoadUrlStrategy(loadUrlConfigNodePtr);
}
xmlNodePtr windowOrientationNodePtr = GetChildrenNode(rootPtr, WEB_WINDOW_ORIENTATION_CONFIG);
if (windowOrientationNodePtr != nullptr) {
WVLOG_D("read config from window orientation node");
ParseWindowOrientationConfig(windowOrientationNodePtr, initArgs);
}
xmlNodePtr nativeMessagingNodePtr = GetChildrenNode(rootPtr, WEB_NATIVE_MESSAGING_EXTENSION_CONFIG);
if (nativeMessagingNodePtr != nullptr) {
WVLOG_D("read config from native messaging node");
ParseNativeMessagingConfig(nativeMessagingNodePtr);
}
xmlFreeDoc(docPtr);
}
void NWebConfigHelper::ParseNWebLTPOConfig(xmlNodePtr nodePtr)
{
for (xmlNodePtr curNodePtr = nodePtr->xmlChildrenNode; curNodePtr; curNodePtr = curNodePtr->next) {
if (curNodePtr->name == nullptr || curNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
char* namePtr = (char *)xmlGetProp(curNodePtr, BAD_CAST(XML_ATTR_NAME));
if (!namePtr) {
WVLOG_E("invalid name!");
continue;
}
std::string settingName(namePtr);
xmlFree(namePtr);
if (settingName == WEB_ANIMATION_DYNAMIC_APP) {
ParseNWebLTPOApp(curNodePtr);
continue;
}
if (settingName == WEB_LTPO_STRATEGY) {
ParseNWebLTPOStrategy(curNodePtr);
continue;
}
if (settingName == WEB_THROTTLE_STRATEGY || settingName == WEB_THROTTLE_TIMEOUT
|| settingName == WEB_THROTTLE_RATIO) {
ParseNWebLTPOIntConfig(curNodePtr, settingName);
continue;
}
std::vector<FrameRateSetting> frameRateSetting;
for (xmlNodePtr curDynamicNodePtr = curNodePtr->xmlChildrenNode; curDynamicNodePtr;
curDynamicNodePtr = curDynamicNodePtr->next) {
if (curDynamicNodePtr->name == nullptr || curDynamicNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
FrameRateSetting setting;
int defaultValue = 0;
setting.min_ = safeGetPropAsInt(curDynamicNodePtr, BAD_CAST(XML_ATTR_MIN), defaultValue);
setting.max_ = safeGetPropAsInt(curDynamicNodePtr, BAD_CAST(XML_ATTR_MAX), defaultValue);
setting.preferredFrameRate_ = safeGetPropAsInt(curDynamicNodePtr, BAD_CAST(XML_ATTR_FPS), defaultValue);
if ((setting.max_ >= 0 && setting.min_ >= setting.max_) || setting.preferredFrameRate_ <= 0) {
continue;
}
frameRateSetting.emplace_back(setting);
}
ltpoConfig_[settingName] = frameRateSetting;
}
}
void NWebConfigHelper::ParseNWebLTPOApp(xmlNodePtr nodePtr)
{
for (xmlNodePtr curDynamicNodePtr = nodePtr->xmlChildrenNode; curDynamicNodePtr;
curDynamicNodePtr = curDynamicNodePtr->next) {
if (curDynamicNodePtr->name == nullptr || curDynamicNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
char* bundleNamePtr = (char *)xmlGetProp(curDynamicNodePtr, BAD_CAST(XML_ATTR_NAME));
if (!bundleNamePtr) {
WVLOG_E("invalid bundleName!");
continue;
}
std::string bundleName(bundleNamePtr);
xmlFree(bundleNamePtr);
ltpoAllowedApps_.emplace(bundleName);
WVLOG_D("ltpo dynamic app: %{public}s", bundleName.c_str());
}
}
void NWebConfigHelper::ParseNWebLTPOStrategy(xmlNodePtr nodePtr)
{
xmlChar *content = xmlNodeGetContent(nodePtr);
if (content == nullptr) {
WVLOG_E("read ltpo xml node error");
return;
}
ltpoStrategy_ = atoi((char *)content);
xmlFree(content);
WVLOG_D("ltpo strategy is: %{public}d", ltpoStrategy_);
}
void NWebConfigHelper::ParseNWebLTPOIntConfig(xmlNodePtr nodePtr, const std::string& configName)
{
xmlChar *content = xmlNodeGetContent(nodePtr);
if (content == nullptr) {
WVLOG_E("read ltpo xml node error");
return;
}
ltpoIntConfig_[configName] = atoi((char *)content);
xmlFree(content);
WVLOG_D("ltpo %{public}s is: %{public}d", configName.c_str(), ltpoIntConfig_[configName]);
}
void NWebConfigHelper::ParseNWebLoadUrlStrategy(xmlNodePtr nodePtr)
{
for (xmlNodePtr curNodePtr = nodePtr->xmlChildrenNode; curNodePtr; curNodePtr = curNodePtr->next) {
if (curNodePtr->name == nullptr || curNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
char* namePtr = (char*)xmlGetProp(curNodePtr, BAD_CAST(XML_ATTR_NAME));
if (!namePtr) {
WVLOG_E("invalid node!");
continue;
}
std::string settingName(namePtr);
xmlFree(namePtr);
if (settingName == WEB_LOAD_URL_STRATEGY) {
xmlChar *content = xmlNodeGetContent(curNodePtr);
if (content == nullptr) {
WVLOG_E("read load_url xml node error");
return;
}
loadUrlStrategy_ = atoi((char *)content);
xmlFree(content);
WVLOG_D("load_url is: %{public}d", loadUrlStrategy_);
return;
}
}
}
int32_t NWebConfigHelper::GetLoadUrlStrategy()
{
return loadUrlStrategy_;
}
bool NWebConfigHelper::IsLTPODynamicApp(const std::string& bundleName)
{
return ltpoAllowedApps_.find(bundleName) != ltpoAllowedApps_.end();
}
int32_t NWebConfigHelper::GetLTPOStrategy()
{
return ltpoStrategy_;
}
int32_t NWebConfigHelper::GetLTPOIntConfig(const std::string& configName, int32_t defaultValue)
{
if (ltpoIntConfig_.find(configName) != ltpoIntConfig_.end()) {
return ltpoIntConfig_[configName];
}
return defaultValue;
}
void NWebConfigHelper::ParseNWebDvsync(xmlNodePtr nodePtr)
{
for (xmlNodePtr curNodePtr = nodePtr->xmlChildrenNode; curNodePtr; curNodePtr = curNodePtr->next) {
if (curNodePtr->name == nullptr || curNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
char* namePtr = (char*)xmlGetProp(curNodePtr, BAD_CAST(XML_ATTR_NAME));
if (!namePtr) {
WVLOG_E("invalid node!");
continue;
}
std::string settingName(namePtr);
xmlFree(namePtr);
if (settingName == WEB_DVSYNC_SWITCH) {
ParseNWebDvsyncSwitch(curNodePtr);
continue;
}
}
}
void NWebConfigHelper::ParseNWebDvsyncSwitch(xmlNodePtr nodePtr)
{
xmlChar *content = xmlNodeGetContent(nodePtr);
if (content == nullptr) {
WVLOG_E("read dvsyncSwitch xml node error");
return;
}
dvsyncSwitch_ = atoi((char*)content) == 1;
xmlFree(content);
WVLOG_D("dvsync switch is: %{public}d", dvsyncSwitch_);
}
bool NWebConfigHelper::GetNWebDvsyncSwitch()
{
return dvsyncSwitch_;
}
std::vector<FrameRateSetting> NWebConfigHelper::GetPerfConfig(const std::string& settingName)
{
if (ltpoConfig_.find(settingName) == ltpoConfig_.end()) {
WVLOG_E("%{public}s is not exist", settingName.c_str()) ;
return {};
}
return ltpoConfig_[settingName];
}
void NWebConfigHelper::ParsePerfConfig(xmlNodePtr NodePtr)
{
WVLOG_D("read performance config");
for (xmlNodePtr curNodePtr = NodePtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) {
if (curNodePtr->name == nullptr || curNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
std::string nodeName = reinterpret_cast<const char*>(curNodePtr->name);
for (xmlNodePtr curChildNodePtr = curNodePtr->xmlChildrenNode; curChildNodePtr != nullptr;
curChildNodePtr = curChildNodePtr->next) {
if (curChildNodePtr->name == nullptr || curChildNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
std::string childNodeName = reinterpret_cast<const char*>(curChildNodePtr->name);
xmlChar* content = xmlNodeGetContent(curChildNodePtr);
if (content == nullptr) {
WVLOG_E("read xml node error: nodeName:(%{public}s)", childNodeName.c_str());
continue;
}
std::string contentStr = reinterpret_cast<const char*>(content);
xmlFree(content);
{
std::lock_guard<std::mutex> lock(lock_);
perfConfig_.insert_or_assign(nodeName + "/" + childNodeName, contentStr);
}
WriteConfigValueToSysPara(nodeName + "/" + childNodeName, contentStr);
}
}
}
std::string NWebConfigHelper::ParsePerfConfig(const std::string &configNodeName, const std::string &argsNodeName)
{
std::lock_guard<std::mutex> lock(lock_);
auto it = perfConfig_.find(configNodeName + "/" + argsNodeName);
if (it == perfConfig_.end()) {
WVLOG_W("not found perf config for web_config: %{public}s/%{public}s", configNodeName.c_str(),
argsNodeName.c_str());
return "";
}
WVLOG_D("find performance config %{public}s/%{public}s, value is %{public}s.", configNodeName.c_str(),
argsNodeName.c_str(), it->second.c_str());
return it->second;
}
void NWebConfigHelper::WriteConfigValueToSysPara(const std::string &configName, const std::string &value)
{
if (configName == "flowBufferConfig/maxFdNumber") {
OHOS::system::SetParameter("web.flowbuffer.maxfd", value);
} else if (configName == "TCPConnectedSocketConfig/initialCongestionWindowSize") {
OHOS::system::SetParameter("web.TCPConnectedSocket.initialCongestionWindowSize", value);
}
}
void NWebConfigHelper::ParseDeleteConfig(const xmlNodePtr &rootPtr, std::shared_ptr<NWebEngineInitArgsImpl> initArgs)
{
for (xmlNodePtr curNodePtr = rootPtr->xmlChildrenNode; curNodePtr != nullptr; curNodePtr = curNodePtr->next) {
if (curNodePtr->name == nullptr || curNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
std::string nodeName = reinterpret_cast<const char *>(curNodePtr->name);
for (xmlNodePtr curChildNodePtr = curNodePtr->xmlChildrenNode; curChildNodePtr != nullptr;
curChildNodePtr = curChildNodePtr->next) {
if (curChildNodePtr->name == nullptr || curChildNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
std::string childNodeName = reinterpret_cast<const char *>(curChildNodePtr->name);
xmlChar *content = xmlNodeGetContent(curChildNodePtr);
if (content == nullptr) {
WVLOG_E("read xml node error: nodeName:(%{public}s)", curChildNodePtr->name);
continue;
}
std::string contentStr = reinterpret_cast<const char *>(content);
xmlFree(content);
auto it = configMap.find(nodeName + "/" + childNodeName);
if (it == configMap.end()) {
WVLOG_W("not found for web_config: %{public}s/%{public}s", nodeName.c_str(), childNodeName.c_str());
continue;
}
std::string param = it->second(contentStr);
if (!param.empty()) {
initArgs->AddDeleteArg(param);
}
}
}
}
void NWebConfigHelper::ParseWindowOrientationConfig(xmlNodePtr nodePtr,
std::shared_ptr<NWebEngineInitArgsImpl> initArgs)
{
for (xmlNodePtr curNodePtr = nodePtr->xmlChildrenNode; curNodePtr; curNodePtr = curNodePtr->next) {
if (curNodePtr->name == nullptr || curNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
char* bundleNamePtr = (char *)xmlGetProp(curNodePtr,BAD_CAST(XML_BUNDLE_NAME));
char* orientationPtr = (char *)xmlGetProp(curNodePtr,BAD_CAST(XML_ENABLE_WINDOW_ORIENTATION));
if (!bundleNamePtr || !orientationPtr) {
WVLOG_E("invalid bundleNamePtr or orientationPtr!");
xmlFree(bundleNamePtr);
xmlFree(orientationPtr);
continue;
}
std::string bundleName(bundleNamePtr);
std::string orientation(orientationPtr);
xmlFree(bundleNamePtr);
xmlFree(orientationPtr);
std::string curBundleName;
std::shared_ptr<AbilityRuntime::ApplicationContext> ctx =
AbilityRuntime::ApplicationContext::GetApplicationContext();
if (ctx) {
std::string curBundleName = ctx->GetBundleName();
}
if (curBundleName.empty()) {
WVLOG_E("invalid curBundleName, no need to continue!");
return;
}
if (bundleName == curBundleName || bundleName == WEB_ALL_BUNDLE_NAME) {
if (orientation == "true") {
initArgs->AddArg("--enable-blink-features=OrientationEvent");
} else if (orientation == "false") {
initArgs->AddArg("--disable-blink-features=OrientationEvent");
} else {
WVLOG_E("invalid orientation value!");
}
break;
}
}
}
int NWebConfigHelper::safeGetPropAsInt(xmlNode* node, const xmlChar* propName, int defaultValue)
{
xmlChar* propValue = xmlGetProp(node, propName);
int value = (propValue) ? atoi((const char*)propValue) : defaultValue;
xmlFree(propValue);
return value;
}
void NWebConfigHelper::SetBundleName(const std::string& bundleName)
{
bundleName_ = bundleName;
}
std::string NWebConfigHelper::GetBundleName()
{
return bundleName_;
}
void NWebConfigHelper::ParseNativeMessagingConfig(xmlNodePtr nodePtr)
{
for (xmlNodePtr curNodePtr = nodePtr->xmlChildrenNode; curNodePtr != nullptr;
curNodePtr = curNodePtr->next) {
if (curNodePtr->name == nullptr || curNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
continue;
}
for (xmlNodePtr childPtr = curNodePtr->xmlChildrenNode; childPtr != nullptr;
childPtr = childPtr->next) {
if (ParseNativeMessagingSetting(childPtr)) {
nativeMessagingEnabled_ = true;
WVLOG_D("Native messaging enabled: %{public}d", nativeMessagingEnabled_);
} else {
nativeMessagingEnabled_ = false;
WVLOG_D("Native messaging disabled: %{public}d", nativeMessagingEnabled_);
}
}
}
}
bool NWebConfigHelper::ParseNativeMessagingSetting(xmlNodePtr childNodePtr)
{
if (childNodePtr->name == nullptr || childNodePtr->type == XML_COMMENT_NODE) {
WVLOG_E("invalid node!");
return false;
}
std::string childNodeName = reinterpret_cast<const char*>(childNodePtr->name);
if (childNodeName != "nativeMessagingSetting") {
WVLOG_E("invalid node name for native messaging setting: %{public}s", childNodeName.c_str());
return false;
}
xmlChar* content = xmlNodeGetContent(childNodePtr);
if (content == nullptr) {
WVLOG_E("read xml node error: nodeName:(%{public}s)", childNodePtr->name);
return false;
}
std::string contentStr = reinterpret_cast<const char*>(content);
bool enabled = (contentStr == "true");
xmlFree(content);
return enabled;
}
bool NWebConfigHelper::IsNativeMessagingEnabled()
{
{
std::lock_guard<std::mutex> lock(lock_);
if (isConfigParsed_) {
return nativeMessagingEnabled_;
}
}
std::shared_ptr<NWebEngineInitArgsImpl> initArgs = std::make_shared<NWebEngineInitArgsImpl>();
NWebConfigHelper::Instance().ParseConfig(initArgs);
std::lock_guard<std::mutex> lock(lock_);
return nativeMessagingEnabled_;
}
}