diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..502c7a91 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (c) 2019 LG Electronics, Inc. +# +# 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. +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.0.0) +project(WebAppMgr VERSION 1.0.0 LANGUAGES CXX) + +set(PLATFORM_NAME "WebOS" CACHE STRING "Target platform name") +set(CHROMIUM_SRC_DIR "" CACHE PATH "Chromium source directory path") + +option(USE_PMLOG "Use PmLog library (WebOS)") +option(USE_LUNA_SERVICE "Use Luna service (WebOS)") +option(USE_SNAPSHOT_BOOT "Use snapshot boot (WebOS)") + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +add_subdirectory(src) + diff --git a/common.pri b/common.pri index ea749679..1eca7fb3 100644 --- a/common.pri +++ b/common.pri @@ -14,8 +14,6 @@ # # SPDX-License-Identifier: Apache-2.0 -CONFIG = qt - BUILD_TYPE = release # or debug ENV_BUILD_TYPE = $$(BUILD_TYPE) !isEmpty(ENV_BUILD_TYPE) { @@ -32,12 +30,11 @@ isEmpty(PREFIX) { } CONFIG += link_pkgconfig -QT = core ################################################################################ # Decide MACHINE_NAME and PLATFORM -MACHINE_NAME = $$(MACHINE) +MACHINE_NAME = "minnowboard" isEmpty(PLATFORM) { error("PLATFORM wasn't set") @@ -47,6 +44,8 @@ DEFINES += $$PLATFORM contains(PLATFORM, PLATFORM_WEBOS) { include(device.pri) + CONFIG = qt + QT = core } else { isEmpty(MACHINE_NAME) { error(MACHINE_NAME should not be empty. $$MACHINE_NAME) @@ -69,12 +68,51 @@ snapshot_boot { LIBS += -lsnapshot-boot } +############################################################################### +# pmlog +# +# Please use CONFIG_BUILD in your recipe. +# +# EXTRA_QMAKEVARS_PRE += "CONFIG_BUILD+=pmlog" +contains(CONFIG_BUILD, pmlog) { + DEFINES += HAS_PMLOG + CONFIG += pmlog + message($$MACHINE_NAME $$PLATFORM use pmlog) +} + +############################################################################### +# luna-service +# +# Please use CONFIG_BUILD in your recipe. +# +# EXTRA_QMAKEVARS_PRE += "CONFIG_BUILD+=luna_service" +contains(CONFIG_BUILD, luna_service) { + DEFINES += HAS_LUNA_SERVICE + CONFIG += luna_service + message($$MACHINE_NAME $$PLATFORM use luna service) +} + + +################################################################################ +# agl-service +# +# Please use CONFIG_BUILD in your recipe. +# +# EXTRA_QMAKEVARS_PRE += "CONFIG_BUILD+=agl_service" +contains(CONFIG_BUILD, agl_service) { + DEFINES += HAS_AGL_SERVICE + CONFIG += agl_service + PKGCONFIG += libwindowmanager libhomescreen ilmControl + message($$MACHINE_NAME $$PLATFORM use agl service) +} + ################################################################################ # Path and CFLAGS VPATH += \ ./src \ + ./src/agl \ ./src/core \ ./src/platform \ ./src/platform/webengine \ @@ -82,7 +120,7 @@ VPATH += \ ./src/util \ ./src/webos -PKGCONFIG += glib-2.0 +PKGCONFIG += glib-2.0 libxml-2.0 jsoncpp INCLUDEPATH += $$VPATH @@ -93,7 +131,7 @@ INCLUDEPATH += $${CHROMIUM_SRC_DIR} DEFINES += PRELOADMANAGER_ENABLED -QMAKE_CXXFLAGS += -fno-rtti -fno-exceptions -Wall -fpermissive -funwind-tables +QMAKE_CXXFLAGS += -fno-rtti -Wall -fpermissive -funwind-tables QMAKE_CXXFLAGS += -std=c++14 QMAKE_LFLAGS += -rdynamic @@ -101,7 +139,7 @@ QMAKE_CFLAGS += -Wno-psabi QMAKE_CXXFLAGS += -Wno-psabi QMAKE_LFLAGS += -Wl,--no-as-needed -QMAKE_CXXFLAGS += -Werror \ +#QMAKE_CXXFLAGS += -Werror \ ################################################################################ # .o and .moc @@ -112,3 +150,11 @@ MOC_DIR = $$DESTDIR/.moc LIBS += -L$$DESTDIR LIBS += -lcbe + +# Link against boost_filesystem assuming it's on WAM's sysroot +# This relies on a patch in meta-agl-lge adding boost as dependency +# of WAM. +# TODO: Once WAM build system is ported to CMake, better configure-time checkings +# will be used (e.g: find_package(Boost, 1.68 COMPONENTS filesystem REQUIRED). +LIBS += -lboost_filesystem + diff --git a/files/launch/WebAppMgr.env b/files/launch/WebAppMgr.env new file mode 100644 index 00000000..8d1a28e2 --- /dev/null +++ b/files/launch/WebAppMgr.env @@ -0,0 +1,198 @@ +XDG_SESSION_ID="c2" +XDG_RUNTIME_DIR="/run/user/0" + +# Set wam executable file path +HOOK_SEGV=NO +WAM_EXE_PATH="/usr/bin/WebAppMgr" + +# Set wam name for user-agent +WAM_NAME="WebAppManager" + +# Only allow UTF8 encoding for luna-service messages. +LS_ENABLE_UTF8=1 + +# Set effective userid and groupid +#WAM_UID="wam" +#WAM_GID="compositor" + +# Set location of error page (will follow localization rules based on this path) +#WAM_ERROR_PAGE="file:///usr/share/localization/wam/loaderror.html" + +# suspending javascript execution delay for page visibility +WAM_SUSPEND_DELAY_IN_MS=250 + +#if [ -e "etc/wam/make_shm.sh" ] ; then +# /etc/wam/make_shm.sh +#fi + +# Set user data directory for WebAppMgr +WAM_DATA_PATH="/home/0/wamdata" + +# ensure that wam data directories exist +#mkdir -p ${WAM_DATA_PATH} + +# set directories permission +#chown ${WAM_UID}:${WAM_GID} ${WAM_DATA_PATH} + +# setup 50 Mb maximum for ApplicationCache +WAM_APPCACHE_MAXSIZE=52428800 + +# setup 10 Mb maximum for ApplicationCache per domain +WAM_APPCACHE_DOMAINLIMIT=10485760 + +# setup 50 Mb maximum for DiskCache +WAM_DISKCACHE_MAXSIZE=52428800 + +# setup 256 Kb maximum for resource buffer allocation +WAM_RESOURCE_BUFFER_MAX_ALLOC_SIZE=262144 + +# setup 1 Mb for resource buffer +WAM_RESOURCE_BUFFER_SIZE=1048576 + +# setup 200 seconds for watchdog timeout of render process +WATCHDOG_RENDER_TIMEOUT=200 + +# setup nubmer of raster threads to 1 +BLINK_NUM_RASTER_THREADS=2 + +# use default tile width if not sed by recipe +#if [ "$BLINK_NUM_RASTER_THREADS" = "WEBOS${BLINK_NUM_RASTER_THREADS#WEBOS}" ]; then +BLINK_NUM_RASTER_THREADS=1 +#fi + +# setup 6 Mb maximum for the program GPU cache +GPU_PROGRAM_CACHE_SIZE=6144 + +# disable using enyo system app specfic optimization +# currently used optimizations : inline caching off +#USE_SYSTEM_APP_OPTIMIZATION="0" + +# Set location of NaCl modules +#CHROMIUM_PATH="/usr/palm/applications/com.lge.app.chromium" +#NACL_PLUGIN=${CHROMIUM_PATH}"/libppGoogleNaClPluginChrome.so" +#NACL_IRT_LIBRARY=${CHROMIUM_PATH}"/nacl_irt_arm.nexe" +#NACL_HELPER=${CHROMIUM_PATH}"/nacl_helper" +#NACL_HELPER_BOOTSTRAP=${CHROMIUM_PATH}"/nacl_helper_bootstrap" + +# Set location of NPAPI plugins for all Apps including default Apps +# This is for the flash plugin of Signage, webOS TV doesn't use it. +#PRIVILEGED_PLUGIN_PATH="" + +# Set location of NPAPI plugins for NetCast Apps +# NetCast Apps should access only the plugins in this path +#NETCAST_PLUGIN_PATH="/usr/lib/BrowserPlugins" + +# Set location of NPAPI plugins for HbbTV app. +#HBBTV_PLUGIN_PATH="/usr/lib/HbbtvPlugins" + +# Set InetTV player stored path +#INETTV_HTML_PLAYER_PATH="/usr/share/inettv/inettv_player/index.html" + +# Set location of extra libraries +#CDM_LIB_PATH="/usr/lib" + +# Set location of all NPAPI plugins +NPAPI_PLUGIN_PATH=${HBBTV_PLUGIN_PATH}":"${NETCAST_PLUGIN_PATH}":"${PRIVILEGED_PLUGIN_PATH} + +#if [ -e "etc/wam/make_shm.sh" ] ; then +# /etc/wam/make_shm.sh +#fi + +# setup 8 Mb minimum codecache capacity +JSC_minGlobalCodeCacheCapacity=8388608 + +# Enable more explicit logging of timing with regards to rendering +# export WAM2_ENABLE_DEBUG_RENDER_TIMING=1 + +# enable Web Inspector and Tellurium if in developer mode +TELLURIUM_NUB_PATH=/usr/palm/tellurium/telluriumnub.js +ENABLE_INSPECTOR=1 + +# Enable cursor by default +ENABLE_CURSOR_BY_DEFAULT=1 + +# Enable launch optimization +ENABLE_LAUNCH_OPTIMIZATION=1 + +# Set the duration(seconds) passed from last network activity (e.g. FMP Detector) +# If set to a positive value, adjust a custom timeout for a network stable timer in FMPDetector +NETWORK_STABLE_TIMEOUT=3 + +# please keep it in alphabetical order +#WAM_EXTRA_FLAGS="" +#WAM_JS_FLAGS="" +#WAM_COMMON_SWITCHES=" \ +# --application-cache-domain-limit=$WAM_APPCACHE_DOMAINLIMIT \ +# --application-cache-size=$WAM_APPCACHE_MAXSIZE \ +# --browser-subprocess-path=$WAM_EXE_PATH \ +# --disable-direct-npapi-requests \ +# --disable-extensions \ +# --disable-low-res-tiling \ +# --disable-new-video-renderer \ +# --disk-cache-size=$WAM_DISKCACHE_MAXSIZE \ +# --enable-aggressive-release-policy \ +# --enable-accelerated-plugin-rendering \ +# --accelerated-plugin-rendering-blacklist=device;drmAgent;sound;service \ +# --enable-gpu-rasterization \ +# --disable-gpu-rasterization-for-first-frame \ +# --enable-key-event-throttling \ +# --enable-threaded-compositing \ +# --enable-watchdog \ +# --hide-selection-handles \ +# --ignore-gpu-blacklist \ +# --ignore-netif=p2p \ +# --in-process-gpu \ +# --max-unused-resource-memory-usage-percentage=0 \ +# --network-stable-timeout=$NETWORK_STABLE_TIMEOUT \ +# --noerrdialogs \ +# --num-raster-threads=$BLINK_NUM_RASTER_THREADS \ +# --ozone-platform=wayland \ +# --remote-debugging-port=9998 \ +# --resource-buffer-max-allocation-size=$WAM_RESOURCE_BUFFER_MAX_ALLOC_SIZE \ +# --resource-buffer-size=$WAM_RESOURCE_BUFFER_SIZE \ +# --touch-events=disabled \ +# --ui-disable-opaque-shader-program \ +# --user-agent-suffix=SmartTV \ +# --user-data-dir=$WAM_DATA_PATH \ +# --enable-devtools-experiments \ +# --webos-wam \ " + +#WAM_LITE_SWITCHES=" --in-process-zygote " + +#export WAM_WEBOS_LITE=NO +#if [ "${WAM_WEBOS_LITE}" = "YES" ] ; then +# export WAM_SWITCHES=${WAM_COMMON_SWITCHES}${WAM_LITE_SWITCHES} +# export SKIA_FONT_CACHE_SIZE=1 +# export SKIA_IMAGE_CACHE_SIZE=40 +# export SKIA_BACKGROUND_FONT_CACHE_SIZE=0 +#else +# export WAM_SWITCHES=${WAM_COMMON_SWITCHES} +# export SKIA_FONT_CACHE_SIZE=8 +# export SKIA_IMAGE_CACHE_SIZE=80 +# export SKIA_BACKGROUND_FONT_CACHE_SIZE=512 +#fi + +#export WAM_EXTRA_SKIA_CACHE_SWITCHES=" \ +# --skia-font-cache-size-mb=$SKIA_FONT_CACHE_SIZE \ +# --skia-image-cache-size-mb=$SKIA_IMAGE_CACHE_SIZE \ +# --skia-background-font-cache-size-kb=$SKIA_BACKGROUND_FONT_CACHE_SIZE \ +# " + +#export WAM_EXTRA_GPU_TUNING_SWITCHES=" \ +# --gpu-program-cache-size-kb=$GPU_PROGRAM_CACHE_SIZE \ +# " +#export WAM_WATCHDOG_RENDER_TIMEOUT_SWITCHES=" \ +# --watchdog-render-timeout=$WATCHDOG_RENDER_TIMEOUT \ +# " + +#WEBOS_LOAD_ACCESSIBILITY_PLUGIN=1 + +#WAM_V8_CODE_CACHE_SWITCHES=" --enable-local-resource-code-cache --disallow-code-cache-from-file-uris-with-query-string " + +# Load any special configuration from plugins +#if [ -e "/etc/wam/plugins/conf.sh" ] ; then +# . /etc/wam/plugins/conf.sh || true +#fi + +#exec $WAM_EXE_PATH $WAM_SWITCHES $WAM_EXTRA_SKIA_CACHE_SWITCHES $WAM_EXTRA_GPU_TUNING_SWITCHES $WAM_WATCHDOG_RENDER_TIMEOUT_SWITCHES $WAM_EXTRA_FLAGS $WAM_V8_CODE_CACHE_SWITCHES --js-flags="$WAM_JS_FLAGS" + diff --git a/files/launch/WebAppMgr.service b/files/launch/WebAppMgr.service new file mode 100644 index 00000000..742344f2 --- /dev/null +++ b/files/launch/WebAppMgr.service @@ -0,0 +1,27 @@ +# @@@LICENSE +# +# Copyright (c) 2017-2018 LG Electronics, Inc. +# +# Confidential computer software. Valid license from LG required for +# possession, use or copying. Consistent with FAR 12.211 and 12.212, +# Commercial Computer Software, Computer Software Documentation, and +# Technical Data for Commercial Items are licensed to the U.S. Government +# under vendor's standard commercial license. +# +# LICENSE@@@ + +[Unit] +Description="WebAppMgr is responsible for running web apps and manage their lifecycle" +After=afm-service-windowmanager-service-2017@0.1.service afm-appli-homescreen-2017@0.1.service +Wants=afm-service-windowmanager-service-2017@0.1.service afm-appli-homescreen-2017@0.1.service + +[Service] +Type=simple +OOMScoreAdjust=-1000 +EnvironmentFile=-/etc/default/WebAppMgr.env +ExecStart=/usr/bin/WebAppMgr --no-sandbox --in-process-gpu --remote-debugging-port=9998 --user-data-dir="/home/0/wamdata" --webos-wam +Restart=on-failure +RestartSec=50 + +[Install] +WantedBy=default.target diff --git a/files/pkgconfig/WebAppMgr.pc.in b/files/pkgconfig/WebAppMgr.pc.in new file mode 100644 index 00000000..362e69a3 --- /dev/null +++ b/files/pkgconfig/WebAppMgr.pc.in @@ -0,0 +1,11 @@ +prefix=@WAM_DEST_DIR@ +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include/webappmanager + +Name: libWebAppMgr +Description: Web Application Manager library +Version: 1.0.0 + +Libs: -L${libdir} @PKGCONFIG_WAM_LIBS@ +Cflags: -I${includedir} diff --git a/files/pkgconfig/WebAppMgrCore.pc.in b/files/pkgconfig/WebAppMgrCore.pc.in new file mode 100644 index 00000000..a5b5cbce --- /dev/null +++ b/files/pkgconfig/WebAppMgrCore.pc.in @@ -0,0 +1,11 @@ +prefix=@WAM_DEST_DIR@ +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include/webappmanager + +Name: libWebAppMgrCore +Description: Web Application Manager core library +Version: 1.0.0 + +Libs: -L${libdir} @PKGCONFIG_WAM_CORE_LIBS@ +Cflags: -I${includedir} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..cae6cf1d --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,360 @@ +# Copyright (c) 2019 LG Electronics, Inc. +# +# 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. +# +# SPDX-License-Identifier: Apache-2.0 + +set(IS_WEBOS FALSE) +set(IS_AGL FALSE) + +string(TOLOWER ${PLATFORM_NAME} PLATFORM) + +if(${PLATFORM} STREQUAL "webos") + set(IS_WEBOS TRUE) +elseif(${PLATFORM} MATCHES ".*agl") + set(IS_AGL TRUE) +else() + message(FATAL_ERROR "Unsupported platform: ${PLATFORM}") +endif() + +if(EXISTS ${CHROMIUM_SRC_DIR}) + set(CHROMIUM_INCLUDE_DIRS ${CHROMIUM_SRC_DIR}) + set(CHROMIUM_LDFLAGS -lcbe) +else() + message(FATAL_ERROR "Invalid Chromium source dir: ${CHROMIUM_SRC_DIR}") +endif() + +# Disable compiler-specific extensions +set(CMAKE_CXX_EXTENSIONS OFF) + +set(WAM_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(WAM_DEST_DIR ${CMAKE_INSTALL_PREFIX}) +set(WAM_PKGCONFIG_DIR "${CMAKE_SOURCE_DIR}/files/pkgconfig") +set(WAM_COMMON_DEFINES PRELOADMANAGER_ENABLED _REENTRANT) + +message(STATUS "** Build Type: ${CMAKE_BUILD_TYPE}") +message(STATUS "** Build platform: ${PLATFORM}") +message(STATUS "** Chromium src dir: ${CHROMIUM_SRC_DIR}") +message(STATUS "** Destination dir: ${WAM_DEST_DIR}") + +find_package(Boost COMPONENTS filesystem REQUIRED) +find_package(PkgConfig REQUIRED) +pkg_search_module(GLIB REQUIRED glib-2.0) +pkg_search_module(LIBXML REQUIRED libxml-2.0) +pkg_search_module(JSONCPP REQUIRED jsoncpp) + +if(IS_WEBOS) + set(CMAKE_AUTOMOC ON) + if(USE_LUNA_SERVICE) + pkg_search_module(LIBLUNAPREFS REQUIRED luna-prefs) + list(APPEND WAM_COMMON_DEFINES HAS_LUNA_SERVICE) + endif() + if(USE_PMLOG) + pkg_search_module(LIBPMLOG REQUIRED PmLogLib) + list(APPEND WAM_COMMON_DEFINES HAS_LUNA_SERVICE) + endif() +elseif(IS_AGL) + pkg_search_module(LIBWM REQUIRED libwindowmanager) + pkg_search_module(LIBHS REQUIRED libhomescreen) + pkg_search_module(ILMCTRL REQUIRED ilmControl) + pkg_search_module(ILMCOMMON REQUIRED ilmCommon) + list(APPEND WAM_COMMON_DEFINES HAS_AGL_SERVICE) +endif() + +set(WAM_COMMON_CXX_FLAGS + -Wall + -Werror + -Wno-psabi + -Wno-unused-variable + -Wno-unused-but-set-variable + -fpermissive + -funwind-tables + -fno-rtti +) + +########################################################### +# WebAppMgrCore Shared Library +########################################################### +set(WAM_CORE_LIB_NAME WebAppMgrCore) +set(WAM_CORE_SOURCES + core/ApplicationDescription.cpp + core/ContainerAppManager.cpp + core/DeviceInfo.cpp + core/PalmSystemBase.cpp + core/PlugInService.cpp + core/WebAppBase.cpp + core/WebAppFactoryManager.cpp + core/WebAppManager.cpp + core/WebAppManagerConfig.cpp + core/WebAppManagerService.cpp + core/WebPageBase.cpp + core/WebPageObserver.cpp + core/WebProcessManager.cpp + core/WindowTypes.cpp + util/JsonHelper.cpp + util/LogManager.cpp + util/NetworkStatus.cpp + util/NetworkStatusManager.cpp + util/StringUtils.cpp + util/Timer.cpp + util/Url.cpp + util/WebAppManagerUtils.cpp +) + +set(WAM_CORE_HEADERS + core/ApplicationDescription.h + core/ContainerAppManager.h + core/DeviceInfo.h + core/PalmSystemBase.h + core/PlatformModuleFactory.h + core/PlugInService.h + core/ServiceSender.h + core/WebAppBase.h + core/WebAppFactoryInterface.h + core/WebAppFactoryManager.h + core/WebAppManagerConfig.h + core/WebAppManager.h + core/WebAppManagerService.h + core/WebPageBase.h + core/WebPageObserver.h + core/WebProcessManager.h + core/WebRuntime.h + core/WindowTypes.h + util/JsonHelper.h + util/LogManager.h + util/LogMsgId.h + util/NetworkStatus.h + util/NetworkStatusManager.h + util/ObserverList.h + util/StringUtils.h + util/Timer.h + util/Url.h + util/WebAppManagerUtils.h +) + +set(WAM_CORE_INCLUDE_DIRS + ${WAM_SOURCE_DIR}/core + ${WAM_SOURCE_DIR}/util + ${CHROMIUM_INCLUDE_DIRS} + ${GLIB_INCLUDE_DIRS} +) + +set(WAM_CORE_LIBRARIES + Boost::filesystem + ${GLIB_LDFLAGS} + ${CHROMIUM_LDFLAGS} +) + +if(IS_WEBOS) + list(APPEND WAM_CORE_SOURCES plugin/WebAppFactoryManagerQtPlugin.cpp) + list(APPEND WAM_CORE_LIBRARIES Qt5::Core) + if(USE_LUNA_SERVICE) + list(APPEND WAM_CORE_LIBRARIES ${LIBLUNAPREFS_LDFLAGS}) + endif() + if(USE_PMLOG) + list(APPEND WAM_CORE_SOURCES util/LogManagerPmLog.cpp) + list(APPEND WAM_CORE_LIBRARIES ${LIBPMLOG_LDFLAGS}) + endif() + if(USE_SNAPSHOT_BOOT) + list(APPEND WAM_CORE_LIBRARIES -lsnapshot-boot) + endif() +elseif(IS_AGL) + list(APPEND WAM_CORE_SOURCES agl/WebAppFactoryManagerAGL.cpp) +endif() + +add_library(wamcorelib SHARED ${WAM_CORE_HEADERS} ${WAM_CORE_SOURCES}) +target_compile_options(wamcorelib PRIVATE ${WAM_COMMON_CXX_FLAGS}) +target_compile_definitions(wamcorelib PRIVATE ${WAM_COMMON_DEFINES}) +target_include_directories(wamcorelib PUBLIC ${WAM_CORE_INCLUDE_DIRS}) +target_link_libraries(wamcorelib PRIVATE ${WAM_CORE_LIBRARIES}) +set_target_properties(wamcorelib PROPERTIES + OUTPUT_NAME ${WAM_CORE_LIB_NAME} + VERSION "1.0.0" + SOVERSION "1.0" +) +install(TARGETS wamcorelib LIBRARY DESTINATION lib) +install(FILES ${WAM_CORE_HEADERS} DESTINATION include/webappmanager) + +# Generate and Install pkgconfig file for WebAppMgrCore library +set(PKGCONFIG_WAM_CORE_LIBS "-l${WAM_CORE_LIB_NAME}") +CONFIGURE_FILE(${WAM_PKGCONFIG_DIR}/WebAppMgrCore.pc.in "WebAppMgrCore.pc" @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/WebAppMgrCore.pc DESTINATION lib/pkgconfig) + +########################################################### +# WebAppMgr Shared Library +########################################################### +set(WAM_LIB_NAME WebAppMgr) +set(WAM_LIB_SOURCES + platform/PalmSystemWebOS.cpp + platform/WebAppWayland.cpp + platform/WebAppWaylandWindow.cpp + platform/webengine/BlinkWebProcessManager.cpp + platform/webengine/BlinkWebView.cpp + platform/webengine/BlinkWebViewProfileHelper.cpp + platform/webengine/PalmSystemBlink.cpp + platform/webengine/WebPageBlink.cpp + webos/PlatformModuleFactoryImpl.cpp + webos/DeviceInfoImpl.cpp +) + +set(WAM_LIB_HEADERS + platform/PalmSystemWebOS.h + platform/WebAppWayland.h + platform/WebAppWaylandWindow.h + platform/webengine/BlinkWebProcessManager.h + platform/webengine/BlinkWebView.h + platform/webengine/BlinkWebViewProfileHelper.h + platform/webengine/PalmSystemBlink.h + platform/webengine/WebPageBlinkDelegate.h + platform/webengine/WebPageBlink.h + platform/webengine/WebPageBlinkObserver.h + webos/PlatformModuleFactoryImpl.h +) + +set(WAM_LIB_DEFINES ${WAM_COMMON_DEFINES}) + +set(WAM_LIB_INCLUDE_DIRS + ${WAM_SOURCE_DIR}/platform + ${WAM_SOURCE_DIR}/platform/webengine + ${WAM_SOURCE_DIR}/webos # TODO: webos-specific? + ${LIBXML_INCLUDE_DIRS} +) + +set(WAM_LIB_LIBRARIES + ${GLIB_LDFLAGS} + ${CHROMIUM_LDFLAGS} + ${LIBWM_LDFLAGS} + ${LIBHS_LDFLAGS} + ${ILMCTRL_LDFLAGS} + ${JSONCPP_LDFLAGS} + ${LIBXML_LDFLAGS} + Boost::filesystem + wamcorelib +) + +# TODO: Remove this after replacing pub/prv luna bus API with unified one +list (APPEND WAM_LIB_DEFINES SECURITY_COMPATIBILITY) + +if(IS_WEBOS) + list(APPEND WAM_LIB_SOURCES + webos/PalmServiceBase.cpp + webos/PlugInServiceLuna.cpp + webos/ServiceSenderLuna.cpp + webos/WebAppManagerServiceLuna.cpp + webos/WebAppManagerServiceLunaImpl.cpp + webos/WebRuntimeWebOS.cpp + ) + list(APPEND WAM_LIB_HEADERS + webos/DeviceInfoImpl.h + webos/PalmServiceBase.h + webos/PlugInServiceLuna.h + webos/ServiceSenderLuna.h + webos/WebAppManagerServiceLuna.h + webos/WebAppManagerServiceLunaImpl.h + webos/WebRuntimeWebOS.h + ) +elseif(IS_AGL) + list(APPEND WAM_LIB_SOURCES + agl/WebAppFactoryAGL.cpp + agl/WebAppManagerServiceAGL.cpp + agl/WebAppWaylandAGL.cpp + agl/WebRuntimeAGL.cpp + ) + list(APPEND WAM_LIB_HEADERS + agl/WebAppFactoryAGL.h + agl/WebAppManagerServiceAGL.h + agl/WebAppWaylandAGL.h + agl/WebRuntimeAGL.h + ) +endif() + +add_library(wamlib SHARED ${WAM_LIB_HEADERS} ${WAM_LIB_SOURCES}) +target_compile_options(wamlib PRIVATE ${WAM_COMMON_CXX_FLAGS}) +target_compile_definitions(wamlib PRIVATE ${WAM_LIB_DEFINES}) +target_include_directories(wamlib PUBLIC ${WAM_LIB_INCLUDE_DIRS}) +target_link_libraries(wamlib PRIVATE ${WAM_LIB_LIBRARIES}) +set_target_properties(wamlib PROPERTIES + OUTPUT_NAME ${WAM_LIB_NAME} + VERSION "1.0.0" + SOVERSION "1.0" +) +install(TARGETS wamlib DESTINATION lib) +install(FILES ${WAM_LIB_HEADERS} DESTINATION include/webappmanager) + +# Generate and Install pkgconfig file for WebAppMgr library +set(PKGCONFIG_WAM_LIBS "-l${WAM_LIB_NAME}") +CONFIGURE_FILE(${WAM_PKGCONFIG_DIR}/WebAppMgr.pc.in "WebAppMgr.pc" @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/WebAppMgr.pc DESTINATION lib/pkgconfig) + +########################################################### +# WebAppMgr Executable +########################################################### +set(WAM_EXE_INCLUDE_DIRS + ${WAM_SOURCE_DIR}/core + ${WAM_SOURCE_DIR}/util +) +set(WAM_EXE_LIBRARIES + ${CHROMIUM_LDFLAGS} + ${ILMCOMMON_LDFLAGS} + Boost::filesystem + wamcorelib + wamlib +) +set(WAM_EXE_LD_FLAGS -Wl,--no-as-needed) + +if(IS_WEBOS) + if(USE_LUNA_SERVICE) + list(APPEND WAM_EXE_INCLUDE_DIRS ${WAM_SOURCE_DIR}/webos) + endif() +elseif(IS_AGL) + list(APPEND WAM_EXE_INCLUDE_DIRS ${WAM_SOURCE_DIR}/agl) +endif() + +add_executable(wamexec Main.cpp) +target_compile_options(wamexec PRIVATE ${WAM_COMMON_CXX_FLAGS}) +target_compile_definitions(wamexec PRIVATE ${WAM_COMMON_DEFINES}) +target_include_directories(wamexec PRIVATE ${WAM_EXE_INCLUDE_DIRS}) +target_link_libraries(wamexec PRIVATE ${WAM_EXE_LIBRARIES}) +set_target_properties(wamexec PROPERTIES OUTPUT_NAME "WebAppMgr") +set_property(TARGET wamexec APPEND_STRING PROPERTY LINK_FLAGS " ${WAM_EXE_LD_FLAGS}") +install(TARGETS wamexec DESTINATION bin) + +########################################################### +# WebAppMgr Default Plugin (webos-only) +########################################################### +if(IS_WEBOS) + set(WAM_PLUGIN_SOURCES + plugin/WebAppFactoryLuna.cpp + plugin/WebAppWaylandWebOS.cpp + ) + set(WAM_PLUGIN_HEADERS + plugin/WebAppFactoryLuna.h + plugin/WebAppWaylandWebOS.h + ) + set(WAM_PLUGIN_INCLUDE_DIRS + ${WAM_SOURCE_DIR}/platform + ${WAM_SOURCE_DIR}/platform/webengine + ${WAM_SOURCE_DIR}/webos + ${LIBXML_INCLUDE_DIRS} + ) + set(WAM_PLUGIN_LIBRARIES wamlib Qt5::Core) + + add_library(wamplugin SHARED ${WAM_PLUGIN_HEADERS} ${WAM_PLUGIN_SOURCES}) + target_compile_options(wamplugin PRIVATE ${WAM_COMMON_CXX_FLAGS}) + target_compile_definitions(wamplugin PRIVATE ${WAM_COMMON_DEFINES}) + target_include_directories(wamplugin PRIVATE ${WAM_PLUGIN_INCLUDE_DIRS}) + target_link_libraries(wamplugin PRIVATE ${WAM_PLUGIN_LIBRARIES}) + set_target_properties(wamplugin PROPERTIES OUTPUT_NAME "webappmgr-default-plugin") + install(TARGETS wamplugin DESTINATION lib/webappmanager/plugins) + install(FILES ${WAM_PLUGIN_HEADERS} DESTINATION include/webappmanager) +endif() diff --git a/src/Main.cpp b/src/Main.cpp index c6d09d63..b950099a 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -14,48 +14,19 @@ // // SPDX-License-Identifier: Apache-2.0 -#include -#include +#include -#include #include #include #include #include "LogManager.h" -#include "PlatformModuleFactoryImpl.h" -#include "WebAppManager.h" -#include "WebAppManagerServiceLuna.h" -#include -namespace -{ - void qMessageHandler(const QtMsgType type, const QMessageLogContext &context, - const QString &msg) - { - const char* function = context.function; - char* userMessage = msg.toUtf8().data(); - switch (type) { - case QtDebugMsg: - LOG_DEBUG("%s, %s", function, userMessage); - break; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) - case QtInfoMsg: - LOG_INFO(MSGID_QINFO, 0, "%s, %s", function, userMessage); - break; +#if defined(HAS_LUNA_SERVICE) +#include "WebRuntimeWebOS.h" +#elif defined(HAS_AGL_SERVICE) +#include "WebRuntimeAGL.h" #endif - case QtWarningMsg: - LOG_WARNING(MSGID_QWARNING, 0, "%s, %s", function, userMessage); - break; - case QtCriticalMsg: - LOG_ERROR(MSGID_QCRITICAL, 0, "%s, %s", function, userMessage); - break; - case QtFatalMsg: - LOG_CRITICAL(MSGID_QFATAL, 0, "%s, %s", function, userMessage); - break; - } - } -} static void changeUserIDGroupID() { @@ -86,30 +57,17 @@ static void changeUserIDGroupID() } } -static void startWebAppManager() +int main (int argc, const char** argv) { - // FIXME: Remove this when we don't use qDebug, qWarning any more. - qInstallMessageHandler(qMessageHandler); + LOG_DEBUG("### Starting %s", argv[0]); + changeUserIDGroupID(); - changeUserIDGroupID(); +#if defined(HAS_AGL_SERVICE) + WebRuntimeAGL runtime; +#else + WebRuntimeWebOS runtime; +#endif - WebAppManagerServiceLuna* webAppManagerServiceLuna = WebAppManagerServiceLuna::instance(); - assert(webAppManagerServiceLuna); - bool result = webAppManagerServiceLuna->startService(); - assert(result); - WebAppManager::instance()->setPlatformModules(std::unique_ptr(new PlatformModuleFactoryImpl())); + return runtime.run(argc, argv); } -class WebOSMainDelegateWAM : public webos::WebOSMainDelegate { -public: - void AboutToCreateContentBrowserClient() override { - startWebAppManager(); - } -}; - -int main (int argc, const char** argv) -{ - WebOSMainDelegateWAM delegate; - webos::WebOSMain webOSMain(&delegate); - return webOSMain.Run(argc, argv); -} diff --git a/src/agl/WebAppFactoryAGL.cpp b/src/agl/WebAppFactoryAGL.cpp new file mode 100644 index 00000000..8f0b9dc0 --- /dev/null +++ b/src/agl/WebAppFactoryAGL.cpp @@ -0,0 +1,57 @@ +// Copyright (c) 2014-2018 LG Electronics, Inc. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#include "WebAppFactoryAGL.h" + +#include "ApplicationDescription.h" +#include "WebAppWaylandAGL.h" +#include "WebPageBase.h" +#include "WebAppBase.h" +#include "WebAppWayland.h" +#include "WebPageBlink.h" +#include "WindowTypes.h" +#include "LogManager.h" +#include "Url.h" + +WebAppBase* WebAppFactoryAGL::createWebApp(const std::string& winType, std::shared_ptr desc) +{ + WebAppBase* app = 0; + + if(winType == WT_CARD || winType == WT_POPUP || winType == WT_MINIMAL || winType == WT_FLOATING) { + app = new WebAppWaylandAGL(winType, desc); + } else if(winType == WT_OVERLAY) { + app = new WebAppWayland(winType, desc->surfaceId()); + } else if(winType == WT_SYSTEM_UI) { + app = new WebAppWayland(winType, desc->surfaceId()); + } else if(winType == WT_NONE) { + app = new WebAppWayland(winType, desc->surfaceId()); + } else { + LOG_WARNING(MSGID_BAD_WINDOW_TYPE, 1, + PMLOGKS("WINDOW_TYPE", qPrintable(winType)), ""); + } + return app; +} + +WebAppBase* WebAppFactoryAGL::createWebApp(const std::string& winType, WebPageBase* page, std::shared_ptr desc) +{ + return createWebApp(winType, desc); +} + +WebPageBase* WebAppFactoryAGL::createWebPage(const Url& url, std::shared_ptr desc, const std::string& launchParams) +{ + return new WebPageBlink(url, desc, launchParams); +} + diff --git a/src/agl/WebAppFactoryAGL.h b/src/agl/WebAppFactoryAGL.h new file mode 100644 index 00000000..406027fa --- /dev/null +++ b/src/agl/WebAppFactoryAGL.h @@ -0,0 +1,31 @@ +// Copyright (c) 2014-2018 LG Electronics, Inc. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef WEBAPPFACTORYAGL_H +#define WEBAPPFACTORYAGL_H + +#include + +#include "WebAppFactoryInterface.h" + +class WebAppFactoryAGL : public WebAppFactoryInterface { +public: + virtual WebAppBase* createWebApp(const std::string& winType, std::shared_ptr desc = 0); + virtual WebAppBase* createWebApp(const std::string& winType, WebPageBase* page, std::shared_ptr desc = 0); + virtual WebPageBase* createWebPage(const Url& url, std::shared_ptr desc, const std::string& launchParams = ""); +}; + +#endif /* WEBAPPFACTORYAGL_H */ diff --git a/src/agl/WebAppFactoryManagerAGL.cpp b/src/agl/WebAppFactoryManagerAGL.cpp new file mode 100644 index 00000000..6b55ed4e --- /dev/null +++ b/src/agl/WebAppFactoryManagerAGL.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2008-2018 LG Electronics, Inc. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#include "WebAppFactoryManager.h" + +#include "LogManager.h" +#include "WebAppBase.h" +#include "WebAppFactoryAGL.h" +#include "WebAppManagerConfig.h" +#include "WebAppManager.h" +#include "WebPageBase.h" + +class WebAppFactoryManagerAGL : public WebAppFactoryManager { +protected: + virtual WebAppFactoryInterface* loadInterfaceInstance(const std::string& appType); + +private: + friend class WebAppFactoryManager; + WebAppFactoryManagerAGL(); + + WebAppFactoryInterface *m_defaultInterface; +}; + +WebAppFactoryManager* WebAppFactoryManager::instance() +{ + if(!m_instance) { + m_instance = new WebAppFactoryManagerAGL(); + } + return m_instance; +} + +WebAppFactoryManagerAGL::WebAppFactoryManagerAGL() + : m_defaultInterface(new WebAppFactoryAGL()) +{ + m_interfaces.emplace(kDefaultAppType, m_defaultInterface); +} + +WebAppFactoryInterface* WebAppFactoryManagerAGL::loadInterfaceInstance(const std::string& appType) +{ + if (!appType.empty()) + return nullptr; + + return m_defaultInterface; +} + diff --git a/src/agl/WebAppManagerServiceAGL.cpp b/src/agl/WebAppManagerServiceAGL.cpp new file mode 100644 index 00000000..90b8aab0 --- /dev/null +++ b/src/agl/WebAppManagerServiceAGL.cpp @@ -0,0 +1,479 @@ +#include "WebAppManagerServiceAGL.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "LogManager.h" +#include "JsonHelper.h" + +#include "WebAppManager.h" +#include "WebAppBase.h" + +class WamSocketLockFile { +public: + WamSocketLockFile() { + const char* runtime_dir; + if ((runtime_dir = getenv("XDG_RUNTIME_DIR")) == NULL) { + LOG_DEBUG("Failed to retrieve XDG_RUNTIME_DIR, falling back to /tmp"); + runtime_dir = "/tmp"; + } + lock_file_ = std::string(runtime_dir); + lock_file_.append("/wamsocket.lock"); + } + + ~WamSocketLockFile() { + if (lock_fd_ != -1) + releaseLock(lock_fd_); + if (lock_fd_ != -1) + close(lock_fd_); + } + + bool createAndLock() { + lock_fd_ = openLockFile(); + if (!acquireLock(lock_fd_)) { + LOG_DEBUG("Failed to lock file %d", lock_fd_); + return false; + } + return true; + } + + bool ownsLock() { + return lock_fd_ != -1; + } + + bool tryAcquireLock() { + int fd = openLockFile(); + if (fd != -1) { + if (acquireLock(fd)) { + releaseLock(fd); + return true; + } + } + return false; + } + +private: + + int openLockFile() { + int fd = open(lock_file_.c_str(), O_CREAT | O_TRUNC, S_IRWXU); + if (fd == -1) { + LOG_DEBUG("Failed to open lock file descriptor"); + return fd; + } + + int flags = fcntl(fd, F_GETFD); + if (flags == -1) + LOG_DEBUG("Could not get flags for lock file %d", fd); + + flags |= FD_CLOEXEC; + + if (fcntl(fd, F_SETFD, flags) == -1) + LOG_DEBUG("Could not set flags for lock file %d", fd); + + return fd; + } + + bool acquireLock(int fd) { + if (flock(fd, LOCK_EX | LOCK_NB) != 0) + return false; + return true; + } + + void releaseLock(int fd) { + flock(fd, LOCK_UN); + } + + std::string lock_file_; + int lock_fd_ = -1; +}; + +class WamSocket { +public: + WamSocket() { + const char* runtime_dir; + if ((runtime_dir = getenv("XDG_RUNTIME_DIR")) == NULL) { + LOG_DEBUG("Failed to retrieve XDG_RUNTIME_DIR, falling back to /tmp"); + runtime_dir = "/tmp"; + } + wam_socket_path_ = std::string(runtime_dir); + wam_socket_path_.append("/wamsocket"); + } + + ~WamSocket() { + if (socket_fd_ != -1) + close(socket_fd_); + } + + bool createSocket(bool server) { + // Create the socket file descriptor + socket_fd_ = socket(AF_UNIX, SOCK_DGRAM, 0); + if (socket_fd_ == -1) { + LOG_DEBUG("Failed to open socket file descriptor"); + return false; + } + + sock_addr.sun_family = AF_UNIX; + strncpy(sock_addr.sun_path, wam_socket_path_.c_str(), sizeof(sock_addr.sun_path)); + + if (server) { + LOG_DEBUG("service binding"); + unlink(wam_socket_path_.c_str()); + if (bind(socket_fd_, (struct sockaddr *) &sock_addr, sizeof(struct sockaddr_un)) != 0) { + LOG_DEBUG("Failed to bind to named socket"); + return false; + } + } else { + LOG_DEBUG("client connecting"); + if (connect(socket_fd_, (struct sockaddr *) &sock_addr, sizeof(struct sockaddr_un)) != 0) { + LOG_DEBUG("Failed to connect to named socket"); + return false; + } + } + return true; + } + + void sendMsg(int argc, const char **argv) { + std::string cmd; + for (int i = 0; i < argc; ++i) + cmd.append(argv[i]).append(" "); + // Remove the last appended space if any + if (argc > 1) + cmd.pop_back(); + LOG_DEBUG("Sending message=[%s]", cmd.c_str()); + ssize_t bytes = write(socket_fd_, cmd.c_str(), cmd.length()); + LOG_DEBUG("Wrote %zd bytes.", bytes); + } + + int waitForMsg() { + char buf[PATH_MAX] = {}; + ssize_t bytes; + + LOG_DEBUG("Waiting for data..."); + while (TEMP_FAILURE_RETRY((bytes = recv(socket_fd_, (void *)buf, sizeof(buf), 0)) != -1)) { + int last = bytes - 1; + // Remove the new line if there's one + if (buf[last] == '\n') + buf[last] = '\0'; + LOG_DEBUG("Got %zd bytes=[%s].", bytes, buf); + + std::string data(buf); + std::istringstream iss(data); + std::vector res; + for(std::string s; iss >> s; ) { + res.push_back(strdup(s.c_str())); + } + + if (std::string(res[0]) == kStartApp) { + WebAppManagerServiceAGL::instance()->setStartupApplication( + std::string(res[1]), std::string(res[2]), atoi(res[3]), + std::string(res[4])); + + WebAppManagerServiceAGL::instance()->triggerStartupApp(); + } else { + WebAppManagerServiceAGL::instance()->setAppIdForEventTarget(std::string(res[1])); + + WebAppManagerServiceAGL::instance()->triggetEventForApp(std::string(res[0])); + } + return 1; + } + return 0; + } + +private: + + std::string wam_socket_path_; + int socket_fd_; + struct sockaddr_un sock_addr; +}; + +WebAppManagerServiceAGL::WebAppManagerServiceAGL() + : socket_(std::make_unique()), + lock_file_(std::make_unique()) +{ +} + +WebAppManagerServiceAGL* WebAppManagerServiceAGL::instance() { + static WebAppManagerServiceAGL *srv = new WebAppManagerServiceAGL(); + return srv; +} + +bool WebAppManagerServiceAGL::initializeAsHostService() { + if (lock_file_->createAndLock()) + return socket_->createSocket(true); + return false; +} + +bool WebAppManagerServiceAGL::initializeAsHostClient() { + return socket_->createSocket(false); +} + +bool WebAppManagerServiceAGL::isHostServiceRunning() +{ + return !lock_file_->tryAcquireLock(); +} + +void WebAppManagerServiceAGL::launchOnHost(int argc, const char **argv) +{ + LOG_DEBUG("Dispatching launchOnHost"); + socket_->sendMsg(argc, argv); +} + +void WebAppManagerServiceAGL::sendEvent(int argc, const char **argv) +{ + LOG_DEBUG("Sending event"); + socket_->sendMsg(argc, argv); +} + +void WebAppManagerServiceAGL::setStartupApplication( + const std::string& startup_app_id, + const std::string& startup_app_uri, int startup_app_surface_id, + const std::string& startup_proxy_port) +{ + startup_app_id_ = startup_app_id; + startup_app_uri_ = startup_app_uri; + startup_app_surface_id_ = startup_app_surface_id; + startup_proxy_port_ = startup_proxy_port; +} + +void WebAppManagerServiceAGL::setAppIdForEventTarget(const std::string& app_id) { + // This might be a subject to races. But it works ok as a temp solution. + if (app_id_event_target_.empty()) + app_id_event_target_ = app_id; +} + +void *run_socket(void *socket) { + WamSocket *s = (WamSocket*)socket; + while(s->waitForMsg()); + return 0; +} + +bool WebAppManagerServiceAGL::startService() +{ + if (lock_file_->ownsLock()) { + pthread_t thread_id; + if( pthread_create( &thread_id , nullptr, run_socket, socket_.get()) < 0) { + perror("could not create thread"); + LOG_DEBUG("Couldnt create thread..."); + return false; + } + } + + triggerStartupApp(); + + return true; +} + +void WebAppManagerServiceAGL::triggerStartupApp() +{ + LOG_DEBUG("Triggering app start: %s", startup_app_uri_.c_str()); + if (!startup_app_uri_.empty()) { + if (startup_app_uri_.find("http://") == 0) { + startup_app_timer_.start(1000, this, + &WebAppManagerServiceAGL::launchStartupAppFromURL); + } else { + startup_app_timer_.start(1000, this, + &WebAppManagerServiceAGL::launchStartupAppFromConfig); + } + } +} + +void WebAppManagerServiceAGL::triggetEventForApp(const std::string& action) { + if (app_id_event_target_.empty()) + return; + + if (action == kActivateEvent) { + startup_app_timer_.start(1000, this, + &WebAppManagerServiceAGL::onActivateEvent); + } else if (action == kDeactivateEvent) { + startup_app_timer_.start(1000, this, + &WebAppManagerServiceAGL::onDeactivateEvent); + } +} + +void WebAppManagerServiceAGL::launchStartupAppFromConfig() +{ + std::string configfile; + configfile.append(startup_app_uri_); + configfile.append("/config.xml"); + + xmlDoc *doc = xmlReadFile(configfile.c_str(), nullptr, 0); + xmlNode *root = xmlDocGetRootElement(doc); + + xmlChar *id = nullptr; + xmlChar *version = nullptr; + xmlChar *name = nullptr; + xmlChar *content = nullptr; + xmlChar *description = nullptr; + xmlChar *author = nullptr; + xmlChar *icon = nullptr; + + id = xmlGetProp(root, (const xmlChar*)"id"); + version = xmlGetProp(root, (const xmlChar*)"version"); + for (xmlNode *node = root->children; node; node = node->next) { + if (!xmlStrcmp(node->name, (const xmlChar*)"name")) + name = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (!xmlStrcmp(node->name, (const xmlChar*)"icon")) + icon = xmlGetProp(node, (const xmlChar*)"src"); + if (!xmlStrcmp(node->name, (const xmlChar*)"content")) + content = xmlGetProp(node, (const xmlChar*)"src"); + if (!xmlStrcmp(node->name, (const xmlChar*)"description")) + description = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (!xmlStrcmp(node->name, (const xmlChar*)"author")) + author = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + } + fprintf(stdout, "...\n"); + LOG_DEBUG("id: %s", id); + LOG_DEBUG("version: %s", version); + LOG_DEBUG("name: %s", name); + LOG_DEBUG("content: %s", content); + LOG_DEBUG("description: %s", description); + LOG_DEBUG("author: %s", author); + LOG_DEBUG("icon: %s", icon); + + + Json::Value obj(Json::objectValue); + obj["id"] = (const char*)id; + obj["version"] = (const char*)version; + obj["vendor"] = (const char*)author; + obj["type"] = "web"; + obj["main"] = (const char*)content; + obj["title"] = (const char*)name; + obj["uiRevision"] = "2"; + obj["icon"] = (const char*)icon; + obj["folderPath"] = startup_app_uri_.c_str(); + obj["surfaceId"] = startup_app_surface_id_; + + xmlFree(id); + xmlFree(version); + xmlFree(name); + xmlFree(content); + xmlFree(description); + xmlFree(author); + xmlFree(icon); + xmlFreeDoc(doc); + + std::string appDesc; + dumpJsonToString(obj, appDesc); + std::string params; + std::string app_id = obj["id"].asString(); + int errCode = 0; + std::string errMsg; + WebAppManagerService::onLaunch(appDesc, params, app_id, errCode, errMsg); +} + +void WebAppManagerServiceAGL::launchStartupAppFromURL() +{ + LOG_DEBUG("WebAppManagerServiceAGL::launchStartupAppFromURL"); + LOG_DEBUG(" url: %s", startup_app_uri_.c_str()); + Json::Value obj(Json::objectValue); + obj["id"] = startup_app_id_; + obj["version"] = "1.0"; + obj["vendor"] = "some vendor"; + obj["type"] = "web"; + obj["main"] = startup_app_uri_; + obj["title"] = "webapp"; + obj["uiRevision"] = "2"; + //obj["icon"] = (const char*)icon; + //obj["folderPath"] = startup_app_.c_str(); + obj["surfaceId"] = startup_app_surface_id_; + + std::string appDesc; + dumpJsonToString(obj, appDesc); + std::string app_id = startup_app_id_; + int errCode = 0; + std::string params, errMsg; + + LOG_DEBUG("Launching with appDesc=[%s]", appDesc.c_str()); + + if (!startup_proxy_port_.empty()) { + WebAppManagerService::buildWebViewProfile(app_id, "localhost", startup_proxy_port_); + LOG_DEBUG("buildWebViewProfile: Done."); + } + + WebAppManagerService::onLaunch(appDesc, params, app_id, errCode, errMsg); + LOG_DEBUG("onLaunch: Done."); +} + +Json::Value WebAppManagerServiceAGL::launchApp(const Json::Value &request) +{ + return Json::Value(Json::objectValue); +} + +Json::Value WebAppManagerServiceAGL::killApp(const Json::Value &request) +{ + return Json::Value(Json::objectValue); +} + +Json::Value WebAppManagerServiceAGL::logControl(const Json::Value &request) +{ + return Json::Value(Json::objectValue); +} + +Json::Value WebAppManagerServiceAGL::setInspectorEnable(const Json::Value &request) +{ + return Json::Value(Json::objectValue); +} + +Json::Value WebAppManagerServiceAGL::closeAllApps(const Json::Value &request) +{ + return Json::Value(Json::objectValue); +} + +Json::Value WebAppManagerServiceAGL::discardCodeCache(const Json::Value &request) +{ + return Json::Value(Json::objectValue); +} + +Json::Value WebAppManagerServiceAGL::listRunningApps(const Json::Value &request, bool subscribed) +{ + return Json::Value(Json::objectValue); +} + +Json::Value WebAppManagerServiceAGL::closeByProcessId(const Json::Value &request) +{ + return Json::Value(Json::objectValue); +} + +Json::Value WebAppManagerServiceAGL::getWebProcessSize(const Json::Value &request) +{ + return Json::Value(Json::objectValue); +} + +Json::Value WebAppManagerServiceAGL::clearBrowsingData(const Json::Value &request) +{ + return Json::Value(Json::objectValue); +} + +Json::Value WebAppManagerServiceAGL::webProcessCreated(const Json::Value &request, bool subscribed) +{ + return Json::Value(Json::objectValue); +} + +void WebAppManagerServiceAGL::onActivateEvent() { + LOG_DEBUG("Activate app=%s", app_id_event_target_.c_str()); + WebAppBase* web_app = WebAppManager::instance()->findAppById(app_id_event_target_); + if (web_app) + web_app->onStageActivated(); + app_id_event_target_.clear(); +} + +void WebAppManagerServiceAGL::onDeactivateEvent() { + LOG_DEBUG("Dectivate app=%s", app_id_event_target_.c_str()); + WebAppBase* web_app = WebAppManager::instance()->findAppById(app_id_event_target_); + if (web_app) + web_app->onStageDeactivated(); + app_id_event_target_.clear(); +} diff --git a/src/agl/WebAppManagerServiceAGL.h b/src/agl/WebAppManagerServiceAGL.h new file mode 100644 index 00000000..bcdc80e1 --- /dev/null +++ b/src/agl/WebAppManagerServiceAGL.h @@ -0,0 +1,72 @@ +#ifndef WEBAPPMANAGERSERVICEAGL_H +#define WEBAPPMANAGERSERVICEAGL_H + +#include + +#include "WebAppManagerService.h" +#include "Timer.h" + +constexpr char kStartApp[] = "start-app"; +constexpr char kActivateEvent[] = "activate-event"; +constexpr char kDeactivateEvent[] = "deactivate-event"; + +class WamSocket; +class WamSocketLockFile; + +class WebAppManagerServiceAGL : public WebAppManagerService { +public: + static WebAppManagerServiceAGL* instance(); + + bool initializeAsHostService(); + bool initializeAsHostClient(); + + bool isHostServiceRunning(); + + void setStartupApplication(const std::string& startup_app_id, + const std::string& startup_app_uri, int startup_app_surface_id, + const std::string& startup_proxy_port = std::string()); + void setAppIdForEventTarget(const std::string& app_id); + + void launchOnHost(int argc, const char **argv); + void sendEvent(int argc, const char **argv); + + // WebAppManagerService + bool startService() override; + Json::Value launchApp(const Json::Value &request) override; + Json::Value killApp(const Json::Value &request) override; + Json::Value logControl(const Json::Value &request) override; + Json::Value setInspectorEnable(const Json::Value &request) override; + Json::Value closeAllApps(const Json::Value &request) override; + Json::Value discardCodeCache(const Json::Value &request) override; + Json::Value listRunningApps(const Json::Value &request, bool subscribed) override; + Json::Value closeByProcessId(const Json::Value &request) override; + Json::Value getWebProcessSize(const Json::Value &request) override; + Json::Value clearBrowsingData(const Json::Value &request) override; + Json::Value webProcessCreated(const Json::Value &request, bool subscribed) override; + + void triggerStartupApp(); + void triggetEventForApp(const std::string& action); + +private: + + WebAppManagerServiceAGL(); + + void launchStartupAppFromConfig(); + void launchStartupAppFromURL(); + + void onActivateEvent(); + void onDeactivateEvent(); + + std::string app_id_event_target_; + + std::string startup_app_id_; + std::string startup_app_uri_; + std::string startup_proxy_port_; + int startup_app_surface_id_; + OneShotTimer startup_app_timer_; + + std::unique_ptr socket_; + std::unique_ptr lock_file_; +}; + +#endif // WEBAPPMANAGERSERVICEAGL_H diff --git a/src/agl/WebAppWaylandAGL.cpp b/src/agl/WebAppWaylandAGL.cpp new file mode 100644 index 00000000..a3a26250 --- /dev/null +++ b/src/agl/WebAppWaylandAGL.cpp @@ -0,0 +1,23 @@ +// Copyright (c) 2008-2018 LG Electronics, Inc. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#include "WebAppWaylandAGL.h" +#include "ApplicationDescription.h" + +WebAppWaylandAGL::WebAppWaylandAGL(const std::string& winType, std::shared_ptr desc) + : WebAppWayland(winType, desc->surfaceId(), desc->widthOverride(), desc->heightOverride()) +{ +} diff --git a/src/agl/WebAppWaylandAGL.h b/src/agl/WebAppWaylandAGL.h new file mode 100644 index 00000000..54d9ce89 --- /dev/null +++ b/src/agl/WebAppWaylandAGL.h @@ -0,0 +1,32 @@ +// Copyright (c) 2008-2018 LG Electronics, Inc. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef WEBAPPWAYLANDAGL_H +#define WEBAPPWAYLANDAGL_H + +#include +#include + +#include "WebAppWayland.h" + +class ApplicationDescription; + +class WebAppWaylandAGL : public WebAppWayland { +public: + WebAppWaylandAGL(const std::string& winType, std::shared_ptr desc = 0); +}; + +#endif /* WEBAPPWAYLANDAGL_H */ diff --git a/src/agl/WebRuntimeAGL.cpp b/src/agl/WebRuntimeAGL.cpp new file mode 100644 index 00000000..af386ba7 --- /dev/null +++ b/src/agl/WebRuntimeAGL.cpp @@ -0,0 +1,524 @@ +#include "WebRuntimeAGL.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include "LogManager.h" +#include "PlatformModuleFactoryImpl.h" +#include "StringUtils.h" +#include "WebAppManager.h" +#include "WebAppManagerServiceAGL.h" + + +#define WEBAPP_CONFIG "config.xml" + +volatile sig_atomic_t e_flag = 0; + + +static std::string getAppId(const std::vector& args) { + const char *afm_id = getenv("AFM_ID"); + if (afm_id == nullptr || !afm_id[0]) { + return args[0]; + } else { + return std::string(afm_id); + } +} + +static std::string getAppUrl(const std::vector& args) { + for (size_t i=0; i < args.size(); i++) { + std::size_t found = args[i].find(std::string("http://")); + if (found != std::string::npos) + return args[i]; + } + return std::string(); +} + +static bool isBrowserProcess(const std::vector& args) { + // if type is not given then we are browser process + for (size_t i=0; i < args.size(); i++) { + std::string param("--type="); + std::size_t found = args[i].find(param); + if (found != std::string::npos) + return false; + } + return true; +} + +static bool isSharedBrowserProcess(const std::vector& args) { + // if 'http://' param is not present then assume shared browser process + for (size_t i=0; i < args.size(); i++) { + std::size_t found = args[i].find(std::string("http://")); + if (found != std::string::npos) + return false; + } + return true; +} + +static bool isWaitForHostService(const std::vector& args) { + const char *value = getenv("WAIT_FOR_HOST_SERVICE"); + if (value == nullptr || !value[0]) { + return false; + } else { + return (strcmp(value, "1") == 0); + } +} + +class AGLMainDelegateWAM : public webos::WebOSMainDelegate { +public: + void AboutToCreateContentBrowserClient() override { + WebAppManagerServiceAGL::instance()->startService(); + WebAppManager::instance()->setPlatformModules(std::unique_ptr(new PlatformModuleFactoryImpl())); + } +}; + +class AGLRendererDelegateWAM : public webos::WebOSMainDelegate { +public: + void AboutToCreateContentBrowserClient() override { + // do nothing + } +}; + +void Launcher::register_surfpid(pid_t app_pid, pid_t surf_pid) +{ + if (app_pid != m_rid) + return; + bool result = m_pid_map.insert({app_pid, surf_pid}).second; + if (!result) { + LOG_DEBUG("register_surfpid, (app_pid=%d) already registered surface_id with (surface_id=%d)", + (int)app_pid, (int)surf_pid); + } +} + +void Launcher::unregister_surfpid(pid_t app_pid, pid_t surf_pid) +{ + size_t erased_count = m_pid_map.erase(app_pid); + if (erased_count == 0) { + LOG_DEBUG("unregister_surfpid, (app_pid=%d) doesn't have a registered surface", + (int)app_pid); + } +} + +pid_t Launcher::find_surfpid_by_rid(pid_t app_pid) +{ + auto surface_id = m_pid_map.find(app_pid); + if (surface_id != m_pid_map.end()) { + LOG_DEBUG("found return(%d, %d)", (int)app_pid, (int)surface_id->second); + return surface_id->second; + } + return -1; +} + +int SingleBrowserProcessWebAppLauncher::launch(const std::string& id, const std::string& uri) { + m_rid = (int)getpid(); + WebAppManagerServiceAGL::instance()->setStartupApplication(id, uri, m_rid); + return m_rid; +} + +int SingleBrowserProcessWebAppLauncher::loop(int argc, const char** argv, volatile sig_atomic_t& e_flag) { + AGLMainDelegateWAM delegate; + webos::WebOSMain webOSMain(&delegate); + return webOSMain.Run(argc, argv); +} + +int SharedBrowserProcessWebAppLauncher::launch(const std::string& id, const std::string& uri) { + if (!WebAppManagerServiceAGL::instance()->initializeAsHostClient()) { + LOG_DEBUG("Failed to initialize as host client"); + return -1; + } + + tiny_proxy_ = std::make_unique(); + int port = tiny_proxy_->port(); + std::string proxy_port = std::to_string(port); + + m_rid = (int)getpid(); + std::string m_rid_s = std::to_string(m_rid); + std::vector data; + data.push_back(kStartApp); + data.push_back(id.c_str()); + data.push_back(uri.c_str()); + data.push_back(m_rid_s.c_str()); + data.push_back(proxy_port.c_str()); + + WebAppManagerServiceAGL::instance()->launchOnHost(data.size(), data.data()); + return m_rid; +} + +int SharedBrowserProcessWebAppLauncher::loop(int argc, const char** argv, volatile sig_atomic_t& e_flag) { + // TODO: wait for a pid + while (1) + sleep(1); + return 0; +} + +int WebAppLauncherRuntime::run(int argc, const char** argv) { + std::vector args(argv + 1, argv + argc); + bool isWaitHostService = isWaitForHostService(args); + m_id = getAppId(args); + m_url = getAppUrl(args); + m_role = "WebApp"; + + if(isWaitHostService) { + while(!WebAppManagerServiceAGL::instance()->isHostServiceRunning()) { + LOG_DEBUG("WebAppLauncherRuntime::run - waiting for host service"); + sleep(1); + } + } + + if(isWaitHostService || WebAppManagerServiceAGL::instance()->isHostServiceRunning()) { + LOG_DEBUG("WebAppLauncherRuntime::run - creating SharedBrowserProcessWebAppLauncher"); + m_launcher = new SharedBrowserProcessWebAppLauncher(); + } else { + LOG_DEBUG("WebAppLauncherRuntime::run - creating SingleBrowserProcessWebAppLauncher"); + m_launcher = new SingleBrowserProcessWebAppLauncher(); + } + + + // Initialize SIGTERM handler + // TODO: init_signal(); + + if (!init()) + return -1; + + /* Launch WAM application */ + m_launcher->m_rid = m_launcher->launch(m_id, m_url); + + if (m_launcher->m_rid < 0) { + LOG_DEBUG("cannot launch WAM app (%s)", m_id.c_str()); + } + + // take care 1st time launch + LOG_DEBUG("waiting for notification: surface created"); + m_pending_create = true; + + return m_launcher->loop(argc, argv, e_flag); +} + +bool WebAppLauncherRuntime::init() { + // based on https://tools.ietf.org/html/rfc3986#page-50 + std::regex url_regex ( + R"(^(([^:\/?#]+):)?(//([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)", + std::regex::extended + ); + + std::smatch url_match_result; + if (std::regex_match(m_url, url_match_result, url_regex)) { + unsigned counter = 0; + for (const auto& res : url_match_result) { + LOG_DEBUG(" %d: %s", counter++, res.str().c_str()); + } + + if (url_match_result.size() > 4) { + std::string authority = url_match_result[4].str(); + std::size_t n = authority.find(':'); + if (n != std::string::npos) { + std::string sport = authority.substr(n+1); + m_role.append("-"); + m_role.append(sport); + m_port = stringTo(sport); + } + } + + if (url_match_result.size() > 7) { + std::string query = url_match_result[7].str(); + std::size_t n = query.find('='); + if (n != std::string::npos) { + m_token = query.substr(n+1); + } + } + + auto path = std::string(getenv("AFM_APP_INSTALL_DIR")); + path = path + "/" + WEBAPP_CONFIG; + + // Parse config file of runxdg + if (parse_config(path.c_str())) { + LOG_DEBUG("Error in config"); + return false; + } + + LOG_DEBUG("id=[%s], name=[%s], role=[%s], url=[%s], port=%d, token=[%s]", + m_id.c_str(), m_name.c_str(), m_role.c_str(), m_url.c_str(), + m_port, m_token.c_str()); + + // Setup HomeScreen/WindowManager API + if (!init_wm()) { + LOG_DEBUG("cannot setup wm API"); + return false; + } + + if (!init_hs()) { + LOG_DEBUG("cannot setup hs API"); + return false; + } + + // Setup ilmController API + m_ic = new ILMControl(notify_ivi_control_cb_static, this); + + return true; + } else { + LOG_DEBUG("Malformed url."); + return false; + } +} + +bool WebAppLauncherRuntime::init_wm() { + m_wm = new LibWindowmanager(); + if (m_wm->init(m_port, m_token.c_str())) { + LOG_DEBUG("cannot initialize windowmanager"); + return false; + } + + std::function< void(json_object*) > h_active = [](json_object* object) { + LOG_DEBUG("Got Event_Active"); + }; + + std::function< void(json_object*) > h_inactive = [](json_object* object) { + LOG_DEBUG("Got Event_Inactive"); + }; + + std::function< void(json_object*) > h_visible = [this](json_object* object) { + LOG_DEBUG("Got Event_Visible"); + + std::vector data; + data.push_back(kActivateEvent); + data.push_back(this->m_id.c_str()); + + WebAppManagerServiceAGL::instance()->sendEvent(data.size(), data.data()); + }; + + std::function< void(json_object*) > h_invisible = [this](json_object* object) { + LOG_DEBUG("Got Event_Invisible"); + + std::vector data; + data.push_back(kDeactivateEvent); + data.push_back(this->m_id.c_str()); + + WebAppManagerServiceAGL::instance()->sendEvent(data.size(), data.data()); + }; + + std::function< void(json_object*) > h_syncdraw = + [this](json_object* object) { + LOG_DEBUG("Got Event_SyncDraw"); + this->m_wm->endDraw(this->m_role.c_str()); + }; + + std::function< void(json_object*) > h_flushdraw= [](json_object* object) { + LOG_DEBUG("Got Event_FlushDraw"); + }; + + m_wm->set_event_handler(LibWindowmanager::Event_Active, h_active); + m_wm->set_event_handler(LibWindowmanager::Event_Inactive, h_inactive); + m_wm->set_event_handler(LibWindowmanager::Event_Visible, h_visible); + m_wm->set_event_handler(LibWindowmanager::Event_Invisible, h_invisible); + m_wm->set_event_handler(LibWindowmanager::Event_SyncDraw, h_syncdraw); + m_wm->set_event_handler(LibWindowmanager::Event_FlushDraw, h_flushdraw); + + return true; +} + +bool WebAppLauncherRuntime::init_hs() { + m_hs = new LibHomeScreen(); + if (m_hs->init(m_port, m_token.c_str())) { + LOG_DEBUG("cannot initialize homescreen"); + return false; + } + + std::function< void(json_object*) > handler = [this] (json_object* object) { + LOG_DEBUG("Activesurface %s ", this->m_role.c_str()); + this->m_wm->activateWindow(this->m_role.c_str(), "normal.full"); + }; + m_hs->set_event_handler(LibHomeScreen::Event_ShowWindow, handler); + + std::function< void(json_object*) > h_default= [](json_object* object) { + const char *j_str = json_object_to_json_string(object); + LOG_DEBUG("Got event [%s]", j_str); + }; + m_hs->set_event_handler(LibHomeScreen::Event_OnScreenMessage, h_default); + + return true; +} + +int WebAppLauncherRuntime::parse_config (const char *path_to_config) +{ + xmlDoc *doc = xmlReadFile(path_to_config, nullptr, 0); + xmlNode *root = xmlDocGetRootElement(doc); + + xmlChar *id = nullptr; + xmlChar *version = nullptr; + xmlChar *name = nullptr; + xmlChar *content = nullptr; + xmlChar *description = nullptr; + xmlChar *author = nullptr; + xmlChar *icon = nullptr; + + id = xmlGetProp(root, (const xmlChar*)"id"); + version = xmlGetProp(root, (const xmlChar*)"version"); + for (xmlNode *node = root->children; node; node = node->next) { + if (!xmlStrcmp(node->name, (const xmlChar*)"name")) + name = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (!xmlStrcmp(node->name, (const xmlChar*)"icon")) + icon = xmlGetProp(node, (const xmlChar*)"src"); + if (!xmlStrcmp(node->name, (const xmlChar*)"content")) + content = xmlGetProp(node, (const xmlChar*)"src"); + if (!xmlStrcmp(node->name, (const xmlChar*)"description")) + description = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (!xmlStrcmp(node->name, (const xmlChar*)"author")) + author = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + } + fprintf(stdout, "...parse_config...\n"); + LOG_DEBUG("id: %s", id); + LOG_DEBUG("version: %s", version); + LOG_DEBUG("name: %s", name); + LOG_DEBUG("content: %s", content); + LOG_DEBUG("description: %s", description); + LOG_DEBUG("author: %s", author); + LOG_DEBUG("icon: %s", icon); + + m_name = std::string((const char*)name); + + xmlFree(id); + xmlFree(version); + xmlFree(name); + xmlFree(content); + xmlFree(description); + xmlFree(author); + xmlFree(icon); + xmlFreeDoc(doc); + + return 0; +} + +void WebAppLauncherRuntime::setup_surface (int id) +{ + std::string sid = std::to_string(id); + + // This surface is mine, register pair app_name and ivi id. + LOG_DEBUG("requestSurfaceXDG(%s,%d)", m_role.c_str(), id); + m_wm->requestSurfaceXDG(this->m_role.c_str(), id); + + if (m_pending_create) { + // Recovering 1st time tap_shortcut is dropped because + // the application has not been run yet (1st time launch) + m_pending_create = false; + m_wm->activateWindow(this->m_role.c_str(), "normal.full"); + } +} + +void WebAppLauncherRuntime::notify_ivi_control_cb (ilmObjectType object, t_ilm_uint id, + t_ilm_bool created) +{ + if (object == ILM_SURFACE) { + // This call is broadcasted and all the launchers receive this call with the same id, + // but we cannot rely on surf_pid when calling find_surfpid_by_rid, because all the + // created surfaces are created by WebAppMgr, which has only one pid. This results + // in a wrong launcher requesting surfaces, which may lead to a sitatution, when app just + // creashes. Thus, let's temporarely use an assumption that each launcher has only one + // surface. + if (!m_launcher->m_pid_map.empty()) { + LOG_DEBUG("This launcher has already had a surface"); + return; + } + + struct ilmSurfaceProperties surf_props; + + ilm_getPropertiesOfSurface(id, &surf_props); + pid_t surf_pid = surf_props.creatorPid; + + if (!created) { + LOG_DEBUG("ivi surface (id=%d, surf_pid=%d) [m_rid:%d] destroyed.", id, surf_pid, m_launcher->m_rid); + m_launcher->unregister_surfpid(id, surf_pid); + m_surfaces.erase(surf_pid); + return; + } + + LOG_DEBUG("ivi surface (id=%d, surf_pid=%d) [m_rid:%d] is created.", id, surf_pid, m_launcher->m_rid); + + m_launcher->register_surfpid(id, surf_pid); + if (m_launcher->m_rid && + surf_pid == m_launcher->find_surfpid_by_rid(m_launcher->m_rid)) { + setup_surface(id); + } + m_surfaces[surf_pid] = id; + } else if (object == ILM_LAYER) { + if (created) + LOG_DEBUG("ivi layer: %d created.", id); + else + LOG_DEBUG("ivi layer: %d destroyed.", id); + } +} + +void WebAppLauncherRuntime::notify_ivi_control_cb_static (ilmObjectType object, t_ilm_uint id, + t_ilm_bool created, void *user_data) +{ + WebAppLauncherRuntime *wam = static_cast(user_data); + wam->notify_ivi_control_cb(object, id, created); +} + + +int SharedBrowserProcessRuntime::run(int argc, const char** argv) { + if (WebAppManagerServiceAGL::instance()->initializeAsHostService()) { + AGLMainDelegateWAM delegate; + webos::WebOSMain webOSMain(&delegate); + return webOSMain.Run(argc, argv); + } else { + LOG_DEBUG("Trying to start shared browser process but process is already running"); + return -1; + } +} + +int RenderProcessRuntime::run(int argc, const char** argv) { + AGLMainDelegateWAM delegate; + webos::WebOSMain webOSMain(&delegate); + return webOSMain.Run(argc, argv); +} + +int WebRuntimeAGL::run(int argc, const char** argv) { + LOG_DEBUG("WebRuntimeAGL::run"); + std::vector args(argv + 1, argv + argc); + if (isBrowserProcess(args)) { + if (isSharedBrowserProcess(args)) { + LOG_DEBUG("WebRuntimeAGL - creating SharedBrowserProcessRuntime"); + m_runtime = new SharedBrowserProcessRuntime(); + } else { + LOG_DEBUG("WebRuntimeAGL - creating WebAppLauncherRuntime"); + m_runtime = new WebAppLauncherRuntime(); + } + } else { + LOG_DEBUG("WebRuntimeAGL - creating RenderProcessRuntime"); + m_runtime = new RenderProcessRuntime(); + } + + return m_runtime->run(argc, argv); +} + +TinyProxy::TinyProxy() { + // Get a free port to listen + int test_socket = socket(AF_INET, SOCK_STREAM, 0); + struct sockaddr_in test_socket_addr; + memset(&test_socket_addr, 0, sizeof(test_socket_addr)); + test_socket_addr.sin_port = htons(0); + test_socket_addr.sin_family = AF_INET; + bind(test_socket, (struct sockaddr*) &test_socket_addr, sizeof(struct sockaddr_in)); + socklen_t len = sizeof(test_socket_addr); + getsockname(test_socket, (struct sockaddr*) &test_socket_addr, &len); + int port = ntohs(test_socket_addr.sin_port); + close(test_socket); + + setPort(port); + + std::string cmd = "tinyproxy -p " + std::to_string(port); + int res = std::system(cmd.data()); + if (res == -1) + LOG_DEBUG("Error while running %s", cmd.data()); +} diff --git a/src/agl/WebRuntimeAGL.h b/src/agl/WebRuntimeAGL.h new file mode 100644 index 00000000..063f3df5 --- /dev/null +++ b/src/agl/WebRuntimeAGL.h @@ -0,0 +1,125 @@ +#ifndef WEBRUNTIME_AGL_H +#define WEBRUNTIME_AGL_H + +#include +#include +#include +#include +#include + +#include + +#include "WebRuntime.h" + +class LibHomeScreen; +class LibWindowmanager; + +class ILMControl +{ + public: + ILMControl(notificationFunc callback, void *user_data) { + ilm_init(); + ilm_registerNotification(callback, user_data); + } + + ~ILMControl(void) { + ilm_unregisterNotification(); + ilm_destroy(); + fprintf(stderr, "ilm_destory().\r\n"); + } +}; + +class Launcher { +public: + virtual void register_surfpid(pid_t app_pid, pid_t surf_pid); + virtual void unregister_surfpid(pid_t app_pid, pid_t surf_pid); + virtual pid_t find_surfpid_by_rid(pid_t app_pid); + virtual int launch(const std::string& id, const std::string& uri) = 0; + virtual int loop(int argc, const char** argv, volatile sig_atomic_t& e_flag) = 0; + + int m_rid = 0; + std::unordered_map m_pid_map; // pair of +}; + +class TinyProxy { + public: + int port() { return port_; } + void setPort(int port) { port_ = port; } + + TinyProxy(); +private: + int port_; +}; + +class SharedBrowserProcessWebAppLauncher : public Launcher { +public: + int launch(const std::string& id, const std::string& uri) override; + int loop(int argc, const char** argv, volatile sig_atomic_t& e_flag) override; +private: + std::unique_ptr tiny_proxy_; +}; + +class SingleBrowserProcessWebAppLauncher : public Launcher { +public: + int launch(const std::string& id, const std::string& uri) override; + int loop(int argc, const char** argv, volatile sig_atomic_t& e_flag) override; +}; + +class WebAppLauncherRuntime : public WebRuntime { +public: + int run(int argc, const char** argv) override; + + void notify_ivi_control_cb(ilmObjectType object, t_ilm_uint id, + t_ilm_bool created); + static void notify_ivi_control_cb_static (ilmObjectType object, + t_ilm_uint id, + t_ilm_bool created, + void *user_data); + +private: + + bool init(); + bool init_wm(); + bool init_hs(); + int parse_config(const char *file); + void setup_surface (int id); + + std::string m_id; + std::string m_role; + std::string m_url; + std::string m_name; + + int m_port; + std::string m_token; + + Launcher *m_launcher; + + LibWindowmanager *m_wm = nullptr; + LibHomeScreen *m_hs = nullptr; + ILMControl *m_ic = nullptr; + + std::unordered_map m_surfaces; // pair of + + bool m_pending_create = false; +}; + +class SharedBrowserProcessRuntime : public WebRuntime { +public: + int run(int argc, const char** argv) override; +}; + +class RenderProcessRuntime : public WebRuntime { +public: + int run(int argc, const char** argv) override; +}; + +class WebRuntimeAGL : public WebRuntime { +public: + int run(int argc, const char** argv) override; + +private: + + WebRuntime *m_runtime; +}; + +#endif // WEBRUNTIME_AGL_H diff --git a/src/core/ApplicationDescription.cpp b/src/core/ApplicationDescription.cpp index 9655f3cb..34b540b0 100644 --- a/src/core/ApplicationDescription.cpp +++ b/src/core/ApplicationDescription.cpp @@ -14,22 +14,16 @@ // // SPDX-License-Identifier: Apache-2.0 +#include "ApplicationDescription.h" #include - #include #include #include -#include -#include -#include -#include -#include -#include - -#include "ApplicationDescription.h" +#include "JsonHelper.h" #include "LogManager.h" +#include "StringUtils.h" bool ApplicationDescription::checkTrustLevel(std::string trustLevel) { @@ -69,13 +63,18 @@ const ApplicationDescription::WindowGroupInfo ApplicationDescription::getWindowG ApplicationDescription::WindowGroupInfo info; if (!m_groupWindowDesc.empty()) { - QJsonDocument jsonDoc = QJsonDocument::fromJson(QByteArray(m_groupWindowDesc.c_str())); - QJsonObject jsonObject = jsonDoc.object(); + Json::Value json; + readJsonFromString(m_groupWindowDesc, json); + + if (json.isObject()) { + auto name = json["name"]; + if (name.isString()) + info.name = name.asString(); - if (!jsonObject.value("name").isUndefined()) - info.name = jsonObject.value("name").toString(); - if (!jsonObject.value("owner").isUndefined()) - info.isOwner = jsonObject.value("owner").toBool(); + auto isOwner = json["owner"]; + if (isOwner.isBool()) + info.isOwner = isOwner.asBool(); + } } return info; @@ -85,21 +84,23 @@ const ApplicationDescription::WindowOwnerInfo ApplicationDescription::getWindowO { ApplicationDescription::WindowOwnerInfo info; if (!m_groupWindowDesc.empty()) { - QJsonDocument jsonDoc = QJsonDocument::fromJson(QByteArray(m_groupWindowDesc.c_str())); - QJsonObject jsonObject = jsonDoc.object(); - - if (!jsonObject.value("ownerInfo").isUndefined()) { - QJsonObject ownerJsonObject = jsonObject.value("ownerInfo").toObject(); - if (!ownerJsonObject.value("allowAnonymous").isUndefined()) - info.allowAnonymous =ownerJsonObject.value("allowAnonymous").toBool(); - - if (!ownerJsonObject.value("layers").isUndefined()) { - QJsonArray ownerJsonArray = ownerJsonObject.value("layers").toArray(); - - for (int i=0; i(zstr.asString()); + info.layers.emplace(name.asString(), z); + } } } } @@ -112,16 +113,18 @@ const ApplicationDescription::WindowClientInfo ApplicationDescription::getWindow { ApplicationDescription::WindowClientInfo info; if (!m_groupWindowDesc.empty()) { - QJsonDocument jsonDoc = QJsonDocument::fromJson(QByteArray(m_groupWindowDesc.c_str())); - QJsonObject jsonObject = jsonDoc.object(); - - if (!jsonObject.value("clientInfo").isUndefined()) { - QJsonObject clientJsonObject = jsonObject.value("clientInfo").toObject(); - if (!clientJsonObject.value("layer").isUndefined()) - info.layer = clientJsonObject.value("layer").toString(); - - if (!clientJsonObject.value("hint").isUndefined()) - info.hint = clientJsonObject.value("hint").toString(); + Json::Value json; + readJsonFromString(m_groupWindowDesc, json); + + auto clientInfo = json["clientInfo"]; + if (clientInfo.isObject()) { + auto layer = clientInfo["layer"]; + if (layer.isString()) + info.layer = layer.asString(); + + auto hint = clientInfo["hint"]; + if (hint.isString()) + info.hint = hint.asString(); } } return info; @@ -129,64 +132,70 @@ const ApplicationDescription::WindowClientInfo ApplicationDescription::getWindow std::unique_ptr ApplicationDescription::fromJsonString(const char* jsonStr) { - QJsonParseError parseError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(QByteArray(jsonStr), &parseError); - if (parseError.error != QJsonParseError::NoError) { + Json::Value jsonObj; + if (!readJsonFromString(jsonStr, jsonObj)) { LOG_WARNING(MSGID_APP_DESC_PARSE_FAIL, 1, PMLOGKFV("JSON", "%s", jsonStr), "Failed to parse JSON string"); return nullptr; } - QJsonObject jsonObj = jsonDoc.object(); auto appDesc = std::unique_ptr(new ApplicationDescription()); - appDesc->m_transparency = jsonObj["transparent"].toBool(); - appDesc->m_vendorExtension = QJsonDocument(jsonObj["vendorExtension"].toObject()).toJson().data(); - appDesc->m_trustLevel = jsonObj["trustLevel"].toString().toStdString(); - appDesc->m_subType = jsonObj["subType"].toString().toStdString(); - appDesc->m_deeplinkingParams = jsonObj["deeplinkingParams"].toString().toStdString(); - appDesc->m_handlesRelaunch = jsonObj["handlesRelaunch"].toBool(); - appDesc->m_defaultWindowType = jsonObj["defaultWindowType"].toString().toStdString(); - appDesc->m_inspectable = jsonObj["inspectable"].toBool(); - appDesc->m_containerJS = jsonObj["containerJS"].toString().toStdString(); - appDesc->m_containerCSS = jsonObj["containerCSS"].toString().toStdString(); - appDesc->m_enyoBundleVersion = jsonObj["enyoBundleVersion"].toString().toStdString(); - appDesc->m_enyoVersion = jsonObj["enyoVersion"].toString().toStdString(); - appDesc->m_version = jsonObj["version"].toString().toStdString(); - appDesc->m_customPlugin = jsonObj["customPlugin"].toBool(); - appDesc->m_backHistoryAPIDisabled = jsonObj["disableBackHistoryAPI"].toBool(); - appDesc->m_groupWindowDesc = QJsonDocument(jsonObj["windowGroup"].toObject()).toJson().data(); - - if (jsonObj.contains("supportedEnyoBundleVersions")) { - QJsonArray versions = jsonObj["supportedEnyoBundleVersions"].toArray(); - for (int i=0; i < versions.size(); i++) - appDesc->m_supportedEnyoBundleVersions.append(versions[i].toString()); + appDesc->m_surfaceId = jsonObj["surfaceId"].asInt(); + appDesc->m_transparency = jsonObj["transparent"].asBool(); + appDesc->m_trustLevel = jsonObj["trustLevel"].asString(); + appDesc->m_subType = jsonObj["subType"].asString(); + appDesc->m_deeplinkingParams = jsonObj["deeplinkingParams"].asString(); + appDesc->m_handlesRelaunch = jsonObj["handlesRelaunch"].asBool(); + appDesc->m_defaultWindowType = jsonObj["defaultWindowType"].asString(); + appDesc->m_inspectable = jsonObj["inspectable"].asBool(); + appDesc->m_containerJS = jsonObj["containerJS"].asString(); + appDesc->m_containerCSS = jsonObj["containerCSS"].asString(); + appDesc->m_enyoBundleVersion = jsonObj["enyoBundleVersion"].asString(); + appDesc->m_enyoVersion = jsonObj["enyoVersion"].asString(); + appDesc->m_version = jsonObj["version"].asString(); + appDesc->m_customPlugin = jsonObj["customPlugin"].asBool(); + appDesc->m_backHistoryAPIDisabled = jsonObj["disableBackHistoryAPI"].asBool(); + + auto vendorExtension = jsonObj.get("vendorExtension", Json::Value(Json::objectValue)); + auto groupWindowDesc = jsonObj.get("windowGroup", Json::Value(Json::objectValue)); + dumpJsonToString(vendorExtension, appDesc->m_vendorExtension); + dumpJsonToString(groupWindowDesc, appDesc->m_groupWindowDesc); + + auto supportedVersions = jsonObj["supportedEnyoBundleVersions"]; + if (supportedVersions.isArray()) { + for (const Json::Value &version : supportedVersions) + appDesc->m_supportedEnyoBundleVersions.insert(version.asString()); } - appDesc->m_id = jsonObj["id"].toString().toStdString(); - appDesc->m_entryPoint= jsonObj["main"].toString().toStdString(); - appDesc->m_icon = jsonObj["icon"].toString().toStdString(); - appDesc->m_folderPath = jsonObj["folderPath"].toString().toStdString(); - appDesc->m_requestedWindowOrientation = jsonObj["requestedWindowOrientation"].toString().toStdString(); - appDesc->m_title = jsonObj["title"].toString().toStdString(); - appDesc->m_doNotTrack = jsonObj["doNotTrack"].toBool(); - appDesc->m_handleExitKey = jsonObj["handleExitKey"].toBool(); - appDesc->m_enableBackgroundRun = jsonObj["enableBackgroundRun"].toBool(); - appDesc->m_allowVideoCapture = jsonObj["allowVideoCapture"].toBool(); - appDesc->m_allowAudioCapture = jsonObj["allowAudioCapture"].toBool(); - appDesc->m_usePrerendering = jsonObj.contains("usePrerendering") && jsonObj["usePrerendering"].toBool(); - appDesc->m_disallowScrollingInMainFrame = !jsonObj.contains("disallowScrollingInMainFrame") || jsonObj["disallowScrollingInMainFrame"].toBool(); + appDesc->m_id = jsonObj["id"].asString(); + appDesc->m_entryPoint= jsonObj["main"].asString(); + appDesc->m_icon = jsonObj["icon"].asString(); + appDesc->m_folderPath = jsonObj["folderPath"].asString(); + appDesc->m_requestedWindowOrientation = jsonObj["requestedWindowOrientation"].asString(); + appDesc->m_title = jsonObj["title"].asString(); + appDesc->m_doNotTrack = jsonObj["doNotTrack"].asBool(); + appDesc->m_handleExitKey = jsonObj["handleExitKey"].asBool(); + appDesc->m_enableBackgroundRun = jsonObj["enableBackgroundRun"].asBool(); + appDesc->m_allowVideoCapture = jsonObj["allowVideoCapture"].asBool(); + appDesc->m_allowAudioCapture = jsonObj["allowAudioCapture"].asBool(); + + auto usePrerendering = jsonObj["usePrerendering"]; + appDesc->m_usePrerendering = usePrerendering.isBool() && usePrerendering.asBool(); + auto disallowScrolling = jsonObj["disallowScrollingInMainFrame"]; + appDesc->m_disallowScrollingInMainFrame = disallowScrolling.isBool() && disallowScrolling.asBool(); // Handle accessibility, supportsAudioGuidance - if (!jsonObj.value("accessibility").isUndefined() && jsonObj.value("accessibility").isObject()) { - QJsonObject accessibilityObj = jsonObj["accessibility"].toObject(); - if (!accessibilityObj.value("supportsAudioGuidance").isUndefined()) - appDesc->m_supportsAudioGuidance = accessibilityObj["supportsAudioGuidance"].toBool(); + auto accessibility = jsonObj["accessibility"]; + if (accessibility.isObject()) { + auto audioGuidance = accessibility["supportsAudioGuidance"]; + appDesc->m_supportsAudioGuidance = audioGuidance.isBool() && audioGuidance.asBool(); } // Handle v8 snapshot file - if (!jsonObj.value("v8SnapshotFile").isUndefined()) { - std::string snapshotFile = jsonObj["v8SnapshotFile"].toString().toStdString(); + auto v8SnapshotFile = jsonObj["v8SnapshotFile"]; + if (v8SnapshotFile.isString()) { + std::string snapshotFile = v8SnapshotFile.asString(); if (snapshotFile.length() > 0) { if (snapshotFile.at(0) == '/') appDesc->m_v8SnapshotPath = snapshotFile; @@ -196,16 +205,18 @@ std::unique_ptr ApplicationDescription::fromJsonString(c } // Handle v8 extra flags - if (!jsonObj.value("v8ExtraFlags").isUndefined()) - appDesc->m_v8ExtraFlags = jsonObj["v8ExtraFlags"].toString().toStdString(); + auto v8ExtraFlags = jsonObj["v8ExtraFlags"]; + if (v8ExtraFlags.isString()) + appDesc->m_v8ExtraFlags = v8ExtraFlags.asString(); // Handle resolution - if (!jsonObj.value("resolution").isUndefined()) { - QString overrideResolution = jsonObj["resolution"].toString(); - QStringList resList(overrideResolution.split("x", QString::KeepEmptyParts, Qt::CaseInsensitive)); + auto resolution = jsonObj["resolution"]; + if (resolution.isString()) { + std::string overrideResolution = jsonObj["resolution"].asString(); + auto resList = splitString(overrideResolution, 'x', true, true); if(resList.size() == 2) { - appDesc->m_widthOverride = resList.at(0).toInt(); - appDesc->m_heightOverride = resList.at(1).toInt(); + appDesc->m_widthOverride = stringTo(resList.at(0)); + appDesc->m_heightOverride = stringTo(resList.at(1)); } if(appDesc->m_widthOverride < 0 || appDesc->m_heightOverride < 0) { appDesc->m_widthOverride = 0; @@ -215,12 +226,15 @@ std::unique_ptr ApplicationDescription::fromJsonString(c // Handle keyFilterTable //Key code is changed only for facebooklogin WebApp - if (!jsonObj.value("keyFilterTable").isUndefined()) { - QJsonArray keyFilterTable = jsonObj["keyFilterTable"].toArray(); - for (int i=0 ; i < keyFilterTable.size() ; i++) { - QVariantMap map = keyFilterTable[i].toObject().toVariantMap(); - if (!map.empty()) - appDesc->m_keyFilterTable[map["from"].toString().toInt()] = qMakePair(map["to"].toString().toInt(), map["modifier"].toString().toInt()); + auto keyFilterTable = jsonObj["keyFilterTable"]; + if (keyFilterTable.isArray()) { + for (const auto &k : keyFilterTable) { + if (!k.isObject()) + continue; + int from = stringTo(k["from"].asString()); + int to = stringTo(k["to"].asString()); + int mod = stringTo(k["mod"].asString()); + appDesc->m_keyFilterTable[from] = std::make_pair(to, mod); } } @@ -241,9 +255,9 @@ std::unique_ptr ApplicationDescription::fromJsonString(c // class : { "hidden" : boolean } // WindowClass classValue = WindowClass_Normal; - if (!jsonObj.value("class").isUndefined() && jsonObj.value("class").isObject()) { - QJsonObject classObj = jsonObj["class"].toObject(); - if (classObj["hidden"].toBool()) + auto clazz = jsonObj["class"]; + if (clazz.isObject()) { + if (clazz["hidden"].isBool() && clazz["hidden"].asBool()) classValue = WindowClass_Hidden; } appDesc->m_windowClassValue = classValue; @@ -261,20 +275,20 @@ std::unique_ptr ApplicationDescription::fromJsonString(c appDesc->m_icon = tempPath; } } - appDesc->m_useNativeScroll = jsonObj.contains("useNativeScroll") && jsonObj["useNativeScroll"].toBool(); + appDesc->m_useNativeScroll = jsonObj["useNativeScroll"].isBool() && jsonObj["useNativeScroll"].asBool(); // Set network stable timeout - if(jsonObj.contains("networkStableTimeout")) { - if (jsonObj["networkStableTimeout"].type() != QJsonValue::Double) - LOG_ERROR(MSGID_TYPE_ERROR, 2, PMLOGKS("APP_ID", appDesc->id().c_str()), - PMLOGKFV("DATA_TYPE", "%d", jsonObj["networkStableTimeout"].type()), "Invaild QJsonValue type"); - else - appDesc->m_networkStableTimeout = jsonObj["networkStableTimeout"].toDouble(); - } + auto networkStableTimeout = jsonObj["networkStableTimeout"]; + if (!networkStableTimeout.isDouble()) + LOG_ERROR(MSGID_TYPE_ERROR, 2, PMLOGKS("APP_ID", appDesc->id().c_str()), + PMLOGKFV("DATA_TYPE", "%d", networkStableTimeout.type()), "Invaild JsonValue type"); + else + appDesc->m_networkStableTimeout = networkStableTimeout.asDouble(); // Set delay millisecond for launch optimization - if (jsonObj.contains("delayMsForLaunchOptimization")) { - int delayMs = jsonObj["delayMsForLaunchOptimization"].toInt(); + auto delayMsForLaunchOptimization = jsonObj["delayMsForLaunchOptimization"]; + if (delayMsForLaunchOptimization.isInt()) { + int delayMs = delayMsForLaunchOptimization.asInt(); appDesc->m_delayMsForLanchOptimization = (delayMs >= 0) ? delayMs : 0; } diff --git a/src/core/ApplicationDescription.h b/src/core/ApplicationDescription.h index f87a0368..097d04a4 100644 --- a/src/core/ApplicationDescription.h +++ b/src/core/ApplicationDescription.h @@ -18,12 +18,9 @@ #define APPLICATIONDESCRIPTION_H #include - -#include -#include -#include -#include -#include +#include +#include +#include class ApplicationDescription { public: @@ -97,7 +94,7 @@ class ApplicationDescription { return m_enyoBundleVersion; } - const QStringList& supportedEnyoBundleVersions() const + const std::set& supportedEnyoBundleVersions() const { return m_supportedEnyoBundleVersions; } @@ -149,7 +146,7 @@ class ApplicationDescription { bool allowAudioCapture() const { return m_allowAudioCapture; } //Key code is changed only for facebooklogin WebApp - const QMap>& keyFilterTable() const + const std::unordered_map>& keyFilterTable() const { return m_keyFilterTable; } @@ -165,12 +162,12 @@ class ApplicationDescription { } bool allowAnonymous; - QMap layers; + std::unordered_map layers; }; struct WindowClientInfo { - QString layer; - QString hint; + std::string layer; + std::string hint; }; struct WindowGroupInfo { @@ -179,7 +176,7 @@ class ApplicationDescription { { } - QString name; + std::string name; bool isOwner; }; @@ -187,6 +184,8 @@ class ApplicationDescription { const WindowOwnerInfo getWindowOwnerInfo(); const WindowClientInfo getWindowClientInfo(); + int surfaceId() { return m_surfaceId; } + private: std::string m_id; std::string m_title; @@ -206,7 +205,7 @@ class ApplicationDescription { std::string m_containerJS; std::string m_containerCSS; std::string m_enyoBundleVersion; - QStringList m_supportedEnyoBundleVersions; + std::set m_supportedEnyoBundleVersions; std::string m_enyoVersion; std::string m_version; std::string m_v8SnapshotPath; @@ -216,7 +215,7 @@ class ApplicationDescription { bool m_backHistoryAPIDisabled; int m_widthOverride; int m_heightOverride; - QMap> m_keyFilterTable; + std::unordered_map> m_keyFilterTable; std::string m_groupWindowDesc; bool m_doNotTrack; bool m_handleExitKey; @@ -230,6 +229,7 @@ class ApplicationDescription { double m_networkStableTimeout; bool m_disallowScrollingInMainFrame; int m_delayMsForLanchOptimization; + int m_surfaceId; }; #endif /* APPLICATIONDESCRIPTION_H */ diff --git a/src/core/ContainerAppManager.cpp b/src/core/ContainerAppManager.cpp index c2cad24b..9dd52861 100644 --- a/src/core/ContainerAppManager.cpp +++ b/src/core/ContainerAppManager.cpp @@ -16,10 +16,8 @@ #include "ContainerAppManager.h" -#include -#include - #include "ApplicationDescription.h" +#include "JsonHelper.h" #include "LogManager.h" #include "WebAppBase.h" #include "WebAppFactoryManager.h" @@ -28,7 +26,7 @@ #include "WebPageBase.h" #include "WindowTypes.h" -static QString s_containerAppId = "com.webos.app.container"; +static std::string s_containerAppId = "com.webos.app.container"; static int kContainerAppLaunchDuration = 300; static int kContainerAppLaunchCpuThresh = 500; // 100 = 10% static int kContainerAppLaunchTryMax = 20; @@ -62,26 +60,24 @@ ContainerAppManager::~ContainerAppManager() void ContainerAppManager::loadContainerInfo() { - QFile file; - file.setFileName("/var/luna/preferences/container.json"); - if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QString str; - str = file.readAll(); - file.close(); - - QJsonDocument containerDoc = QJsonDocument::fromJson(str.toUtf8()); - if(!containerDoc.isNull()) { - QJsonObject containerSettings = containerDoc.object(); - if(!containerSettings["appId"].isUndefined()) - s_containerAppId = containerSettings["appId"].toString(); - if(!containerSettings["relaunchDelay"].isUndefined()) - kContainerAppLaunchDuration = containerSettings["relaunchDelay"].toDouble(); - if(!containerSettings["relaunchCpuThresh"].isUndefined()) - kContainerAppLaunchCpuThresh = containerSettings["relaunchCpuThresh"].toDouble(); + Json::Value containerSettings; + if (readJsonFromFile("/var/luna/preferences/container.json", containerSettings)) { + if(containerSettings.isObject()) { + auto appId = containerSettings["appId"]; + if(appId.isString()) + s_containerAppId = appId.asString(); + + auto relaunchDelay = containerSettings["relaunchDelay"]; + if(relaunchDelay.isDouble()) + kContainerAppLaunchDuration = relaunchDelay.asDouble(); + + auto relaunchCpuThresh = containerSettings["relaunchCpuThresh"]; + if(relaunchCpuThresh.isDouble()) + kContainerAppLaunchCpuThresh = relaunchCpuThresh.asDouble(); } } - LOG_DEBUG("Container settings: app_id=%s, delay=%d, thresh=%d", qPrintable(s_containerAppId), kContainerAppLaunchDuration, kContainerAppLaunchCpuThresh); + LOG_DEBUG("Container settings: app_id=%s, delay=%d, thresh=%d", s_containerAppId.c_str(), kContainerAppLaunchDuration, kContainerAppLaunchCpuThresh); } void ContainerAppManager::startContainerTimer() @@ -97,7 +93,7 @@ void ContainerAppManager::stopContainerTimer() m_containerAppLaunchTimer.stop(); } -QString& ContainerAppManager::getContainerAppId() +std::string& ContainerAppManager::getContainerAppId() { return s_containerAppId; } @@ -140,7 +136,7 @@ WebAppBase* ContainerAppManager::launchContainerAppInternal(const std::string& i return nullptr; std::string url = desc->entryPoint(); - WebPageBase* page = WebAppFactoryManager::instance()->createWebPage(WT_CARD, QUrl(url.c_str()), desc, desc->subType().c_str()); + WebPageBase* page = WebAppFactoryManager::instance()->createWebPage(WT_CARD, Url(url), desc, desc->subType().c_str()); // Turning off inline caching on container app, too. if (m_useContainerAppOptimization) @@ -149,7 +145,7 @@ WebAppBase* ContainerAppManager::launchContainerAppInternal(const std::string& i app->setAppDescription(desc); app->setHiddenWindow(true); - app->setInstanceId(QString::fromStdString(instanceId)); + app->setInstanceId(instanceId); app->attach(page); page->load(); WebAppManager::instance()->webPageAdded(page); @@ -160,7 +156,7 @@ WebAppBase* ContainerAppManager::launchContainerAppInternal(const std::string& i WebAppManager::instance()->insertAppIntoList(m_containerApp); #endif - LOG_INFO(MSGID_CONTAINER_APP_RELAUNCHED, 2, PMLOGKS("APP_ID", qPrintable(QString::fromStdString(desc->id()))), PMLOGKFV("PID", "%d", page->getWebProcessPID()), ""); + LOG_INFO(MSGID_CONTAINER_APP_RELAUNCHED, 2, PMLOGKS("APP_ID", desc->id().c_str()), PMLOGKFV("PID", "%d", page->getWebProcessPID()), ""); return m_containerApp; } diff --git a/src/core/ContainerAppManager.h b/src/core/ContainerAppManager.h index 258ec51a..5aed1898 100644 --- a/src/core/ContainerAppManager.h +++ b/src/core/ContainerAppManager.h @@ -17,11 +17,10 @@ #ifndef CONTAINERAPPMANAGER_H #define CONTAINERAPPMANAGER_H -#include "Timer.h" - -#include #include +#include "Timer.h" + class WebAppBase; class ContainerAppManager { @@ -31,7 +30,7 @@ class ContainerAppManager { void startContainerTimer(); void stopContainerTimer(); - QString& getContainerAppId(); + std::string& getContainerAppId(); WebAppBase* launchContainerApp(const std::string& appDesc, const std::string& instanceId, int& errorCode); void closeContainerApp(); void reloadContainerApp(); diff --git a/src/core/DeviceInfo.cpp b/src/core/DeviceInfo.cpp index 5da9573e..86c6efa0 100644 --- a/src/core/DeviceInfo.cpp +++ b/src/core/DeviceInfo.cpp @@ -16,59 +16,61 @@ #include "DeviceInfo.h" +#include "StringUtils.h" + bool DeviceInfo::getDisplayWidth(int &value) { bool ret = false; - QString valueStr; + std::string valueStr; ret = getDeviceInfo("DisplayWidth", valueStr); - value = valueStr.toInt(); + value = stringTo(valueStr); return ret; } void DeviceInfo::setDisplayWidth(int value) { - m_deviceInfo.insert("DisplayWidth", QString::number(value)); + m_deviceInfo.emplace("DisplayWidth", std::to_string(value)); } bool DeviceInfo::getDisplayHeight(int &value) { bool ret = false; - QString valueStr; + std::string valueStr; ret = getDeviceInfo("DisplayHeight", valueStr); - value = valueStr.toInt(); + value = stringTo(valueStr); return ret; } void DeviceInfo::setDisplayHeight(int value) { - m_deviceInfo.insert("DisplayHeight", QString::number(value)); + m_deviceInfo.emplace("DisplayHeight", std::to_string(value)); } -bool DeviceInfo::getSystemLanguage(QString &value) +bool DeviceInfo::getSystemLanguage(std::string &value) { return getDeviceInfo("SystemLanguage", value); } -void DeviceInfo::setSystemLanguage(QString value) +void DeviceInfo::setSystemLanguage(const std::string &value) { - m_deviceInfo.insert("SystemLanguage", value); + m_deviceInfo.emplace("SystemLanguage", value); } -bool DeviceInfo::getDeviceInfo(QString name, QString &value) +bool DeviceInfo::getDeviceInfo(const std::string& name, std::string& value) { - if (m_deviceInfo.contains(name)) { - value = m_deviceInfo.value(name); + auto v = m_deviceInfo.find(name); + if (v != m_deviceInfo.end()) { + value = v->second; return true; } - return false; } -void DeviceInfo::setDeviceInfo(QString name, QString value) +void DeviceInfo::setDeviceInfo(const std::string& name, const std::string& value) { - m_deviceInfo.insert(name, value); + m_deviceInfo.emplace(name, value); } diff --git a/src/core/DeviceInfo.h b/src/core/DeviceInfo.h index c2b8d178..358fb980 100644 --- a/src/core/DeviceInfo.h +++ b/src/core/DeviceInfo.h @@ -17,8 +17,8 @@ #ifndef DEVICEINFO_H #define DEVICEINFO_H -#include -#include +#include +#include class DeviceInfo { public: @@ -30,14 +30,14 @@ class DeviceInfo { virtual bool getDisplayHeight(int& value); virtual void setDisplayHeight(int value); - virtual bool getSystemLanguage(QString& value); - virtual void setSystemLanguage(QString value); + virtual bool getSystemLanguage(std::string& value); + virtual void setSystemLanguage(const std::string& value); - virtual bool getDeviceInfo(QString name, QString& value); - virtual void setDeviceInfo(QString name, QString value); + virtual bool getDeviceInfo(const std::string& name, std::string& value); + virtual void setDeviceInfo(const std::string& name, const std::string& value); private: - QMap m_deviceInfo; + std::unordered_map m_deviceInfo; }; #endif /* DEVICEINFO_H */ diff --git a/src/core/PalmSystemBase.cpp b/src/core/PalmSystemBase.cpp index fd463f56..c698f346 100644 --- a/src/core/PalmSystemBase.cpp +++ b/src/core/PalmSystemBase.cpp @@ -15,63 +15,57 @@ // SPDX-License-Identifier: Apache-2.0 #include "PalmSystemBase.h" -#include "WebAppManager.h" -#include -#include +#include +#include + +#include "JsonHelper.h" +#include "LogManager.h" +#include "WebAppManager.h" +#include "WebAppManagerUtils.h" -QString PalmSystemBase::getDeviceInfo(QString name) +std::string PalmSystemBase::getDeviceInfo(const std::string& name) { - QString value; + std::string value; WebAppManager::instance()->getDeviceInfo(name, value); return value; } -QVariant PalmSystemBase::getResource(QVariant a, QVariant b) +std::string PalmSystemBase::country() const { - QFile f(a.toString()); - if (!f.open(QIODevice::ReadOnly)) - return QVariant(); - - QByteArray data = f.readAll(); - - return QVariant(data.constData()); -} - -QString PalmSystemBase::country() const -{ - QString localcountry; - QString smartServiceCountry; - QString country; + std::string localcountry; + std::string smartServiceCountry; WebAppManager::instance()->getDeviceInfo("LocalCountry", localcountry); WebAppManager::instance()->getDeviceInfo("SmartServiceCountry", smartServiceCountry); - country = QString("{ \"country\": \"%1\", \"smartServiceCountry\": \"%2\" }"); - country = country.arg(localcountry).arg(smartServiceCountry); - - return country; + std::string json; + Json::Value obj(Json::objectValue); + obj["country"] = localcountry; + obj["smartServiceCountry"] = smartServiceCountry; + dumpJsonToString(obj, json); + return json; } -QString PalmSystemBase::locale() const +std::string PalmSystemBase::locale() const { - QString systemlocale; + std::string systemlocale; WebAppManager::instance()->getSystemLanguage(systemlocale); return systemlocale; } -QString PalmSystemBase::localeRegion() const +std::string PalmSystemBase::localeRegion() const { - return QString("US"); + return "US"; } -QString PalmSystemBase::phoneRegion() const +std::string PalmSystemBase::phoneRegion() const { - return QString(""); + return {}; } -void PalmSystemBase::setContainerAppReady(const QString& appId) +void PalmSystemBase::setContainerAppReady(const std::string& appId) { if (appId == WebAppManager::instance()->getContainerAppId()) WebAppManager::instance()->setContainerAppReady(true); diff --git a/src/core/PalmSystemBase.h b/src/core/PalmSystemBase.h index db25f2cb..f79f9ee2 100644 --- a/src/core/PalmSystemBase.h +++ b/src/core/PalmSystemBase.h @@ -17,8 +17,7 @@ #ifndef PALMSYSTEMBASE_H_ #define PALMSYSTEMBASE_H_ -#include -#include +#include class PalmSystemBase { public: @@ -26,12 +25,11 @@ class PalmSystemBase { virtual ~PalmSystemBase() {} protected: - virtual QString getDeviceInfo(QString name); - virtual QVariant getResource(QVariant a, QVariant b); - virtual QString country() const; - virtual QString locale() const; - virtual QString localeRegion() const; - virtual QString phoneRegion() const; - virtual void setContainerAppReady(const QString& appId); + virtual std::string getDeviceInfo(const std::string& name); + virtual std::string country() const; + virtual std::string locale() const; + virtual std::string localeRegion() const; + virtual std::string phoneRegion() const; + virtual void setContainerAppReady(const std::string& appId); }; #endif diff --git a/src/core/PlugInService.cpp b/src/core/PlugInService.cpp index 122ea788..44bcf6bf 100644 --- a/src/core/PlugInService.cpp +++ b/src/core/PlugInService.cpp @@ -18,12 +18,12 @@ #include "WebAppBase.h" #include "WebAppManager.h" -WebAppBase* PlugInService::findAppById(QString appId) +WebAppBase* PlugInService::findAppById(const std::string& appId) { return WebAppManager::instance()->findAppById(appId); } -QString PlugInService::getActiveAppId() +std::string PlugInService::getActiveAppId() { return WebAppManager::instance()->getActiveAppId(); } diff --git a/src/core/PlugInService.h b/src/core/PlugInService.h index 4852a8ce..0812a0e5 100644 --- a/src/core/PlugInService.h +++ b/src/core/PlugInService.h @@ -17,7 +17,7 @@ #ifndef PLUGINSERVICE_H #define PLUGINSERVICE_H -#include +#include #include class WebAppBase; @@ -28,8 +28,8 @@ class PlugInService { virtual void startService() = 0; protected: - WebAppBase* findAppById(QString appId); - QString getActiveAppId(); + WebAppBase* findAppById(const std::string& appId); + std::string getActiveAppId(); std::list runningApps(); }; diff --git a/src/core/ServiceSender.h b/src/core/ServiceSender.h index 799db35b..6a0c242c 100644 --- a/src/core/ServiceSender.h +++ b/src/core/ServiceSender.h @@ -25,11 +25,12 @@ class ServiceSender { virtual ~ServiceSender() {} virtual void requestActivity(WebAppBase* app) = 0; #ifndef PRELOADMANAGER_ENABLED - virtual void launchContainerApp(const QString& id) = 0; + virtual void launchContainerApp(const std::string& id) = 0; #endif virtual void postlistRunningApps(std::vector& apps) = 0; - virtual void postWebProcessCreated(const QString& appId, uint32_t pid) = 0; - virtual void serviceCall(const QString& url, const QString& payload, const QString& appId) = 0; + virtual void postWebProcessCreated(const std::string& appId, uint32_t pid) = 0; + virtual void serviceCall(const std::string& url, const std::string& payload, + const std::string& appId) = 0; virtual void closeApp(const std::string& id) = 0; }; diff --git a/src/core/WebAppBase.cpp b/src/core/WebAppBase.cpp index c0c3ca76..ac67ea86 100644 --- a/src/core/WebAppBase.cpp +++ b/src/core/WebAppBase.cpp @@ -16,9 +16,7 @@ #include "WebAppBase.h" -#include -#include - +#include "JsonHelper.h" #include "ApplicationDescription.h" #include "LogManager.h" #include "WebAppManagerConfig.h" @@ -41,7 +39,7 @@ class WebAppBasePrivate { delete m_page; - LOG_DEBUG("Delete webapp base for App ID %s", qPrintable(m_appId)); + LOG_DEBUG("Delete webapp base for App ID %s", m_appId.c_str()); } void createActivity() @@ -57,10 +55,10 @@ class WebAppBasePrivate WebPageBase* m_page; bool m_keepAlive; bool m_forceClose; - QString m_launchingAppId; - QString m_appId; - QString m_instanceId; - QString m_url; + std::string m_launchingAppId; + std::string m_appId; + std::string m_instanceId; + std::string m_url; std::shared_ptr m_appDesc; }; @@ -78,7 +76,7 @@ WebAppBase::WebAppBase() WebAppBase::~WebAppBase() { - LOG_INFO(MSGID_WEBAPP_CLOSED, 2, PMLOGKS("APP_ID", appId().isEmpty() ? "unknown" : qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); + LOG_INFO(MSGID_WEBAPP_CLOSED, 2, PMLOGKS("APP_ID", appId().empty() ? "unknown" : appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); cleanResources(); delete d; } @@ -143,37 +141,37 @@ bool WebAppBase::isWindowed() const return false; } -void WebAppBase::setAppId(const QString& appId) +void WebAppBase::setAppId(const std::string& appId) { d->m_appId = appId; } -void WebAppBase::setLaunchingAppId(const QString& appId) +void WebAppBase::setLaunchingAppId(const std::string& appId) { d->m_launchingAppId = appId; } -QString WebAppBase::appId() const +std::string WebAppBase::appId() const { return d->m_appId; } -void WebAppBase::setInstanceId(const QString& instanceId) +void WebAppBase::setInstanceId(const std::string& instanceId) { d->m_instanceId = instanceId; } -QString WebAppBase::instanceId() const +std::string WebAppBase::instanceId() const { return d->m_instanceId; } -QString WebAppBase::url() const +std::string WebAppBase::url() const { return d->m_url; } -QString WebAppBase::launchingAppId() const +std::string WebAppBase::launchingAppId() const { return d->m_launchingAppId; } @@ -201,7 +199,7 @@ int WebAppBase::currentUiHeight() return WebAppManager::instance()->currentUiHeight(); } -void WebAppBase::setActiveAppId(QString id) +void WebAppBase::setActiveAppId(const std::string& id) { WebAppManager::instance()->setActiveAppId(id); } @@ -218,7 +216,7 @@ void WebAppBase::closeAppInternal() void WebAppBase::attach(WebPageBase* page) { - // connect to the signals of the WebBridge + // start observing the WebPage // parse up the ApplicationDescription if (d->m_page) detach(); @@ -227,9 +225,6 @@ void WebAppBase::attach(WebPageBase* page) d->m_page->createPalmSystem(this); observe(d->m_page); - connect(d->m_page, SIGNAL(webPageUrlChanged()), this, SLOT(webPageUrlChangedSlot())); - connect(d->m_page, SIGNAL(webPageLoadFinished()), this, SLOT(webPageLoadFinishedSlot())); - connect(d->m_page, SIGNAL(webPageLoadFailed(int)), this, SLOT(webPageLoadFailedSlot(int))); d->createActivity(); } @@ -237,19 +232,18 @@ WebPageBase* WebAppBase::detach(void) { WebPageBase* p = d->m_page; - disconnect(d->m_page, 0, this, 0); unobserve(d->m_page); d->m_page = 0; return p; } -void WebAppBase::relaunch(const QString& args, const QString& launchingAppId) +void WebAppBase::relaunch(const std::string& args, const std::string& launchingAppId) { LOG_INFO(MSGID_APP_RELAUNCH, 3, - PMLOGKS("APP_ID", qPrintable(appId())), + PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), - PMLOGKS("LAUNCHING_APP_ID", qPrintable(launchingAppId)), ""); + PMLOGKS("LAUNCHING_APP_ID", launchingAppId.c_str()), ""); if (getHiddenWindow()) { setHiddenWindow(false); @@ -269,7 +263,7 @@ void WebAppBase::relaunch(const QString& args, const QString& launchingAppId) if (getCrashState()) { LOG_INFO(MSGID_APP_RELAUNCH, 2, - PMLOGKS("APP_ID", qPrintable(appId())), + PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "Crashed in Background; Reluad Default page"); page()->reloadDefaultPage(); @@ -281,7 +275,7 @@ void WebAppBase::relaunch(const QString& args, const QString& launchingAppId) // try to do relaunch!! if(!(page->relaunch(args, launchingAppId))) { LOG_INFO(MSGID_APP_RELAUNCH, 2, - PMLOGKS("APP_ID", qPrintable(appId())), + PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page->getWebProcessPID()), "Can't handle Relaunch now, backup the args and handle it after page loading finished"); // if relaunch hasn't beeh executed, then set and wait till currnt page loading is finished @@ -291,18 +285,18 @@ void WebAppBase::relaunch(const QString& args, const QString& launchingAppId) } if(d->m_appDesc && !(d->m_appDesc->handlesRelaunch())) { - LOG_DEBUG("[%s] m_appDesc->handlesRelaunch : false, call raise() to make it full screen", qPrintable(appId())); + LOG_DEBUG("[%s] m_appDesc->handlesRelaunch : false, call raise() to make it full screen", appId().c_str()); raise(); } else { LOG_INFO(MSGID_APP_RELAUNCH, 2, - PMLOGKS("APP_ID", qPrintable(appId())), + PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page->getWebProcessPID()), "handlesRelanch : true; Do not call raise()"); } } } -void WebAppBase::webPageLoadFinishedSlot() +void WebAppBase::webPageLoadFinished() { doPendingRelaunch(); } @@ -311,7 +305,7 @@ void WebAppBase::doPendingRelaunch() { if(m_inProgressRelaunchLaunchingAppId.size() || m_inProgressRelaunchParams.size()) { LOG_INFO(MSGID_APP_RELAUNCH, 2, - PMLOGKS("APP_ID", qPrintable(appId())), + PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "Page loading --> done; Do pending Relaunch"); relaunch(m_inProgressRelaunchParams, m_inProgressRelaunchLaunchingAppId); @@ -321,10 +315,10 @@ void WebAppBase::doPendingRelaunch() } } -void WebAppBase::webPageClosePageRequestedSlot() +void WebAppBase::webPageClosePageRequested() { - LOG_INFO(MSGID_WINDOW_CLOSED_JS, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); - WebAppManager::instance()->closeApp(appId().toStdString()); + LOG_INFO(MSGID_WINDOW_CLOSED_JS, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); + WebAppManager::instance()->closeApp(appId()); } void WebAppBase::stagePreparing() @@ -349,39 +343,34 @@ void WebAppBase::showWindow() setUseAccessibility(WebAppManager::instance()->isAccessibilityEnabled()); } -void WebAppBase::showWindowSlot() -{ - showWindow(); -} - void WebAppBase::setAppDescription(std::shared_ptr appDesc) { d->m_appDesc = appDesc; // set appId here from appDesc - d->m_appId = QString::fromStdString(appDesc->id()); + d->m_appId = appDesc->id(); } -void WebAppBase::setAppProperties(QString properties) +void WebAppBase::setAppProperties(const std::string& properties) { - QJsonDocument doc = QJsonDocument::fromJson(properties.toStdString().c_str()); - QJsonObject obj = doc.object(); + Json::Value obj; + readJsonFromString(properties, obj); - if (obj["keepAlive"].toBool()) + if (obj["keepAlive"].asBool()) setKeepAlive(true); else setKeepAlive(false); - if (obj["launchedHidden"].toBool()) + if (obj["launchedHidden"].asBool()) setHiddenWindow(true); } -void WebAppBase::setPreloadState(QString properties) +void WebAppBase::setPreloadState(const std::string& properties) { - QJsonDocument doc = QJsonDocument::fromJson(properties.toStdString().c_str()); - QJsonObject obj = doc.object(); + Json::Value obj; + readJsonFromString(properties, obj); - std::string preload = obj["preload"].toString().toStdString().c_str(); + std::string preload = obj["preload"].asString(); if (preload == "full") { m_preloadState = FULL_PRELOAD; @@ -392,7 +381,7 @@ void WebAppBase::setPreloadState(QString properties) else if (preload == "minimal") { m_preloadState = MINIMAL_PRELOAD; } - else if (obj["launchedHidden"].toBool()) { + else if (obj["launchedHidden"].asBool()) { m_preloadState = PARTIAL_PRELOAD; } @@ -450,12 +439,7 @@ void WebAppBase::setUiSize(int width, int height) { WebAppManager::instance()->setUiSize(width, height); } -void WebAppBase::webPageUrlChangedSlot() -{ - d->m_url = d->m_page->url().toString(); -} - -void WebAppBase::setPreferredLanguages(QString language) +void WebAppBase::setPreferredLanguages(const std::string& language) { if (!d->m_page) return; @@ -463,7 +447,7 @@ void WebAppBase::setPreferredLanguages(QString language) d->m_page->sendLocaleChangeEvent(language); } -void WebAppBase::handleWebAppMessage(WebAppManager::WebAppMessageType type, const QString& message) +void WebAppBase::handleWebAppMessage(WebAppManager::WebAppMessageType type, const std::string& message) { if (!d->m_page) return; @@ -491,16 +475,33 @@ void WebAppBase::setUseAccessibility(bool enabled) void WebAppBase::executeCloseCallback() { - connect(d->m_page, SIGNAL(closeCallbackExecuted()),this, SLOT(closeWebAppSlot())); - connect(d->m_page, SIGNAL(timeoutExecuteCloseCallback()),this, SLOT(closeWebAppSlot())); - connect(d->m_page, SIGNAL(closingAppProcessDidCrashed()),this, SLOT(closeWebAppSlot())); page()->executeCloseCallback(forceClose()); - LOG_INFO(MSGID_EXECUTE_CLOSECALLBACK, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); + LOG_INFO(MSGID_EXECUTE_CLOSECALLBACK, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); +} + +void WebAppBase::closeCallbackExecuted() +{ + closeWebApp(); +} + +void WebAppBase::timeoutExecuteCloseCallback() +{ + closeWebApp(); +} + +void WebAppBase::closingAppProcessDidCrashed() +{ + closeWebApp(); +} + +void WebAppBase::didDispatchUnload() +{ + closeWebApp(); } -void WebAppBase::closeWebAppSlot() +void WebAppBase::closeWebApp() { - LOG_INFO(MSGID_CLEANRESOURCE_COMPLETED, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "closeCallback/about:blank is DONE"); + LOG_INFO(MSGID_CLEANRESOURCE_COMPLETED, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "closeCallback/about:blank is DONE"); WebAppManager::instance()->removeClosingAppList(appId()); #ifdef PRELOADMANAGER_ENABLED if (appId() == WebAppManager::instance()->getContainerAppId()) @@ -512,19 +513,17 @@ void WebAppBase::closeWebAppSlot() void WebAppBase::dispatchUnload() { - connect(d->m_page, SIGNAL(didDispatchUnload()),this, SLOT(closeWebAppSlot())); - connect(d->m_page, SIGNAL(closingAppProcessDidCrashed()),this, SLOT(closeWebAppSlot())); page()->cleanResources(); } -void WebAppBase::onCursorVisibilityChanged(const QString& jsscript) +void WebAppBase::onCursorVisibilityChanged(const std::string& jsscript) { WebAppManager::instance()->sendEventToAllAppsAndAllFrames(jsscript); } -void WebAppBase::serviceCall(const QString& url, const QString& payload, const QString& appId) +void WebAppBase::serviceCall(const std::string& url, const std::string& payload, const std::string& appId) { - LOG_INFO(MSGID_SERVICE_CALL, 2, PMLOGKS("APP_ID", qPrintable(appId)), PMLOGKS("URL", qPrintable(url)), ""); + LOG_INFO(MSGID_SERVICE_CALL, 2, PMLOGKS("APP_ID", appId.c_str()), PMLOGKS("URL", url.c_str()), ""); WebAppManager::instance()->serviceCall(url, payload, appId); } diff --git a/src/core/WebAppBase.h b/src/core/WebAppBase.h index 99b72bbc..6a9bcf12 100644 --- a/src/core/WebAppBase.h +++ b/src/core/WebAppBase.h @@ -19,20 +19,18 @@ #include -#include -#include - #include "WebAppManager.h" #include "WebPageObserver.h" +namespace Json { +class Value; +} + class ApplicationDescription; class WebAppBasePrivate; class WebPageBase; -class WebAppBase : public QObject, - public WebPageObserver { - - Q_OBJECT +class WebAppBase : public WebPageObserver { public: enum PreloadState { @@ -45,7 +43,7 @@ class WebAppBase : public QObject, WebAppBase(); ~WebAppBase() override; - virtual void init(int width, int height) = 0; + virtual void init(int width, int height, int surface_id) = 0; virtual void attach(WebPageBase*); virtual WebPageBase* detach(); virtual void suspendAppRendering() = 0; @@ -59,21 +57,21 @@ class WebAppBase : public QObject, virtual void onStageDeactivated() = 0; virtual void startLaunchTimer() {} virtual void setHiddenWindow(bool hidden); - virtual void configureWindow(QString& type) = 0; + virtual void configureWindow(const std::string& type) = 0; virtual void setKeepAlive(bool keepAlive); virtual bool isWindowed() const; - virtual void relaunch(const QString& args, const QString& launchingAppId); - virtual void setWindowProperty(const QString& name, const QVariant& value) = 0; + virtual void relaunch(const std::string& args, const std::string& launchingAppId); + virtual void setWindowProperty(const std::string& name, const std::string& value) = 0; virtual void platformBack() = 0; - virtual void setCursor(const QString& cursorArg, int hotspot_x, int hotspot_y) = 0; - virtual void setInputRegion(const QJsonDocument& jsonDoc) = 0; - virtual void setKeyMask(const QJsonDocument& jsonDoc) = 0; + virtual void setCursor(const std::string& cursorArg, int hotspot_x, int hotspot_y) = 0; + virtual void setInputRegion(const Json::Value& jsonDoc) = 0; + virtual void setKeyMask(const Json::Value& jsonDoc) = 0; virtual void hide(bool forcedHide = false) = 0; virtual void focus() = 0; virtual void unfocus() = 0; virtual void setOpacity(float opacity) = 0; virtual void setAppDescription(std::shared_ptr); - virtual void setPreferredLanguages(QString language); + virtual void setPreferredLanguages(const std::string& language); virtual void stagePreparing(); virtual void stageReady(); virtual void raise() = 0; @@ -83,7 +81,7 @@ class WebAppBase : public QObject, virtual void keyboardVisibilityChanged(bool visible, int height); virtual void doClose() = 0; virtual bool isKeyboardVisible() { return false; } - static void onCursorVisibilityChanged(const QString& jsscript); + static void onCursorVisibilityChanged(const std::string& jsscript); bool getCrashState(); void setCrashState(bool state); @@ -94,18 +92,18 @@ class WebAppBase : public QObject, void setForceClose(); bool forceClose(); WebPageBase* page() const; - void handleWebAppMessage(WebAppManager::WebAppMessageType type, const QString& message); - void setAppId(const QString& appId); - void setLaunchingAppId(const QString& appId); - QString appId() const; - QString launchingAppId() const; - void setInstanceId(const QString& instanceId); - QString instanceId() const; - QString url() const; + void handleWebAppMessage(WebAppManager::WebAppMessageType type, const std::string& message); + void setAppId(const std::string& appId); + void setLaunchingAppId(const std::string& appId); + std::string appId() const; + std::string launchingAppId() const; + void setInstanceId(const std::string& instanceId); + std::string instanceId() const; + std::string url() const; ApplicationDescription* getAppDescription() const; - void setAppProperties(QString properties); + void setAppProperties(const std::string& properties); void setNeedReload(bool status) { m_needReload = status; } bool needReload() { return m_needReload; } @@ -118,37 +116,38 @@ class WebAppBase : public QObject, void dispatchUnload(); void setUseAccessibility(bool enabled); - void serviceCall(const QString& url, const QString& payload, const QString& appId); + void serviceCall(const std::string& url, const std::string& payload, const std::string& appId); - void setPreloadState(QString properties); + void setPreloadState(const std::string& properties); void clearPreloadState(); PreloadState preloadState() { return m_preloadState; } bool isClosing() const; bool isCheckLaunchTimeEnabled(); + void closeWebApp(); + + // WebPageObserver + virtual void webPageLoadFinished(); + virtual void webPageClosePageRequested(); + virtual void closeCallbackExecuted(); + virtual void timeoutExecuteCloseCallback(); + virtual void closingAppProcessDidCrashed(); + virtual void didDispatchUnload(); protected: virtual void doAttach() = 0; virtual void showWindow(); void setUiSize(int width, int height); - void setActiveAppId(QString id); + void setActiveAppId(const std::string& id); void forceCloseAppInternal(); void closeAppInternal(); -protected Q_SLOTS: - virtual void webPageUrlChangedSlot(); - virtual void webPageClosePageRequestedSlot(); - virtual void showWindowSlot(); - virtual void webPageLoadFinishedSlot(); - virtual void webPageLoadFailedSlot(int errorCode) = 0; - virtual void closeWebAppSlot(); - protected: PreloadState m_preloadState; bool m_addedToWindowMgr; - QString m_inProgressRelaunchParams; - QString m_inProgressRelaunchLaunchingAppId; + std::string m_inProgressRelaunchParams; + std::string m_inProgressRelaunchLaunchingAppId; float m_scaleFactor; private: diff --git a/src/core/WebAppFactoryInterface.h b/src/core/WebAppFactoryInterface.h index 4e655acf..c29ba529 100644 --- a/src/core/WebAppFactoryInterface.h +++ b/src/core/WebAppFactoryInterface.h @@ -19,23 +19,26 @@ #include -#include -#include +#if defined(HAS_LUNA_SERVICE) #include +#endif #include "ApplicationDescription.h" class WebAppBase; class WebPageBase; +class Url; class WebAppFactoryInterface { public: - virtual WebAppBase* createWebApp(QString winType, std::shared_ptr desc = nullptr) = 0; - virtual WebAppBase* createWebApp(QString winType, WebPageBase* page, std::shared_ptr desc = nullptr) = 0; - virtual WebPageBase* createWebPage(QUrl url, std::shared_ptr desc, QString launchParams = "") = 0; + virtual WebAppBase* createWebApp(const std::string& winType, std::shared_ptr desc = 0) = 0; + virtual WebAppBase* createWebApp(const std::string& winType, WebPageBase* page, std::shared_ptr desc = 0) = 0; + virtual WebPageBase* createWebPage(const Url& url, std::shared_ptr desc, const std::string& launchParams = "") = 0; }; +#if defined(HAS_LUNA_SERVICE) #define WebAppFactoryInterface_iid "org.qt-project.Qt.WebAppFactoryInterface" Q_DECLARE_INTERFACE(WebAppFactoryInterface, WebAppFactoryInterface_iid) +#endif #endif // WEBAPPFACTORYINTERFACE_H diff --git a/src/core/WebAppFactoryManager.cpp b/src/core/WebAppFactoryManager.cpp index 5344af98..c2daa38c 100644 --- a/src/core/WebAppFactoryManager.cpp +++ b/src/core/WebAppFactoryManager.cpp @@ -16,12 +16,6 @@ #include "WebAppFactoryManager.h" -#include -#include -#include -#include - -#include "LogManager.h" #include "WebAppBase.h" #include "WebAppManagerConfig.h" #include "WebAppManager.h" @@ -29,104 +23,52 @@ WebAppFactoryManager* WebAppFactoryManager::m_instance = nullptr; -WebAppFactoryManager* WebAppFactoryManager::instance() -{ - if(!m_instance) { - m_instance = new WebAppFactoryManager(); - } - return m_instance; -} - -WebAppFactoryManager::WebAppFactoryManager() - : m_loadPluggableOnDemand(false) +WebAppFactoryManager::~WebAppFactoryManager() { - WebAppManagerConfig* webAppManagerConfig = WebAppManager::instance()->config(); - - QString factoryEnv = webAppManagerConfig->getWebAppFactoryPluginTypes(); - m_factoryEnv = factoryEnv.split(QLatin1Char(':')); - m_factoryEnv.append(QStringLiteral("default")); - - m_webAppFactoryPluginPath = webAppManagerConfig->getWebAppFactoryPluginPath(); - - if (webAppManagerConfig->isDynamicPluggableLoadEnabled()) - m_loadPluggableOnDemand = true; - - if (!m_loadPluggableOnDemand) - loadPluggable(); } -WebAppFactoryInterface* WebAppFactoryManager::getPluggable(QString appType) +WebAppFactoryInterface* WebAppFactoryManager::getInterfaceInstance(const std::string& appType) { - QMap::iterator iter = m_interfaces.find(appType); + auto iter = m_interfaces.find(appType); if (iter != m_interfaces.end()) - return iter.value(); + return iter->second; - return loadPluggable(appType); -} - -WebAppFactoryInterface* WebAppFactoryManager::loadPluggable(QString appType) -{ - if (!appType.isEmpty() && !m_factoryEnv.contains(appType)) - return nullptr; - - WebAppFactoryInterface* interface; - QDir pluginsDir(m_webAppFactoryPluginPath); - Q_FOREACH (QString fileName, pluginsDir.entryList(QDir::Files)) { - QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName)); - QString key = pluginLoader.metaData().value("MetaData").toObject().value("Keys").toArray().at(0).toString(); - - if (key.contains(appType) || !m_loadPluggableOnDemand) { - QObject *plugin = pluginLoader.instance(); - - if (plugin) { - interface = qobject_cast(plugin); - if (interface) - m_interfaces.insert(key, interface); - if (!appType.isEmpty()) - return interface; - } else { - LOG_WARNING(MSGID_PLUGIN_LOAD_FAIL, 1, PMLOGKS("ERROR", pluginLoader.errorString().toStdString().c_str()), ""); - if (pluginLoader.isLoaded()) - pluginLoader.unload(); - if (!appType.isEmpty()) - return nullptr; - } - } - } - return nullptr; + return loadInterfaceInstance(appType); } -WebAppBase* WebAppFactoryManager::createWebApp(QString winType, std::shared_ptr desc, QString appType) +WebAppBase* WebAppFactoryManager::createWebApp(const std::string& winType, std::shared_ptr desc, + const std::string& appType) { - WebAppFactoryInterface* interface = getPluggable(appType); + WebAppFactoryInterface* interface = getInterfaceInstance(appType); if (interface) return interface->createWebApp(winType, desc); return nullptr; } -WebAppBase* WebAppFactoryManager::createWebApp(QString winType, WebPageBase* page, std::shared_ptr desc, QString appType) +WebAppBase* WebAppFactoryManager::createWebApp(const std::string& winType, WebPageBase* page, + std::shared_ptr desc, const std::string& appType) { - WebAppFactoryInterface* interface = getPluggable(appType); + WebAppFactoryInterface* interface = getInterfaceInstance(appType); if (interface) return interface->createWebApp(winType, page, desc); return nullptr; } -WebPageBase* WebAppFactoryManager::createWebPage(QString winType, QUrl url, std::shared_ptr desc, QString appType, QString launchParams) +WebPageBase* WebAppFactoryManager::createWebPage(const std::string& winType, const Url& url, std::shared_ptr desc, + const std::string& appType, const std::string& launchParams) { WebPageBase *page = nullptr; - WebAppFactoryInterface* interface = getPluggable(appType); + WebAppFactoryInterface* interface = getInterfaceInstance(appType); if (interface) { page = interface->createWebPage(url, desc, launchParams); } else { - interface = m_interfaces.value("default"); - if (interface) { - // use default factory if cannot find appType. - page = interface->createWebPage(url, desc, launchParams); - } + // use default factory if cannot find appType. + auto it = m_interfaces.find(kDefaultAppType); + if (it != m_interfaces.end()) + page = it->second->createWebPage(url, desc, launchParams); } if (page) page->init(); diff --git a/src/core/WebAppFactoryManager.h b/src/core/WebAppFactoryManager.h index 8137dd48..e7bd78bb 100644 --- a/src/core/WebAppFactoryManager.h +++ b/src/core/WebAppFactoryManager.h @@ -18,28 +18,33 @@ #define WEBAPPFACTORYMANAGER_H #include - -#include -#include +#include +#include #include "WebAppFactoryInterface.h" +#define kDefaultAppType "default" + class WebAppFactoryManager { public: static WebAppFactoryManager* instance(); - WebAppBase* createWebApp(QString winType, std::shared_ptr desc = nullptr, QString appType = ""); - WebAppBase* createWebApp(QString winType, WebPageBase* page, std::shared_ptr desc = nullptr, QString appType = ""); - WebPageBase* createWebPage(QString winType, QUrl url, std::shared_ptr desc, QString appType = "", QString launchParams = ""); - WebAppFactoryInterface* getPluggable(QString appType); - WebAppFactoryInterface* loadPluggable(QString appType = ""); + virtual ~WebAppFactoryManager(); + + WebAppBase* createWebApp(const std::string& winType, std::shared_ptr desc = 0, + const std::string& appType = ""); + WebAppBase* createWebApp(const std::string& winType, WebPageBase* page, std::shared_ptr desc = 0, + const std::string& appType = ""); + WebPageBase* createWebPage(const std::string& winType, const Url& url, std::shared_ptr desc, + const std::string& appType = "", const std::string& launchParams = ""); + WebAppFactoryInterface* getInterfaceInstance(const std::string& appType); + +protected: + WebAppFactoryManager() {} + virtual WebAppFactoryInterface* loadInterfaceInstance(const std::string& appType) = 0; + std::unordered_map m_interfaces; private: static WebAppFactoryManager* m_instance; - WebAppFactoryManager(); - QMap m_interfaces; - QString m_webAppFactoryPluginPath; - QStringList m_factoryEnv; - bool m_loadPluggableOnDemand; }; #endif /* WEBAPPFACTORY_H */ diff --git a/src/core/WebAppManager.cpp b/src/core/WebAppManager.cpp index 8088c579..46621a39 100644 --- a/src/core/WebAppManager.cpp +++ b/src/core/WebAppManager.cpp @@ -21,15 +21,15 @@ #include #include -#include - #include "ApplicationDescription.h" #include "ContainerAppManager.h" #include "DeviceInfo.h" +#include "JsonHelper.h" #include "LogManager.h" #include "NetworkStatusManager.h" #include "PlatformModuleFactory.h" #include "ServiceSender.h" +#include "StringUtils.h" #include "WebAppBase.h" #include "WebAppFactoryManager.h" #include "WebAppManagerConfig.h" @@ -76,7 +76,7 @@ void WebAppManager::notifyMemoryPressure(webos::WebViewBase::MemoryPressureLevel else { LOG_DEBUG("Skipping memory pressure handler for" " appId(%s) isActivated(%d) isPreload(%d) Level(%d)", - qPrintable(app->appId()), app->isActivated(), + app->appId().c_str(), app->isActivated(), app->page()->isPreload(), level); } } @@ -137,20 +137,49 @@ int WebAppManager::currentUiHeight() return height; } -bool WebAppManager::getSystemLanguage(QString &value) -{ - if (!m_deviceInfo) return false; - return m_deviceInfo->getSystemLanguage(value); -} - -bool WebAppManager::getDeviceInfo(QString name, QString &value) -{ - if (!m_deviceInfo) return false; - return m_deviceInfo->getDeviceInfo(name, value); +static void buildAppJsTriggers(std::string &eventJS, std::string &versionJS, + const ApplicationDescription *app, + const std::string &launchDetail) +{ + using std::string; + using std::stringstream; + + string detail = launchDetail.empty() ? "{}" : launchDetail; + string title = app->title(); + string folderPath = app->folderPath(); + string containerCSS = app->containerCSS(); + string containerJS = app->containerJS(); + + replaceSubstrings(detail, "'", "\\'"); + replaceSubstrings(title, "'", "\\'"); + replaceSubstrings(folderPath, "'", "\\'"); + replaceSubstrings(containerCSS, "'", "\\'"); + replaceSubstrings(containerJS, "'", "\\'"); + + stringstream ejs; + ejs << "setTimeout(function () {" + << " var launchEvent=new CustomEvent('webOSContainer', { detail: " << detail << " });" + << " launchEvent.containerName='" << title << "';" + << " launchEvent.containerDirectory='" << folderPath << "';" + << " launchEvent.containerStyle='" << containerCSS << "';" + << " launchEvent.containerScript='" << containerJS << "';" + << " document.dispatchEvent(launchEvent);" + << "}, 1);"; + eventJS = ejs.str(); + + + string version = app->enyoBundleVersion(); + if (!version.empty()) { + stringstream vjs; + vjs << "if (container.setVersion != null) {" + << " container.setVersion('" << version << "');" + << "}"; + versionJS = vjs.str(); + } } -void WebAppManager::onLaunchContainerBasedApp(const std::string& url, QString& winType, - std::shared_ptr appDesc, +void WebAppManager::onLaunchContainerBasedApp(const std::string& url, const std::string& winType, + const std::shared_ptr appDesc, const std::string& args, const std::string& launchingAppId) { if (!m_containerAppManager) @@ -160,7 +189,7 @@ void WebAppManager::onLaunchContainerBasedApp(const std::string& url, QString& w WebAppBase *app = m_containerAppManager->getContainerApp(); WebPageBase *page = app->page(); - LOG_DEBUG("[%s] WebAppManager::onLaunchContainerBasedApp(); ", qPrintable(QString::fromStdString(appDesc->id()))); + LOG_DEBUG("[%s] WebAppManager::onLaunchContainerBasedApp(); ", appDesc->id().c_str()); app->setHiddenWindow(false); page->resetStateToMarkNextPaintForContainer(); @@ -172,19 +201,19 @@ void WebAppManager::onLaunchContainerBasedApp(const std::string& url, QString& w if (m_webAppManagerConfig->isUseSystemAppOptimization()) page->setUseSystemAppOptimization(true); - page->setAppId(QString::fromStdString(appDesc->id())); + page->setAppId(appDesc->id()); page->updateDatabaseIdentifier(); if (winType == WT_FLOATING) page->setEnableBackgroundRun(appDesc->isEnableBackgroundRun()); - page->replaceBaseUrl(QUrl(url.c_str())); - page->setDefaultUrl(QUrl(url.c_str())); + page->replaceBaseUrl(url); + page->setDefaultUrl(url); app->setAppDescription(appDesc); - app->setAppProperties(QString::fromStdString(args)); - app->setPreloadState(QString::fromStdString(args)); + app->setAppProperties(args); + app->setPreloadState(args); - app->setLaunchingAppId(QString::fromStdString(launchingAppId)); + app->setLaunchingAppId(launchingAppId); if (m_webAppManagerConfig->isCheckLaunchTimeEnabled()) app->startLaunchTimer(); @@ -192,51 +221,28 @@ void WebAppManager::onLaunchContainerBasedApp(const std::string& url, QString& w appId = appDesc->id(); page->setApplicationDescription(appDesc); - page->setLaunchParams(args.c_str()); + page->setLaunchParams(args); app->setWasContainerApp(true); - QString launchDetail(args.c_str()); app->configureWindow(winType); page->updatePageSettings(); page->reloadExtensionData(); //repost web process status to QoSM - postWebProcessCreated(appId.c_str(), getWebProcessId(appId.c_str())); - - QString eventJS = QStringLiteral( - "setTimeout(function () {" - " var launchEvent=new CustomEvent('webOSContainer', { detail: %1 });" - " launchEvent.containerName='%2';" - " launchEvent.containerDirectory='%3';" - " launchEvent.containerStyle='%4';" - " launchEvent.containerScript='%5';" - " document.dispatchEvent(launchEvent);" - "}, 1);" - ); - - page->evaluateJavaScript(eventJS - .arg(launchDetail.size() ? launchDetail.replace(QChar('\''), QString("\\'")) : "{}") - .arg(QString::fromStdString(appDesc->title()).replace(QChar('\''), QString("\\'"))) - .arg(QString::fromStdString(appDesc->folderPath()).replace(QChar('\''), QString("\\'"))) - .arg(QString::fromStdString(appDesc->containerCSS()).replace(QChar('\''), QString("\\'"))) - .arg(QString::fromStdString(appDesc->containerJS()).replace(QChar('\''), QString("\\'"))) - ); - - if (!appDesc->enyoBundleVersion().empty()) { - page->evaluateJavaScript(QStringLiteral( - "if (container.setVersion != null) {" - " container.setVersion('%1');" - "}" - ).arg(QString::fromStdString(appDesc->enyoBundleVersion()))); - } + postWebProcessCreated(appId.c_str(), getWebProcessId(appId)); + + std::string eventJS, versionJS; + buildAppJsTriggers(eventJS, versionJS, appDesc.get(), args); + page->evaluateJavaScript(eventJS); + page->evaluateJavaScript(versionJS); webPageAdded(page); PMTRACE("APP_ATTACHED_TO_CONTAINER"); LOG_INFO_WITH_CLOCK(MSGID_APP_ATTACHED_TO_CONTAINER, 4, - PMLOGKS("PerfType", "AppLaunch"), PMLOGKS("PerfGroup", qPrintable(page->appId())), - PMLOGKS("APP_ID", qPrintable(page->appId())), PMLOGKFV("PID", "%d", page->getWebProcessPID()), ""); + PMLOGKS("PerfType", "AppLaunch"), PMLOGKS("PerfGroup", page->appId().c_str()), + PMLOGKS("APP_ID", page->appId().c_str()), PMLOGKFV("PID", "%d", page->getWebProcessPID()), ""); m_containerAppManager->resetContainerAppManager(); @@ -253,7 +259,7 @@ void WebAppManager::onLaunchContainerBasedApp(const std::string& url, QString& w void WebAppManager::onRelaunchApp(const std::string& instanceId, const std::string& appId, const std::string& args, const std::string& launchingAppId) { - WebAppBase* app = findAppById(QString::fromStdString(appId)); + WebAppBase* app = findAppById(appId); if (!app) { LOG_WARNING(MSGID_APP_RELAUNCH, 0, "Failed to relaunch due to no running app"); @@ -262,15 +268,16 @@ void WebAppManager::onRelaunchApp(const std::string& instanceId, const std::stri // Do not relaunch when preload args is setted // luna-send -n 1 luna://com.webos.applicationManager/launch '{"id": "preload": }' - QJsonDocument doc = QJsonDocument::fromJson(args.c_str()); - QJsonObject obj = doc.object(); + Json::Value obj; + readJsonFromString(args, obj); - if (app->instanceId() == QString::fromStdString(instanceId) + if (app->instanceId() == instanceId && !obj["preload"].isString() - && !obj["launchedHidden"].toBool()) { + && obj["launchedHidden"].isBool() + && !obj["launchedHidden"].asBool()) { app->relaunch(args.c_str(), launchingAppId.c_str()); } else { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(app->appId())), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), "Relaunch with preload option, ignore"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", app->appId().c_str()), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), "Relaunch with preload option, ignore"); } } @@ -298,13 +305,12 @@ bool WebAppManager::isDiscardCodeCacheRequired() return false; // Deprecated (2016-04-01) } -bool WebAppManager::setInspectorEnable(QString & appId) +bool WebAppManager::setInspectorEnable(const std::string& appId) { // 1. find appId from then running App List, - for (AppList::const_iterator it = m_appList.begin(); it != m_appList.end(); ++it) { - WebAppBase* app = (*it); + for (const auto &app : m_appList) { if(appId == app->page()->appId()) { - LOG_DEBUG("[%s] setInspectorEnable", qPrintable(appId)); + LOG_DEBUG("[%s] setInspectorEnable", appId.c_str()); app->page()->setInspectorEnable(); return true; } @@ -319,10 +325,9 @@ void WebAppManager::discardCodeCache(uint32_t pid) bool WebAppManager::onKillApp(const std::string& appId) { - QString __appId = QString::fromStdString(appId); - WebAppBase* app = findAppById(__appId); + WebAppBase* app = findAppById(appId); if (!app) { - LOG_INFO(MSGID_KILL_APP, 1, PMLOGKS("APP_ID", qPrintable(QString::fromStdString(appId))), "App doesn't exist; return"); + LOG_INFO(MSGID_KILL_APP, 1, PMLOGKS("APP_ID", appId.c_str()), "App doesn't exist; return"); return false; } @@ -355,12 +360,12 @@ std::list WebAppManager::runningApps(uint32_t pid) return apps; } -WebAppBase* WebAppManager::onLaunchUrl(const std::string& url, QString winType, - std::shared_ptr appDesc, const std::string& instanceId, +WebAppBase* WebAppManager::onLaunchUrl(const std::string& url, const std::string& winType, + const std::shared_ptr appDesc, const std::string& instanceId, const std::string& args, const std::string& launchingAppId, int& errCode, std::string& errMsg) { - WebAppBase* app = WebAppFactoryManager::instance()->createWebApp(winType, appDesc, appDesc->subType().c_str()); + WebAppBase* app = WebAppFactoryManager::instance()->createWebApp(winType, appDesc, appDesc->subType()); if (!app) { errCode = ERR_CODE_LAUNCHAPP_UNSUPPORTED_TYPE; @@ -368,7 +373,7 @@ WebAppBase* WebAppManager::onLaunchUrl(const std::string& url, QString winType, return nullptr; } - WebPageBase* page = WebAppFactoryManager::instance()->createWebPage(winType, QUrl(url.c_str()), appDesc, appDesc->subType().c_str(), args.c_str()); + WebPageBase* page = WebAppFactoryManager::instance()->createWebPage(winType, Url(url), appDesc, appDesc->subType(), args); //set use launching time optimization true while app loading. page->setUseLaunchOptimization(true); @@ -384,13 +389,13 @@ WebAppBase* WebAppManager::onLaunchUrl(const std::string& url, QString winType, page->setEnableBackgroundRun(appDesc->isEnableBackgroundRun()); app->setAppDescription(appDesc); - app->setAppProperties(QString::fromStdString(args)); - app->setInstanceId(QString::fromStdString(instanceId)); - app->setLaunchingAppId(QString::fromStdString(launchingAppId)); + app->setAppProperties(args); + app->setInstanceId(instanceId); + app->setLaunchingAppId(launchingAppId); if (m_webAppManagerConfig->isCheckLaunchTimeEnabled()) app->startLaunchTimer(); app->attach(page); - app->setPreloadState(QString::fromStdString(args)); + app->setPreloadState(args); page->load(); webPageAdded(page); @@ -407,7 +412,7 @@ WebAppBase* WebAppManager::onLaunchUrl(const std::string& url, QString winType, m_appVersion[appDesc->id()] = appDesc->version(); } - LOG_INFO(MSGID_START_LAUNCHURL, 2, PMLOGKS("APP_ID", qPrintable(app->appId())), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), ""); + LOG_INFO(MSGID_START_LAUNCHURL, 2, PMLOGKS("APP_ID", app->appId().c_str()), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), ""); #ifndef PRELOADMANAGER_ENABLED if (m_containerAppManager && m_containerAppManager->getLaunchContainerAppOnDemand() && getContainerAppProxyID() == m_webProcessManager->getWebProcessProxyID(appDesc.get())) { @@ -425,32 +430,32 @@ void WebAppManager::forceCloseAppInternal(WebAppBase* app) closeAppInternal(app); } -void WebAppManager::removeClosingAppList(const QString& appId) +void WebAppManager::removeClosingAppList(const std::string& appId) { - QMap::iterator it = m_closingAppList.find(appId); + const auto &it = m_closingAppList.find(appId); if (it == m_closingAppList.end()) return; - m_closingAppList.remove(appId); + m_closingAppList.erase(it); } void WebAppManager::closeAppInternal(WebAppBase* app, bool ignoreCleanResource) { WebPageBase* page = app->page(); assert(page); - if (page->isClosing()) { - LOG_INFO(MSGID_CLOSE_APP_INTERNAL, 2, PMLOGKS("APP_ID", qPrintable(app->appId())), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), "In Closing; return"); + if (page && page->isClosing()) { + LOG_INFO(MSGID_CLOSE_APP_INTERNAL, 2, PMLOGKS("APP_ID", app->appId().c_str()), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), "In Closing; return"); return; } - LOG_INFO(MSGID_CLOSE_APP_INTERNAL, 2, PMLOGKS("APP_ID", qPrintable(app->appId())), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), ""); + LOG_INFO(MSGID_CLOSE_APP_INTERNAL, 2, PMLOGKS("APP_ID", app->appId().c_str()), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), ""); std::string type = app->getAppDescription()->defaultWindowType(); appDeleted(app); webPageRemoved(app->page()); removeWebAppFromWebProcessInfoMap(app->appId()); postRunningAppList(); - m_lastCrashedAppIds = QMap(); + m_lastCrashedAppIds = std::unordered_map(); // Set m_isClosing flag first, this flag will be checked in web page suspending page->setClosing(true); @@ -464,19 +469,21 @@ void WebAppManager::closeAppInternal(WebAppBase* app, bool ignoreCleanResource) if (ignoreCleanResource) delete app; else { - m_closingAppList.insert(app->appId(), app); + m_closingAppList.emplace(app->appId(), app); if (app == getContainerApp()) m_containerAppManager->closeContainerApp(); else if (page->isRegisteredCloseCallback()) { - LOG_INFO(MSGID_CLOSE_APP_INTERNAL, 2, PMLOGKS("APP_ID", qPrintable(app->appId())), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), "CloseCallback; execute"); + LOG_INFO(MSGID_CLOSE_APP_INTERNAL, 2, PMLOGKS("APP_ID", app->appId().c_str()), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), "CloseCallback; execute"); app->executeCloseCallback(); } else { - LOG_INFO(MSGID_CLOSE_APP_INTERNAL, 2, PMLOGKS("APP_ID", qPrintable(app->appId())), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), "NO CloseCallback; load about:blank"); + LOG_INFO(MSGID_CLOSE_APP_INTERNAL, 2, PMLOGKS("APP_ID", app->appId().c_str()), PMLOGKFV("PID", "%d", app->page()->getWebProcessPID()), "NO CloseCallback; load about:blank"); app->dispatchUnload(); } } + + deleteWebViewProfile(app->appId()); } bool WebAppManager::closeAllApps(uint32_t pid) @@ -520,10 +527,17 @@ bool WebAppManager::closeContainerApp() void WebAppManager::webPageAdded(WebPageBase* page) { - if (m_appPageMap.contains(page->appId().toStdString(), page)) - return; + auto appId = page->appId(); + if (m_appPageMap.count(appId) > 0) { + auto range = m_appPageMap.equal_range(appId); + for (auto i = range.first; i != range.second; ++i) { + if (i->second == page) { + return; + } + } + } - m_appPageMap.insert(page->appId().toStdString(), page); + m_appPageMap.insert(std::make_pair(appId, page)); } void WebAppManager::webPageRemoved(WebPageBase* page) @@ -536,35 +550,39 @@ void WebAppManager::webPageRemoved(WebPageBase* page) } } - m_appPageMap.remove(page->appId().toStdString(), page); + auto appId = page->appId(); + if (m_appPageMap.count(appId) > 0) { + auto range = m_appPageMap.equal_range(appId); + for (auto i = range.first; i != range.second; ++i) { + if (i->second == page) { + m_appPageMap.erase(i); + } + } + } + + m_shellPageMap.erase(appId); } -void WebAppManager::removeWebAppFromWebProcessInfoMap(QString appId) +void WebAppManager::removeWebAppFromWebProcessInfoMap(const std::string& appId) { // Deprecated (2016-04-01) } -WebAppBase* WebAppManager::findAppById(const QString& appId) +WebAppBase* WebAppManager::findAppById(const std::string& appId) { - for (AppList::iterator it = m_appList.begin(); it != m_appList.end(); ++it) { - WebAppBase* app = (*it); - + for (const auto &app : m_appList) { if (app->page() && app->appId() == appId) return app; } - return 0; } -WebAppBase* WebAppManager::findAppByInstanceId(const QString& instanceId) +WebAppBase* WebAppManager::findAppByInstanceId(const std::string& instanceId) { - for (AppList::iterator it = m_appList.begin(); it != m_appList.end(); ++it) { - WebAppBase* app = (*it); - - if (app->page() && (app->instanceId() == instanceId)) + for (const auto &app : m_appList) { + if (app->page() && app->instanceId() == instanceId) return app; } - return 0; } @@ -575,15 +593,21 @@ void WebAppManager::appDeleted(WebAppBase* app) std::string appId; if (app->page()) - appId = app->appId().toStdString(); + appId = app->appId(); m_appList.remove(app); if (!appId.empty()) - m_shellPageMap.remove(appId); + m_shellPageMap.erase(appId); +} + +bool WebAppManager::getSystemLanguage(std::string &value) +{ + if (!m_deviceInfo) return false; + return m_deviceInfo->getSystemLanguage(value); } -void WebAppManager::setSystemLanguage(QString language) +void WebAppManager::setSystemLanguage(const std::string& language) { if (!m_deviceInfo) return; @@ -595,22 +619,29 @@ void WebAppManager::setSystemLanguage(QString language) app->setPreferredLanguages(language); } - LOG_DEBUG("New system language: %s", language.toStdString().c_str()); + LOG_DEBUG("New system language: %s", language.c_str()); +} + +bool WebAppManager::getDeviceInfo(const std::string& name, std::string& value) +{ + if (!m_deviceInfo) return false; + return m_deviceInfo->getDeviceInfo(name, value); } -void WebAppManager::setDeviceInfo(QString name, QString value) +void WebAppManager::setDeviceInfo(const std::string& name, const std::string& value) { if (!m_deviceInfo) return; - QString oldValue; - if (m_deviceInfo->getDeviceInfo(name, oldValue) && (oldValue == value)) return; + std::string oldValue; + if (m_deviceInfo->getDeviceInfo(name, oldValue) && (oldValue == value)) + return; m_deviceInfo->setDeviceInfo(name, value); broadcastWebAppMessage(WebAppMessageType::DeviceInfoChanged, name); - LOG_DEBUG("SetDeviceInfo %s; %s to %s", name.toStdString().c_str(), oldValue.toStdString().c_str(), value.toStdString().c_str()); + LOG_DEBUG("SetDeviceInfo %s; %s to %s", name.c_str(), oldValue.c_str(), value.c_str()); } -void WebAppManager::broadcastWebAppMessage(WebAppMessageType type, const QString& message) +void WebAppManager::broadcastWebAppMessage(WebAppMessageType type, const std::string& message) { for (AppList::const_iterator it = m_appList.begin(); it != m_appList.end(); ++it) { WebAppBase* app = (*it); @@ -630,8 +661,9 @@ void WebAppManager::requestActivity(WebAppBase* app) m_serviceSender->requestActivity(app); } -bool WebAppManager::processCrashed(QString appId) { - if (m_containerAppManager && (appId == m_containerAppManager->getContainerAppId())) { +bool WebAppManager::processCrashed(const std::string& appId) { + auto containerAppId = m_containerAppManager->getContainerAppId(); + if (m_containerAppManager && (appId == containerAppId)) { m_containerAppManager->setContainerAppReady(false); #ifndef PRELOADMANAGER_ENABLED m_containerAppManager->startContainerTimer(); @@ -647,29 +679,30 @@ bool WebAppManager::processCrashed(QString appId) { if (app->isWindowed()) { if (app->isActivated()) { - int count = m_lastCrashedAppIds[app->appId()]; - m_lastCrashedAppIds[app->appId()] = count + 1; + auto id = app->appId(); + int count = m_lastCrashedAppIds[id]; + m_lastCrashedAppIds[id] = count + 1; int reloadingLimit = app->isNormal() ? kContinuousReloadingLimit-1 : kContinuousReloadingLimit; - if (m_lastCrashedAppIds[app->appId()] >= reloadingLimit) { - LOG_INFO(MSGID_WEBPROC_CRASH, 3, PMLOGKS("APP_ID", qPrintable(appId)), PMLOGKS("InForeground", "true"), PMLOGKS("Reloading limit", "Close app"), ""); + if (m_lastCrashedAppIds[id] >= reloadingLimit) { + LOG_INFO(MSGID_WEBPROC_CRASH, 3, PMLOGKS("APP_ID", appId.c_str()), PMLOGKS("InForeground", "true"), PMLOGKS("Reloading limit", "Close app"), ""); closeAppInternal(app, true); } else { - LOG_INFO(MSGID_WEBPROC_CRASH, 3, PMLOGKS("APP_ID", qPrintable(appId)), PMLOGKS("InForeground", "true"), PMLOGKS("Reloading limit", "OK; Reload default page"), ""); + LOG_INFO(MSGID_WEBPROC_CRASH, 3, PMLOGKS("APP_ID", appId.c_str()), PMLOGKS("InForeground", "true"), PMLOGKS("Reloading limit", "OK; Reload default page"), ""); app->page()->reloadDefaultPage(); } } else if (app->isMinimized()) { - LOG_INFO(MSGID_WEBPROC_CRASH, 2, PMLOGKS("APP_ID", qPrintable(appId)), PMLOGKS("InBackground", "Will be Reloaded in Relaunch"), ""); + LOG_INFO(MSGID_WEBPROC_CRASH, 2, PMLOGKS("APP_ID", appId.c_str()), PMLOGKS("InBackground", "Will be Reloaded in Relaunch"), ""); app->setCrashState(true); } } return true; } -const QString WebAppManager::windowTypeFromString(const std::string& str) +const std::string WebAppManager::windowTypeFromString(const std::string& str) { if(str == "overlay") return WT_OVERLAY; @@ -684,16 +717,16 @@ const QString WebAppManager::windowTypeFromString(const std::string& str) return WT_CARD; } -void WebAppManager::setForceCloseApp(QString appId) +void WebAppManager::setForceCloseApp(const std::string& appId) { - WebAppBase *app = findAppById(appId); + WebAppBase* app = findAppById(appId); if (!app) return; if (app->isWindowed()) { if (app->keepAlive() && app->getHiddenWindow()) { forceCloseAppInternal(app); - LOG_INFO(MSGID_FORCE_CLOSE_KEEP_ALIVE_APP, 1, PMLOGKS("APP_ID", qPrintable(appId)), ""); + LOG_INFO(MSGID_FORCE_CLOSE_KEEP_ALIVE_APP, 1, PMLOGKS("APP_ID", appId.c_str()), ""); return; } } @@ -724,12 +757,12 @@ uint32_t WebAppManager::getContainerAppProxyID() return proxyID; } -void WebAppManager::deleteStorageData(const QString& identifier) +void WebAppManager::deleteStorageData(const std::string& identifier) { m_webProcessManager->deleteStorageData(identifier); } -void WebAppManager::killCustomPluginProcess(const QString &basePath) +void WebAppManager::killCustomPluginProcess(const std::string& basePath) { // Deprecated (2016-04-01) } @@ -748,22 +781,28 @@ void WebAppManager::killCustomPluginProcess(const QString &basePath) std::string WebAppManager::launch(const std::string& appDescString, const std::string& params, const std::string& launchingAppId, int& errCode, std::string& errMsg) { + LOG_DEBUG("Begin"); std::shared_ptr desc(ApplicationDescription::fromJsonString(appDescString.c_str())); + LOG_DEBUG("parse app desc: Done"); + if (!desc) return std::string(); std::string instanceId = ""; std::string url = desc->entryPoint(); - QString winType = windowTypeFromString(desc->defaultWindowType()); + std::string winType = windowTypeFromString(desc->defaultWindowType()); errMsg.erase(); + LOG_DEBUG("windowType=[%s] Done", winType.c_str()); + // Check if app is container itself, it shouldn't be relaunched like normal app if (isContainerApp(url)) { + LOG_DEBUG("isContainerApp=[%s]", url.c_str()); if (!isRunningApp(desc->id(), instanceId)) instanceId = onLaunchContainerApp(appDescString); else { - LOG_INFO(MSGID_CONTAINER_APP_RELAUNCHED, 2, PMLOGKS("APP_ID", qPrintable(QString::fromStdString(desc->id()))), - PMLOGKS("INSTANCE_ID", qPrintable(QString::fromStdString(instanceId))), "ContainerApp; Already Running"); + LOG_INFO(MSGID_CONTAINER_APP_RELAUNCHED, 2, PMLOGKS("APP_ID", desc->id().c_str()), + PMLOGKS("INSTANCE_ID", instanceId.c_str()), "ContainerApp; Already Running"); } } // Check if app is already running @@ -772,12 +811,13 @@ std::string WebAppManager::launch(const std::string& appDescString, const std::s } // Check if app is container-based else if (isContainerBasedApp(desc.get())) { + LOG_DEBUG("isContainerBasedApp=[%s]", url.c_str()); if (desc->trustLevel() != "default" && desc->trustLevel() != "trusted") { errCode = ERR_CODE_LAUNCHAPP_INVALID_TRUSTLEVEL; errMsg = err_invalidTrustLevel; return std::string(); } - instanceId = m_containerAppManager->getContainerApp()->instanceId().toStdString(); + instanceId = m_containerAppManager->getContainerApp()->instanceId(); onLaunchContainerBasedApp(url.c_str(), winType, desc, @@ -786,11 +826,13 @@ std::string WebAppManager::launch(const std::string& appDescString, const std::s // Run as a normal app else { instanceId = generateInstanceId(); + LOG_DEBUG("normal app url=[%s] instanceId=[%s]", url.c_str(), instanceId.c_str()); if (!onLaunchUrl(url, winType, desc, instanceId, params, launchingAppId, errCode, errMsg)) { return std::string(); } } + LOG_DEBUG("Done."); return instanceId; } @@ -799,7 +841,7 @@ bool WebAppManager::isContainerApp(const std::string& url) if (!m_containerAppManager) return false; - if (url.find((m_containerAppManager->getContainerAppId()).toStdString()) != std::string::npos) + if (url.find(m_containerAppManager->getContainerAppId()) != std::string::npos) return true; return false; @@ -808,18 +850,17 @@ bool WebAppManager::isContainerApp(const std::string& url) bool WebAppManager::isRunningApp(const std::string& id, std::string& instanceId) { std::list running = runningApps(); - QString appIdToFind = QString::fromStdString(id); - for (auto it = running.begin(); it != running.end(); ++it) { - if ((*it)->appId() == appIdToFind) { - instanceId = (*it)->instanceId().toStdString(); + for (const auto &app : running) { + if (app->appId() == id) { + instanceId = app->instanceId(); return true; } } if (m_containerAppManager) { WebAppBase* container = m_containerAppManager->getContainerApp(); - if (container && m_containerAppManager->getContainerAppId() == appIdToFind) { - instanceId = container->instanceId().toStdString(); + if (container && m_containerAppManager->getContainerAppId() == id) { + instanceId = container->instanceId(); return true; } } @@ -838,8 +879,9 @@ bool WebAppManager::isContainerBasedApp(ApplicationDescription* containerBasedAp // check the enyo bundle version if (!containerBasedAppDesc->enyoBundleVersion().empty()) { - QString enyoBundleVersion = QString::fromStdString(containerBasedAppDesc->enyoBundleVersion()); - return containerAppDesc->supportedEnyoBundleVersions().contains(enyoBundleVersion); + std::string enyoBundleVersion = containerBasedAppDesc->enyoBundleVersion(); + auto versions = containerAppDesc->supportedEnyoBundleVersions(); + return versions.find(enyoBundleVersion) != versions.end(); } // check the enyo version @@ -851,23 +893,21 @@ bool WebAppManager::isContainerUsedApp(const ApplicationDescription* containerUs } -std::vector WebAppManager::list( bool includeSystemApps ) +std::vector WebAppManager::list(bool includeSystemApps) { std::vector list; std::list running = runningApps(); - for (auto it = running.begin(); it != running.end(); ++it) { - const WebAppBase* webAppBase = *it; - if( webAppBase->appId().size() || (!webAppBase->appId().size() && includeSystemApps ) ) { - uint32_t pid = m_webProcessManager->getWebProcessPID(webAppBase); - list.push_back(ApplicationInfo( webAppBase->instanceId(), webAppBase->appId(), pid)); + for (const auto &app : running) { + if(app->appId().size() || (!app->appId().size() && includeSystemApps)) { + uint32_t pid = m_webProcessManager->getWebProcessPID(app); + list.push_back(ApplicationInfo(app->instanceId(), app->appId(), pid)); } } - return list; } -QJsonObject WebAppManager::getWebProcessProfiling() +Json::Value WebAppManager::getWebProcessProfiling() { return m_webProcessManager->getWebProcessProfiling(); } @@ -878,7 +918,7 @@ void WebAppManager::sendLaunchContainerApp() if (!m_containerAppManager) return; - QString appId = getContainerAppId(); + std::string appId = getContainerAppId(); if (m_serviceSender) m_serviceSender->launchContainerApp(appId); @@ -919,9 +959,9 @@ void WebAppManager::reloadContainerApp() m_containerAppManager->reloadContainerApp(); } -QString& WebAppManager::getContainerAppId() +std::string& WebAppManager::getContainerAppId() { - static QString nullStr = ""; + static std::string nullStr = ""; if (m_containerAppManager) return m_containerAppManager->getContainerAppId(); @@ -958,7 +998,7 @@ void WebAppManager::postRunningAppList() m_serviceSender->postlistRunningApps(apps); } -void WebAppManager::postWebProcessCreated(const QString& appId, uint32_t pid) +void WebAppManager::postWebProcessCreated(const std::string& appId, uint32_t pid) { if (!m_serviceSender) return; @@ -969,7 +1009,7 @@ void WebAppManager::postWebProcessCreated(const QString& appId, uint32_t pid) m_serviceSender->postWebProcessCreated(appId, pid); } -uint32_t WebAppManager::getWebProcessId(const QString& appId) +uint32_t WebAppManager::getWebProcessId(const std::string& appId) { uint32_t pid = 0; WebAppBase* app = findAppById(appId); @@ -1004,25 +1044,24 @@ void WebAppManager::setAccessibilityEnabled(bool enabled) m_isAccessibilityEnabled = enabled; } -void WebAppManager::sendEventToAllAppsAndAllFrames(const QString& jsscript) +void WebAppManager::sendEventToAllAppsAndAllFrames(const std::string& jsscript) { - for (auto it = m_appList.begin(); it != m_appList.end(); ++it) { - WebAppBase* app = (*it); + for (const auto &app : m_appList) { if (app->page()) { - LOG_DEBUG("[%s] send event with %s", qPrintable(app->appId()), qPrintable(jsscript)); + LOG_DEBUG("[%s] send event with %s", app->appId().c_str(), jsscript.c_str()); // to send all subFrame, use this function instead of evaluateJavaScriptInAllFrames() app->page()->evaluateJavaScriptInAllFrames(jsscript); } } } -void WebAppManager::serviceCall(const QString& url, const QString& payload, const QString& appId) +void WebAppManager::serviceCall(const std::string& url, const std::string& payload, const std::string& appId) { if (m_serviceSender) m_serviceSender->serviceCall(url, payload, appId); } -void WebAppManager::updateNetworkStatus(const QJsonObject& object) +void WebAppManager::updateNetworkStatus(const Json::Value& object) { NetworkStatus status; status.fromJsonObject(object); @@ -1031,7 +1070,7 @@ void WebAppManager::updateNetworkStatus(const QJsonObject& object) m_networkStatusManager->updateNetworkStatus(status); } -bool WebAppManager::isEnyoApp(const QString& appId) +bool WebAppManager::isEnyoApp(const std::string& appId) { WebAppBase* app = findAppById(appId); if (app && !app->getAppDescription()->enyoVersion().empty()) @@ -1049,3 +1088,15 @@ int WebAppManager::maskForBrowsingDataType(const char* type) { return m_webProcessManager->maskForBrowsingDataType(type); } + +void WebAppManager::buildWebViewProfile(const std::string& app_id, const std::string& proxy_host, const std::string& proxy_port) +{ + if (m_webProcessManager) + m_webProcessManager->buildWebViewProfile(app_id, proxy_host, proxy_port); +} + +void WebAppManager::deleteWebViewProfile(const std::string& app_id) +{ + if (m_webProcessManager) + m_webProcessManager->deleteWebViewProfile(app_id); +} diff --git a/src/core/WebAppManager.h b/src/core/WebAppManager.h index c13f183a..4c76055b 100644 --- a/src/core/WebAppManager.h +++ b/src/core/WebAppManager.h @@ -18,15 +18,11 @@ #define WEBAPPMANAGER_H #include -#include #include +#include #include #include -#include -#include -#include - #include "webos/webview_base.h" class ApplicationDescription; @@ -40,9 +36,13 @@ class WebAppManagerConfig; class WebAppBase; class WebPageBase; +namespace Json { +class Value; +}; + class ApplicationInfo { public: - ApplicationInfo(const QString& inInstanceId, const QString& inAppId, const uint32_t& inPid) + ApplicationInfo(const std::string& inInstanceId, const std::string& inAppId, const uint32_t& inPid) : instanceId(inInstanceId) , appId(inAppId) , pid(inPid) @@ -50,8 +50,8 @@ class ApplicationInfo { } ~ApplicationInfo() {} - QString instanceId; - QString appId; + std::string instanceId; + std::string appId; uint32_t pid; }; @@ -63,9 +63,9 @@ class WebAppManager { static WebAppManager* instance(); - bool getSystemLanguage(QString& value); - bool getDeviceInfo(QString name, QString& value); - void broadcastWebAppMessage(WebAppMessageType type, const QString& message); + bool getSystemLanguage(std::string& value); + bool getDeviceInfo(const std::string& name, std::string& value); + void broadcastWebAppMessage(WebAppMessageType type, const std::string& message); WebProcessManager* getWebProcessManager() { return m_webProcessManager.get(); } @@ -77,8 +77,8 @@ class WebAppManager { std::list runningApps(); std::list runningApps(uint32_t pid); - WebAppBase* findAppById(const QString& appId); - WebAppBase* findAppByInstanceId(const QString& instanceId); + WebAppBase* findAppById(const std::string& appId); + WebAppBase* findAppByInstanceId(const std::string& instanceId); std::string launch(const std::string& appDescString, const std::string& params, @@ -88,7 +88,7 @@ class WebAppManager { std::vector list(bool includeSystemApps = false); - QJsonObject getWebProcessProfiling(); + Json::Value getWebProcessProfiling(); #ifndef PRELOADMANAGER_ENABLED void sendLaunchContainerApp(); void startContainerTimer(); @@ -100,78 +100,80 @@ class WebAppManager { void reloadContainerApp(); void setContainerAppReady(bool ready); void setContainerAppLaunched(bool launched); - QString& getContainerAppId(); + std::string& getContainerAppId(); WebAppBase* getContainerApp(); int currentUiWidth(); int currentUiHeight(); void setUiSize(int width, int height); - void setActiveAppId(QString id) { m_activeAppId = id; } - const QString getActiveAppId() { return m_activeAppId; } + void setActiveAppId(std::string id) { m_activeAppId = id; } + const std::string getActiveAppId() { return m_activeAppId; } void onGlobalProperties(int key); bool purgeSurfacePool(uint32_t pid); bool onKillApp(const std::string& appId); bool isDiscardCodeCacheRequired(); - bool setInspectorEnable(QString& appId); + bool setInspectorEnable(const std::string& appId); void discardCodeCache(uint32_t pid); - void setSystemLanguage(QString value); - void setDeviceInfo(QString name, QString value); + void setSystemLanguage(const std::string& value); + void setDeviceInfo(const std::string& name, const std::string& value); WebAppManagerConfig* config() { return m_webAppManagerConfig.get(); } void requestActivity(WebAppBase* app); - const QString windowTypeFromString(const std::string& str); + const std::string windowTypeFromString(const std::string& str); bool closeAllApps(uint32_t pid = 0); bool closeContainerApp(); - void setForceCloseApp(QString appId); + void setForceCloseApp(const std::string& appId); void requestKillWebProcess(uint32_t pid); bool shouldLaunchContainerAppOnDemand(); int getSuspendDelay() { return m_suspendDelay; } - void deleteStorageData(const QString& identifier); - void killCustomPluginProcess(const QString& basePath); - bool processCrashed(QString appId); + void deleteStorageData(const std::string& identifier); + void killCustomPluginProcess(const std::string& basePath); + bool processCrashed(const std::string& appId); void closeAppInternal(WebAppBase* app, bool ignoreCleanResource = false); void forceCloseAppInternal(WebAppBase* app); void webPageAdded(WebPageBase* page); void webPageRemoved(WebPageBase* page); - void removeWebAppFromWebProcessInfoMap(QString appId); + void removeWebAppFromWebProcessInfoMap(const std::string& appId); void appDeleted(WebAppBase* app); void postRunningAppList(); std::string generateInstanceId(); - void removeClosingAppList(const QString& appId); + void removeClosingAppList(const std::string& appId); bool isAccessibilityEnabled() { return m_isAccessibilityEnabled; } void setAccessibilityEnabled(bool enabled); - void postWebProcessCreated(const QString& appId, uint32_t pid); - uint32_t getWebProcessId(const QString& appId); - void sendEventToAllAppsAndAllFrames(const QString& jsscript); - void serviceCall(const QString& url, const QString& payload, const QString& appId); - void updateNetworkStatus(const QJsonObject& object); + void postWebProcessCreated(const std::string& appId, uint32_t pid); + uint32_t getWebProcessId(const std::string& appId); + void sendEventToAllAppsAndAllFrames(const std::string& jsscript); + void serviceCall(const std::string& url, const std::string& payload, const std::string& appId); + void updateNetworkStatus(const Json::Value& object); void notifyMemoryPressure(webos::WebViewBase::MemoryPressureLevel level); - bool isEnyoApp(const QString& appId); + bool isEnyoApp(const std::string& appId); void closeApp(const std::string& appId); void clearBrowsingData(const int removeBrowsingDataMask); int maskForBrowsingDataType(const char* type); + void buildWebViewProfile(const std::string& app_id, const std::string& proxy_host, const std::string& proxy_port); + void deleteWebViewProfile(const std::string& app_id); protected: private: void loadEnvironmentVariable(); - WebAppBase* onLaunchUrl(const std::string& url, QString winType, - std::shared_ptr appDesc, const std::string& instanceId, + WebAppBase* onLaunchUrl(const std::string& url, const std::string& winType, + const std::shared_ptr appDesc, const std::string& instanceId, const std::string& args, const std::string& launchingAppId, int& errCode, std::string& errMsg); - void onLaunchContainerBasedApp(const std::string& url, QString& winType, - std::shared_ptr appDesc, const std::string& args, const std::string& launchingAppId); + void onLaunchContainerBasedApp(const std::string& url, const std::string& winType, + const std::shared_ptr appDesc, const std::string& args, const std::string& launchingAppId); std::string onLaunchContainerApp(const std::string& appDesc); void onRelaunchApp(const std::string& instanceId, const std::string& appId, const std::string& args, const std::string& launchingAppId); @@ -187,17 +189,17 @@ class WebAppManager { bool isContainerApp(const std::string& url); uint32_t getContainerAppProxyID(); - QMap m_closingAppList; + std::unordered_map m_closingAppList; // Mappings - QMap m_shellPageMap; + std::unordered_map m_shellPageMap; AppList m_appList; - QMultiMap m_appPageMap; + std::unordered_multimap m_appPageMap; PageList m_pagesToDeleteList; bool m_deletingPages; - QString m_activeAppId; + std::string m_activeAppId; std::unique_ptr m_serviceSender; std::unique_ptr m_containerAppManager; @@ -206,11 +208,11 @@ class WebAppManager { std::unique_ptr m_webAppManagerConfig; std::unique_ptr m_networkStatusManager; - QMap m_lastCrashedAppIds; + std::unordered_map m_lastCrashedAppIds; int m_suspendDelay; - std::map m_appVersion; + std::unordered_map m_appVersion; bool m_isAccessibilityEnabled; }; diff --git a/src/core/WebAppManagerConfig.cpp b/src/core/WebAppManagerConfig.cpp index dbbfc9b3..d60f4e0c 100644 --- a/src/core/WebAppManagerConfig.cpp +++ b/src/core/WebAppManagerConfig.cpp @@ -18,6 +18,9 @@ #include +#include "StringUtils.h" +#include "WebAppManagerUtils.h" + WebAppManagerConfig::WebAppManagerConfig() : m_suspendDelayTime(0) , m_devModeEnabled(false) @@ -34,71 +37,64 @@ WebAppManagerConfig::WebAppManagerConfig() void WebAppManagerConfig::initConfiguration() { - m_webAppFactoryPluginTypes = QLatin1String(qgetenv("WEBAPPFACTORY")); + m_webAppFactoryPluginTypes = WebAppManagerUtils::getEnv("WEBAPPFACTORY"); - m_webAppFactoryPluginPath = QLatin1String(qgetenv("WEBAPPFACTORY_PLUGIN_PATH")); - if (m_webAppFactoryPluginPath.isEmpty()) { - m_webAppFactoryPluginPath = QLatin1String("/usr/lib/webappmanager/plugins"); + m_webAppFactoryPluginPath = WebAppManagerUtils::getEnv("WEBAPPFACTORY_PLUGIN_PATH"); + if (m_webAppFactoryPluginPath.empty()) { + m_webAppFactoryPluginPath = "/usr/lib/webappmanager/plugins"; } - QString suspendDelay = QLatin1String(qgetenv("WAM_SUSPEND_DELAY_IN_MS")); - m_suspendDelayTime = std::max(suspendDelay.toInt(), 1); + std::string suspendDelay = WebAppManagerUtils::getEnv("WAM_SUSPEND_DELAY_IN_MS"); + m_suspendDelayTime = std::max(stringTo(suspendDelay), 1); - m_webProcessConfigPath = QLatin1String(qgetenv("WEBPROCESS_CONFIGURATION_PATH")); - if (m_webProcessConfigPath.isEmpty()) - m_webProcessConfigPath = QLatin1String("/etc/wam/com.webos.wam.json"); + m_webProcessConfigPath = WebAppManagerUtils::getEnv("WEBPROCESS_CONFIGURATION_PATH"); + if (m_webProcessConfigPath.empty()) + m_webProcessConfigPath = "/etc/wam/com.webos.wam.json"; - m_errorPageUrl = QLatin1String(qgetenv("WAM_ERROR_PAGE")); + m_errorPageUrl = WebAppManagerUtils::getEnv("WAM_ERROR_PAGE"); - if (qgetenv("DISABLE_CONTAINER") == "1") + if (WebAppManagerUtils::getEnv("DISABLE_CONTAINER") == "1") m_containerAppEnabled = false; - if (qgetenv("LOAD_DYNAMIC_PLUGGABLE") == "1") + if (WebAppManagerUtils::getEnv("LOAD_DYNAMIC_PLUGGABLE") == "1") m_dynamicPluggableLoadEnabled = true; - if (qgetenv("POST_WEBPROCESS_CREATED_DISABLED") == "1") + if (WebAppManagerUtils::getEnv("POST_WEBPROCESS_CREATED_DISABLED") == "1") m_postWebProcessCreatedDisabled = true; - if (qgetenv("LAUNCH_TIME_CHECK") == "1") + if (WebAppManagerUtils::getEnv("LAUNCH_TIME_CHECK") == "1") m_checkLaunchTimeEnabled = true; - if (qgetenv("USE_SYSTEM_APP_OPTIMIZATION") == "1") + if (WebAppManagerUtils::getEnv("USE_SYSTEM_APP_OPTIMIZATION") == "1") m_useSystemAppOptimization = true; - if (qgetenv("ENABLE_LAUNCH_OPTIMIZATION") == "1") + if (WebAppManagerUtils::getEnv("ENABLE_LAUNCH_OPTIMIZATION") == "1") m_launchOptimizationEnabled = true; - m_userScriptPath = QLatin1String(qgetenv("USER_SCRIPT_PATH")); - if (m_userScriptPath.isEmpty()) - m_userScriptPath = QLatin1String("webOSUserScripts/userScript.js"); - - m_name = qgetenv("WAM_NAME").data(); -} - -QVariant WebAppManagerConfig::getConfiguration(QString name) -{ - QVariant value(0); - - if (m_configuration.contains(name)) { - value = m_configuration.value(name); - } + m_userScriptPath = WebAppManagerUtils::getEnv("USER_SCRIPT_PATH"); + if (m_userScriptPath.empty()) + m_userScriptPath = "webOSUserScripts/userScript.js"; - return value; -} - -void WebAppManagerConfig::setConfiguration(QString name, QVariant value) -{ - m_configuration.insert(name, value); + m_name = WebAppManagerUtils::getEnv("WAM_NAME"); } void WebAppManagerConfig::postInitConfiguration() { - if (access("/var/luna/preferences/debug_system_apps", F_OK) == 0) { + std::string dir; +#if defined(HAS_AGL_SERVICE) + dir = "/var/agl-devel/preferences/"; +#else + dir = "/var/luna/preferences/"; +#endif + + std::string debug_apps_setting = dir + "debug_system_apps"; + if (access(debug_apps_setting.c_str(), F_OK) == 0) { m_inspectorEnabled = true; } - if (access("/var/luna/preferences/devmode_enabled", F_OK) == 0) { + std::string devmode_setting = dir + "devmode_enabled"; + if (access(devmode_setting.c_str(), F_OK) == 0) { m_devModeEnabled = true; - m_telluriumNubPath = QLatin1String(qgetenv("TELLURIUM_NUB_PATH")); + m_telluriumNubPath = WebAppManagerUtils::getEnv("TELLURIUM_NUB_PATH"); } } diff --git a/src/core/WebAppManagerConfig.h b/src/core/WebAppManagerConfig.h index f8225874..d26eb5ba 100644 --- a/src/core/WebAppManagerConfig.h +++ b/src/core/WebAppManagerConfig.h @@ -17,59 +17,52 @@ #ifndef WEBAPPMANAGERCONFIG_H #define WEBAPPMANAGERCONFIG_H -#include -#include -#include +#include +#include class WebAppManagerConfig { public: WebAppManagerConfig(); virtual ~WebAppManagerConfig() {} - virtual QString getWebAppFactoryPluginTypes() const { return m_webAppFactoryPluginTypes; } - virtual QString getWebAppFactoryPluginPath() const { return m_webAppFactoryPluginPath; } + virtual std::string getWebAppFactoryPluginTypes() const { return m_webAppFactoryPluginTypes; } + virtual std::string getWebAppFactoryPluginPath() const { return m_webAppFactoryPluginPath; } virtual int getSuspendDelayTime() const { return m_suspendDelayTime; } - virtual QString getWebProcessConfigPath() const { return m_webProcessConfigPath; } + virtual std::string getWebProcessConfigPath() const { return m_webProcessConfigPath; } virtual bool isInspectorEnabled() const { return m_inspectorEnabled; } virtual bool isDevModeEnabled() const { return m_devModeEnabled; } - virtual QString getErrorPageUrl() const { return m_errorPageUrl; } - virtual QString getTelluriumNubPath() const { return m_telluriumNubPath; } + virtual std::string getErrorPageUrl() const { return m_errorPageUrl; } + virtual std::string getTelluriumNubPath() const { return m_telluriumNubPath; } virtual bool isContainerAppEnabled() const { return m_containerAppEnabled; } virtual void postInitConfiguration(); virtual bool isDynamicPluggableLoadEnabled() const { return m_dynamicPluggableLoadEnabled; } virtual bool isPostWebProcessCreatedDisabled() const { return m_postWebProcessCreatedDisabled; } virtual bool isCheckLaunchTimeEnabled() const { return m_checkLaunchTimeEnabled; } virtual bool isUseSystemAppOptimization() const { return m_useSystemAppOptimization; } - virtual QString getUserScriptPath() const { return m_userScriptPath; } + virtual std::string getUserScriptPath() const { return m_userScriptPath; } virtual std::string getName() const { return m_name; } virtual bool isLaunchOptimizationEnabled() const { return m_launchOptimizationEnabled; } -protected: - virtual QVariant getConfiguration(QString name); - virtual void setConfiguration(QString name, QVariant value); - private: void initConfiguration(); - QString m_webAppFactoryPluginTypes; - QString m_webAppFactoryPluginPath; + std::string m_webAppFactoryPluginTypes; + std::string m_webAppFactoryPluginPath; int m_suspendDelayTime; - QString m_webProcessConfigPath; + std::string m_webProcessConfigPath; bool m_devModeEnabled; bool m_inspectorEnabled; - QString m_errorPageUrl; - QString m_telluriumNubPath; + std::string m_errorPageUrl; + std::string m_telluriumNubPath; bool m_containerAppEnabled; bool m_dynamicPluggableLoadEnabled; bool m_postWebProcessCreatedDisabled; bool m_checkLaunchTimeEnabled; bool m_useSystemAppOptimization; bool m_launchOptimizationEnabled; - QString m_userScriptPath; + std::string m_userScriptPath; std::string m_name; - - QMap m_configuration; }; #endif /* WEBAPPMANAGERCONFIG_H */ diff --git a/src/core/WebAppManagerService.cpp b/src/core/WebAppManagerService.cpp index 188e3123..bbf801fd 100644 --- a/src/core/WebAppManagerService.cpp +++ b/src/core/WebAppManagerService.cpp @@ -14,11 +14,13 @@ // // SPDX-License-Identifier: Apache-2.0 +#include "WebAppManagerService.h" + +#include #include #include "LogManager.h" #include "WebAppBase.h" -#include "WebAppManagerService.h" WebAppManagerService::WebAppManagerService() { @@ -32,21 +34,21 @@ std::string WebAppManagerService::onLaunch(const std::string& appDescString, con bool WebAppManagerService::onKillApp(const std::string& appId) { - LOG_INFO(MSGID_LUNA_API, 2, PMLOGKS("APP_ID", qPrintable(QString::fromStdString(appId))), PMLOGKS("API", "killApp"), ""); + LOG_INFO(MSGID_LUNA_API, 2, PMLOGKS("APP_ID", appId.c_str()), PMLOGKS("API", "killApp"), ""); return WebAppManager::instance()->onKillApp(appId); } -QJsonObject WebAppManagerService::onLogControl(const std::string& keys, const std::string& value) +Json::Value WebAppManagerService::onLogControl(const std::string& keys, const std::string& value) { LogManager::setLogControl(keys, value); - QJsonObject reply; + Json::Value reply(Json::objectValue); reply["event"] = LogManager::getDebugEventsEnabled(); reply["bundleMessage"] = LogManager::getDebugBundleMessagesEnabled(); reply["mouseMove"] = LogManager::getDebugMouseMoveEnabled(); - return reply; + return std::move(reply); } bool WebAppManagerService::onCloseAllApps(uint32_t pid) @@ -76,7 +78,7 @@ bool WebAppManagerService::onPurgeSurfacePool(uint32_t pid) return WebAppManager::instance()->purgeSurfacePool(pid); } -QJsonObject WebAppManagerService::getWebProcessProfiling() +Json::Value WebAppManagerService::getWebProcessProfiling() { return WebAppManager::instance()->getWebProcessProfiling(); } @@ -108,7 +110,7 @@ void WebAppManagerService::restartContainerApp() } #endif -void WebAppManagerService::setDeviceInfo(const QString &name, const QString &value) +void WebAppManagerService::setDeviceInfo(const std::string &name, const std::string &value) { WebAppManager::instance()->setDeviceInfo(name, value); } @@ -118,29 +120,29 @@ void WebAppManagerService::setUiSize(int width, int height) WebAppManager::instance()->setUiSize(width, height); } -void WebAppManagerService::setSystemLanguage(const QString &language) +void WebAppManagerService::setSystemLanguage(const std::string &language) { WebAppManager::instance()->setSystemLanguage(language); } -QString WebAppManagerService::getSystemLanguage() +std::string WebAppManagerService::getSystemLanguage() { - QString language; + std::string language; WebAppManager::instance()->getSystemLanguage(language); return language; } -void WebAppManagerService::setForceCloseApp(const QString &appId) +void WebAppManagerService::setForceCloseApp(const std::string &appId) { WebAppManager::instance()->setForceCloseApp(appId); } -void WebAppManagerService::deleteStorageData(const QString &identifier) +void WebAppManagerService::deleteStorageData(const std::string &identifier) { WebAppManager::instance()->deleteStorageData(identifier); } -void WebAppManagerService::killCustomPluginProcess(const QString &appBasePath) +void WebAppManagerService::killCustomPluginProcess(const std::string& appBasePath) { WebAppManager::instance()->killCustomPluginProcess(appBasePath); } @@ -170,25 +172,25 @@ std::vector WebAppManagerService::list(bool includeSystemApps) return WebAppManager::instance()->list(includeSystemApps); } -QJsonObject WebAppManagerService::closeByInstanceId(QString instanceId) +Json::Value WebAppManagerService::closeByInstanceId(const std::string& instanceId) { - LOG_INFO(MSGID_LUNA_API, 2, PMLOGKS("INSTANCE_ID", qPrintable(instanceId)), PMLOGKS("API", "closeByInstanceId"), ""); + LOG_INFO(MSGID_LUNA_API, 2, PMLOGKS("INSTANCE_ID", instanceId.c_str()), PMLOGKS("API", "closeByInstanceId"), ""); WebAppBase* app = WebAppManager::instance()->findAppByInstanceId(instanceId); - QString appId; + std::string appId; if (app) { appId = app->appId(); WebAppManager::instance()->forceCloseAppInternal(app); } - QJsonObject reply; - if(!appId.isNull()) { + Json::Value reply(Json::objectValue); + if(!appId.empty()) { reply["appId"] = appId; reply["processId"] = instanceId; reply["returnValue"] = true; } else { - LOG_INFO(MSGID_LUNA_API, 2, PMLOGKS("INSTANCE_ID", qPrintable(instanceId)), PMLOGKS("API", "closeByInstanceId"), "No matched App; return false"); - QString errMsg("Unknown Process"); + LOG_INFO(MSGID_LUNA_API, 2, PMLOGKS("INSTANCE_ID", instanceId.c_str()), PMLOGKS("API", "closeByInstanceId"), "No matched App; return false"); + std::string errMsg("Unknown Process"); reply["returnValue"] = false; reply["errorText"] = errMsg; } @@ -200,12 +202,12 @@ void WebAppManagerService::setAccessibilityEnabled(bool enable) WebAppManager::instance()->setAccessibilityEnabled(enable); } -uint32_t WebAppManagerService::getWebProcessId(const QString& appId) +uint32_t WebAppManagerService::getWebProcessId(const std::string& appId) { return WebAppManager::instance()->getWebProcessId(appId); } -void WebAppManagerService::updateNetworkStatus(const QJsonObject& object) +void WebAppManagerService::updateNetworkStatus(const Json::Value& object) { WebAppManager::instance()->updateNetworkStatus(object); } @@ -215,7 +217,7 @@ void WebAppManagerService::notifyMemoryPressure(webos::WebViewBase::MemoryPressu WebAppManager::instance()->notifyMemoryPressure(level); } -bool WebAppManagerService::isEnyoApp(const QString& appId) +bool WebAppManagerService::isEnyoApp(const std::string& appId) { return WebAppManager::instance()->isEnyoApp(appId); } @@ -224,3 +226,8 @@ int WebAppManagerService::maskForBrowsingDataType(const char* type) { return WebAppManager::instance()->maskForBrowsingDataType(type); } + +void WebAppManagerService::buildWebViewProfile(const std::string& app_id, const std::string& proxy_host, const std::string& proxy_port) +{ + WebAppManager::instance()->buildWebViewProfile(app_id, proxy_host, proxy_port); +} diff --git a/src/core/WebAppManagerService.h b/src/core/WebAppManagerService.h index 6bb56fa0..e284ae63 100644 --- a/src/core/WebAppManagerService.h +++ b/src/core/WebAppManagerService.h @@ -17,12 +17,14 @@ #ifndef WEBAPPMANAGERSERVICE_H #define WEBAPPMANAGERSERVICE_H -#include - #include "WebAppManager.h" #include "webos/webview_base.h" +namespace Json { +class Value; +} + enum ErrorCode { ERR_CODE_LAUNCHAPP_MISS_PARAM = 1000, ERR_CODE_LAUNCHAPP_UNSUPPORTED_TYPE = 1001, @@ -52,17 +54,17 @@ class WebAppManagerService { virtual bool startService() = 0; // methods published to the bus - virtual QJsonObject launchApp(QJsonObject request) = 0; - virtual QJsonObject killApp(QJsonObject request) = 0; - virtual QJsonObject logControl(QJsonObject request) = 0; - virtual QJsonObject setInspectorEnable(QJsonObject request) = 0; - virtual QJsonObject closeAllApps(QJsonObject request) = 0; - virtual QJsonObject discardCodeCache(QJsonObject request) = 0; - virtual QJsonObject listRunningApps(QJsonObject request, bool subscribed) = 0; - virtual QJsonObject closeByProcessId(QJsonObject request) = 0; - virtual QJsonObject getWebProcessSize(QJsonObject request) = 0; - virtual QJsonObject clearBrowsingData(QJsonObject request) = 0; - virtual QJsonObject webProcessCreated(QJsonObject request, bool subscribed) = 0; + virtual Json::Value launchApp(const Json::Value &request) = 0; + virtual Json::Value killApp(const Json::Value &request) = 0; + virtual Json::Value logControl(const Json::Value &request) = 0; + virtual Json::Value setInspectorEnable(const Json::Value &request) = 0; + virtual Json::Value closeAllApps(const Json::Value &request) = 0; + virtual Json::Value discardCodeCache(const Json::Value &request) = 0; + virtual Json::Value listRunningApps(const Json::Value &request, bool subscribed) = 0; + virtual Json::Value closeByProcessId(const Json::Value &request) = 0; + virtual Json::Value getWebProcessSize(const Json::Value &request) = 0; + virtual Json::Value clearBrowsingData(const Json::Value &request) = 0; + virtual Json::Value webProcessCreated(const Json::Value &request, bool subscribed) = 0; protected: std::string onLaunch(const std::string& appDescString, @@ -72,16 +74,17 @@ class WebAppManagerService { std::string& errMsg); bool onKillApp(const std::string& appId); - QJsonObject onLogControl(const std::string& keys, const std::string& value); + Json::Value onLogControl(const std::string& keys, const std::string& value); bool onCloseAllApps(uint32_t pid = 0); bool closeContainerApp(); bool isDiscardCodeCacheRequired(); void onDiscardCodeCache(uint32_t pid); bool onPurgeSurfacePool(uint32_t pid); - QJsonObject getWebProcessProfiling(); - QJsonObject closeByInstanceId(QString instanceId); + Json::Value getWebProcessProfiling(); + Json::Value closeByInstanceId(const std::string& instanceId); int maskForBrowsingDataType(const char* type); void onClearBrowsingData(const int removeBrowsingDataMask); + void buildWebViewProfile(const std::string& app_id, const std::string& proxy_host, const std::string& proxy_port); WebAppBase* getContainerApp(); #ifndef PRELOADMANAGER_ENABLED @@ -89,25 +92,25 @@ class WebAppManagerService { void startContainerTimer(); void restartContainerApp(); #endif - void setDeviceInfo(const QString& name, const QString& value); + void setDeviceInfo(const std::string& name, const std::string& value); void setUiSize(int width, int height); - void setSystemLanguage(const QString& language); - QString getSystemLanguage(); - void setForceCloseApp(const QString& appId); - void deleteStorageData(const QString& identifier); - void killCustomPluginProcess(const QString& appBasePath); + void setSystemLanguage(const std::string& language); + std::string getSystemLanguage(); + void setForceCloseApp(const std::string& appId); + void deleteStorageData(const std::string& identifier); + void killCustomPluginProcess(const std::string& appBasePath); void requestKillWebProcess(uint32_t pid); bool shouldLaunchContainerAppOnDemand(); - void updateNetworkStatus(const QJsonObject& object); + void updateNetworkStatus(const Json::Value& object); void notifyMemoryPressure(webos::WebViewBase::MemoryPressureLevel level); void setAccessibilityEnabled(bool enable); - uint32_t getWebProcessId(const QString& appId); + uint32_t getWebProcessId(const std::string& appId); std::list runningApps(); std::list runningApps(uint32_t pid); std::vector list(bool includeSystemApps = false); - bool isEnyoApp(const QString& apppId); + bool isEnyoApp(const std::string& apppId); }; #endif // WEBAPPMANAGERSERVICE_H diff --git a/src/core/WebAppManagerTracer.h b/src/core/WebAppManagerTracer.h index 426d4c0f..8dbe1435 100644 --- a/src/core/WebAppManagerTracer.h +++ b/src/core/WebAppManagerTracer.h @@ -56,7 +56,7 @@ #define PMTRACE_FUNCTION_EXIT(label) \ tracepoint(pmtrace_webappmanager3, function_exit, label) #define PMTRACE_FUNCTION \ - PmTraceFunction traceFunction(const_cast(Q_FUNC_INFO)) + PmTraceFunction traceFunction(const_cast(__PRETTY_FUNCTION__)) class PmTraceScope { public: diff --git a/src/core/WebPageBase.cpp b/src/core/WebPageBase.cpp index 7931564d..704d7ab6 100644 --- a/src/core/WebPageBase.cpp +++ b/src/core/WebPageBase.cpp @@ -16,12 +16,11 @@ #include -#include -#include -#include -#include +#include +#include #include "ApplicationDescription.h" +#include "JsonHelper.h" #include "LogManager.h" #include "WebAppManagerConfig.h" #include "WebAppManager.h" @@ -29,7 +28,9 @@ #include "WebPageObserver.h" #include "WebProcessManager.h" -#define CONSOLE_DEBUG(AAA) evaluateJavaScript(QStringLiteral("console.debug('") + QStringLiteral(AAA) + QStringLiteral("');")) +#define CONSOLE_DEBUG(AAA) evaluateJavaScript("console.debug('" + AAA + "');") + +namespace fs = boost::filesystem; WebPageBase::WebPageBase() : m_appDesc(nullptr) @@ -38,15 +39,15 @@ WebPageBase::WebPageBase() , m_isLoadErrorPageFinish(false) , m_isLoadErrorPageStart(false) , m_enableBackgroundRun(false) - , m_loadErrorPolicy(QStringLiteral("default")) + , m_loadErrorPolicy("default") , m_cleaningResources(false) , m_isPreload(false) { } -WebPageBase::WebPageBase(const QUrl& url, std::shared_ptr desc, const QString& params) +WebPageBase::WebPageBase(const Url& url, std::shared_ptr desc, const std::string& params) : m_appDesc(desc) - , m_appId(QString::fromStdString(desc->id())) + , m_appId(desc->id()) , m_suspendAtLoad(false) , m_isClosing(false) , m_isLoadErrorPageFinish(false) @@ -54,7 +55,7 @@ WebPageBase::WebPageBase(const QUrl& url, std::shared_ptrgetContainerAppId()) - return QStringLiteral(""); + if(appId().empty() || appId() == WebAppManager::instance()->getContainerAppId()) + return {}; return m_appId; } void WebPageBase::load() { - LOG_INFO(MSGID_WEBPAGE_LOAD, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", getWebProcessPID()), "m_launchParams:%s", qPrintable(m_launchParams)); + LOG_INFO(MSGID_WEBPAGE_LOAD, 2, PMLOGKS("APP_ID", appId().c_str()), + PMLOGKFV("PID", "%d", getWebProcessPID()), + "m_launchParams:%s", m_launchParams.c_str()); /* this function is main load of WebPage : load default url */ setupLaunchEvent(); if (!doDeeplinking(m_launchParams)) { - LOG_INFO(MSGID_WEBPAGE_LOAD, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", getWebProcessPID()), "loadDefaultUrl()"); + LOG_INFO(MSGID_WEBPAGE_LOAD, 2, PMLOGKS("APP_ID", appId().c_str()), + PMLOGKFV("PID", "%d", getWebProcessPID()), "loadDefaultUrl()"); loadDefaultUrl(); } } void WebPageBase::setupLaunchEvent() { - QString launchEventJS = QStringLiteral( - "(function() {" - " var launchEvent = new CustomEvent('webOSLaunch', { detail: %1 });" - " if(document.readyState === 'complete') {" - " setTimeout(function() {" - " document.dispatchEvent(launchEvent);" - " }, 1);" - " } else {" - " document.addEventListener('DOMContentLoaded', function() {" - " setTimeout(function() {" - " document.dispatchEvent(launchEvent);" - " }, 1);" - " });" - " }" - "})();" - ).arg(launchParams().isEmpty() ? "{}" : launchParams()); - addUserScript(launchEventJS); -} - -void WebPageBase::sendLocaleChangeEvent(const QString& language) -{ - evaluateJavaScript(QStringLiteral( + std::stringstream launchEventJS; + std::string params = launchParams().empty() ? "{}" : launchParams(); + launchEventJS + << "(function() {" + << " var launchEvent = new CustomEvent('webOSLaunch', { detail: " << params << " });" + << " if(document.readyState === 'complete') {" + << " setTimeout(function() {" + << " document.dispatchEvent(launchEvent);" + << " }, 1);" + << " } else {" + << " document.addEventListener('DOMContentLoaded', function() {" + << " setTimeout(function() {" + << " document.dispatchEvent(launchEvent);" + << " }, 1);" + << " });" + << " }" + << "})();"; + addUserScript(launchEventJS.str()); +} + +void WebPageBase::sendLocaleChangeEvent(const std::string&) +{ + evaluateJavaScript( "setTimeout(function () {" " var localeEvent=new CustomEvent('webOSLocaleChange');" " document.dispatchEvent(localeEvent);" "}, 1);" - )); + ); } void WebPageBase::cleanResources() @@ -138,7 +143,7 @@ void WebPageBase::cleanResources() setCleaningResources(true); } -bool WebPageBase::relaunch(const QString& launchParams, const QString& launchingAppId) +bool WebPageBase::relaunch(const std::string& launchParams, const std::string& launchingAppId) { resumeWebPagePaintingAndJSExecution(); @@ -149,12 +154,12 @@ bool WebPageBase::relaunch(const QString& launchParams, const QString& launching // 2-3. send webOSRelaunch event if(doHostedWebAppRelaunch(launchParams)) { - LOG_DEBUG("[%s] Hosted webapp; handled", qPrintable(m_appId)); + LOG_DEBUG("[%s] Hosted webapp; handled", appId().c_str()); return true; } if (!hasBeenShown()){ - LOG_INFO(MSGID_WEBPAGE_RELAUNCH, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", getWebProcessPID()), "In Loading(%d%%), Can not handle relaunch now, return false", progress()); + LOG_INFO(MSGID_WEBPAGE_RELAUNCH, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", getWebProcessPID()), "In Loading(%d%%), Can not handle relaunch now, return false", progress()); return false; } @@ -165,7 +170,7 @@ bool WebPageBase::relaunch(const QString& launchParams, const QString& launching return true; } -bool WebPageBase::doHostedWebAppRelaunch(const QString& launchParams) +bool WebPageBase::doHostedWebAppRelaunch(const std::string& launchParams) { /* hosted webapp deeplinking spec // legacy case @@ -180,13 +185,14 @@ bool WebPageBase::doHostedWebAppRelaunch(const QString& launchParams) To support backward compatibility, should cover the case not having "handledBy" */ // check deeplinking relaunch condition - QJsonObject obj = QJsonDocument::fromJson(launchParams.toUtf8()).object(); + Json::Value obj; + readJsonFromString(launchParams, obj); if (url().scheme() == "file" || m_defaultUrl.scheme() != "file" - || obj.isEmpty() /* no launchParams, { }, and this should be check with object().isEmpty()*/ - || obj.value("contentTarget").isUndefined() + || !obj.isObject() /* no launchParams, { }, and this should be check with object().isEmpty()*/ + || obj["contentTarget"].isNull() || (m_appDesc && !m_appDesc->handlesDeeplinking())) { - LOG_INFO(MSGID_WEBPAGE_RELAUNCH, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", getWebProcessPID()), + LOG_INFO(MSGID_WEBPAGE_RELAUNCH, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", getWebProcessPID()), "%s; NOT enough deeplinking condition; return false", __func__); return false; } @@ -196,16 +202,18 @@ bool WebPageBase::doHostedWebAppRelaunch(const QString& launchParams) return doDeeplinking(launchParams); } -bool WebPageBase::doDeeplinking(const QString& launchParams) +// TODO: Optimization: Consider use previously parsed Json::Object here instead of std::string +bool WebPageBase::doDeeplinking(const std::string& launchParams) { - QJsonObject obj = QJsonDocument::fromJson(launchParams.toUtf8()).object(); - if (obj.isEmpty() || obj.value("contentTarget").isUndefined()) + Json::Value obj; + readJsonFromString(launchParams, obj); + if (!obj.isObject() || obj["contentTarget"].isNull()) return false; - std::string handledBy = obj.value("handledBy").isUndefined() ? "default" : obj.value("handledBy").toString().toStdString(); + std::string handledBy = obj["handledBy"].isNull() ? "default" : obj["handledBy"].asString(); if (handledBy == "platform") { - std::string targetUrl = obj.value("contentTarget").toString().toStdString(); - LOG_INFO(MSGID_DEEPLINKING, 3, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", getWebProcessPID()), + std::string targetUrl = obj["contentTarget"].asString(); + LOG_INFO(MSGID_DEEPLINKING, 3, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", getWebProcessPID()), PMLOGKS("handledBy", handledBy.c_str()), "%s; load target URL:%s", __func__, targetUrl.c_str()); // load the target URL directly @@ -217,7 +225,7 @@ bool WebPageBase::doDeeplinking(const QString& launchParams) return false; } else { // handledBy == "default" or "other values" - LOG_INFO(MSGID_DEEPLINKING, 3, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", getWebProcessPID()), + LOG_INFO(MSGID_DEEPLINKING, 3, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", getWebProcessPID()), PMLOGKS("handledBy", handledBy.c_str()), "%s; loadDefaultUrl", __func__); loadDefaultUrl(); return true; @@ -227,21 +235,19 @@ bool WebPageBase::doDeeplinking(const QString& launchParams) void WebPageBase::sendRelaunchEvent() { setVisible(true); - LOG_INFO(MSGID_SEND_RELAUNCHEVENT, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", getWebProcessPID()), ""); + LOG_INFO(MSGID_SEND_RELAUNCHEVENT, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", getWebProcessPID()), ""); // Send the relaunch event on the next tick after javascript is loaded // This is a workaround for a problem where WebKit can't free the page // if we don't use a timeout here. - evaluateJavaScript(QStringLiteral( - "setTimeout(function () {" - " console.log('[WAM] fires webOSRelaunch event');" - " var launchEvent=new CustomEvent('webOSRelaunch', { detail: %1 });" - " document.dispatchEvent(launchEvent);" - "}, 1);").arg(launchParams().isEmpty() ? "{}" : launchParams())); -} -void WebPageBase::urlChangedSlot() -{ - Q_EMIT webPageUrlChanged(); + std::stringstream jss; + std::string detail = launchParams().empty() ? "{}" : launchParams(); + jss << "setTimeout(function () {" + << " console.log('[WAM] fires webOSRelaunch event');" + << " var launchEvent=new CustomEvent('webOSRelaunch', { detail: " << detail << " });" + << " document.dispatchEvent(launchEvent);" + << "}, 1);"; + evaluateJavaScript(jss.str()); } void WebPageBase::handleLoadStarted() @@ -251,11 +257,14 @@ void WebPageBase::handleLoadStarted() void WebPageBase::handleLoadFinished() { - LOG_INFO(MSGID_WEBPAGE_LOAD_FINISHED, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", getWebProcessPID()), "m_suspendAtLoad : %s", m_suspendAtLoad ? "true; suspend in this time" : "false"); + LOG_INFO(MSGID_WEBPAGE_LOAD_FINISHED, 2, PMLOGKS("APP_ID", appId().c_str()), + PMLOGKFV("PID", "%d", getWebProcessPID()), + "m_suspendAtLoad : %s", m_suspendAtLoad ? "true; suspend in this time" : "false"); + if (appId() == WebAppManager::instance()->getContainerAppId()) WebAppManager::instance()->setContainerAppLaunched(true); - Q_EMIT webPageLoadFinished(); + FOR_EACH_OBSERVER(WebPageObserver, m_observers, webPageLoadFinished()); // if there was an attempt made to suspend while this page was loading, then // we flag m_suspendAtLoad = true, and suspend it after it is loaded. This is @@ -268,7 +277,7 @@ void WebPageBase::handleLoadFinished() void WebPageBase::handleLoadFailed(int errorCode) { - LOG_INFO(MSGID_WEBPAGE_LOAD_FAILED, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", getWebProcessPID()), ""); + LOG_INFO(MSGID_WEBPAGE_LOAD_FAILED, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", getWebProcessPID()), ""); // errorCode 204 specifically states that the web browser not relocate // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html @@ -292,12 +301,12 @@ void WebPageBase::handleForceDeleteWebPage() delete this; } -bool WebPageBase::getSystemLanguage(QString &value) +bool WebPageBase::getSystemLanguage(std::string &value) { return WebAppManager::instance()->getSystemLanguage(value); } -bool WebPageBase::getDeviceInfo(QString name, QString &value) +bool WebPageBase::getDeviceInfo(const std::string& name, std::string& value) { return WebAppManager::instance()->getDeviceInfo(name, value); } @@ -332,41 +341,39 @@ int WebPageBase::suspendDelay() return WebAppManager::instance()->getSuspendDelay(); } -QString WebPageBase::telluriumNubPath() +std::string WebPageBase::telluriumNubPath() { return getWebAppManagerConfig()->getTelluriumNubPath(); } -void WebPageBase::doLoadSlot() -{ - loadDefaultUrl(); -} - bool WebPageBase::hasLoadErrorPolicy(bool isHttpResponseError, int errorCode) { - if (!m_loadErrorPolicy.compare("event")) { - evaluateJavaScript(QStringLiteral( - "{" - " console.log('[WAM3] create webOSLoadError event');" - " var launchEvent=new CustomEvent('webOSLoadError', { detail : { genericError : %1, errorCode : %2}});" - " document.dispatchEvent(launchEvent);" - "}" ).arg(isHttpResponseError?"false":"true").arg(errorCode)); - //App has load error policy, do not show platform load error page - return true; + if (m_loadErrorPolicy == "event") { + std::stringstream jss; + std::string genError = isHttpResponseError ? "false" : "true"; + jss <<"{" + << " console.log('[WAM3] create webOSLoadError event');" + << " var launchEvent=new CustomEvent('webOSLoadError', " + << " { detail : { genericError : " << genError << ", errorCode : " << errorCode << "}});" + << " document.dispatchEvent(launchEvent);" + << "}"; + //App has load error policy, do not show platform load error page + evaluateJavaScript(jss.str()); + return true; } return false; } -void WebPageBase::applyPolicyForUrlResponse(bool isMainFrame, const QString& url, int status_code) +void WebPageBase::applyPolicyForUrlResponse(bool isMainFrame, const std::string& urlStr, int status_code) { - QUrl qUrl(url); + Url url(urlStr); static const int s_httpErrorStatusCode = 400; - if (qUrl.scheme() != "file" && status_code >= s_httpErrorStatusCode) { + if (url.scheme() != "file" && status_code >= s_httpErrorStatusCode) { if(!hasLoadErrorPolicy(true, status_code) && isMainFrame) { // If app does not have policy for load error and // this error response is from main frame document // then before open server error page, reset the body's background color to white - setBackgroundColorOfBody(QStringLiteral("white")); + setBackgroundColorOfBody("white"); } } } @@ -381,39 +388,38 @@ void WebPageBase::postWebProcessCreated(uint32_t pid) WebAppManager::instance()->postWebProcessCreated(m_appId, pid); } -void WebPageBase::setBackgroundColorOfBody(const QString& color) +void WebPageBase::setBackgroundColorOfBody(const std::string& color) { // for error page only, set default background color to white by executing javascript - QString whiteBackground = QStringLiteral( - "(function() {" - " if(document.readyState === 'complete' || document.readyState === 'interactive') { " - " if(document.body.style.backgroundColor)" - " console.log('[Server Error] Already set document.body.style.backgroundColor');" - " else {" - " console.log('[Server Error] set background Color of body to %1');" - " document.body.style.backgroundColor = '%2';" - " }" - " } else {" - " document.addEventListener('DOMContentLoaded', function() {" - " if(document.body.style.backgroundColor)" - " console.log('[Server Error] Already set document.body.style.backgroundColor');" - " else {" - " console.log('[Server Error] set background Color of body to %3');" - " document.body.style.backgroundColor = '%4';" - " }" - " });" - " }" - "})();" - ).arg(color).arg(color).arg(color).arg(color); - evaluateJavaScript(whiteBackground); -} - -QString WebPageBase::defaultFont() -{ - QString defaultFont = "LG Display-Regular"; - QString language; - QString country; + std::stringstream jss; + jss << "(function() {" + << " if(document.readyState === 'complete' || document.readyState === 'interactive') { " + << " if(document.body.style.backgroundColor)" + << " console.log('[Server Error] Already set document.body.style.backgroundColor');" + << " else {" + << " console.log('[Server Error] set background Color of body to " << color << "');" + << " document.body.style.backgroundColor = '" << color << "';" + << " }" + << " } else {" + << " document.addEventListener('DOMContentLoaded', function() {" + << " if(document.body.style.backgroundColor)" + << " console.log('[Server Error] Already set document.body.style.backgroundColor');" + << " else {" + << " console.log('[Server Error] set background Color of body to " << color << "');" + << " document.body.style.backgroundColor = '" << color << "';" + << " }" + << " });" + << " }" + << "})();"; + evaluateJavaScript(jss.str()); +} + +std::string WebPageBase::defaultFont() +{ + std::string defaultFont = "LG Display-Regular"; + std::string language; getSystemLanguage(language); + std::string country; getDeviceInfo("LocalCountry", country); // for the model @@ -425,7 +431,8 @@ QString WebPageBase::defaultFont() else if(language == "ur-IN") defaultFont = "LG Display_Urdu"; - LOG_DEBUG("[%s] country : [%s], language : [%s], default font : [%s]", qPrintable(appId()), qPrintable(country), qPrintable(language), qPrintable(defaultFont)); + LOG_DEBUG("[%s] country : [%s], language : [%s], default font : [%s]", appId().c_str(), + country.c_str(), language.c_str(), defaultFont.c_str()); return defaultFont; } @@ -439,36 +446,36 @@ void WebPageBase::updateIsLoadErrorPageFinish() if (!url().isLocalFile()) return; - QString urlString = url().toString(); - QString urlFileName = url().fileName(); - QString errorPageFileName = QUrl(getWebAppManagerConfig()->getErrorPageUrl()).fileName(); - QString errorPageDirPath = getWebAppManagerConfig()->getErrorPageUrl().remove(errorPageFileName); - if (urlString.startsWith(errorPageDirPath) && !urlFileName.compare(errorPageFileName)) { - LOG_DEBUG("[%s] This is WAM ErrorPage; URL: %s ", qPrintable(appId()), qPrintable(urlString)); + fs::path urlPath(url().toLocalFile()); + fs::path urlFileName = urlPath.filename(); + fs::path urlDirPath = urlPath.parent_path(); + + fs::path errPath(Url(getWebAppManagerConfig()->getErrorPageUrl()).toLocalFile()); + fs::path errFileName = errPath.filename(); + fs::path errDirPath = errPath.parent_path(); + + if ((urlDirPath.string().find(errDirPath.string()) == 0) // urlDirPath starts with errDirPath + && urlFileName == errFileName) { + LOG_DEBUG("[%s] This is WAM ErrorPage; URL: %s ", appId().c_str(), url().toString().c_str()); m_isLoadErrorPageFinish = true; } } -#define URL_SIZE_LIMIT 768 -QString WebPageBase::truncateURL(const QString& url) -{ - if(url.size() < URL_SIZE_LIMIT) - return url; - QString res = QString(url); - return res.replace(URL_SIZE_LIMIT / 2, url.size() - URL_SIZE_LIMIT, QStringLiteral(" ... ")); -} - - void WebPageBase::setCustomUserScript() { // 1. check app folder has userScripts // 2. check userscript.js there is, appfolder/webOSUserScripts/*.js - QString userScriptFilePath = QDir(QString::fromStdString(m_appDesc->folderPath())).filePath(getWebAppManagerConfig()->getUserScriptPath()); - if(!QFileInfo(userScriptFilePath).isReadable()) + auto userScriptFilePath = fs::path(m_appDesc->folderPath()) / getWebAppManagerConfig()->getUserScriptPath(); + + if(!fs::exists(userScriptFilePath) || !fs::is_regular_file(fs::canonical(userScriptFilePath))) { + LOG_DEBUG("WebPageBase: Couldn't set '%s' as user script cause it does not exist/is a regular file.", + userScriptFilePath.string().c_str()); return; + } - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", getWebProcessPID()), "User Scripts exists : %s", qPrintable(userScriptFilePath)); - addUserScriptUrl(QUrl::fromLocalFile(userScriptFilePath)); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", getWebProcessPID()), + "User Scripts exists : %s", userScriptFilePath.string().c_str()); + addUserScriptUrl(Url::fromLocalFile(userScriptFilePath.string())); } void WebPageBase::addObserver(WebPageObserver* observer) diff --git a/src/core/WebPageBase.h b/src/core/WebPageBase.h index 5253e647..1798a214 100644 --- a/src/core/WebPageBase.h +++ b/src/core/WebPageBase.h @@ -18,12 +18,10 @@ #define WEBPAGEBASE_H #include - -#include -#include -#include +#include #include "ObserverList.h" +#include "Url.h" #include "webos/webview_base.h" @@ -37,9 +35,7 @@ class WebProcessManager; * Common base class for UI independent * web page functionality */ -class WebPageBase : public QObject { - Q_OBJECT - +class WebPageBase { public: // Originally, webview_base.h, WebPageVisibilityState.h, PageVisibilityState.h // we can use enum of webview_base.h directly but this is WebPageBase in core @@ -53,41 +49,41 @@ class WebPageBase : public QObject { }; WebPageBase(); - WebPageBase(const QUrl& url, std::shared_ptr desc, const QString& params); + WebPageBase(const Url& url, std::shared_ptr desc, const std::string& params); virtual ~WebPageBase(); // WebPageBase virtual void init() = 0; virtual void* getWebContents() = 0; - virtual void setLaunchParams(const QString& params); + virtual void setLaunchParams(const std::string& params); virtual void notifyMemoryPressure(webos::WebViewBase::MemoryPressureLevel level) {} - virtual QString getIdentifier() const; - virtual QUrl url() const = 0; /* return current url */ - virtual QUrl defaultUrl() const { return m_defaultUrl; } /* return default url */ - virtual void setDefaultUrl(QUrl url) { m_defaultUrl = url; } /* just set default url */ - virtual void replaceBaseUrl(QUrl newUrl) = 0; + virtual std::string getIdentifier() const; + virtual Url url() const = 0; /* return current url */ + virtual Url defaultUrl() const { return m_defaultUrl; } /* return default url */ + virtual void setDefaultUrl(const Url& url) { m_defaultUrl = url; } /* just set default url */ + virtual void replaceBaseUrl(const Url& newUrl) = 0; virtual void loadUrl(const std::string& url) = 0; virtual int progress() const = 0; virtual bool hasBeenShown() const = 0; virtual void setPageProperties() = 0; - virtual void setPreferredLanguages(const QString& language) = 0; - virtual QString defaultFont(); - virtual void setDefaultFont(const QString& font) = 0; + virtual void setPreferredLanguages(const std::string& language) = 0; + virtual std::string defaultFont(); + virtual void setDefaultFont(const std::string& font) = 0; virtual void cleanResources(); virtual void reloadDefaultPage() = 0; virtual void reload() = 0; virtual void setVisibilityState(WebPageVisibilityState visibilityState) = 0; virtual void setFocus(bool focus) = 0; - virtual QString title() = 0; + virtual std::string title() = 0; virtual bool canGoBack() = 0; virtual void closeVkb() = 0; virtual void keyboardVisibilityChanged(bool visible) {} virtual void updatePageSettings() = 0; - virtual void handleDeviceInfoChanged(const QString& deviceInfo) = 0; - virtual bool relaunch(const QString& args, const QString& launchingAppId); - virtual void evaluateJavaScript(const QString& jsCode) = 0; - virtual void evaluateJavaScriptInAllFrames(const QString& jsCode, const char* method = "") = 0; + virtual void handleDeviceInfoChanged(const std::string& deviceInfo) = 0; + virtual bool relaunch(const std::string& args, const std::string& launchingAppId); + virtual void evaluateJavaScript(const std::string& jsCode) = 0; + virtual void evaluateJavaScriptInAllFrames(const std::string& jsCode, const char* method = "") = 0; virtual void setForceActivateVtg(bool enabled) = 0; virtual uint32_t getWebProcessProxyID() = 0; virtual uint32_t getWebProcessPID() const = 0; @@ -109,7 +105,7 @@ class WebPageBase : public QObject { virtual bool isLoadErrorPageStart() { return m_isLoadErrorPageStart; } virtual void updateIsLoadErrorPageFinish(); virtual void updateDatabaseIdentifier() {} - virtual void deleteWebStorages(const QString& identifier) {} + virtual void deleteWebStorages(const std::string& identifier) {} virtual void setInspectorEnable() {} virtual void setKeepAliveWebApp(bool keepAlive) {} virtual void setContentsScale() {} @@ -119,17 +115,17 @@ class WebPageBase : public QObject { virtual void resetStateToMarkNextPaintForContainer() {} virtual bool isInputMethodActive() const { return false; } - QString launchParams() const; + std::string launchParams() const; void setApplicationDescription(std::shared_ptr desc); void load(); void setEnableBackgroundRun(bool enable) { m_enableBackgroundRun = enable; } - void sendLocaleChangeEvent(const QString& language); + void sendLocaleChangeEvent(const std::string& language); void setCleaningResources(bool cleaningResources) { m_cleaningResources = cleaningResources; } bool cleaningResources() const { return m_cleaningResources; } - bool doHostedWebAppRelaunch(const QString& launchParams); + bool doHostedWebAppRelaunch(const std::string& launchParams); void sendRelaunchEvent(); - void setAppId(const QString& appId) { m_appId = appId; } - const QString& appId() const { return m_appId; } + void setAppId(const std::string& appId) { m_appId = appId; } + const std::string& appId() const { return m_appId; } ApplicationDescription* getAppDescription() { return m_appDesc.get(); } void setClosing(bool status) { m_isClosing = status; } @@ -141,67 +137,52 @@ class WebPageBase : public QObject { void addObserver(WebPageObserver* observer); void removeObserver(WebPageObserver* observer); - static QString truncateURL(const QString& url); - -Q_SIGNALS: - void webPageUrlChanged(); - void webPageLoadFinished(); - void webPageLoadFailed(int errorCode); - void closeCallbackExecuted(); - void timeoutExecuteCloseCallback(); - void closingAppProcessDidCrashed(); - void didDispatchUnload(); - -protected Q_SLOTS: - virtual void urlChangedSlot(); - void doLoadSlot(); - virtual void suspendWebPagePaintingAndJSExecution() = 0; - protected: // WebPageBase virtual void cleanResourcesFinished(); virtual void handleForceDeleteWebPage(); virtual void loadDefaultUrl() = 0; - virtual void addUserScript(const QString& script) = 0; - virtual void addUserScriptUrl(const QUrl& url) = 0; + virtual void addUserScript(const std::string& script) = 0; + virtual void addUserScriptUrl(const Url& url) = 0; virtual int suspendDelay(); virtual bool hasLoadErrorPolicy(bool isHttpResponseError, int errorCode); virtual void loadErrorPage(int errorCode) = 0; virtual void recreateWebView() = 0; virtual void setVisible(bool visible) {} - virtual bool doDeeplinking(const QString& launchParams); + virtual bool doDeeplinking(const std::string& launchParams); + virtual void suspendWebPagePaintingAndJSExecution() = 0; void handleLoadStarted(); void handleLoadFinished(); void handleLoadFailed(int errorCode); - bool getDeviceInfo(QString name, QString& value); - bool getSystemLanguage(QString& value); + bool getDeviceInfo(const std::string& name, std::string& value); + bool getSystemLanguage(std::string& value); int currentUiWidth(); int currentUiHeight(); WebProcessManager* getWebProcessManager(); WebAppManagerConfig* getWebAppManagerConfig(); bool processCrashed(); - QString telluriumNubPath(); + std::string telluriumNubPath(); - void applyPolicyForUrlResponse(bool isMainFrame, const QString& url, int statusCode); + void applyPolicyForUrlResponse(bool isMainFrame, const std::string& url, int statusCode); void postRunningAppList(); void postWebProcessCreated(uint32_t pid); bool isAccessibilityEnabled() const; std::shared_ptr m_appDesc; - QString m_appId; + std::string m_appId; bool m_suspendAtLoad; bool m_isClosing; bool m_isLoadErrorPageFinish; bool m_isLoadErrorPageStart; bool m_enableBackgroundRun; - QUrl m_defaultUrl; - QString m_launchParams; - QString m_loadErrorPolicy; + Url m_defaultUrl; + std::string m_launchParams; + std::string m_loadErrorPolicy; ObserverList m_observers; private: - void setBackgroundColorOfBody(const QString& color); + void setBackgroundColorOfBody(const std::string& color); void setupLaunchEvent(); bool m_cleaningResources; diff --git a/src/core/WebPageObserver.h b/src/core/WebPageObserver.h index cf3982f9..4a1124f5 100644 --- a/src/core/WebPageObserver.h +++ b/src/core/WebPageObserver.h @@ -24,6 +24,15 @@ class WebPageObserver { virtual void titleChanged() {} virtual void firstFrameVisuallyCommitted() {} virtual void navigationHistoryChanged() {} + virtual void webPageLoadFinished() {} + virtual void webPageLoadFailed(int errorCode) {} + virtual void closeCallbackExecuted() {} + virtual void timeoutExecuteCloseCallback() {} + virtual void closingAppProcessDidCrashed() {} + virtual void didDispatchUnload() {} + virtual void webPageClosePageRequested() {} + virtual void webViewRecreated() {} + virtual void compositorFrameSwapped() {} protected: WebPageObserver(WebPageBase* page); diff --git a/src/core/WebProcessManager.cpp b/src/core/WebProcessManager.cpp index 802a12f5..9d4b29d4 100644 --- a/src/core/WebProcessManager.cpp +++ b/src/core/WebProcessManager.cpp @@ -16,21 +16,23 @@ #include "WebProcessManager.h" +#include +#include +#include +#include +#include #include -#include -#include -#include #include "ApplicationDescription.h" +#include "JsonHelper.h" #include "LogManager.h" +#include "StringUtils.h" #include "WebAppBase.h" #include "WebAppManagerConfig.h" #include "WebAppManagerUtils.h" #include "WebAppManager.h" #include "WebPageBase.h" -#include - WebProcessManager::WebProcessManager() : m_maximumNumberOfProcesses(1) { @@ -47,7 +49,7 @@ std::list WebProcessManager::runningApps(uint32_t pid) return WebAppManager::instance()->runningApps(pid); } -WebAppBase* WebProcessManager::findAppById(const QString& appId) +WebAppBase* WebProcessManager::findAppById(const std::string& appId) { return WebAppManager::instance()->findAppById(appId); } @@ -61,7 +63,7 @@ bool WebProcessManager::webProcessInfoMapReady() { uint32_t count = 0; for (const auto& it : m_webProcessInfoMap) { - if (it.proxyID != 0) + if (it.second.proxyID != 0) count++; } @@ -73,81 +75,73 @@ uint32_t WebProcessManager::getWebProcessProxyID(const ApplicationDescription *d if (!desc) return 0; - QString key = getProcessKey(desc); - - QMap::const_iterator it = m_webProcessInfoMap.find(key); - if (it == m_webProcessInfoMap.end() || !it.value().proxyID) { + std::string key = getProcessKey(desc); + auto it = m_webProcessInfoMap.find(key); + if (it == m_webProcessInfoMap.end() || !it->second.proxyID) { return getInitialWebViewProxyID(); } - return it.value().proxyID; + return it->second.proxyID; } uint32_t WebProcessManager::getWebProcessProxyID(uint32_t pid) const { - for (QMap::const_iterator it = m_webProcessInfoMap.begin(); it != m_webProcessInfoMap.end(); it++) { - if (it.value().webProcessPid == pid) - return it.value().proxyID; + for (const auto& it : m_webProcessInfoMap) { + if (it.second.webProcessPid == pid) + return it.second.proxyID; } return 0; } -QString WebProcessManager::getWebProcessMemSize(uint32_t pid) const +// TODO: Refactor to use C++ stream/string API +std::string WebProcessManager::getWebProcessMemSize(uint32_t pid) const { - QString filePath = QString("/proc/") + QString::number(pid) + QString("/status"); - FILE *fd = fopen(filePath.toStdString().c_str(), "r"); - QString vmrss; - char line[128]; + std::string path = "/proc/" + std::to_string(pid) + "/status"; + std::ifstream in(path); - if (!fd) - return vmrss; + if (!in.is_open()) + return {}; - while (fgets(line, 128, fd) != NULL) { - if(!strncmp(line, "VmRSS:", 6)) { - vmrss = QString(&line[8]); - break; + std::string line; + while (std::getline(in, line)) { + if(!line.find("VmRSS:", 0, 6)) { + return trimString(std::string(line, 6)); } } - - fclose(fd); - return vmrss.simplified(); + return {}; } void WebProcessManager::readWebProcessPolicy() { - QString webProcessConfigurationPath = WebAppManager::instance()->config()->getWebProcessConfigPath(); - - QFile file(webProcessConfigurationPath); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) - return; - - QString jsonStr = file.readAll(); - file.close(); + Json::Value webProcessEnvironment; + std::string configPath = WebAppManager::instance()->config()->getWebProcessConfigPath(); + bool configOk = readJsonFromFile(configPath, webProcessEnvironment); - QJsonDocument webProcessEnvironment = QJsonDocument::fromJson(jsonStr.toUtf8()); - if (webProcessEnvironment.isNull()) { - LOG_ERROR(MSGID_WEBPROCESSENV_READ_FAIL, 1, PMLOGKS("CONTENT", jsonStr.toStdString().c_str()), ""); + if (!configOk || webProcessEnvironment.isNull()) { + LOG_ERROR(MSGID_WEBPROCESSENV_READ_FAIL, 1, PMLOGKS("PATH", configPath.c_str()), "JSON parsging failed"); return; } - bool createProcessForEachApp = webProcessEnvironment.object().value("createProcessForEachApp").toBool(); - if (createProcessForEachApp) + auto createProcessForEachApp = webProcessEnvironment["createProcessForEachApp"]; + if (createProcessForEachApp.isBool() && createProcessForEachApp.asBool()) m_maximumNumberOfProcesses = UINT_MAX; else { - QJsonArray webProcessArray = webProcessEnvironment.object().value("webProcessList").toArray(); - Q_FOREACH (const QJsonValue &value, webProcessArray) { - QJsonObject obj = value.toObject(); - if (!obj.value("id").isUndefined()) { - QString id = obj.value("id").toString(); - - m_webProcessGroupAppIDList.append(id); - setWebProcessCacheProperty(obj, id); - } - else if (!obj.value("trustLevel").isUndefined()) { - QString trustLevel = obj.value("trustLevel").toString(); + auto webProcessArray = webProcessEnvironment["webProcessList"]; + if (webProcessArray.isArray()) { + for (const auto &value : webProcessArray) { + if (!value.isObject()) + continue; + auto id = value["id"]; + if (id.isString()) { + m_webProcessGroupAppIDList.push_back(id.asString()); + setWebProcessCacheProperty(value, id.asString()); + } + auto trustLevel = value["trustLevel"]; + if (trustLevel.isString()) { + m_webProcessGroupTrustLevelList.push_back(trustLevel.asString()); + setWebProcessCacheProperty(value, trustLevel.asString()); + } - m_webProcessGroupTrustLevelList.append(trustLevel); - setWebProcessCacheProperty(obj, trustLevel); } } m_maximumNumberOfProcesses = (m_webProcessGroupTrustLevelList.size() + m_webProcessGroupAppIDList.size()); @@ -158,85 +152,78 @@ void WebProcessManager::readWebProcessPolicy() PMLOGKFV("GROUP_APP_IDS_COUNT", "%d", m_webProcessGroupAppIDList.size()), ""); } -void WebProcessManager::setWebProcessCacheProperty(QJsonObject object, QString key) +void WebProcessManager::setWebProcessCacheProperty(const Json::Value &object, const std::string &key) { WebProcessInfo info = WebProcessInfo(0, 0); - QString memoryCacheStr, codeCacheStr; - if (!object.value("memoryCache").isUndefined()) { - memoryCacheStr = object.value("memoryCache").toString(); - if (memoryCacheStr.contains("MB")) - memoryCacheStr.remove(QString("MB")); - - if (memoryCacheStr.toUInt()) - info.memoryCacheSize = memoryCacheStr.toUInt(); + auto memoryCache = object["memoryCache"]; + if (memoryCache.isString()) { + info.memoryCacheSize = stringTo(memoryCache.asString()); } - if (!object.value("codeCache").isUndefined()) { - codeCacheStr = object.value("codeCache").toString(); - if (codeCacheStr.contains("MB")) - codeCacheStr.remove(QString("MB")); - - if (codeCacheStr.toUInt()) - info.codeCacheSize = codeCacheStr.toUInt(); + auto codeCache = object["codeCache"]; + if (codeCache.isString()) { + info.codeCacheSize = stringTo(codeCache.asString()); } - m_webProcessInfoMap.insert(key, info); + m_webProcessInfoMap.emplace(key, info); } -QString WebProcessManager::getProcessKey(const ApplicationDescription* desc) const +std::string WebProcessManager::getProcessKey(const ApplicationDescription* desc) const { if (!desc) - return QString(); + return {}; - QString key; - QStringList idList, trustLevelList; + std::string key; + std::vector idList, trustLevelList; if (m_maximumNumberOfProcesses == 1) - key = QStringLiteral("system"); + key = "system"; else if (m_maximumNumberOfProcesses == UINT_MAX) { if (desc->trustLevel() == "default" || desc->trustLevel() == "trusted") - key = QStringLiteral("system"); + key = "system"; else - key = desc->id().c_str(); + key = desc->id(); } else { - for (int i = 0; i < m_webProcessGroupAppIDList.size(); i++) { - QString appId = m_webProcessGroupAppIDList.at(i); - if (appId.contains("*")) { - appId.remove(QChar('*')); - idList.append(appId.split(",")); - Q_FOREACH(QString id, idList) { - if (QString::fromUtf8(desc->id().c_str()).startsWith(id)) + for (size_t i = 0; i < m_webProcessGroupAppIDList.size(); i++) { + std::string appId = m_webProcessGroupAppIDList.at(i); + if (appId.find('*') != std::string::npos) { + replaceSubstrings(appId, "*"); + auto l = splitString(appId, ','); + idList.insert(idList.end(), l.begin(), l.end()); + for (auto id : idList) + // TODO: Move to StringUtils? (startsWith()) + if (!desc->id().compare(0, id.size(), id)) key = m_webProcessGroupAppIDList.at(i); - } } else { - idList.append(appId.split(",")); - Q_FOREACH(QString id, idList) { - if (!id.compare(desc->id().c_str())) + auto l = splitString(appId, ','); + idList.insert(idList.end(), l.begin(), l.end()); + for (auto id : idList) + if (id == desc->id()) return m_webProcessGroupAppIDList.at(i); - } } } - if (!key.isEmpty()) + if (!key.empty()) return key; - for (int i = 0; i < m_webProcessGroupTrustLevelList.size(); i++) { - QString trustLevel = m_webProcessGroupTrustLevelList.at(i); - trustLevelList.append(trustLevel.split(",")); - Q_FOREACH(QString trust, trustLevelList) { - if (!trust.compare(desc->trustLevel().c_str())) { + for (size_t i = 0; i < m_webProcessGroupTrustLevelList.size(); i++) { + std::string trustLevel = m_webProcessGroupTrustLevelList.at(i); + auto l = splitString(trustLevel, ','); + trustLevelList.insert(trustLevelList.end(), l.begin(), l.end()); + for (auto trust : trustLevelList) { + if (trust == desc->trustLevel()) { return m_webProcessGroupTrustLevelList.at(i); } } } - key = QStringLiteral("system"); + key = "system"; } return key; } void WebProcessManager::killWebProcess(uint32_t pid) { - for(QMap::iterator it = m_webProcessInfoMap.begin(); it != m_webProcessInfoMap.end(); it++) { - if (it.value().webProcessPid == pid) { - it.value().requestKill = false; + for(auto &it : m_webProcessInfoMap) { + if (it.second.webProcessPid == pid) { + it.second.requestKill = false; break; } } @@ -249,10 +236,10 @@ void WebProcessManager::killWebProcess(uint32_t pid) void WebProcessManager::requestKillWebProcess(uint32_t pid) { - for (QMap::iterator it = m_webProcessInfoMap.begin(); it != m_webProcessInfoMap.end(); it++) { - if (it.value().webProcessPid == pid) { + for(auto &it : m_webProcessInfoMap) { + if (it.second.webProcessPid == pid) { LOG_INFO(MSGID_KILL_WEBPROCESS_DELAYED, 1, PMLOGKFV("PID", "%u", pid), ""); - it.value().requestKill = true; + it.second.requestKill = true; return; } } diff --git a/src/core/WebProcessManager.h b/src/core/WebProcessManager.h index cf5c78bb..333362f3 100644 --- a/src/core/WebProcessManager.h +++ b/src/core/WebProcessManager.h @@ -18,16 +18,17 @@ #define WEBPROCESSMANAGER_H #include - -#include -#include -#include -#include +#include +#include class ApplicationDescription; class WebPageBase; class WebAppBase; +namespace Json { +class Value; +} + class WebProcessManager { public: WebProcessManager(); @@ -35,25 +36,27 @@ class WebProcessManager { uint32_t getWebProcessProxyID(const ApplicationDescription* desc) const; uint32_t getWebProcessProxyID(uint32_t pid) const; - QString getWebProcessMemSize(uint32_t pid) const; //change name from webProcessSize(uint32_t pid) + std::string getWebProcessMemSize(uint32_t pid) const; //change name from webProcessSize(uint32_t pid) void killWebProcess(uint32_t pid); void requestKillWebProcess(uint32_t pid); bool webProcessInfoMapReady(); - void setWebProcessCacheProperty(QJsonObject object, QString key); //change name from setWebProcessProperty() + void setWebProcessCacheProperty(const Json::Value &object, const std::string& key); //change name from setWebProcessProperty() void readWebProcessPolicy(); //chane name from setWebProcessEnvironment() - QString getProcessKey(const ApplicationDescription* desc) const; //change name from getKey() + std::string getProcessKey(const ApplicationDescription* desc) const; //change name from getKey() - virtual QJsonObject getWebProcessProfiling() = 0; + virtual Json::Value getWebProcessProfiling() = 0; virtual uint32_t getWebProcessPID(const WebAppBase* app) const = 0; - virtual void deleteStorageData(const QString& identifier) = 0; + virtual void deleteStorageData(const std::string& identifier) = 0; virtual uint32_t getInitialWebViewProxyID() const = 0; virtual void clearBrowsingData(const int removeBrowsingDataMask) = 0; virtual int maskForBrowsingDataType(const char* type) = 0; + virtual void buildWebViewProfile(const std::string& app_id, const std::string& proxy_host, const std::string& proxy_port) = 0; + virtual void deleteWebViewProfile(const std::string& app_id) = 0; protected: std::list runningApps(); std::list runningApps(uint32_t pid); - WebAppBase* findAppById(const QString& appId); + WebAppBase* findAppById(const std::string& appId); WebAppBase* getContainerApp(); protected: @@ -82,11 +85,11 @@ class WebProcessManager { uint32_t codeCacheSize; bool requestKill; }; - QMap m_webProcessInfoMap; + std::unordered_map m_webProcessInfoMap; uint32_t m_maximumNumberOfProcesses; - QList m_webProcessGroupAppIDList; - QList m_webProcessGroupTrustLevelList; + std::vector m_webProcessGroupAppIDList; + std::vector m_webProcessGroupTrustLevelList; }; #endif /* WEBPROCESSMANAGER_H */ diff --git a/src/core/WebRuntime.h b/src/core/WebRuntime.h new file mode 100644 index 00000000..0b8d035e --- /dev/null +++ b/src/core/WebRuntime.h @@ -0,0 +1,12 @@ +#ifndef WEB_RUNTIME_H +#define WEB_RUNTIME_H + +#include +#include + +class WebRuntime { +public: + virtual int run(int argc, const char** argv) = 0; +}; + +#endif // WEB_RUNTIME_H diff --git a/src/core/WindowTypes.cpp b/src/core/WindowTypes.cpp new file mode 100644 index 00000000..266aac37 --- /dev/null +++ b/src/core/WindowTypes.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2008-2018 LG Electronics, Inc. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#include "WindowTypes.h" + +const char WT_CARD[] = "_WEBOS_WINDOW_TYPE_CARD"; +const char WT_POPUP[] = "_WEBOS_WINDOW_TYPE_POPUP"; +const char WT_MINIMAL[] = "_WEBOS_WINDOW_TYPE_RESTRICTED"; +const char WT_OVERLAY[] = "_WEBOS_WINDOW_TYPE_OVERLAY"; +const char WT_NONE[] = "_WEBOS_WINDOW_TYPE_NONE"; +const char WT_FLOATING[] = "_WEBOS_WINDOW_TYPE_FLOATING"; +const char WT_UNKNOWN[] = "_WEBOS_WINDOW_TYPE_UNKNOWN"; +const char WT_SYSTEM_UI[] = "_WEBOS_WINDOW_TYPE_SYSTEM_UI"; + diff --git a/src/core/WindowTypes.h b/src/core/WindowTypes.h index b3a57837..66d1cb6d 100644 --- a/src/core/WindowTypes.h +++ b/src/core/WindowTypes.h @@ -1,13 +1,29 @@ +// Copyright (c) 2008-2018 LG Electronics, Inc. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + #ifndef _WINDOWTYPES_H_ #define _WINDOWTYPES_H_ -#define WT_CARD QStringLiteral("_WEBOS_WINDOW_TYPE_CARD") -#define WT_POPUP QStringLiteral("_WEBOS_WINDOW_TYPE_POPUP") -#define WT_MINIMAL QStringLiteral("_WEBOS_WINDOW_TYPE_RESTRICTED") -#define WT_OVERLAY QStringLiteral("_WEBOS_WINDOW_TYPE_OVERLAY") -#define WT_NONE QStringLiteral("_WEBOS_WINDOW_TYPE_NONE") -#define WT_FLOATING QStringLiteral("_WEBOS_WINDOW_TYPE_FLOATING") -#define WT_UNKNOWN QStringLiteral("_WEBOS_WINDOW_TYPE_UNKNOWN") -#define WT_SYSTEM_UI QStringLiteral("_WEBOS_WINDOW_TYPE_SYSTEM_UI") +extern const char WT_CARD[]; +extern const char WT_POPUP[]; +extern const char WT_MINIMAL[]; +extern const char WT_OVERLAY[]; +extern const char WT_NONE[]; +extern const char WT_FLOATING[]; +extern const char WT_UNKNOWN[]; +extern const char WT_SYSTEM_UI[]; #endif // _WINDOWTYPES_H_ diff --git a/src/platform/PalmSystemWebOS.cpp b/src/platform/PalmSystemWebOS.cpp index e011abe4..fda015d0 100644 --- a/src/platform/PalmSystemWebOS.cpp +++ b/src/platform/PalmSystemWebOS.cpp @@ -17,29 +17,28 @@ #include "PalmSystemWebOS.h" #include "ApplicationDescription.h" +#include "JsonHelper.h" #include "LogManager.h" #include "WebAppBase.h" #include "WebAppWayland.h" #include "WebPageBase.h" -#include -#include -#include +#include PalmSystemWebOS::PalmSystemWebOS(WebAppBase* app) : m_app(static_cast(app)) - , m_launchParams(QString()) + , m_launchParams() { } -void PalmSystemWebOS::setLaunchParams(const QString& params) +void PalmSystemWebOS::setLaunchParams(const std::string& params) { - QString p = params; - QJsonDocument jsonDoc = QJsonDocument::fromJson(QByteArray(params.toStdString().c_str())); - QJsonObject jsonObject = jsonDoc.object(); + std::string p = params; + Json::Value jsonDoc; + readJsonFromString(params, jsonDoc); - if (jsonDoc.isEmpty() || jsonObject.isEmpty()) - p = QString(); + if (jsonDoc.isNull()) + p = ""; m_launchParams = p; } @@ -56,7 +55,8 @@ bool PalmSystemWebOS::isKeyboardVisible() const bool PalmSystemWebOS::isMinimal() const { - return QFile::exists("/var/luna/preferences/ran-firstuse"); + using boost::filesystem::exists; + return exists("/var/luna/preferences/ran-firstuse"); } int PalmSystemWebOS::activityId() const @@ -75,14 +75,13 @@ void PalmSystemWebOS::activate() // ask compositor to raise window. Compositor should raise us, then // give us focus, so we shouldn't have to specifically request focus. - LOG_DEBUG("[%s] called webOSSystem.activate() from the app, call raise() to make full screen", qPrintable(m_app->appId())); - + LOG_DEBUG("[%s] called webOSSystem.activate() from the app, call raise() to make full screen", m_app->appId().c_str()); m_app->raise(); } void PalmSystemWebOS::deactivate() { - LOG_DEBUG("[%s] called webOSSystem.deactivate() from the app, call goBackground() to go background", qPrintable(m_app->appId())); + LOG_DEBUG("[%s] called webOSSystem.deactivate() from the app, call goBackground() to go background", m_app->appId().c_str()); m_app->goBackground(); } @@ -101,20 +100,22 @@ void PalmSystemWebOS::hide() m_app->hide(); } -void PalmSystemWebOS::setInputRegion(const QByteArray& params) +void PalmSystemWebOS::setInputRegion(const std::string& params) { // this function is not related to windowGroup anymore - QJsonDocument jsonDoc = QJsonDocument::fromJson(params); - m_app->setInputRegion(jsonDoc); + Json::Value obj; + readJsonFromString(params, obj); + m_app->setInputRegion(obj); } -void PalmSystemWebOS::setGroupClientEnvironment(GroupClientCallKey callKey, const QByteArray& params) +void PalmSystemWebOS::setGroupClientEnvironment(GroupClientCallKey callKey, const std::string& params) { ApplicationDescription* appDesc = m_app ? m_app->getAppDescription() : 0; if (appDesc) { ApplicationDescription::WindowGroupInfo groupInfo = appDesc->getWindowGroupInfo(); - if (!groupInfo.name.isEmpty() && !groupInfo.isOwner) { - QJsonDocument jsonDoc = QJsonDocument::fromJson(params); + if (!groupInfo.name.empty() && !groupInfo.isOwner) { + Json::Value jsonDoc; + readJsonFromString(params, jsonDoc); switch (callKey) { case KeyMask: m_app->setKeyMask(jsonDoc); @@ -138,29 +139,31 @@ void PalmSystemWebOS::setKeepAlive(bool keep) m_app->setKeepAlive(keep); } -void PalmSystemWebOS::pmLogInfoWithClock(const QVariant& msgid, const QVariant& perfType, const QVariant& perfGroup) +#ifdef HAS_PMLOG +void PalmSystemWebOS::pmLogInfoWithClock(const std::string& msgid, const std::string& perfType, const std::string& perfGroup) { PmLogContext context; - PmLogGetContext(qPrintable(m_app->page()->appId()), &context); - PmLogInfoWithClock(context, msgid.toByteArray().size() ? msgid.toByteArray().data() : NULL, 2, - PMLOGKS("PerfType", perfType.toByteArray().size() ? perfType.toByteArray().data() : "empty"), - PMLOGKS("PerfGroup", perfGroup.toByteArray().size() ? perfGroup.toByteArray().data() : "empty"), ""); + PmLogGetContext(m_app->page()->appId().c_str(), &context); + PmLogInfoWithClock(context, msgid.size() ? msgid.c_str() : NULL, 2, + PMLOGKS("PerfType", perfType.size() ? perfType.c_str() : "empty"), + PMLOGKS("PerfGroup", perfGroup.size() ? perfGroup.c_str() : "empty"), ""); } -void PalmSystemWebOS::pmLogString(PmLogLevel level, const QVariant& msgid, const QVariant& kvpairs, const QVariant& message) +void PalmSystemWebOS::pmLogString(PmLogLevel level, const std::string& msgid, const std::string& kvpairs, const std::string& message) { PmLogContext context; - PmLogGetContext(qPrintable(m_app->page()->appId()), &context); - PmLogString(context, level, msgid.toByteArray().size() ? msgid.toByteArray().data() : NULL, - kvpairs.toByteArray().size() ? kvpairs.toByteArray().data() : NULL, message.toByteArray().data()); + PmLogGetContext(m_app->page()->appId().c_str(), &context); + PmLogString(context, level, msgid.size() ? msgid.c_str() : NULL, + kvpairs.size() ? kvpairs.c_str() : NULL, message.c_str()); } +#endif bool PalmSystemWebOS::cursorVisibility() { return m_app->cursorVisibility(); } -void PalmSystemWebOS::updateLaunchParams(const QString& launchParams) +void PalmSystemWebOS::updateLaunchParams(const std::string& launchParams) { m_app->page()->setLaunchParams(launchParams); } diff --git a/src/platform/PalmSystemWebOS.h b/src/platform/PalmSystemWebOS.h index 52c00913..2daaf881 100644 --- a/src/platform/PalmSystemWebOS.h +++ b/src/platform/PalmSystemWebOS.h @@ -18,7 +18,14 @@ #define PALMSYSTEMWEBOS_H_ #include "PalmSystemBase.h" + +#ifdef HAS_PMLOG #include +#endif + +namespace Json { +class Value; +}; class WebAppBase; class WebAppWayland; @@ -28,8 +35,8 @@ class PalmSystemWebOS : public PalmSystemBase { PalmSystemWebOS(WebAppBase* app); virtual void setCountry() {} - virtual void setFolderPath(const QString& params) {} - virtual void setLaunchParams(const QString& params); + virtual void setFolderPath(const std::string& params) {} + virtual void setLaunchParams(const std::string& params); protected: enum GroupClientCallKey { @@ -38,12 +45,12 @@ class PalmSystemWebOS : public PalmSystemBase { FocusLayer }; - virtual QString identifier() const = 0; - virtual QString launchParams() const { return m_launchParams; } - virtual QString version() const { return QString(); } + virtual std::string identifier() const = 0; + virtual std::string launchParams() const { return m_launchParams; } + virtual std::string version() const { return {}; } - virtual QString screenOrientation() const { return QString("up"); } - virtual QString windowOrientation() const { return QString("free"); } + virtual std::string screenOrientation() const { return "up"; } + virtual std::string windowOrientation() const { return "free"; } virtual bool isActivated() const; virtual bool isKeyboardVisible() const; @@ -58,18 +65,19 @@ class PalmSystemWebOS : public PalmSystemBase { virtual void hide(); virtual void setKeepAlive(bool keep); - virtual void setLoadErrorPolicy(const QString& params) {} - virtual void setInputRegion(const QByteArray& params); - virtual void setGroupClientEnvironment(GroupClientCallKey callKey, const QByteArray& params); - - virtual void pmLogInfoWithClock(const QVariant& msgid, const QVariant& perfType, const QVariant& perfGroup); - virtual void pmLogString(PmLogLevel level, const QVariant& msgid, const QVariant& kvpairs, const QVariant& message); + virtual void setLoadErrorPolicy(const std::string& params) {} + virtual void setInputRegion(const std::string& params); + virtual void setGroupClientEnvironment(GroupClientCallKey callKey, const std::string& params); +#ifdef HAS_PMLOG + virtual void pmLogInfoWithClock(const std::string& msgid, const std::string& perfType, const std::string& perfGroup); + virtual void pmLogString(PmLogLevel level, const std::string& msgid, const std::string& kvpairs, const std::string& message); +#endif virtual bool cursorVisibility(); - virtual void updateLaunchParams(const QString& launchParams); + virtual void updateLaunchParams(const std::string& launchParams); protected: WebAppWayland* m_app; - QString m_launchParams; + std::string m_launchParams; }; #endif // PALMSYSTEMWEBOS_H_ diff --git a/src/platform/WebAppWayland.cpp b/src/platform/WebAppWayland.cpp index 95df4279..6db0868e 100644 --- a/src/platform/WebAppWayland.cpp +++ b/src/platform/WebAppWayland.cpp @@ -16,12 +16,15 @@ #include "WebAppWayland.h" -#include -#include +#include +#include +#include #include "ApplicationDescription.h" #include "LogManager.h" +#include "StringUtils.h" #include "WebAppWaylandWindow.h" +#include "WebAppManagerUtils.h" #include "WebPageBase.h" #include "WindowTypes.h" @@ -33,15 +36,16 @@ static int kLaunchFinishAssureTimeoutMs = 5000; #define URL_SIZE_LIMIT 512 -static QString truncateURL(const QString& url) +static std::string truncateURL(const std::string& url) { if(url.size() < URL_SIZE_LIMIT) return url; - QString res = QString(url); - return res.replace(URL_SIZE_LIMIT / 2, url.size() - URL_SIZE_LIMIT, QStringLiteral(" ... ")); + std::stringstream res; + res << url.substr(0, URL_SIZE_LIMIT/2) << " ... "; + return res.str(); } -WebAppWayland::WebAppWayland(QString type, int width, int height) +WebAppWayland::WebAppWayland(const std::string& type, int surface_id, int width, int height) : WebAppBase() , m_appWindow(0) , m_windowType(type) @@ -51,10 +55,10 @@ WebAppWayland::WebAppWayland(QString type, int width, int height) , m_vkbHeight(0) , m_lostFocusBySetWindowProperty(false) { - init(width, height); + init(width, height, surface_id); } -WebAppWayland::WebAppWayland(QString type, WebAppWaylandWindow* window, int width, int height) +WebAppWayland::WebAppWayland(const std::string& type, WebAppWaylandWindow* window, int width, int height) : WebAppBase() , m_appWindow(window) , m_windowType(type) @@ -64,7 +68,7 @@ WebAppWayland::WebAppWayland(QString type, WebAppWaylandWindow* window, int widt , m_vkbHeight(0) , m_lostFocusBySetWindowProperty(false) { - init(width, height); + init(width, height, 0); } WebAppWayland::~WebAppWayland() @@ -72,10 +76,11 @@ WebAppWayland::~WebAppWayland() delete m_appWindow; } -void WebAppWayland::init(int width, int height) +void WebAppWayland::init(int width, int height, int surface_id) { if (!m_appWindow) - m_appWindow = WebAppWaylandWindow::take(); + m_appWindow = WebAppWaylandWindow::take(surface_id); + m_appWindow->SetWindowSurfaceId(surface_id); if (!(width && height)) { setUiSize(m_appWindow->DisplayWidth(), m_appWindow->DisplayHeight()); m_appWindow->InitWindow(m_appWindow->DisplayWidth(), m_appWindow->DisplayHeight()); @@ -88,11 +93,13 @@ void WebAppWayland::init(int width, int height) m_appWindow->setWebApp(this); // set compositor window type - setWindowProperty(QStringLiteral("_WEBOS_WINDOW_TYPE"), m_windowType); - LOG_DEBUG("App created window [%s]", qPrintable(m_windowType)); + setWindowProperty("_WEBOS_WINDOW_TYPE", m_windowType); + LOG_DEBUG("App created window [%s]", m_windowType.c_str()); - if (qgetenv("LAUNCH_FINISH_ASSURE_TIMEOUT").toInt() != 0) - kLaunchFinishAssureTimeoutMs = qgetenv("LAUNCH_FINISH_ASSURE_TIMEOUT").toInt(); + try { + std::string launchTimeoutStr = WebAppManagerUtils::getEnv("LAUNCH_FINISH_ASSURE_TIMEOUT"); + kLaunchFinishAssureTimeoutMs = stringTo(launchTimeoutStr); + } catch(...) {} if (!webos::WebOSPlatform::GetInstance()->GetInputPointer()) { // Create InputManager instance. @@ -103,7 +110,7 @@ void WebAppWayland::init(int width, int height) void WebAppWayland::startLaunchTimer() { if(!getHiddenWindow()) { - LOG_DEBUG("APP_LAUNCHTIME_CHECK_STARTED [appId:%s]", qPrintable(appId())); + LOG_DEBUG("APP_LAUNCHTIME_CHECK_STARTED [appId:%s]", appId().c_str()); m_elapsedLaunchTimer.start(); } } @@ -125,7 +132,7 @@ void WebAppWayland::onLaunchTimeout() if(m_elapsedLaunchTimer.isRunning()) { m_launchTimeoutTimer.stop(); m_elapsedLaunchTimer.stop(); - LOG_DEBUG("APP_LAUNCHTIME_CHECK_ALL_FRAMES_DONE [appId:%s time:%d]", qPrintable(appId()), m_lastSwappedTime); + LOG_DEBUG("APP_LAUNCHTIME_CHECK_ALL_FRAMES_DONE [appId:%s time:%d]", appId().c_str(), m_lastSwappedTime); } } @@ -138,25 +145,17 @@ void WebAppWayland::attach(WebPageBase *page) { WebAppBase::attach(page); - setWindowProperty(QStringLiteral("appId"), appId()); - setWindowProperty(QStringLiteral("launchingAppId"), launchingAppId()); - setWindowProperty(QStringLiteral("title"), - QString::fromStdString(getAppDescription()->title())); - setWindowProperty(QStringLiteral("icon"), - QString::fromStdString(getAppDescription()->icon())); - setWindowProperty(QStringLiteral("subtitle"), QStringLiteral("")); - setWindowProperty(QStringLiteral("_WEBOS_WINDOW_CLASS"), - QVariant((int)getAppDescription()->windowClassValue())); - setWindowProperty(QStringLiteral("_WEBOS_ACCESS_POLICY_KEYS_BACK"), - getAppDescription()->backHistoryAPIDisabled() - ? QStringLiteral("true") : QStringLiteral("false")); - setWindowProperty(QStringLiteral("_WEBOS_ACCESS_POLICY_KEYS_EXIT"), - getAppDescription()->handleExitKey() - ? QStringLiteral("true") : QStringLiteral("false")); - setKeyMask(webos::WebOSKeyMask::KEY_MASK_BACK, - getAppDescription()->backHistoryAPIDisabled()); - setKeyMask(webos::WebOSKeyMask::KEY_MASK_EXIT, - getAppDescription()->handleExitKey()); + setWindowProperty("appId", appId()); + setWindowProperty("launchingAppId", launchingAppId()); + setWindowProperty("title", getAppDescription()->title()); + setWindowProperty("icon", getAppDescription()->icon()); + setWindowProperty("subtitle", ""); + setWindowProperty("_WEBOS_WINDOW_CLASS", std::to_string((int)getAppDescription()->windowClassValue())); + setWindowProperty("_WEBOS_ACCESS_POLICY_KEYS_BACK", getAppDescription()->backHistoryAPIDisabled() ? "true" : "false"); + setWindowProperty("_WEBOS_ACCESS_POLICY_KEYS_EXIT", getAppDescription()->handleExitKey() ? "true" : "false"); + + setKeyMask(webos::WebOSKeyMask::KEY_MASK_BACK, getAppDescription()->backHistoryAPIDisabled()); + setKeyMask(webos::WebOSKeyMask::KEY_MASK_EXIT, getAppDescription()->handleExitKey()); if (getAppDescription()->widthOverride() && getAppDescription()->heightOverride()) { float scaleX = static_cast(m_appWindow->DisplayWidth()) / getAppDescription()->widthOverride(); @@ -225,7 +224,7 @@ void WebAppWayland::onStageActivated() executingStageActivated = true; if (getCrashState()) { - LOG_INFO(MSGID_WEBAPP_STAGE_ACITVATED, 3, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), PMLOGKS("getCrashState()", "true; Reload default Page"), ""); + LOG_INFO(MSGID_WEBAPP_STAGE_ACITVATED, 3, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), PMLOGKS("getCrashState()", "true; Reload default Page"), ""); page()->reloadDefaultPage(); setCrashState(false); } @@ -240,7 +239,7 @@ void WebAppWayland::onStageActivated() if (getHiddenWindow() || keepAlive()) m_appWindow->show(); - LOG_INFO(MSGID_WEBAPP_STAGE_ACITVATED, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); + LOG_INFO(MSGID_WEBAPP_STAGE_ACITVATED, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); executingStageActivated = false; } @@ -251,31 +250,26 @@ void WebAppWayland::onStageDeactivated() page()->setVisibilityState(WebPageBase::WebPageVisibilityState::WebPageVisibilityStateHidden); page()->suspendWebPageAll(); - LOG_INFO(MSGID_WEBAPP_STAGE_DEACITVATED, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); + LOG_INFO(MSGID_WEBAPP_STAGE_DEACITVATED, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); } -void WebAppWayland::configureWindow(QString& type) +void WebAppWayland::configureWindow(const std::string& type) { m_windowType = type; m_appWindow->setWebApp(this); - setWindowProperty(QStringLiteral("_WEBOS_WINDOW_TYPE"), type); - setWindowProperty(QStringLiteral("appId"), appId()); - setWindowProperty(QStringLiteral("launchingAppId"), launchingAppId()); - setWindowProperty(QStringLiteral("title"), QString::fromStdString(getAppDescription()->title())); - setWindowProperty(QStringLiteral("icon"), QString::fromStdString(getAppDescription()->icon())); - setWindowProperty(QStringLiteral("subtitle"), QStringLiteral("")); - setWindowProperty(QStringLiteral("_WEBOS_WINDOW_CLASS"), QVariant((int)getAppDescription()->windowClassValue())); - setWindowProperty(QStringLiteral("_WEBOS_ACCESS_POLICY_KEYS_BACK"), - getAppDescription()->backHistoryAPIDisabled() - ? QStringLiteral("true") : QStringLiteral("false")); - setWindowProperty(QStringLiteral("_WEBOS_ACCESS_POLICY_KEYS_EXIT"), - getAppDescription()->handleExitKey() - ? QStringLiteral("true") : QStringLiteral("false")); - setKeyMask(webos::WebOSKeyMask::KEY_MASK_BACK, - getAppDescription()->backHistoryAPIDisabled()); - setKeyMask(webos::WebOSKeyMask::KEY_MASK_EXIT, - getAppDescription()->handleExitKey()); + setWindowProperty("_WEBOS_WINDOW_TYPE", type); + setWindowProperty("launchingAppId", launchingAppId()); + setWindowProperty("appId", appId()); + setWindowProperty("title", getAppDescription()->title()); + setWindowProperty("icon", getAppDescription()->icon()); + setWindowProperty("subtitle", ""); + setWindowProperty("_WEBOS_WINDOW_CLASS", std::to_string((int)getAppDescription()->windowClassValue())); + setWindowProperty("_WEBOS_ACCESS_POLICY_KEYS_BACK", getAppDescription()->backHistoryAPIDisabled() ? "true" : "false"); + setWindowProperty("_WEBOS_ACCESS_POLICY_KEYS_EXIT", getAppDescription()->handleExitKey() ? "true" : "false"); + + setKeyMask(webos::WebOSKeyMask::KEY_MASK_BACK, getAppDescription()->backHistoryAPIDisabled()); + setKeyMask(webos::WebOSKeyMask::KEY_MASK_EXIT, getAppDescription()->handleExitKey()); ApplicationDescription* appDesc = getAppDescription(); if (!appDesc->groupWindowDesc().empty()) @@ -289,24 +283,22 @@ void WebAppWayland::setupWindowGroup(ApplicationDescription* desc) return; ApplicationDescription::WindowGroupInfo groupInfo = desc->getWindowGroupInfo(); - if (groupInfo.name.isEmpty()) + if (groupInfo.name.empty()) return; if (groupInfo.isOwner) { ApplicationDescription::WindowOwnerInfo ownerInfo = desc->getWindowOwnerInfo(); - webos::WindowGroupConfiguration config(groupInfo.name.toStdString()); + webos::WindowGroupConfiguration config(groupInfo.name); config.SetIsAnonymous(ownerInfo.allowAnonymous); - QMap::iterator iter = ownerInfo.layers.begin(); - while (iter != ownerInfo.layers.end()){ - config.AddLayer(webos::WindowGroupLayerConfiguration(iter.key().toStdString(), iter.value())); - iter++; + for (const auto &l : ownerInfo.layers) { + config.AddLayer(webos::WindowGroupLayerConfiguration(l.first, l.second)); } m_appWindow->CreateWindowGroup(config); - LOG_INFO(MSGID_CREATE_SURFACEGROUP, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); + LOG_INFO(MSGID_CREATE_SURFACEGROUP, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); } else { ApplicationDescription::WindowClientInfo clientInfo = desc->getWindowClientInfo(); - m_appWindow->AttachToWindowGroup(groupInfo.name.toStdString(), clientInfo.layer.toStdString()); - LOG_INFO(MSGID_ATTACH_SURFACEGROUP, 3, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKS("OWNER_ID", qPrintable(groupInfo.name)), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); + m_appWindow->AttachToWindowGroup(groupInfo.name, clientInfo.layer); + LOG_INFO(MSGID_ATTACH_SURFACEGROUP, 3, PMLOGKS("APP_ID", appId().c_str()), PMLOGKS("OWNER_ID", groupInfo.name.c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); } } @@ -322,34 +314,35 @@ void WebAppWayland::setKeyMask(webos::WebOSKeyMask keyMask, bool value) void WebAppWayland::applyInputRegion() { +#if defined(OS_WEBOS) if (!m_enableInputRegion && !m_inputRegion.empty()) { m_enableInputRegion = true; m_appWindow->SetInputRegion(m_inputRegion); } +#endif } -void WebAppWayland::setInputRegion(const QJsonDocument& jsonDoc) +void WebAppWayland::setInputRegion(const Json::Value& jsonDoc) { m_inputRegion.clear(); if (jsonDoc.isArray()) { - QJsonArray jsonArray = jsonDoc.array(); - - for (int i = 0; i < jsonArray.size(); i++) { - QVariantMap map = jsonArray[i].toObject().toVariantMap(); + for (const Json::Value& map : jsonDoc) { m_inputRegion.push_back(gfx::Rect( - map["x"].toInt() * m_scaleFactor, - map["y"].toInt() * m_scaleFactor, - map["width"].toInt() * m_scaleFactor, - map["height"].toInt() * m_scaleFactor)); + map["x"].asInt() * m_scaleFactor, + map["y"].asInt() * m_scaleFactor, + map["width"].asInt() * m_scaleFactor, + map["height"].asInt() * m_scaleFactor)); } } +#if defined(OS_WEBOS) m_appWindow->SetInputRegion(m_inputRegion); +#endif } -void WebAppWayland::setWindowProperty(const QString& name, const QVariant& value) +void WebAppWayland::setWindowProperty(const std::string& name, const std::string& value) { webos::WebOSKeyMask mask = static_cast(0); if (name == "_WEBOS_ACCESS_POLICY_KEYS_BACK") @@ -357,9 +350,12 @@ void WebAppWayland::setWindowProperty(const QString& name, const QVariant& value else if (name == "_WEBOS_ACCESS_POLICY_KEYS_EXIT") mask = webos::WebOSKeyMask::KEY_MASK_EXIT; // if mask is not set, not need to call setKeyMask - if (mask != static_cast(0)) - setKeyMask(mask, value.toBool()); - m_appWindow->SetWindowProperty(name.toStdString(), value.toString().toStdString()); + if (mask != static_cast(0)) { + bool boolValue; // TODO: Maybe migrate to boost::lexical_cast() + std::istringstream(value) >> std::boolalpha >> boolValue; + setKeyMask(mask, boolValue); + } + m_appWindow->SetWindowProperty(name, value); } void WebAppWayland::platformBack() @@ -367,63 +363,62 @@ void WebAppWayland::platformBack() m_appWindow->platformBack(); } -void WebAppWayland::setCursor(const QString& cursorArg, int hotspot_x, int hotspot_y) +void WebAppWayland::setCursor(const std::string& cursorArg, int hotspot_x, int hotspot_y) { m_appWindow->setCursor(cursorArg, hotspot_x, hotspot_y); } -static QMap& getKeyMaskTable() -{ - static QMap mapTable; - - if (mapTable.isEmpty()) { - mapTable["KeyMaskNone"] = static_cast(0); - mapTable["KeyMaskHome"] = webos::WebOSKeyMask::KEY_MASK_HOME; - mapTable["KeyMaskBack"] = webos::WebOSKeyMask::KEY_MASK_BACK; - mapTable["KeyMaskExit"] = webos::WebOSKeyMask::KEY_MASK_EXIT; - mapTable["KeyMaskLeft"] = webos::WebOSKeyMask::KEY_MASK_LEFT; - mapTable["KeyMaskRight"] = webos::WebOSKeyMask::KEY_MASK_RIGHT; - mapTable["KeyMaskUp"] = webos::WebOSKeyMask::KEY_MASK_UP; - mapTable["KeyMaskDown"] = webos::WebOSKeyMask::KEY_MASK_DOWN; - mapTable["KeyMaskOk"] = webos::WebOSKeyMask::KEY_MASK_OK; - mapTable["KeyMaskNumeric"] = webos::WebOSKeyMask::KEY_MASK_NUMERIC; - mapTable["KeyMaskRed"] = webos::WebOSKeyMask::KEY_MASK_REMOTECOLORRED; - mapTable["KeyMaskGreen"] = webos::WebOSKeyMask::KEY_MASK_REMOTECOLORGREEN; - mapTable["KeyMaskYellow"] = webos::WebOSKeyMask::KEY_MASK_REMOTECOLORYELLOW; - mapTable["KeyMaskBlue"] = webos::WebOSKeyMask::KEY_MASK_REMOTECOLORBLUE; - mapTable["KeyMaskProgramme"] = webos::WebOSKeyMask::KEY_MASK_REMOTEPROGRAMMEGROUP; - mapTable["KeyMaskPlayback"] = webos::WebOSKeyMask::KEY_MASK_REMOTEPLAYBACKGROUP; - mapTable["KeyMaskTeletext"] = webos::WebOSKeyMask::KEY_MASK_REMOTETELETEXTGROUP; - mapTable["KeyMaskDefault"] = webos::WebOSKeyMask::KEY_MASK_DEFAULT; - } - +static std::unordered_map& getKeyMaskTable() +{ + static std::unordered_map mapTable { + { "KeyMaskNone", static_cast(0) }, + { "KeyMaskHome", webos::WebOSKeyMask::KEY_MASK_HOME }, + { "KeyMaskBack", webos::WebOSKeyMask::KEY_MASK_BACK }, + { "KeyMaskExit", webos::WebOSKeyMask::KEY_MASK_EXIT }, + { "KeyMaskLeft", webos::WebOSKeyMask::KEY_MASK_LEFT }, + { "KeyMaskRight", webos::WebOSKeyMask::KEY_MASK_RIGHT }, + { "KeyMaskUp", webos::WebOSKeyMask::KEY_MASK_UP }, + { "KeyMaskDown", webos::WebOSKeyMask::KEY_MASK_DOWN }, + { "KeyMaskOk", webos::WebOSKeyMask::KEY_MASK_OK }, + { "KeyMaskNumeric", webos::WebOSKeyMask::KEY_MASK_NUMERIC }, + { "KeyMaskRed", webos::WebOSKeyMask::KEY_MASK_REMOTECOLORRED }, + { "KeyMaskGreen", webos::WebOSKeyMask::KEY_MASK_REMOTECOLORGREEN }, + { "KeyMaskYellow", webos::WebOSKeyMask::KEY_MASK_REMOTECOLORYELLOW }, + { "KeyMaskBlue", webos::WebOSKeyMask::KEY_MASK_REMOTECOLORBLUE }, + { "KeyMaskProgramme", webos::WebOSKeyMask::KEY_MASK_REMOTEPROGRAMMEGROUP }, + { "KeyMaskPlayback", webos::WebOSKeyMask::KEY_MASK_REMOTEPLAYBACKGROUP }, + { "KeyMaskTeletext", webos::WebOSKeyMask::KEY_MASK_REMOTETELETEXTGROUP }, + { "KeyMaskDefault", webos::WebOSKeyMask::KEY_MASK_DEFAULT } + }; return mapTable; } -void WebAppWayland::setKeyMask(const QJsonDocument& jsonDoc) +void WebAppWayland::setKeyMask(const Json::Value& jsonDoc) { - static QMap& mapTable = getKeyMaskTable(); + static std::unordered_map& mapTable = getKeyMaskTable(); unsigned int keyMask = 0; if (jsonDoc.isArray()) { - QJsonArray jsonArray = jsonDoc.array(); - - for (int i = 0; i < jsonArray.size(); i++) - keyMask |= mapTable.value(jsonArray[i].toString()); + for (const Json::Value& child : jsonDoc) + keyMask |= mapTable[child.asString()]; } +#if defined(OS_WEBOS) m_appWindow->SetKeyMask(static_cast(keyMask)); +#endif } void WebAppWayland::setKeyMask(webos::WebOSKeyMask keyMask) { +#if defined(OS_WEBOS) m_appWindow->SetKeyMask(keyMask); +#endif } void WebAppWayland::focusOwner() { m_appWindow->FocusWindowGroupOwner(); - LOG_DEBUG("FocusOwner [%s]", qPrintable(appId())); + LOG_DEBUG("FocusOwner [%s]", appId().c_str()); } void WebAppWayland::focusLayer() @@ -432,7 +427,7 @@ void WebAppWayland::focusLayer() ApplicationDescription * desc = getAppDescription(); if (desc) { ApplicationDescription::WindowClientInfo clientInfo = desc->getWindowClientInfo(); - LOG_DEBUG("FocusLayer(layer:%s) [%s]",qPrintable(clientInfo.layer) ,qPrintable(appId())); + LOG_DEBUG("FocusLayer(layer:%s) [%s]", clientInfo.layer.c_str(), appId().c_str()); } } @@ -481,10 +476,6 @@ void WebAppWayland::doAttach() page()->setKeepAliveWebApp(keepAlive()); setForceActivateVtgIfRequired(); - - connect(page(), SIGNAL(webPageClosePageRequested()), this, SLOT(webPageClosePageRequestedSlot())); - connect(page(), SIGNAL(webPageTitleChanged()), this, SLOT(webPageTitleChangedSlot())); - connect(page(), SIGNAL(webViewRecreated()), this, SLOT(webViewRecreatedSlot())); } void WebAppWayland::raise() @@ -495,10 +486,10 @@ void WebAppWayland::raise() //1. When overlay window is raised //2. When there's only one keepAlive app, and this keepAlive app is closed and is shown again if ((getWindowType() == WT_OVERLAY) || (keepAlive() && !wasMinimizedState)) { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::raise(); call onStageActivated"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::raise(); call onStageActivated"); onStageActivated(); } else { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::raise(); call setWindowState(webos::NATIVE_WINDOW_FULLSCREEN)"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::raise(); call setWindowState(webos::NATIVE_WINDOW_FULLSCREEN)"); m_appWindow->SetWindowHostState(webos::NATIVE_WINDOW_FULLSCREEN); } @@ -509,15 +500,15 @@ void WebAppWayland::raise() void WebAppWayland::goBackground() { if (getWindowType() == WT_OVERLAY) { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::goBackground(); windowType:OVERLAY; Try close; call doClose()"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::goBackground(); windowType:OVERLAY; Try close; call doClose()"); doClose(); } else { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::goBackground(); call setWindowState(webos::NATIVE_WINDOW_MINIMIZED)"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::goBackground(); call setWindowState(webos::NATIVE_WINDOW_MINIMIZED)"); m_appWindow->SetWindowHostState(webos::NATIVE_WINDOW_MINIMIZED); } } -void WebAppWayland::webPageLoadFinishedSlot() +void WebAppWayland::webPageLoadFinished() { if (getHiddenWindow()) return; @@ -527,18 +518,18 @@ void WebAppWayland::webPageLoadFinishedSlot() return; } - QString logUrl = truncateURL(page()->url().toString()); + std::string logUrl = truncateURL(page()->url().toString()); LOG_INFO_WITH_CLOCK(MSGID_APP_LOADED, 5, PMLOGKS("PerfType", "AppLaunch"), - PMLOGKS("PerfGroup", qPrintable((page()->appId()))), - PMLOGKS("APP_ID", qPrintable((page()->appId()))), - PMLOGKS("URL", qPrintable(logUrl)), + PMLOGKS("PerfGroup", page()->appId().c_str()), + PMLOGKS("APP_ID", page()->appId().c_str()), + PMLOGKS("URL", logUrl.c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), ""); doPendingRelaunch(); } -void WebAppWayland::webPageLoadFailedSlot(int errorCode) +void WebAppWayland::webPageLoadFailed(int errorCode) { // Do not load error page while preoload app launching. if (preloadState() != NONE_PRELOAD) @@ -548,13 +539,13 @@ void WebAppWayland::webPageLoadFailedSlot(int errorCode) void WebAppWayland::doClose() { if (forceClose()) { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::doClose(); forceClose() TRUE; call forceCloseAppInternal() and return"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::doClose(); forceClose() TRUE; call forceCloseAppInternal() and return"); forceCloseAppInternal(); return; } if (keepAlive() && !page()->isLoadErrorPageFinish()) { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::doClose(); KeepAlive; just Hide this app"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::doClose(); KeepAlive; just Hide this app"); page()->closeVkb(); m_appWindow->hide(); deleteSurfaceGroup(); @@ -563,14 +554,14 @@ void WebAppWayland::doClose() return; } - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::doClose(); call closeAppInternal()"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::doClose(); call closeAppInternal()"); closeAppInternal(); } void WebAppWayland::stateAboutToChange(webos::NativeWindowState willBe) { if (willBe == webos::NATIVE_WINDOW_MINIMIZED) { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::stateAboutToChange; will be Minimized; suspend media and fire visibilitychange event"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::stateAboutToChange; will be Minimized; suspend media and fire visibilitychange event"); page()->suspendWebPageMedia(); page()->setVisibilityState(WebPageBase::WebPageVisibilityState::WebPageVisibilityStateHidden); } @@ -581,7 +572,7 @@ void WebAppWayland::showWindow() setForceActivateVtgIfRequired(); if (m_preloadState != NONE_PRELOAD) { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::showWindow(); But Preloaded app; return"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "WebAppWayland::showWindow(); But Preloaded app; return"); return; } @@ -592,24 +583,19 @@ void WebAppWayland::showWindow() WebAppBase::showWindow(); } -void WebAppWayland::showWindowSlot() -{ - showWindow(); -} - void WebAppWayland::titleChanged() { - setWindowProperty(QStringLiteral("subtitle"), page()->title()); + setWindowProperty("subtitle", page()->title()); } void WebAppWayland::firstFrameVisuallyCommitted() { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "firstFrameVisuallyCommitted"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "firstFrameVisuallyCommitted"); // if m_preloadState != NONE_PRELOAD, then we must ignore the first frame commit // if getHiddenWindow() == true, then we have specifically requested that the window is to be hidden, // and therefore we have to do an explicit show if (!getHiddenWindow() && m_preloadState == NONE_PRELOAD) { - LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", qPrintable(appId())), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "Not hidden window, preload, call showWindow"); + LOG_INFO(MSGID_WAM_DEBUG, 2, PMLOGKS("APP_ID", appId().c_str()), PMLOGKFV("PID", "%d", page()->getWebProcessPID()), "Not hidden window, preload, call showWindow"); if (getAppDescription()->usePrerendering()) m_appWindow->resetPageFrameSwapped(); showWindow(); @@ -625,14 +611,14 @@ void WebAppWayland::navigationHistoryChanged() { if (!getAppDescription()->backHistoryAPIDisabled()) { // if backHistoryAPIDisabled is true, no chance to change this value - setWindowProperty(QStringLiteral("_WEBOS_ACCESS_POLICY_KEYS_BACK"), + setWindowProperty("_WEBOS_ACCESS_POLICY_KEYS_BACK", page()->canGoBack() ? - QStringLiteral("true") : /* send next back key to WAM */ - QStringLiteral("false")); /* Do not send back key to WAM. LSM should handle it */ + "true" : /* send next back key to WAM */ + "false"); /* Do not send back key to WAM. LSM should handle it */ } } -void WebAppWayland::webViewRecreatedSlot() +void WebAppWayland::webViewRecreated() { m_appWindow->attachWebContents(page()->getWebContents()); m_appWindow->RecreatedWebContents(); @@ -648,8 +634,7 @@ void WebAppWayland::didSwapPageCompositorFrame() void WebAppWayland::setForceActivateVtgIfRequired() { - QString screenRotation; - + std::string screenRotation; if (WebAppManager::instance() && page()) { if (WebAppManager::instance()->getDeviceInfo("ScreenRotation", screenRotation) && screenRotation != "off") page()->setForceActivateVtg(true); @@ -665,28 +650,29 @@ void InputManager::OnCursorVisibilityChanged(bool visible) LOG_DEBUG("InputManager::onCursorVisibilityChanged; Global Cursor visibility Changed to %s; send cursorStateChange event to all app, all frames", visible? "true" : " false"); SetVisible(visible); // send event about cursorStateChange - QString cursorStateChangeEvt = QStringLiteral( - " var cursorEvent=new CustomEvent('cursorStateChange', { detail: { 'visibility' : %1 } });" - " cursorEvent.visibility = %2;" - " if(document) document.dispatchEvent(cursorEvent);" - ).arg(visible ? "true" : "false"). arg(visible ? "true" : "false"); + std::stringstream jss; + std::string v = visible ? "true" : "false"; + jss << " var cursorEvent=new CustomEvent('cursorStateChange', { detail: { 'visibility' : " << v << " } });" + << " cursorEvent.visibility = " << v << ";" + << " if(document) document.dispatchEvent(cursorEvent);"; // send javascript event : cursorStateChange with param to All app // if javascript has setTimeout() like webOSlaunch or webOSRelaunch, then app can not get this event when app is in background // because javascript is freezed and timer is too, since app is in background, timer is never fired - WebAppBase::onCursorVisibilityChanged(cursorStateChangeEvt); + WebAppBase::onCursorVisibilityChanged(jss.str()); } -void WebAppWayland::sendWebOSMouseEvent(const QString& eventName) +void WebAppWayland::sendWebOSMouseEvent(const std::string& eventName) { if (eventName == "Enter" || eventName == "Leave") { // send webOSMouse event to app - QString javascript = QStringLiteral( - "console.log('[WAM] fires webOSMouse event : %1');" - "var mouseEvent =new CustomEvent('webOSMouse', { detail: { type : '%2' }});" - "document.dispatchEvent(mouseEvent);").arg(eventName).arg(eventName); - LOG_DEBUG("[%s] WebAppWayland::sendWebOSMouseEvent; dispatch webOSMouse; %s", qPrintable(appId()), qPrintable(eventName)); - page()->evaluateJavaScript(javascript); + std::stringstream javascript; + javascript + << "console.log('[WAM] fires webOSMouse event : " << eventName << "');" + << "var mouseEvent =new CustomEvent('webOSMouse', { detail: { type : '" << eventName << "' }});" + << "document.dispatchEvent(mouseEvent);"; + LOG_DEBUG("[%s] WebAppWayland::sendWebOSMouseEvent; dispatch webOSMouse; %s", appId().c_str(), eventName.c_str()); + page()->evaluateJavaScript(javascript.str()); } } @@ -723,7 +709,9 @@ void WebAppWayland::moveInputRegion(int height) } m_inputRegion.clear(); m_inputRegion = newRegion; +#if defined(OS_WEBOS) m_appWindow->SetInputRegion(m_inputRegion); +#endif } void WebAppWayland::keyboardVisibilityChanged(bool visible, int height) { diff --git a/src/platform/WebAppWayland.h b/src/platform/WebAppWayland.h index 1fb613f8..70d78123 100644 --- a/src/platform/WebAppWayland.h +++ b/src/platform/WebAppWayland.h @@ -22,12 +22,14 @@ #include "WebPageBlinkObserver.h" -#include - #include "webos/common/webos_constants.h" #include "webos/common/webos_event.h" #include "webos/webos_platform.h" +namespace Json { +class Value; +} + class ApplicationDescription; class WebAppWaylandWindow; @@ -48,16 +50,14 @@ class InputManager : public webos::InputPointer { }; class WebAppWayland : public WebAppBase, WebPageBlinkObserver { - Q_OBJECT - public: - WebAppWayland(QString type, int width = 0, int height = 0); - WebAppWayland(QString type, WebAppWaylandWindow* window, int width = 0, int height = 0); + WebAppWayland(const std::string& type, int surface_id, int width = 0, int height = 0); + WebAppWayland(const std::string& type, WebAppWaylandWindow* window, int width = 0, int height = 0); ~WebAppWayland() override; // WebAppBase - void init(int width, int height) override; + void init(int width, int height, int surface_id) override; void attach(WebPageBase*) override; WebPageBase* detach() override; void suspendAppRendering() override; @@ -69,14 +69,14 @@ class WebAppWayland : public WebAppBase, WebPageBlinkObserver { bool isNormal() override; void onStageActivated() override; void onStageDeactivated() override; - void configureWindow(QString& type) override; + void configureWindow(const std::string& type) override; void setKeepAlive(bool keepAlive) override; bool isWindowed() const override { return true; } - void setWindowProperty(const QString& name, const QVariant& value) override; + void setWindowProperty(const std::string& name, const std::string& value) override; void platformBack() override; - void setCursor(const QString& cursorArg, int hotspot_x = -1, int hotspot_y = -1) override; - void setInputRegion(const QJsonDocument& jsonDoc) override; - void setKeyMask(const QJsonDocument& jsonDoc) override; + void setCursor(const std::string& cursorArg, int hotspot_x = -1, int hotspot_y = -1) override; + void setInputRegion(const Json::Value& jsonDoc) override; + void setKeyMask(const Json::Value& jsonDoc) override; void setOpacity(float opacity) override; void hide(bool forcedHide = false) override; void focus() override; @@ -97,10 +97,10 @@ class WebAppWayland : public WebAppBase, WebPageBlinkObserver { virtual void firstFrameVisuallyCommitted(); virtual void navigationHistoryChanged(); - QString getWindowType() const { return m_windowType; } + std::string getWindowType() const { return m_windowType; } bool cursorVisibility() { return InputManager::instance()->globalCursorVisibility(); } void startLaunchTimer(); - void sendWebOSMouseEvent(const QString& eventName); + void sendWebOSMouseEvent(const std::string& eventName); void postEvent(WebOSEvent* ev); void onDelegateWindowFrameSwapped(); @@ -124,15 +124,14 @@ class WebAppWayland : public WebAppBase, WebPageBlinkObserver { void moveInputRegion(int height); void setForceActivateVtgIfRequired(); -protected Q_SLOTS: - virtual void showWindowSlot(); - virtual void webPageLoadFinishedSlot(); - virtual void webPageLoadFailedSlot(int errorCode); - virtual void webViewRecreatedSlot(); + // WebPageObserver + virtual void webPageLoadFailed(int errorCode); + virtual void webViewRecreated(); + virtual void webPageLoadFinished(); private: WebAppWaylandWindow* m_appWindow; - QString m_windowType; + std::string m_windowType; int m_lastSwappedTime; std::vector m_inputRegion; diff --git a/src/platform/WebAppWaylandWindow.cpp b/src/platform/WebAppWaylandWindow.cpp index 6e195e60..6fbc75a9 100644 --- a/src/platform/WebAppWaylandWindow.cpp +++ b/src/platform/WebAppWaylandWindow.cpp @@ -14,14 +14,16 @@ // // SPDX-License-Identifier: Apache-2.0 +#include "WebAppWaylandWindow.h" + #include "ApplicationDescription.h" #include "LogManager.h" #include "WebAppWayland.h" -#include "WebAppWaylandWindow.h" +#include "WebAppManagerUtils.h" WebAppWaylandWindow* WebAppWaylandWindow::s_instance = nullptr; -WebAppWaylandWindow* WebAppWaylandWindow::take() +WebAppWaylandWindow* WebAppWaylandWindow::take(int surface_id) { WebAppWaylandWindow* window; @@ -75,12 +77,12 @@ WebAppWaylandWindow::WebAppWaylandWindow() , m_hasPageFrameBeenSwapped(false) , m_pendingShow(false) { - m_cursorEnabled = (qgetenv("ENABLE_CURSOR_BY_DEFAULT") == "1") ? true : false;; + m_cursorEnabled = (WebAppManagerUtils::getEnv("ENABLE_CURSOR_BY_DEFAULT") == "1") ? true : false;; } void WebAppWaylandWindow::hide() { - LOG_INFO(MSGID_WAM_DEBUG, 1, PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), "WebAppWaylandWindow::hide(); call onStageDeactivated"); + LOG_INFO(MSGID_WAM_DEBUG, 1, PMLOGKS("APP_ID", m_webApp->appId().c_str()), "WebAppWaylandWindow::hide(); call onStageDeactivated"); onStageDeactivated(); WebAppWindowBase::Hide(); @@ -92,7 +94,7 @@ void WebAppWaylandWindow::show() if (!m_hasPageFrameBeenSwapped) { m_pendingShow = true; } else { - LOG_INFO(MSGID_WAM_DEBUG, 1, PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), "WebAppWaylandWindow::show(); call onStageActivated"); + LOG_INFO(MSGID_WAM_DEBUG, 1, PMLOGKS("APP_ID", m_webApp->appId().c_str()), "WebAppWaylandWindow::show(); call onStageActivated"); onStageActivated(); WebAppWindowBase::Show(); m_pendingShow = false; @@ -101,23 +103,25 @@ void WebAppWaylandWindow::show() void WebAppWaylandWindow::platformBack() { - LOG_INFO(MSGID_WAM_DEBUG, 1, PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), "WebAppWaylandWindow::platformBack(); generate RECENT key"); + LOG_INFO(MSGID_WAM_DEBUG, 1, PMLOGKS("APP_ID", m_webApp->appId().c_str()), "WebAppWaylandWindow::platformBack(); generate RECENT key"); } -void WebAppWaylandWindow::setCursor(const QString & cursorArg, int hotspot_x, int hotspot_y) +void WebAppWaylandWindow::setCursor(const std::string& cursorArg, int hotspot_x, int hotspot_y) { webos::CustomCursorType type = webos::CUSTOM_CURSOR_NOT_USE; - if (cursorArg.isEmpty() || !cursorArg.compare("default")) - LOG_DEBUG("[%s] %s; arg: %s; Restore Cursor to webos::CUSTOM_CURSOR_NOT_USE", qPrintable(m_webApp->appId()), __PRETTY_FUNCTION__, cursorArg.toUtf8().data()); - else if (!cursorArg.compare("blank")) { - LOG_DEBUG("[%s] %s; arg: %s; Set Cursor to webos::CUSTOM_CURSOR_BLANK", qPrintable(m_webApp->appId()), __PRETTY_FUNCTION__, cursorArg.toUtf8().data()); + if (cursorArg.empty() || cursorArg == "default") + LOG_DEBUG("[%s] %s; arg: %s; Restore Cursor to webos::CUSTOM_CURSOR_NOT_USE", m_webApp->appId().c_str(), __PRETTY_FUNCTION__, cursorArg.c_str()); + else if (cursorArg == "blank") { + LOG_DEBUG("[%s] %s; arg: %s; Set Cursor to webos::CUSTOM_CURSOR_BLANK", m_webApp->appId().c_str(), __PRETTY_FUNCTION__, cursorArg.c_str()); type = webos::CUSTOM_CURSOR_BLANK; } else { - LOG_DEBUG("[%s] %s; Custom Cursor file path : %s, hotspot_x : %d, hotspot_y : %d", __PRETTY_FUNCTION__, qPrintable(m_webApp->appId()), cursorArg.toUtf8().data(), hotspot_x, hotspot_y); + LOG_DEBUG("[%s] %s; Custom Cursor file path : %s, hotspot_x : %d, hotspot_y : %d", __PRETTY_FUNCTION__, m_webApp->appId().c_str(), cursorArg.c_str(), hotspot_x, hotspot_y); type = webos::CUSTOM_CURSOR_PATH; } - SetCustomCursor(type, cursorArg.toUtf8().data(), hotspot_x, hotspot_y); +#if defined(OS_WEBOS) + SetCustomCursor(type, cursorArg.c_str(), hotspot_x, hotspot_y); +#endif if (type == webos::CUSTOM_CURSOR_BLANK) m_cursorEnabled = false; @@ -152,12 +156,12 @@ bool WebAppWaylandWindow::event(WebOSEvent* event) switch (event->GetType()) { case WebOSEvent::Close: - LOG_INFO(MSGID_WINDOW_CLOSED, 1, PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), ""); + LOG_INFO(MSGID_WINDOW_CLOSED, 1, PMLOGKS("APP_ID", m_webApp->appId().c_str()), ""); m_webApp->doClose(); return true; case WebOSEvent::WindowStateChange: if (GetWindowHostState() == webos::NATIVE_WINDOW_MINIMIZED) { - LOG_INFO(MSGID_WINDOW_STATECHANGE, 1, PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), "WebOSEvent::WindowStateChange; Minimize; m_lastMouseEvent's type : %s", m_lastMouseEvent.GetType() == WebOSEvent::MouseButtonPress ? "Press; Generate MouseButtonRelease event" : "Release"); + LOG_INFO(MSGID_WINDOW_STATECHANGE, 1, PMLOGKS("APP_ID", m_webApp->appId().c_str()), "WebOSEvent::WindowStateChange; Minimize; m_lastMouseEvent's type : %s", m_lastMouseEvent.GetType() == WebOSEvent::MouseButtonPress ? "Press; Generate MouseButtonRelease event" : "Release"); if (m_lastMouseEvent.GetType() == WebOSEvent::MouseButtonPress) { m_lastMouseEvent.SetType(WebOSEvent::MouseButtonRelease); m_webApp->forwardWebOSEvent(&m_lastMouseEvent); @@ -201,11 +205,11 @@ bool WebAppWaylandWindow::event(WebOSEvent* event) m_webApp->focus(); LOG_INFO_WITH_CLOCK(MSGID_WINDOW_FOCUSIN, 3, PMLOGKS("PerfType", "AppLaunch"), - PMLOGKS("PerfGroup", qPrintable(m_webApp->appId())), - PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), ""); + PMLOGKS("PerfGroup", m_webApp->appId().c_str()), + PMLOGKS("APP_ID", m_webApp->appId().c_str()), ""); break; case WebOSEvent::FocusOut: - LOG_INFO(MSGID_WINDOW_FOCUSOUT, 1, PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), "m_lastMouseEvent's type : %s", m_lastMouseEvent.GetType() == WebOSEvent::MouseButtonPress ? "Press; Generate MouseButtonRelease event" : "Release"); + LOG_INFO(MSGID_WINDOW_FOCUSOUT, 1, PMLOGKS("APP_ID", m_webApp->appId().c_str()), "m_lastMouseEvent's type : %s", m_lastMouseEvent.GetType() == WebOSEvent::MouseButtonPress ? "Press; Generate MouseButtonRelease event" : "Release"); // Cherry-pick http://wall.lge.com:8110/#/c/89417/ partially. // The FocusAboutToChange event is specific to Qt and it is for the @@ -254,7 +258,7 @@ void WebAppWaylandWindow::onStageDeactivated() void WebAppWaylandWindow::onWindowStateChangeEvent() { if (m_webApp->isClosing()) { - LOG_INFO(MSGID_WINDOW_STATE_CHANGED, 1, PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), "In Closing; return;"); + LOG_INFO(MSGID_WINDOW_STATE_CHANGED, 1, PMLOGKS("APP_ID", m_webApp->appId().c_str()), "In Closing; return;"); return; } @@ -264,16 +268,16 @@ void WebAppWaylandWindow::onWindowStateChangeEvent() case webos::NATIVE_WINDOW_DEFAULT: case webos::NATIVE_WINDOW_MAXIMIZED: case webos::NATIVE_WINDOW_FULLSCREEN: - LOG_INFO(MSGID_WINDOW_STATE_CHANGED, 1, PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), "To FullScreen; call onStageActivated"); + LOG_INFO(MSGID_WINDOW_STATE_CHANGED, 1, PMLOGKS("APP_ID", m_webApp->appId().c_str()), "To FullScreen; call onStageActivated"); m_webApp->applyInputRegion(); onStageActivated(); break; case webos::NATIVE_WINDOW_MINIMIZED: - LOG_INFO(MSGID_WINDOW_STATE_CHANGED, 1, PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), "To Minimized; call onStageDeactivated"); + LOG_INFO(MSGID_WINDOW_STATE_CHANGED, 1, PMLOGKS("APP_ID", m_webApp->appId().c_str()), "To Minimized; call onStageDeactivated"); onStageDeactivated(); break; default: - LOG_INFO(MSGID_WINDOW_STATE_CHANGED, 2, PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), PMLOGKFV("HOST_STATE", "%d", state), "Unknown state. Do not calling nothing anymore."); + LOG_INFO(MSGID_WINDOW_STATE_CHANGED, 2, PMLOGKS("APP_ID", m_webApp->appId().c_str()), PMLOGKFV("HOST_STATE", "%d", state), "Unknown state. Do not calling nothing anymore."); break; } } @@ -292,17 +296,19 @@ bool WebAppWaylandWindow::onCursorVisibileChangeEvent(WebOSEvent* e) unsigned int WebAppWaylandWindow::CheckKeyFilterTable(unsigned keycode, unsigned* modifier) { - QMap> table = m_webApp->getAppDescription()->keyFilterTable(); + auto table = m_webApp->getAppDescription()->keyFilterTable(); if (table.empty()) return 0; - if (!table.contains(keycode)) + auto it = table.find(keycode); + if (it == table.end()) return 0; - *modifier = table[keycode].second; + std::pair p = it->second; + *modifier = p.second; - return table[keycode].first; + return p.first; } void WebAppWaylandWindow::logEventDebugging(WebOSEvent* event) @@ -312,13 +318,13 @@ void WebAppWaylandWindow::logEventDebugging(WebOSEvent* event) if (m_cursorEnabled) { // log all mouse move events LOG_INFO(MSGID_MOUSE_MOVE_EVENT, 3, - PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), + PMLOGKS("APP_ID", m_webApp->appId().c_str()), PMLOGKFV("X", "%.f", static_cast(event)->GetX()), PMLOGKFV("Y", "%.f", static_cast(event)->GetY()), ""); } else { LOG_INFO(MSGID_MOUSE_MOVE_EVENT, 1, - PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), + PMLOGKS("APP_ID", m_webApp->appId().c_str()), "Mouse event should be Disabled by blank cursor"); } } @@ -328,20 +334,20 @@ void WebAppWaylandWindow::logEventDebugging(WebOSEvent* event) if (event->GetType() == WebOSEvent::KeyPress || event->GetType() == WebOSEvent::KeyRelease) { // remote key event LOG_INFO(MSGID_KEY_EVENT, 3, - PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), + PMLOGKS("APP_ID", m_webApp->appId().c_str()), PMLOGKFV("VALUE_HEX", "%x", static_cast(event)->GetCode()), PMLOGKS("STATUS", event->GetType() == WebOSEvent::KeyPress ? "KeyPress" : "KeyRelease"), ""); } else if (event->GetType() == WebOSEvent::MouseButtonPress || event->GetType() == WebOSEvent::MouseButtonRelease) { if (!m_cursorEnabled) { LOG_INFO(MSGID_MOUSE_BUTTON_EVENT, 1, - PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), + PMLOGKS("APP_ID", m_webApp->appId().c_str()), "Mouse event should be Disabled by blank cursor"); } else { // mouse button event LOG_INFO(MSGID_MOUSE_BUTTON_EVENT, 3, - PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), + PMLOGKS("APP_ID", m_webApp->appId().c_str()), PMLOGKFV("VALUE", "%d", (int)static_cast(event)->GetButton()), PMLOGKS("STATUS", event->GetType() == WebOSEvent::MouseButtonPress ? "MouseButtonPress" : "MouseButtonRelease"), ""); } @@ -350,7 +356,7 @@ void WebAppWaylandWindow::logEventDebugging(WebOSEvent* event) // log all window event except mouseMove // to print mouseMove event, set mouseMove : true LOG_INFO(MSGID_WINDOW_EVENT, 2, - PMLOGKS("APP_ID", qPrintable(m_webApp->appId())), + PMLOGKS("APP_ID", m_webApp->appId().c_str()), PMLOGKFV("TYPE", "%d", event->GetType()), ""); } } @@ -358,9 +364,11 @@ void WebAppWaylandWindow::logEventDebugging(WebOSEvent* event) void WebAppWaylandWindow::sendKeyCode(int keyCode) { +#if defined(OS_WEBOS) if (!m_xinputActivated) { XInputActivate(); m_xinputActivated = true; } XInputInvokeAction(keyCode); +#endif } diff --git a/src/platform/WebAppWaylandWindow.h b/src/platform/WebAppWaylandWindow.h index 416bfb32..81c72b37 100644 --- a/src/platform/WebAppWaylandWindow.h +++ b/src/platform/WebAppWaylandWindow.h @@ -25,7 +25,7 @@ class WebAppWaylandWindow : public webos::WebAppWindowBase { public: WebAppWaylandWindow(); virtual ~WebAppWaylandWindow() {} - static WebAppWaylandWindow* take(); + static WebAppWaylandWindow* take(int surface_id); static void prepareRenderingContext(); static void prepare(); @@ -36,7 +36,7 @@ class WebAppWaylandWindow : public webos::WebAppWindowBase { virtual void show(); void platformBack(); - void setCursor(const QString& cursorArg, int hotspot_x = -1, int hotspot_y = -1); + void setCursor(const std::string& cursorArg, int hotspot_x = -1, int hotspot_y = -1); void attachWebContents(void* webContents); diff --git a/src/platform/webengine/BlinkWebProcessManager.cpp b/src/platform/webengine/BlinkWebProcessManager.cpp index 1b69dc21..d364a3dc 100644 --- a/src/platform/webengine/BlinkWebProcessManager.cpp +++ b/src/platform/webengine/BlinkWebProcessManager.cpp @@ -14,12 +14,14 @@ // // SPDX-License-Identifier: Apache-2.0 -#include -#include -#include -#include - #include "BlinkWebProcessManager.h" + +#include +#include +#include + +#include + #include "WebPageBlink.h" #include "WebAppBase.h" #include "WebAppManagerUtils.h" @@ -33,46 +35,43 @@ uint32_t BlinkWebProcessManager::getWebProcessPID(const WebAppBase* app) const return static_cast(app->page())->renderProcessPid(); } -QJsonObject BlinkWebProcessManager::getWebProcessProfiling() +Json::Value BlinkWebProcessManager::getWebProcessProfiling() { - QJsonObject reply; - QJsonArray processArray; - QJsonObject processObject; + Json::Value reply(Json::objectValue); + Json::Value processArray(Json::arrayValue); uint32_t pid; - QList processIdList; + std::set processIdList; - QMap runningAppList; + std::unordered_multimap runningAppsMap; std::list running = runningApps(); - for (std::list::iterator it = running.begin(); it != running.end(); ++it) { - WebAppBase* app = findAppById((*it)->appId()); + for (auto it = running.begin(); it != running.end(); ++it) { + std::string appid = (*it)->appId(); + WebAppBase* app = findAppById(appid); pid = getWebProcessPID(app); - if (!processIdList.contains(pid)) - processIdList.append(pid); - - runningAppList.insertMulti(pid, app->appId()); + processIdList.insert(pid); + runningAppsMap.emplace(pid, app->appId()); } WebAppBase* containerApp = getContainerApp(); if (containerApp) { pid = getWebProcessPID(containerApp); - if (!processIdList.contains(pid)) - processIdList.append(pid); + processIdList.insert(pid); - runningAppList.insertMulti(pid, containerApp->appId()); + runningAppsMap.emplace(pid, containerApp->appId()); } - for (int id = 0; id < processIdList.size(); id++) { - QJsonObject appObject; - QJsonArray appArray; - pid = processIdList.at(id); + for (uint32_t pid : processIdList) { + Json::Value processObject(Json::objectValue); + Json::Value appArray(Json::arrayValue); - processObject["pid"] = QString::number(pid); + processObject["pid"] = std::to_string(pid); processObject["webProcessSize"] = getWebProcessMemSize(pid); //starfish-surface is note used on Blink processObject["tileSize"] = 0; - QList processApp = runningAppList.values(pid); - for (int app = 0; app < processApp.size(); app++) { - appObject["id"] = processApp.at(app); + auto processes = runningAppsMap.equal_range(pid); + for (auto p = processes.first; p != processes.second; ++p) { + Json::Value appObject(Json::objectValue); + appObject["id"] = p->second; appArray.append(appObject); } processObject["runningApps"] = appArray; @@ -81,10 +80,10 @@ QJsonObject BlinkWebProcessManager::getWebProcessProfiling() reply["WebProcesses"] = processArray; reply["returnValue"] = true; - return reply; + return std::move(reply); } -void BlinkWebProcessManager::deleteStorageData(const QString& identifier) +void BlinkWebProcessManager::deleteStorageData(const std::string& identifier) { std::list runningAppList = runningApps(); if (!runningAppList.empty()) { @@ -100,7 +99,7 @@ void BlinkWebProcessManager::deleteStorageData(const QString& identifier) BlinkWebView* webview = new BlinkWebView(); if (webview) { - webview->DeleteWebStorages(identifier.toStdString()); + webview->DeleteWebStorages(identifier); delete webview; } } @@ -119,3 +118,12 @@ int BlinkWebProcessManager::maskForBrowsingDataType(const char* type) { return BlinkWebViewProfileHelper::maskForBrowsingDataType(type); } + +void BlinkWebProcessManager::buildWebViewProfile(const std::string& app_id, const std::string& proxy_host, const std::string& proxy_port) { + BlinkWebViewProfileHelper::instance()->buildProfile(app_id, proxy_host, proxy_port); +} + +void BlinkWebProcessManager::deleteWebViewProfile(const std::string& app_id) +{ + BlinkWebViewProfileHelper::instance()->deleteProfile(app_id); +} diff --git a/src/platform/webengine/BlinkWebProcessManager.h b/src/platform/webengine/BlinkWebProcessManager.h index 6fa51115..7ab09f24 100644 --- a/src/platform/webengine/BlinkWebProcessManager.h +++ b/src/platform/webengine/BlinkWebProcessManager.h @@ -19,18 +19,23 @@ #include "WebProcessManager.h" -class QString; class WebAppBase; +namespace Json { +class Value; +} + class BlinkWebProcessManager : public WebProcessManager { public: // WebProcessManager - QJsonObject getWebProcessProfiling() override; + Json::Value getWebProcessProfiling() override; uint32_t getWebProcessPID(const WebAppBase* app) const override; - void deleteStorageData(const QString& identifier) override; + void deleteStorageData(const std::string& identifier) override; uint32_t getInitialWebViewProxyID() const override; void clearBrowsingData(const int removeBrowsingDataMask) override; int maskForBrowsingDataType(const char* type) override; + void buildWebViewProfile(const std::string& app_id, const std::string& proxy_host, const std::string& proxy_port) override; + void deleteWebViewProfile(const std::string& app_id) override; }; #endif /* BLINKEBPROCESSMANAGER_H */ diff --git a/src/platform/webengine/BlinkWebView.cpp b/src/platform/webengine/BlinkWebView.cpp index 7081e300..b0f36dad 100644 --- a/src/platform/webengine/BlinkWebView.cpp +++ b/src/platform/webengine/BlinkWebView.cpp @@ -18,7 +18,6 @@ #include "WebPageBlinkDelegate.h" #include "LogManager.h" -#include BlinkWebView::BlinkWebView(bool doInitialize) : WebViewBase::WebViewBase() @@ -57,10 +56,10 @@ void BlinkWebView::setDelegate(WebPageBlinkDelegate* delegate) void BlinkWebView::HandleBrowserControlCommand(const std::string& command, const std::vector& arguments) { if (m_delegate) { - QString message = QString::fromStdString(command); - QStringList params; - Q_FOREACH (const std::string& arg, arguments) - params << QString::fromStdString(arg); + std::string message = command; + std::vector params; + for (const std::string& arg : arguments) + params.push_back(arg); m_delegate->handleBrowserControlCommand(message, params); } } @@ -68,13 +67,13 @@ void BlinkWebView::HandleBrowserControlCommand(const std::string& command, const void BlinkWebView::HandleBrowserControlFunction(const std::string& command, const std::vector& arguments, std::string* result) { if (m_delegate) { - QString message = QString::fromStdString(command); - QStringList params; - Q_FOREACH (const std::string& arg, arguments) - params << QString::fromStdString(arg); - QString ret; + std::string message = command; + std::vector params; + for (const std::string& arg : arguments) + params.push_back(arg); + std::string ret; m_delegate->handleBrowserControlFunction(message, params, &ret); - *result = ret.toStdString(); + *result = ret; } } @@ -159,6 +158,10 @@ void BlinkWebView::LoadFinished(const std::string& url) return; m_delegate->loadFinished(url); + +#if !defined(OS_WEBOS) + LoadVisuallyCommitted(); +#endif } void BlinkWebView::LoadFailed(const std::string& url, int errCode, const std::string& errDesc) diff --git a/src/platform/webengine/BlinkWebView.h b/src/platform/webengine/BlinkWebView.h index 467cd975..98d7c653 100644 --- a/src/platform/webengine/BlinkWebView.h +++ b/src/platform/webengine/BlinkWebView.h @@ -18,7 +18,7 @@ #define BLINKWEBVIEW_H #include "webos/webview_base.h" -#include +#include #include class WebPageBlinkDelegate; @@ -27,7 +27,7 @@ class BlinkWebView : public webos::WebViewBase { public: // TODO need to refactor both constructors (here & pluggables) BlinkWebView(bool doInitialize = true); - BlinkWebView(const QString& group) + BlinkWebView(const std::string& group) : BlinkWebView() { } diff --git a/src/platform/webengine/BlinkWebViewProfileHelper.cpp b/src/platform/webengine/BlinkWebViewProfileHelper.cpp index be5e24a3..f8c34176 100644 --- a/src/platform/webengine/BlinkWebViewProfileHelper.cpp +++ b/src/platform/webengine/BlinkWebViewProfileHelper.cpp @@ -16,8 +16,16 @@ #include "BlinkWebViewProfileHelper.h" + #include "webos/webview_profile.h" -#include + +#include +#include + +BlinkWebViewProfileHelper* BlinkWebViewProfileHelper::instance() { + static BlinkWebViewProfileHelper* sInstance = new BlinkWebViewProfileHelper(); + return sInstance; +} void BlinkWebViewProfileHelper::clearBrowsingData(const int removeBrowsingDataMask, webos::WebViewProfile *profile) @@ -64,3 +72,26 @@ int BlinkWebViewProfileHelper::maskForBrowsingDataType(const char* type) { return 0; } + +webos::WebViewProfile* BlinkWebViewProfileHelper::getProfile(const std::string& app_id) { + if (m_appProfileMap.find(app_id) == m_appProfileMap.end()) + return nullptr; + return m_appProfileMap[app_id]; +} + +void BlinkWebViewProfileHelper::buildProfile(const std::string& app_id, const std::string& proxy_host, const std::string& proxy_port) +{ + assert(m_appProfileMap.count(app_id) == 0); + webos::WebViewProfile* profile = new webos::WebViewProfile(app_id); + profile->SetProxyServer(proxy_host, proxy_port, {}, {}); + m_appProfileMap[app_id] = profile; + fprintf(stderr, "BlinkWebViewProfileHelper: added WebViewProfile for app %s\n", app_id.c_str()); +} + +void BlinkWebViewProfileHelper::deleteProfile(const std::string& app_id) +{ + assert(m_appProfileMap.count(app_id) == 1); + delete m_appProfileMap[app_id]; + m_appProfileMap.erase(app_id); + fprintf(stderr, "BlinkWebViewProfileHelper: removed WebViewProfile for app %s\n", app_id.c_str()); +} diff --git a/src/platform/webengine/BlinkWebViewProfileHelper.h b/src/platform/webengine/BlinkWebViewProfileHelper.h index ec9897cd..20bd8575 100644 --- a/src/platform/webengine/BlinkWebViewProfileHelper.h +++ b/src/platform/webengine/BlinkWebViewProfileHelper.h @@ -17,6 +17,9 @@ #ifndef BLINK_WEB_VIEW_PROFILE_HELPER_H_ #define BLINK_WEB_VIEW_PROFILE_HELPER_H_ +#include +#include + namespace webos { class WebViewProfile; } @@ -38,13 +41,21 @@ const char kWebSQL[] = "webSQL"; class BlinkWebViewProfileHelper { public: - BlinkWebViewProfileHelper() {} - virtual ~BlinkWebViewProfileHelper() {} + static BlinkWebViewProfileHelper* instance(); static void clearBrowsingData(const int removeBrowsingDataMask, webos::WebViewProfile* profile = nullptr); static void clearDefaultBrowsingData(const int removeBrowsingDataMask); static int maskForBrowsingDataType(const char* key); + webos::WebViewProfile* getProfile(const std::string& app_id); + void buildProfile(const std::string& app_id, const std::string& proxy_host, const std::string& proxy_port); + void deleteProfile(const std::string& app_id); + +private: + BlinkWebViewProfileHelper() {} + virtual ~BlinkWebViewProfileHelper() = default; + + std::unordered_map m_appProfileMap; }; #endif // BLINK_WEB_VIEW_PROFILE_HELPER_H_ diff --git a/src/platform/webengine/PalmSystemBlink.cpp b/src/platform/webengine/PalmSystemBlink.cpp index 6544b7f4..a544ef54 100755 --- a/src/platform/webengine/PalmSystemBlink.cpp +++ b/src/platform/webengine/PalmSystemBlink.cpp @@ -14,26 +14,30 @@ // // SPDX-License-Identifier: Apache-2.0 +#include "PalmSystemBlink.h" + +#include + #include "ApplicationDescription.h" +#include "JsonHelper.h" #include "LogManager.h" -#include "PalmSystemBlink.h" +#include "StringUtils.h" #include "WebAppBase.h" #include "WebAppWayland.h" #include "WebPageBlink.h" -#include -#include -#include PalmSystemBlink::PalmSystemBlink(WebAppBase* app) : PalmSystemWebOS(app) , m_initialized(false) { } -QString PalmSystemBlink::handleBrowserControlMessage(const QString& message, const QStringList& params) +std::string PalmSystemBlink::handleBrowserControlMessage(const std::string& message, const std::vector& params) { if (message == "initialize") { - return initialize().toJson(); + std::string json; + dumpJsonToString(initialize(), json); + return json; } else if (message == "country") { return country(); } else if (message == "locale") { @@ -41,12 +45,7 @@ QString PalmSystemBlink::handleBrowserControlMessage(const QString& message, con } else if (message == "localeRegion") { return localeRegion(); } else if (message == "isMinimal") { - if(isMinimal()) - return QString("true"); - else - return QString("false"); - } else if (message == "identifier") { - return identifier(); + return isMinimal() ? "true" : "false"; } else if (message == "screenOrientation") { return screenOrientation(); } else if (message == "currentCountryGroup") { @@ -56,67 +55,62 @@ QString PalmSystemBlink::handleBrowserControlMessage(const QString& message, con } else if (message == "containerReady") { setContainerAppReady(m_app->appId()); } else if (message == "activate") { - LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", qPrintable(m_app->appId())), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.activate()"); + LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", m_app->appId().c_str()), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.activate()"); activate(); } else if (message == "deactivate") { - LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", qPrintable(m_app->appId())), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.deactivate()"); + LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", m_app->appId().c_str()), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.deactivate()"); deactivate(); } else if (message == "isActivated") { - if(isActivated()) - return QString("true"); - else - return QString("false"); + return isActivated() ? "true" : "false"; } else if (message == "isKeyboardVisible") { - if(isKeyboardVisible()) - return QString("true"); - else - return QString("false"); + return isKeyboardVisible() ? "true" : "false"; } else if (message == "getIdentifier" || message == "identifier") { - return QString(identifier().toUtf8()); + return identifier(); } else if (message == "launchParams") { - LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", qPrintable(m_app->appId())), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.launchParams Updated by app; %s", qPrintable(params[0])); + LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", m_app->appId().c_str()), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.launchParams Updated by app; %s", params[0].c_str()); updateLaunchParams(params[0]); } else if (message == "screenOrientation") { - QByteArray res; - QDataStream out(res); - out << QVariant(screenOrientation()); - return QString(res); + return screenOrientation(); } else if (message == "keepAlive") { if (params.size() > 0) setKeepAlive(params[0] == "true"); } else if (message == "PmLogInfoWithClock") { - if (params.size() == 3) +#ifdef HAS_PMLOG + if (params.size() == 3) { pmLogInfoWithClock(params[0], params[1], params[2]); + } +#endif } else if (message == "PmLogString") { - if (params.size() > 3) - pmLogString(static_cast(params[0].toInt()), params[1], params[2], params[3]); +#ifdef HAS_PMLOG + if (params.size() > 3) { + auto level = static_cast(stringTo(params[0])); + pmLogString(level, params[1], parasm[2], params[3]); + } +#endif } else if (message == "setWindowProperty") { if (params.size() > 1) { - LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", qPrintable(m_app->appId())), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), - "webOSSystem.window.setProperty('%s', '%s')", qPrintable(params[0]), qPrintable(params[1])); + LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", m_app->appId().c_str()), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), + "webOSSystem.window.setProperty('%s', '%s')", params[0].c_str(), params[1].c_str()); m_app->setWindowProperty(params[0], params[1]); } } else if (message == "platformBack") { - LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", qPrintable(m_app->appId())), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.platformBack()"); + LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", m_app->appId().c_str()), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.platformBack()"); m_app->platformBack(); } else if (message == "setCursor") { - QVariant v1, v2, v3; - v1 = params.at(0); - v2 = params.at(1); - v3 = params.at(2); - m_app->setCursor(v1.toString(), v2.toInt(), v3.toInt()); + auto v1 = params[0]; + auto v2 = stringTo(params[1]); + auto v3 = stringTo(params[2]); + m_app->setCursor(v1, v2, v3); } else if (message == "setInputRegion") { - QByteArray data; - for (int i = 0; i < params.count(); i++) { - data.append(params.at(i)); - } - setInputRegion(data); + std::stringstream ss; + for (const auto ¶m : params) + ss << param; + setInputRegion(ss.str()); } else if (message == "setKeyMask") { - QByteArray data; - for (int i = 0; i < params.count(); i++) { - data.append(params.at(i)); - } - setGroupClientEnvironment(KeyMask, data); + std::stringstream ss; + for (const auto ¶m : params) + ss << param; + setGroupClientEnvironment(KeyMask, ss.str()); } else if (message == "focusOwner") { setGroupClientEnvironment(FocusOwner, NULL); } else if (message == "focusLayer") { @@ -125,64 +119,63 @@ QString PalmSystemBlink::handleBrowserControlMessage(const QString& message, con hide(); } else if (message == "setLoadErrorPolicy") { if (params.size() > 0) { - LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", qPrintable(m_app->appId())), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.setLoadErrorPolicy(%s)", qPrintable(params[0])); + LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", m_app->appId().c_str()), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.setLoadErrorPolicy(%s)", params[0].c_str()); setLoadErrorPolicy(params[0]); } } else if (message == "onCloseNotify") { if (params.size() > 0) { - LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", qPrintable(m_app->appId())), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.onCloseNotify(%s)", qPrintable(params[0])); + LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", m_app->appId().c_str()), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.onCloseNotify(%s)", params[0].c_str()); onCloseNotify(params[0]); } } else if (message == "cursorVisibility") { return cursorVisibility() ? "true" : "false"; } else if (message == "serviceCall") { if (m_app->page()->isClosing()) { - LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", qPrintable(m_app->appId())), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.serviceCall(%s, %s)", qPrintable(params[0]), qPrintable(params[1])); + LOG_INFO(MSGID_PALMSYSTEM, 2, PMLOGKS("APP_ID", m_app->appId().c_str()), PMLOGKFV("PID", "%d", m_app->page()->getWebProcessPID()), "webOSSystem.serviceCall(%s, %s)", params[0].c_str(), params[1].c_str()); m_app->serviceCall(params[0], params[1], m_app->appId()); } else { - LOG_WARNING(MSGID_SERVICE_CALL_FAIL, 2, PMLOGKS("APP_ID", qPrintable(m_app->appId())), - PMLOGKS("URL", qPrintable(params[0])), "Page is NOT in closing"); + LOG_WARNING(MSGID_SERVICE_CALL_FAIL, 2, PMLOGKS("APP_ID", m_app->appId().c_str()), + PMLOGKS("URL", params[0].c_str()), "Page is NOT in closing"); } } - return QString(); + return {}; } void PalmSystemBlink::setCountry() { - static_cast(m_app->page())->updateExtensionData(QStringLiteral("country"), country()); + static_cast(m_app->page())->updateExtensionData("country", country()); } -void PalmSystemBlink::setLaunchParams(const QString& params) +void PalmSystemBlink::setLaunchParams(const std::string& params) { PalmSystemWebOS::setLaunchParams(params); - static_cast(m_app->page())->updateExtensionData(QStringLiteral("launchParams"), launchParams()); + static_cast(m_app->page())->updateExtensionData("launchParams", launchParams()); } -void PalmSystemBlink::setLocale(const QString& params) +void PalmSystemBlink::setLocale(const std::string& params) { - static_cast(m_app->page())->updateExtensionData(QStringLiteral("locale"), params); + static_cast(m_app->page())->updateExtensionData("locale", params); } -QString PalmSystemBlink::identifier() const +std::string PalmSystemBlink::identifier() const { if (!m_app->page()) - return QStringLiteral(""); - + return {}; return static_cast(m_app->page())->getIdentifier(); } -void PalmSystemBlink::setLoadErrorPolicy(const QString& params) +void PalmSystemBlink::setLoadErrorPolicy(const std::string& params) { static_cast(m_app->page())->setLoadErrorPolicy(params); } -QString PalmSystemBlink::trustLevel() const +std::string PalmSystemBlink::trustLevel() const { return static_cast(m_app->page())->trustLevel(); } -void PalmSystemBlink::onCloseNotify(const QString& params) +void PalmSystemBlink::onCloseNotify(const std::string& params) { if (params == "didSetOnCloseCallback") static_cast(m_app->page())->setHasOnCloseCallback(true); @@ -197,29 +190,25 @@ double PalmSystemBlink::devicePixelRatio() return static_cast(m_app->page())->devicePixelRatio(); } -QJsonDocument PalmSystemBlink::initialize() +Json::Value PalmSystemBlink::initialize() { - m_initialized = true; + // Setup initial data set + Json::Value data; + data["launchParams"] = launchParams(); + data["country"] = country(); + data["currentCountryGroup"] = getDeviceInfo("CountryGroup"); + data["locale"] = locale(); + data["localeRegion"] = localeRegion(); + data["isMinimal"] = isMinimal(); + data["identifier"] = identifier(); + data["screenOrientation"] = screenOrientation(); + data["activityId"] = (double)activityId(); + data["phoneRegion"] = phoneRegion(); + data["folderPath"] = m_app->getAppDescription()->folderPath(); + data["devicePixelRatio"] = devicePixelRatio(); + data["trustLevel"] = trustLevel(); - QJsonObject data; - data.insert(QStringLiteral("launchParams"), launchParams()); - data.insert(QStringLiteral("country"), country()); - data.insert(QStringLiteral("tvSystemName"), getDeviceInfo("TvSystemName")); - data.insert(QStringLiteral("currentCountryGroup"), getDeviceInfo("CountryGroup")); - data.insert(QStringLiteral("locale"), locale()); - data.insert(QStringLiteral("localeRegion"), localeRegion()); - data.insert(QStringLiteral("isMinimal"), isMinimal()); - data.insert(QStringLiteral("identifier"), identifier()); - data.insert(QStringLiteral("screenOrientation"), screenOrientation()); - data.insert(QStringLiteral("deviceInfo"), getDeviceInfo("TvDeviceInfo")); - data.insert(QStringLiteral("activityId"), QJsonValue((double)activityId())); - data.insert(QStringLiteral("phoneRegion"), phoneRegion()); - data.insert(QStringLiteral("folderPath"), QString::fromStdString((m_app->getAppDescription())->folderPath())); - - data.insert(QStringLiteral("devicePixelRatio"), devicePixelRatio()); - data.insert(QStringLiteral("trustLevel"), trustLevel()); - QJsonDocument doc(data); - return doc; + m_initialized = true; + return data; } - diff --git a/src/platform/webengine/PalmSystemBlink.h b/src/platform/webengine/PalmSystemBlink.h index ef9f9cf0..8eb912ec 100755 --- a/src/platform/webengine/PalmSystemBlink.h +++ b/src/platform/webengine/PalmSystemBlink.h @@ -17,31 +17,38 @@ #ifndef PALMSYSTEMBLINK_H_ #define PALMSYSTEMBLINK_H_ +#include +#include + #include "PalmSystemWebOS.h" +namespace Json { +class Value; +} + class PalmSystemBlink : public PalmSystemWebOS { public: PalmSystemBlink(WebAppBase* app); - QString handleBrowserControlMessage(const QString& message, const QStringList& params); + std::string handleBrowserControlMessage(const std::string& message, const std::vector& params); // PalmSystemWebOS void setCountry() override; - void setLaunchParams(const QString& params) override; + void setLaunchParams(const std::string& params) override; - virtual void setLocale(const QString& params); + virtual void setLocale(const std::string& params); virtual double devicePixelRatio(); void resetInitialized() { m_initialized = false; } bool isInitialized() { return m_initialized; } protected: // PalmSystemWebOS - QJsonDocument initialize(); - QString identifier() const override; - void setLoadErrorPolicy(const QString& params) override; + Json::Value initialize(); + std::string identifier() const override; + void setLoadErrorPolicy(const std::string& params) override; - virtual QString trustLevel() const; - virtual void onCloseNotify(const QString& params); + virtual std::string trustLevel() const; + virtual void onCloseNotify(const std::string& params); private: bool m_initialized; diff --git a/src/platform/webengine/WebPageBlink.cpp b/src/platform/webengine/WebPageBlink.cpp index 217bebbf..225ef608 100644 --- a/src/platform/webengine/WebPageBlink.cpp +++ b/src/platform/webengine/WebPageBlink.cpp @@ -16,24 +16,39 @@ #include "WebPageBlink.h" +#include #include +#include +#include +#include +#include -#include -#include -#include -#include -#include +#include +#include #include "ApplicationDescription.h" #include "BlinkWebProcessManager.h" #include "BlinkWebView.h" +#include "BlinkWebViewProfileHelper.h" #include "LogManager.h" #include "PalmSystemBlink.h" +#include "StringUtils.h" #include "WebAppManagerConfig.h" #include "WebAppManagerTracer.h" +#include "WebAppManagerUtils.h" #include "WebPageObserver.h" #include "WebPageBlinkObserver.h" +#include "webos/webview_profile.h" + +#define DBG(fmt, ...) \ + do { \ + fprintf(stderr, "### [WebPageBlink] "); \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + } while (0) + +namespace fs = boost::filesystem; + /** * Hide dirty implementation details from * public API @@ -41,18 +56,7 @@ static const int kExecuteCloseCallbackTimeOutMs = 10000; -QString getHostname(const std::string& url) -{ - // Convert given url to QURL and - // return its hostname. - QString q_url = QString::fromStdString(url); - return QUrl(q_url).host(); -} - -class WebPageBlinkPrivate : public QObject -{ - Q_OBJECT - +class WebPageBlinkPrivate { public: WebPageBlinkPrivate(WebPageBlink * page) : q(page) @@ -75,7 +79,7 @@ class WebPageBlinkPrivate : public QObject }; -WebPageBlink::WebPageBlink(const QUrl& url, std::shared_ptr desc, const QString& params) +WebPageBlink::WebPageBlink(const Url& url, std::shared_ptr desc, const std::string& params) : WebPageBase(url, desc, params) , d(new WebPageBlinkPrivate(this)) , m_isPaused(false) @@ -85,7 +89,7 @@ WebPageBlink::WebPageBlink(const QUrl& url, std::shared_ptrtrustLevel())) + , m_trustLevel(desc->trustLevel()) , m_observer(nullptr) { } @@ -103,6 +107,11 @@ void WebPageBlink::init() { d->pageView = createPageView(); d->pageView->setDelegate(this); + webos::WebViewProfile* profile = BlinkWebViewProfileHelper::instance()->getProfile(m_appDesc->id()); + if (profile) { + DBG("### Setting profile for page %s\n", m_appDesc->id().c_str()); + d->pageView->SetProfile(profile->GetProfileDelegate()); + } d->pageView->Initialize(m_appDesc->id(), m_appDesc->folderPath(), m_appDesc->trustLevel(), @@ -114,13 +123,12 @@ void WebPageBlink::init() d->pageView->SetVisible(false); d->pageView->SetUserAgent(d->pageView->DefaultUserAgent() + " " + getWebAppManagerConfig()->getName()); - // TODO : need to replace qgetenv - if(qgetenv("ENABLE_INSPECTOR") == "1") + if(WebAppManagerUtils::getEnv("ENABLE_INSPECTOR") == "1") d->pageView->SetInspectable(true); - if(!qgetenv("PRIVILEGED_PLUGIN_PATH").isEmpty()) { - QString privileged_plugin_path = QLatin1String(qgetenv("PRIVILEGED_PLUGIN_PATH")); - d->pageView->AddAvailablePluginDir(privileged_plugin_path.toStdString()); + std::string pluginPath = WebAppManagerUtils::getEnv("PRIVILEGED_PLUGIN_PATH"); + if (!pluginPath.empty()) { + d->pageView->AddAvailablePluginDir(pluginPath); } d->pageView->SetAllowFakeBoldText(false); @@ -145,8 +153,8 @@ void WebPageBlink::init() if (!std::isnan(m_appDesc->networkStableTimeout()) && (m_appDesc->networkStableTimeout() >= 0.0)) d->pageView->SetNetworkStableTimeout(m_appDesc->networkStableTimeout()); - if (QString::fromStdString(m_appDesc->trustLevel()) == "trusted") { - LOG_DEBUG("[%s] trustLevel : trusted; allow load local Resources", qPrintable(appId())); + if (m_appDesc->trustLevel() == "trusted") { + LOG_DEBUG("[%s] trustLevel : trusted; allow load local Resources", appId().c_str()); d->pageView->SetAllowLocalResourceLoad(true); } d->pageView->AddUserStyleSheet("body { -webkit-user-select: none; } :focus { outline: none }"); @@ -156,11 +164,11 @@ void WebPageBlink::init() d->pageView->SetFontHinting(webos::WebViewBase::FontRenderParams::HINTING_SLIGHT); - QString language; + std::string language; getSystemLanguage(language); setPreferredLanguages(language); - d->pageView->SetAppId(appId().toStdString()); - d->pageView->SetSecurityOrigin(appId().toStdString()); + d->pageView->SetAppId(appId()); + d->pageView->SetSecurityOrigin(appId()); updateHardwareResolution(); updateBoardType(); updateDatabaseIdentifier(); @@ -182,22 +190,22 @@ void* WebPageBlink::getWebContents() return (void*)d->pageView->GetWebContents(); } -void WebPageBlink::handleBrowserControlCommand(const QString& command, const QStringList& arguments) +void WebPageBlink::handleBrowserControlCommand(const std::string& command, const std::vector& arguments) { handleBrowserControlMessage(command, arguments); } -void WebPageBlink::handleBrowserControlFunction(const QString& command, const QStringList& arguments, QString* result) +void WebPageBlink::handleBrowserControlFunction(const std::string& command, const std::vector& arguments, std::string* result) { *result = handleBrowserControlMessage(command, arguments); } -QString WebPageBlink::handleBrowserControlMessage(const QString& message, const QStringList& params) +std::string WebPageBlink::handleBrowserControlMessage(const std::string& message, const std::vector& params) { if (!d->m_palmSystem) - return QString(); + return {}; - QString res = d->m_palmSystem->handleBrowserControlMessage(message, params); + auto res = d->m_palmSystem->handleBrowserControlMessage(message, params); return res; } @@ -206,9 +214,9 @@ bool WebPageBlink::canGoBack() return d->pageView->CanGoBack(); } -QString WebPageBlink::title() +std::string WebPageBlink::title() { - return QString(d->pageView->DocumentTitle().c_str()); + return d->pageView->DocumentTitle(); } void WebPageBlink::setFocus(bool focus) @@ -218,7 +226,7 @@ void WebPageBlink::setFocus(bool focus) void WebPageBlink::loadDefaultUrl() { - d->pageView->LoadUrl(defaultUrl().toString().toStdString()); + d->pageView->LoadUrl(defaultUrl().toString()); } int WebPageBlink::progress() const @@ -231,14 +239,14 @@ bool WebPageBlink::hasBeenShown() const return m_hasBeenShown; } -void WebPageBlink::replaceBaseUrl(QUrl newUrl) +void WebPageBlink::replaceBaseUrl(const Url& newUrl) { - d->pageView->ReplaceBaseURL(newUrl.toString().toStdString(), url().toString().toStdString()); + d->pageView->ReplaceBaseURL(newUrl.toString(), url().toString()); } -QUrl WebPageBlink::url() const +Url WebPageBlink::url() const { - return QUrl(d->pageView->GetUrl().c_str()); + return Url(d->pageView->GetUrl()); } uint32_t WebPageBlink::getWebProcessProxyID() @@ -246,7 +254,7 @@ uint32_t WebPageBlink::getWebProcessProxyID() return 0; } -void WebPageBlink::setPreferredLanguages(const QString& language) +void WebPageBlink::setPreferredLanguages(const std::string& language) { if (d->m_palmSystem) d->m_palmSystem->setLocale(language); @@ -254,19 +262,19 @@ void WebPageBlink::setPreferredLanguages(const QString& language) #ifndef TARGET_DESKTOP // just set system language for accept-language for http header, navigator.language, navigator.languages // even window.languagechange event too - d->pageView->SetAcceptLanguages(language.toStdString()); + d->pageView->SetAcceptLanguages(language); d->pageView->UpdatePreferences(); #endif } -void WebPageBlink::setDefaultFont(const QString& font) +void WebPageBlink::setDefaultFont(const std::string& font) { - d->pageView->SetStandardFontFamily(font.toStdString()); - d->pageView->SetFixedFontFamily(font.toStdString()); - d->pageView->SetSerifFontFamily(font.toStdString()); - d->pageView->SetSansSerifFontFamily(font.toStdString()); - d->pageView->SetCursiveFontFamily(font.toStdString()); - d->pageView->SetFantasyFontFamily(font.toStdString()); + d->pageView->SetStandardFontFamily(font); + d->pageView->SetFixedFontFamily(font); + d->pageView->SetSerifFontFamily(font); + d->pageView->SetSansSerifFontFamily(font); + d->pageView->SetCursiveFontFamily(font); + d->pageView->SetFantasyFontFamily(font); } void WebPageBlink::reloadDefaultPage() @@ -278,29 +286,37 @@ void WebPageBlink::reloadDefaultPage() loadDefaultUrl(); } +static fs::path genPathForLang(const std::string &localeStr) +{ + auto encodingBegin = localeStr.find('.'); + auto variantBegin = localeStr.find('@'); + auto size = std::min(encodingBegin, variantBegin); + std::string lang(localeStr, 0, size); + std::vector tokens; + boost::split(tokens, lang, boost::is_any_of("_")); + return boost::join(tokens, "/"); +} + + void WebPageBlink::loadErrorPage(int errorCode) { - QString errorpage = getWebAppManagerConfig()->getErrorPageUrl(); - if(!errorpage.isEmpty()) { + std::string errorpage = getWebAppManagerConfig()->getErrorPageUrl(); + if(!errorpage.empty()) { if(hasLoadErrorPolicy(false, errorCode)) { // has loadErrorPolicy, do not show error page - LOG_DEBUG("[%s] has own policy for Error Page, do not load Error page; send webOSLoadError event; return", qPrintable(appId())); + LOG_DEBUG("[%s] has own policy for Error Page, do not load Error page; send webOSLoadError event; return", + appId().c_str()); return; } - QString language; - getSystemLanguage(language); - QLocale locale(language); - // Break the provided URL down into it's component pieces // we always assume the error page will be a file:// url, because that's // the only thing that makes sense. - QUrl errorUrl(errorpage); - QFile file(errorUrl.toLocalFile()); - QFileInfo fileinfo(file); - QString fileName = fileinfo.fileName(); - QString searchPath = fileinfo.canonicalPath(); - QString errCode = QString::number(errorCode); + Url errorUrl(errorpage); + fs::path errPagePath(errorUrl.toLocalFile()); + fs::path fileName = errPagePath.filename(); + fs::path searchPath = fs::canonical(errPagePath); + std::string errCode = std::to_string(errorCode); // search order: // searchPath/resources//