diff options
Diffstat (limited to 'meta-agl-html5-demo/recipes-wam')
58 files changed, 11281 insertions, 0 deletions
diff --git a/meta-agl-html5-demo/recipes-wam/cef/cef_git.bb b/meta-agl-html5-demo/recipes-wam/cef/cef_git.bb new file mode 100644 index 000000000..4a87631ba --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/cef_git.bb @@ -0,0 +1,355 @@ +require gn-utils.inc + +inherit qemu python3native + +LICENSE = "Apache-2.0 & BSD-3-Clause & LGPL-2.0-only & LGPL-2.1-only" + +LIC_FILES_CHKSUM = "\ + file://LICENSE;md5=c408a301e3407c3803499ce9290515d6 \ + file://third_party/blink/renderer/core/LICENSE-LGPL-2;md5=36357ffde2b64ae177b2494445b79d21 \ + file://third_party/blink/renderer/core/LICENSE-LGPL-2.1;md5=a778a33ef338abbaf8b8a7c36b6eec80 \ +" + +CHROMIUM_VERSION = "118.0.5993.80" +BRANCH = "5993" +SRCREV = "3cffa575446727e2fe1f6499efa21f8e096e8ca0" + +PV = "${CHROMIUM_VERSION}.${BRANCH}+git" + +FILESEXTRAPATHS:prepend := "${THISDIR}/files/cef:" +FILESEXTRAPATHS:prepend := "${THISDIR}/files/chromium:" + +# The [agl]-prefixed patches are the changes needed to make WAM work with +# agl-compositor. The [meta-browser] patches comes from the https://github.com/OSSystems/meta-browser +# project that does similar work on keeping up to the new chromium milestones +# and the [MXX-Fix] patches are the fixes done by us to fix build issues for +# the current chromium milestone. +# For more information about the current milestones: https://chromiumdash.appspot.com/releases?platform=Linux +SRC_URI = "\ + https://commondatastorage.googleapis.com/chromium-browser-official/chromium-${CHROMIUM_VERSION}.tar.xz \ + file://0001-agl-compositor-Add-agl_shell_wrapper-AGL-wayland-ext.patch \ + file://0002-agl-Add-waylandwindow-window-tree-host-essential-par.patch \ + file://0003-agl-Only-bind-to-agl_shell-if-it-s-the-browser-proce.patch \ + file://0004-agl-Add-a-method-to-check-if-the-agl-window-is-confi.patch \ + file://0005-agl-Start-using-agl-shell-version-4.patch \ + file://0006-agl-Don-t-use-DRI-for-renesas.patch \ + file://0007-meta-browser-Remove-the-GN-settings-done-for-clang-t.patch \ + file://0008-meta-browser-Pass-no-static-libstdc-to-gen.py.patch \ + file://0009-meta-browser-IWYU-Add-includes-for-size_t-and-int64_.patch \ + file://0010-meta-browser-BUILD-do-not-specify-march-on-arm.patch \ + file://0011-meta-browser-Avoid-parenthesized-initialization-of-a.patch \ + file://0012-meta-browser-Fix-constexpr-variable-cannot-have-non-.patch \ + file://0013-meta-browser-Add-missing-typename-s.patch \ + file://0014-meta-browser-Avoid-std-ranges-find_if.patch \ + file://0015-meta-browser-Avoid-capturing-structured-bindings.patch \ + file://0016-meta-browser-Delete-compiler-options-not-available-i.patch \ + file://0017-meta-browser-Don-t-pass-disable-auto-upgrade-debug-i.patch \ + file://0018-meta-browser-Fix-undefined-symbol-PaintOpWriter-Seri.patch \ + file://0019-upstream-Initialize-ServerCvc-with-designated-initia.patch \ + file://0020-M118-fix-Don-t-look-for-depot_tools-in-chrommium-s-t.patch \ + file://0021-M118-fix-Add-multiple-missing-includes.patch \ + file://0022-M118-fix-Fix-aggregate-initialization-in-trace_log.patch \ + file://0023-M118-fix-Add-missing-typename-keyword-in-multiple-st.patch \ + file://0024-M118-fix-Fix-comparison-in-HostResolverCache.patch \ + file://0025-M118-fix-Avoid-using-std-ranges-any_of-find_if-none_.patch \ + file://0026-M118-fix-Add-deleted-constructors-operators.patch \ + file://0027-M118-fix-Initialize-percentages-member-on-blink-Font.patch \ + file://0028-M118-fix-Don-t-delete-ZstdSourceStream-copy-move-cto.patch \ + file://0029-M118-fix-Fix-issue-with-structured-bindinds-captured.patch \ + file://0030-M118-fix-Only-default-arm_use_neon-to-true-if-its-va.patch \ + file://0031-M118-fix-Add-a-way-to-set-different-lib-paths-host-a.patch \ + file://0032-M118-fix-zlib-Fix-arm-build.patch \ + file://0033-M118-fix-Fix-skia-linker-issues-for-arm-neon.patch \ + file://0034-v8-qemu-wrapper.patch \ + \ + git://bitbucket.org/chromiumembedded/cef.git;branch=${BRANCH};protocol=https;rev=${SRCREV};name=cef;destsuffix=chromium-${CHROMIUM_VERSION}/cef \ + file://0001-Add-an-option-to-use-an-output-directory-outside-src.patch;patchdir=cef \ + file://0002-Add-an-option-to-override-the-default-distrib-direct.patch;patchdir=cef \ + file://0003-Add-an-option-to-use-an-alternative-base-output-dire.patch;patchdir=cef \ + file://0004-Add-an-option-to-bypass-sysroot-checking-and-force.patch;patchdir=cef \ + file://0005-Add-AGL-wayland-window-related-calls.patch;patchdir=cef \ + file://0006-Add-a-method-to-check-if-the-agl-window-is-configure.patch;patchdir=cef \ + file://0007-Add-the-SetActivateRegion-method.patch;patchdir=cef \ + file://0008-Allow-passing-the-app_id-on-widget-creation.patch;patchdir=cef \ + file://0009-Update-generated-api.patch;patchdir=cef \ + file://0010-Make-patcher-work-outside-a-git-checkout.patch;patchdir=cef \ + file://0011-Avoid-the-RuntimeError-dictionary-changed-size-durin.patch;patchdir=cef \ +" + +SRC_URI[sha256sum] = "741c5528a151bc364999969077a13d7a283cfd0eaf34adf47de667a34e5e58ff" + +CHROMIUM_DIR = "${WORKDIR}/chromium-${CHROMIUM_VERSION}" +CEF_DIR = "${CHROMIUM_DIR}/cef" +DEPOT_TOOLS_DIR="${STAGING_DIR_NATIVE}${datadir}/depot_tools" +S = "${CHROMIUM_DIR}" +B = "${WORKDIR}/build" + +OUT_PATH = "${B}/out/Release_GN_${GN_TARGET_ARCH_NAME}" +DIST_PATH = "${OUT_PATH}/dist/cef-minimal_${GN_TARGET_ARCH_NAME}" +CEF_DATA_PATH = "${datadir}/cef" + +DEPENDS:append = " ca-certificates-native curl clang clang-native gperf-native dbus libcxx libcxx-native libpng libxslt jpeg jpeg-native compiler-rt libxkbcommon nss nss-native atk at-spi2-atk libdrm pango cairo virtual/egl qemu-native pciutils glib-2.0 pkgconfig-native pulseaudio xz-native compiler-rt compiler-rt-native expat-native" + +do_sync[depends] += "depot-tools-wam-native:do_populate_sysroot" +do_configure[depends] += "depot-tools-wam-native:do_populate_sysroot" +do_compile[depends] += "depot-tools-wam-native:do_populate_sysroot" + +# needs to fetch a font package +do_configure[network] = "1" + +GN_UNBUNDLE_LIBS = " libjpeg libpng libxslt" + +# gn defaults from CEF wiki, except for use_sysroot +GN_DEFINES = "use_sysroot=false \ + symbol_level=0 \ + is_cfi=false \ + use_thin_lto=false \ +" + +# Disable GTK and prevent cef from +# building its gtk demos +GN_DEFINES:append = " \ + use_gtk=false \ + cef_use_gtk=false \ +" + +GN_DEFINES:append = " \ + treat_warnings_as_errors=false \ + is_component_build=false \ + use_cups=false \ + use_kerberos=false \ + use_ozone=true \ + use_xkbcommon=true \ + use_wayland_gbm=true \ + use_gnome_keyring=false \ + enable_remoting=false \ + enable_js_type_check=false \ +" + +# ozone options +GN_DEFINES:append = " \ + use_ozone=true \ + ozone_auto_platforms=false \ + ozone_platform_headless=true \ + ozone_platform_wayland=true \ + ozone_platform_x11=false \ + use_system_minigbm=true \ + use_system_libdrm=true \ + use_system_libwayland=false \ + use_system_libffi=true \ +" + +GN_DEFINES:append = " \ + dcheck_always_on=false \ + is_debug=false \ + is_official_build=true \ +" + +GN_DEFINES:append = " \ + use_egl=true \ + use_glib=true \ + use_dri=false \ +" + +RUNTIME = "llvm" +TOOLCHAIN = "clang" +TOOLCHAIN:class-native = "clang" +LIBCPLUSPLUS = "-stdlib=libc++" + +BUILD_CPPFLAGS:append:runtime-llvm = " -isysroot=${STAGING_DIR_NATIVE} -stdlib=libc++" +BUILD_LDFLAGS:append:runtime-llvm = " -rtlib=libgcc -unwindlib=libgcc -stdlib=libc++ -lc++abi -rpath ${STAGING_LIBDIR_NATIVE}" +CXXFLAGS:append:runtime-llvm = " -isysroot=${STAGING_DIR_NATIVE} -stdlib=libc++" + +BUILD_AR:toolchain-clang = "llvm-ar" +BUILD_CC:toolchain-clang = "clang" +BUILD_CXX:toolchain-clang = "clang++" +BUILD_LD:toolchain-clang = "clang" + +COMPATIBLE_MACHINE = "(-)" +COMPATIBLE_MACHINE:aarch64 = "(.*)" +COMPATIBLE_MACHINE:armv6 = "(.*)" +COMPATIBLE_MACHINE:armv7a = "(.*)" +COMPATIBLE_MACHINE:armv7ve = "(.*)" +COMPATIBLE_MACHINE:x86 = "(.*)" +COMPATIBLE_MACHINE:x86-64 = "(.*)" + +# ARM builds need special additional flags (see ${S}/build/config/arm.gni). +# If we do not pass |arm_arch| and friends to GN, it will deduce a value that +# will then conflict with TUNE_CCARGS and CC. +# Note that as of M61 in some corner cases parts of the build system disable +# the "compiler_arm_fpu" GN config, whereas -mfpu is always passed via ${CC}. +# We might want to rework that if there are issues in the future. +def get_compiler_flag(params, param_name, d): + """Given a sequence of compiler arguments in |params|, returns the value of + an option |param_name| or an empty string if the option is not present.""" + for param in params: + if param.startswith(param_name): + return param.split('=')[1] + return '' + +ARM_FLOAT_ABI = "${@bb.utils.contains('TUNE_FEATURES', 'callconvention-hard', 'hard', 'softfp', d)}" +ARM_FPU = "${@get_compiler_flag(d.getVar('TUNE_CCARGS').split(), '-mfpu', d)}" +ARM_TUNE = "${@get_compiler_flag(d.getVar('TUNE_CCARGS').split(), '-mcpu', d)}" +ARM_VERSION:aarch64 = "8" +ARM_VERSION:armv7a = "7" +ARM_VERSION:armv7ve = "7" +ARM_VERSION:armv6 = "6" + +# GN computes and defaults to it automatically where needed +# forcing it from cmdline breaks build on places where it ends up +# overriding what GN wants +TUNE_CCARGS:remove = "-mthumb" + +GN_DEFINES:append:arm = " \ + arm_float_abi=\"${ARM_FLOAT_ABI}\" \ + arm_fpu=\"${ARM_FPU}\" \ + arm_tune=\"${ARM_TUNE}\" \ + arm_version=${ARM_VERSION} \ +" +# tcmalloc's atomicops-internals-arm-v6plus.h uses the "dmb" instruction that +# is not available on (some?) ARMv6 models, which causes the build to fail. +GN_DEFINES:append:armv6 = ' use_allocator="none"' +# The WebRTC code fails to build on ARMv6 when NEON is enabled. +# https://bugs.chromium.org/p/webrtc/issues/detail?id=6574 + +# Disable unknown attribute warnings that are generating tons of logs +# TODO(rzanoni): check if https://chromium-review.googlesource.com/c/chromium/src/+/4322480 +# needs to be reverted +BUILD_CXXFLAGS:remove = '-Wunknown-attributes' +BUILD_CXXFLAGS:append = ' -Wno-unknown-attributes' +BUILD_CPPFLAGS:remove = '-Wunknown-attributes' +BUILD_CPPFLAGS:append = ' -Wno-unknown-attributes' +CXXFLAGS:remove = '-Wunknown-attributes' +CXXFLAGS:append = ' -Wno-unknown-attributes' +CPPFLAGS:remove = '-Wunknown-attributes' +CPPFLAGS:append = ' -Wno-unknown-attributes' + +GN_DEFINES:append = ' \ + arm_use_neon=false \ + use_lld=true \ + use_gold=false \ + use_custom_libcxx_for_host=false \ + use_custom_libcxx=false \ + chrome_pgo_phase=0 \ + gold_path="" \ + is_clang=true \ + current_os="linux" \ + clang_use_chrome_plugins=false \ + clang_base_path="${STAGING_DIR_NATIVE}/usr" \ + clang_version="14.0.6" \ + clang_base_path_target="${STAGING_DIR_TARGET}/usr" \ + custom_toolchain="//build/toolchain/cros:target" \ + host_toolchain="//build/toolchain/cros:host" \ + v8_snapshot_toolchain="//build/toolchain/cros:v8_snapshot" \ + target_cpu="${@gn_target_arch_name(d)}" \ + use_v8_context_snapshot=false \ + custom_toolchain="//build/toolchain/yocto:yocto_target" \ + host_toolchain="//build/toolchain/yocto:yocto_native" \ + v8_snapshot_toolchain="//build/toolchain/yocto:yocto_target" \ +' + +PACKAGECONFIG ??= "upower use-egl" +PACKAGECONFIG[use-egl] = ",,virtual/egl virtual/libgles2" +PACKAGECONFIG[upower] = ",,,upower" + +GN_DEFINES:append = ' \ + ${PACKAGECONFIG_CONFARGS} \ +' + +python do_write_toolchain_file () { + """Writes a BUILD.gn file for Yocto detailing its toolchains.""" + toolchain_dir = d.expand("${S}/build/toolchain/yocto") + bb.utils.mkdirhier(toolchain_dir) + toolchain_file = os.path.join(toolchain_dir, "BUILD.gn") + write_toolchain_file(d, toolchain_file) +} +addtask write_toolchain_file after do_patch before do_configure + +# V8's JIT infrastructure requires binaries such as mksnapshot and +# mkpeephole to be run in the host during the build. However, these +# binaries must have the same bit-width as the target (e.g. a x86_64 +# host targeting ARMv6 needs to produce a 32-bit binary). Instead of +# depending on a third Yocto toolchain, we just build those binaries +# for the target and run them on the host with QEMU. +python do_create_v8_qemu_wrapper () { + """Creates a small wrapper that invokes QEMU to run some target V8 binaries + on the host.""" + qemu_libdirs = [d.expand('${STAGING_DIR_HOST}${libdir}'), + d.expand('${STAGING_DIR_HOST}${base_libdir}')] + qemu_cmd = qemu_wrapper_cmdline(d, d.getVar('STAGING_DIR_HOST', True), + qemu_libdirs) + wrapper_path = d.expand('${OUT_PATH}/v8-qemu-wrapper.sh') + with open(wrapper_path, 'w') as wrapper_file: + wrapper_file.write("""#!/bin/sh + +# This file has been generated automatically. +# It invokes QEMU to run binaries built for the target in the host during the +# build process. + +%s "$@" +""" % qemu_cmd) + os.chmod(wrapper_path, 0o755) +} +do_create_v8_qemu_wrapper[dirs] = "${OUT_PATH}" +addtask create_v8_qemu_wrapper after do_patch before do_configure + +do_configure () { + bbnote "do_configure:" + bbnote "Base out path: ${B}" + + export DEPOT_TOOLS_UPDATE=0 + export GCLIENT_PY3=1 + export PATH="${DEPOT_TOOLS_DIR}:$PATH" + export GN_DEFINES="${GN_DEFINES}" + export SSL_CERT_DIR="$OECORE_NATIVE_SYSROOT/etc/ssl/certs/" + cd ${S} + python3 ./build/linux/unbundle/replace_gn_files.py --system-libraries ${GN_UNBUNDLE_LIBS} + + # Download a few dependencies. Check the current chromium DEPS file when + # upgrading to a new milestone. + vpython3 third_party/depot_tools/download_from_google_storage.py --no_resume --extract --no_auth --bucket chromium-fonts -s third_party/test_fonts/test_fonts.tar.gz.sha1 + vpython3 third_party/depot_tools/download_from_google_storage.py --no_resume --extract --no_auth --bucket chromium-nodejs/16.13.0 -s third_party/node/linux/node-linux-x64.tar.gz.sha1 + vpython3 tools/rust/update_rust.py + + cd ${S}/cef + python3 tools/gclient_hook.py --base-out-path ${B} --bypass-sysroot-check +} + +do_compile[progress] = "outof:^\[(\d+)/(\d+)\]\s+" +do_compile () { + if [ ! -f ${OUT_PATH}/build.ninja ]; then + do_configure + fi + + export PATH="${DEPOT_TOOLS_DIR}:$PATH" + export PATH="$PATH:${S}/third_party/ninja" + ninja ${PARALLEL_MAKE} -C ${OUT_PATH} libcef chrome_sandbox +} + +do_install () { + cd ${S}/cef + python3 tools/make_distrib.py --output-dir ${OUT_PATH}/dist \ + --dist-path-name cef-minimal \ + --base-out-path ${B} \ + --no-docs \ + --no-symbols \ + --no-archive \ + --ninja-build \ + --minimal \ + --${GN_TARGET_ARCH_NAME}-build \ + --ozone + + install -d ${D}${CEF_DATA_PATH} + + cp -R --no-dereference --preserve=mode,links -v ${DIST_PATH}/* ${D}${CEF_DATA_PATH} + # TODO(rzanoni): Follow the wiki instructions to install the sandbox +} + +# TODO: fix QA issues, libraries in the wrong location +FILES:${PN} += " \ + ${CEF_DATA_PATH} \ +" + +INSANE_SKIP:${PN} += "libdir" + +PROVIDES:${PN} += "cef" diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0001-Add-an-option-to-use-an-output-directory-outside-src.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0001-Add-an-option-to-use-an-output-directory-outside-src.patch new file mode 100644 index 000000000..af2ea0baa --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0001-Add-an-option-to-use-an-output-directory-outside-src.patch @@ -0,0 +1,38 @@ +From 97e9e8dd589d7d3467d762f6ab25ec4a4f30505f Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Mon, 24 Apr 2023 10:52:57 +0200 +Subject: [PATCH 1/9] Add an option to use an output directory outside src + +--- + tools/make_distrib.py | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/tools/make_distrib.py b/tools/make_distrib.py +index c808ad7df..ea798b86f 100644 +--- a/tools/make_distrib.py ++++ b/tools/make_distrib.py +@@ -459,6 +459,12 @@ This utility builds the CEF Binary Distribution. + """ + + parser = OptionParser(description=disc) ++ ++parser.add_option( ++ '--base-out-path', ++ dest='baseoutpath', ++ default='', ++ help="Use an anternative base path for the generated gn outputs instead of using chromium source dir") + parser.add_option( + '--output-dir', + dest='outputdir', +@@ -700,6 +706,8 @@ else: + + # Determine the build directory paths. + out_dir = os.path.join(src_dir, 'out') ++if options.baseoutpath != '': ++ out_dir = os.path.join(options.baseoutpath, 'out') + build_dir_debug = os.path.join(out_dir, 'Debug' + build_dir_suffix) + build_dir_release = os.path.join(out_dir, 'Release' + build_dir_suffix) + +-- +2.42.0 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0002-Add-an-option-to-override-the-default-distrib-direct.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0002-Add-an-option-to-override-the-default-distrib-direct.patch new file mode 100644 index 000000000..0061c4d15 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0002-Add-an-option-to-override-the-default-distrib-direct.patch @@ -0,0 +1,39 @@ +From d0ab00e0a22cab8f00d2b1b8c6904c68ff3fa09a Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Mon, 24 Apr 2023 13:56:10 +0200 +Subject: [PATCH 2/9] Add an option to override the default distrib directory + name + +--- + tools/make_distrib.py | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/tools/make_distrib.py b/tools/make_distrib.py +index ea798b86f..6ed748fe7 100644 +--- a/tools/make_distrib.py ++++ b/tools/make_distrib.py +@@ -465,6 +465,11 @@ parser.add_option( + dest='baseoutpath', + default='', + help="Use an anternative base path for the generated gn outputs instead of using chromium source dir") ++parser.add_option( ++ '--dist-path-name', ++ dest='distpathname', ++ default='', ++ help="Override the default name of the distribution output path.") + parser.add_option( + '--output-dir', + dest='outputdir', +@@ -677,6 +682,9 @@ else: + if options.ozone: + output_dir_name = output_dir_name + '_ozone' + ++if options.distpathname != '': ++ output_dir_name = options.distpathname + '_' + binary_arch ++ + output_dir = create_output_dir(output_dir_name, options.outputdir) + + # create the README.TXT file +-- +2.42.0 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0003-Add-an-option-to-use-an-alternative-base-output-dire.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0003-Add-an-option-to-use-an-alternative-base-output-dire.patch new file mode 100644 index 000000000..600d59dcb --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0003-Add-an-option-to-use-an-alternative-base-output-dire.patch @@ -0,0 +1,61 @@ +From e54832c051aa34708025f350e81d08bafd3025f7 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Thu, 30 Mar 2023 15:22:32 +0200 +Subject: [PATCH 3/9] Add an option to use an alternative base output directory + +--- + tools/gclient_hook.py | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/tools/gclient_hook.py b/tools/gclient_hook.py +index c525984e3..3d4375ec0 100644 +--- a/tools/gclient_hook.py ++++ b/tools/gclient_hook.py +@@ -6,12 +6,23 @@ + from __future__ import absolute_import + from __future__ import print_function + from file_util import make_dir, write_file ++from optparse import OptionParser + from gclient_util import * + from gn_args import GetAllPlatformConfigs, GetConfigFileContents + import issue_1999 + import os + import sys + ++parser = OptionParser() ++ ++parser.add_option( ++ '--base-out-path', ++ dest='baseoutpath', ++ default='', ++ help="Use an anternative base path for the generated gn outputs instead of using chromium source dir") ++ ++(options, args) = parser.parse_args() ++ + # The CEF directory is the parent directory of _this_ script. + cef_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) + # The src directory is the parent directory of the CEF directory. +@@ -136,14 +147,18 @@ if platform == 'windows': + configs = GetAllPlatformConfigs(gn_args) + for dir, config in configs.items(): + # Create out directories and write the args.gn file. +- out_path = os.path.join(src_dir, 'out', dir) ++ base_out_dir = src_dir ++ if options.baseoutpath != '': ++ base_out_dir = options.baseoutpath ++ out_path = os.path.join(base_out_dir, 'out', dir) + make_dir(out_path, False) + args_gn_path = os.path.join(out_path, 'args.gn') + args_gn_contents = GetConfigFileContents(config) + write_file(args_gn_path, args_gn_contents) + + # Generate the Ninja config. +- cmd = ['gn', 'gen', os.path.join('out', dir)] ++ cmd = ['gn', 'gen', os.path.join('out', out_path)] ++ + if 'GN_ARGUMENTS' in os.environ.keys(): + cmd.extend(os.environ['GN_ARGUMENTS'].split(' ')) + RunAction(src_dir, cmd) +-- +2.42.0 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0004-Add-an-option-to-bypass-sysroot-checking-and-force.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0004-Add-an-option-to-bypass-sysroot-checking-and-force.patch new file mode 100644 index 000000000..c57907441 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0004-Add-an-option-to-bypass-sysroot-checking-and-force.patch @@ -0,0 +1,134 @@ +From 26d02223b99765f4c6d5ce5807947d4e0c925a0b Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Tue, 16 May 2023 16:11:15 +0200 +Subject: [PATCH 4/9] Add an option to bypass sysroot checking and force + +--- + tools/gclient_hook.py | 8 +++++++- + tools/gn_args.py | 28 ++++++++++++++-------------- + 2 files changed, 21 insertions(+), 15 deletions(-) + +diff --git a/tools/gclient_hook.py b/tools/gclient_hook.py +index 3d4375ec0..c971b9399 100644 +--- a/tools/gclient_hook.py ++++ b/tools/gclient_hook.py +@@ -20,6 +20,12 @@ parser.add_option( + dest='baseoutpath', + default='', + help="Use an anternative base path for the generated gn outputs instead of using chromium source dir") ++parser.add_option( ++ '--bypass-sysroot-check', ++ action='store_true', ++ dest='bypasssysrootcheck', ++ default=False, ++ help='Don\'t chech if the sysroot exist while generating output directores.') + + (options, args) = parser.parse_args() + +@@ -144,7 +150,7 @@ if platform == 'windows': + gn_args['windows_sdk_path'] = os.environ['SDK_ROOT'] + gn_args['windows_sdk_version'] = os.environ['SDK_VERSION'] + +-configs = GetAllPlatformConfigs(gn_args) ++configs = GetAllPlatformConfigs(gn_args, bypass_sysroot_check=options.bypasssysrootcheck) + for dir, config in configs.items(): + # Create out directories and write the args.gn file. + base_out_dir = src_dir +diff --git a/tools/gn_args.py b/tools/gn_args.py +index c1acac17b..80545da49 100644 +--- a/tools/gn_args.py ++++ b/tools/gn_args.py +@@ -327,7 +327,7 @@ def GetMergedArgs(build_args): + return MergeDicts(dict, required) + + +-def ValidateArgs(args): ++def ValidateArgs(args, bypass_sysroot_check=False): + """ + Validate GN arg combinations that we know about. Also provide suggestions + where appropriate. +@@ -365,11 +365,11 @@ def ValidateArgs(args): + + if platform == 'linux': + if target_cpu == 'x86': +- assert use_sysroot, 'target_cpu="x86" requires use_sysroot=true' ++ assert use_sysroot or bypass_sysroot_check, 'target_cpu="x86" requires use_sysroot=true' + elif target_cpu == 'arm': +- assert use_sysroot, 'target_cpu="arm" requires use_sysroot=true' ++ assert use_sysroot or bypass_sysroot_check, 'target_cpu="arm" requires use_sysroot=true' + elif target_cpu == 'arm64': +- assert use_sysroot, 'target_cpu="arm64" requires use_sysroot=true' ++ assert use_sysroot or bypass_sysroot_check, 'target_cpu="arm64" requires use_sysroot=true' + + # ASAN requires Release builds. + if is_asan: +@@ -460,7 +460,7 @@ def ValidateArgs(args): + "visual_studio_path requires INCLUDE, LIB and PATH env variables" + + +-def GetConfigArgs(args, is_debug, cpu): ++def GetConfigArgs(args, is_debug, cpu, bypass_sysroot_check=False): + """ + Return merged GN args for the configuration and validate. + """ +@@ -490,11 +490,11 @@ def GetConfigArgs(args, is_debug, cpu): + if key.startswith('arm_'): + del result[key] + +- ValidateArgs(result) ++ ValidateArgs(result, bypass_sysroot_check) + return result + + +-def GetConfigArgsSandbox(platform, args, is_debug, cpu): ++def GetConfigArgsSandbox(platform, args, is_debug, cpu, bypass_sysroot_check=False): + """ + Return merged GN args for the cef_sandbox configuration and validate. + """ +@@ -566,7 +566,7 @@ def LinuxSysrootExists(cpu): + return os.path.isdir(os.path.join(sysroot_root, sysroot_name)) + + +-def GetAllPlatformConfigs(build_args): ++def GetAllPlatformConfigs(build_args, bypass_sysroot_check=False): + """ + Return a map of directory name to GN args for the current platform. + """ +@@ -586,10 +586,10 @@ def GetAllPlatformConfigs(build_args): + + if platform == 'linux': + use_sysroot = GetArgValue(args, 'use_sysroot') +- if use_sysroot: ++ if bypass_sysroot_check or use_sysroot: + # Only generate configurations for sysroots that have been installed. + for cpu in ('x64', 'arm', 'arm64'): +- if LinuxSysrootExists(cpu): ++ if bypass_sysroot_check or LinuxSysrootExists(cpu): + supported_cpus.append(cpu) + else: + msg('Not generating %s configuration due to missing sysroot directory' +@@ -611,17 +611,17 @@ def GetAllPlatformConfigs(build_args): + + for cpu in supported_cpus: + if create_debug: +- result['Debug_GN_' + cpu] = GetConfigArgs(args, True, cpu) +- result['Release_GN_' + cpu] = GetConfigArgs(args, False, cpu) ++ result['Debug_GN_' + cpu] = GetConfigArgs(args, True, cpu, bypass_sysroot_check) ++ result['Release_GN_' + cpu] = GetConfigArgs(args, False, cpu, bypass_sysroot_check) + + if platform in ('windows', 'mac') and GetArgValue(args, + 'is_official_build'): + # Build cef_sandbox.lib with a different configuration. + if create_debug: + result['Debug_GN_' + cpu + '_sandbox'] = GetConfigArgsSandbox( +- platform, args, True, cpu) ++ platform, args, True, cpu, bypass_sysroot_check) + result['Release_GN_' + cpu + '_sandbox'] = GetConfigArgsSandbox( +- platform, args, False, cpu) ++ platform, args, False, cpu, bypass_sysroot_check) + + return result + +-- +2.42.0 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0005-Add-AGL-wayland-window-related-calls.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0005-Add-AGL-wayland-window-related-calls.patch new file mode 100644 index 000000000..d717b8174 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0005-Add-AGL-wayland-window-related-calls.patch @@ -0,0 +1,198 @@ +From ee2c3e430fd0d1025e46c108a79a4e0b07608dff Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Thu, 18 May 2023 10:34:08 +0200 +Subject: [PATCH 5/9] Add AGL wayland window related calls + +--- + include/views/cef_window.h | 34 ++++++++++++++++ + libcef/browser/views/view_util.h | 10 +++++ + libcef/browser/views/view_util_aura.cc | 54 ++++++++++++++++++++++++++ + libcef/browser/views/window_impl.cc | 24 ++++++++++++ + libcef/browser/views/window_impl.h | 10 +++++ + 5 files changed, 132 insertions(+) + +diff --git a/include/views/cef_window.h b/include/views/cef_window.h +index ec3843b25..22fe2e2a1 100644 +--- a/include/views/cef_window.h ++++ b/include/views/cef_window.h +@@ -366,6 +366,40 @@ class CefWindow : public CefPanel { + /// + /*--cef()--*/ + virtual void RemoveAllAccelerators() = 0; ++ ++ // AGL-related calls ++ ++ /// ++ /// Tells the agl compositor to activate the app ++ /// ++ /*--cef()--*/ ++ virtual void AglActivateApp(const CefString& app) = 0; ++ ++ /// ++ /// Tells the agl compositor the application id ++ /// ++ /*--cef()--*/ ++ virtual void AglSetAppId(const CefString& app_id) = 0; ++ ++ /// ++ /// Tells the agl compositor that everything is set-up and good to go ++ /// ++ /*--cef()--*/ ++ virtual void AglSetAppReady() = 0; ++ ++ /// ++ /// Tells the agl compositor that the app is the background application ++ /// ++ /*--cef()--*/ ++ virtual void AglSetBackGroundApp() = 0; ++ ++ /// ++ /// Tells the agl compositor that the app is a panel ++ /// ++ /*--cef()--*/ ++ virtual void AglSetPanelApp(uint32_t edge) = 0; ++ ++ // ----------------- + }; + + #endif // CEF_INCLUDE_VIEWS_CEF_WINDOW_H_ +diff --git a/libcef/browser/views/view_util.h b/libcef/browser/views/view_util.h +index a5fb6e522..bc12a9ddc 100644 +--- a/libcef/browser/views/view_util.h ++++ b/libcef/browser/views/view_util.h +@@ -165,6 +165,16 @@ views::View* GetHostView(views::Widget* widget); + float GetNSWindowTitleBarHeight(views::Widget* widget); + #endif + ++// AGL-Related calls ++ ++void AglActivateApp(views::Widget* widget, const std::string& app); ++void AglSetAppId(views::Widget* widget, const std::string& app_id); ++void AglSetAppReady(views::Widget* widget); ++void AglSetBackGroundApp(views::Widget* widget); ++void AglSetPanelApp(views::Widget* widget, uint32_t edge); ++ ++// ----------------- ++ + } // namespace view_util + + #endif // CEF_LIBCEF_BROWSER_VIEWS_VIEW_UTIL_H_ +diff --git a/libcef/browser/views/view_util_aura.cc b/libcef/browser/views/view_util_aura.cc +index 24be3311b..2dabf5eae 100644 +--- a/libcef/browser/views/view_util_aura.cc ++++ b/libcef/browser/views/view_util_aura.cc +@@ -58,4 +58,58 @@ views::View* GetHostView(views::Widget* widget) { + return widget->GetNativeView()->GetProperty(views::kHostViewKey); + } + ++// AGL-Related calls ++ ++void AglActivateApp(views::Widget* widget, const std::string& app) { ++ if (!widget) { ++ return; ++ } ++ aura::Window* window = widget->GetNativeWindow(); ++ if (window && window->GetRootWindow()) { ++ return window->GetHost()->SetAglActivateApp(app); ++ } ++} ++ ++void AglSetAppId(views::Widget* widget, const std::string& app_id) { ++ if (!widget) { ++ return; ++ } ++ aura::Window* window = widget->GetNativeWindow(); ++ if (window && window->GetRootWindow()) { ++ return window->GetHost()->SetAglAppId(app_id); ++ } ++} ++ ++void AglSetAppReady(views::Widget* widget) { ++ if (!widget) { ++ return; ++ } ++ aura::Window* window = widget->GetNativeWindow(); ++ if (window && window->GetRootWindow()) { ++ return window->GetHost()->SetAglReady(); ++ } ++} ++ ++void AglSetBackGroundApp(views::Widget* widget) { ++ if (!widget) { ++ return; ++ } ++ aura::Window* window = widget->GetNativeWindow(); ++ if (window && window->GetRootWindow()) { ++ return window->GetHost()->SetAglBackground(); ++ } ++} ++ ++void AglSetPanelApp(views::Widget* widget, uint32_t edge) { ++ if (!widget) { ++ return; ++ } ++ aura::Window* window = widget->GetNativeWindow(); ++ if (window && window->GetRootWindow()) { ++ return window->GetHost()->SetAglPanel(edge); ++ } ++} ++ ++// ----------------- ++ + } // namespace view_util +diff --git a/libcef/browser/views/window_impl.cc b/libcef/browser/views/window_impl.cc +index 3da94b08a..8b347bf4a 100644 +--- a/libcef/browser/views/window_impl.cc ++++ b/libcef/browser/views/window_impl.cc +@@ -768,3 +768,27 @@ void CefWindowImpl::CreateWidget(gfx::AcceleratedWidget parent_widget) { + delegate()->OnWindowCreated(this); + } + } ++ ++// AGL-Related calls ++ ++void CefWindowImpl::AglActivateApp(const CefString& app) { ++ view_util::AglActivateApp(widget_, app); ++} ++ ++void CefWindowImpl::AglSetAppId(const CefString& app_id) { ++ view_util::AglSetAppId(widget_, app_id); ++} ++ ++void CefWindowImpl::AglSetAppReady() { ++ view_util::AglSetAppReady(widget_); ++} ++ ++void CefWindowImpl::AglSetBackGroundApp() { ++ view_util::AglSetBackGroundApp(widget_); ++} ++ ++void CefWindowImpl::AglSetPanelApp(uint32_t edge) { ++ view_util::AglSetPanelApp(widget_, edge); ++} ++ ++// ----------------- +diff --git a/libcef/browser/views/window_impl.h b/libcef/browser/views/window_impl.h +index fae0ae832..20514fc32 100644 +--- a/libcef/browser/views/window_impl.h ++++ b/libcef/browser/views/window_impl.h +@@ -134,6 +134,16 @@ class CefWindowImpl + views::Widget* widget() const { return widget_; } + bool initialized() const { return initialized_; } + ++ // AGL-Related calls ++ ++ void AglActivateApp(const CefString& app) override; ++ void AglSetAppId(const CefString& app_id) override; ++ void AglSetAppReady() override; ++ void AglSetBackGroundApp() override; ++ void AglSetPanelApp(uint32_t edge) override; ++ ++ // ----------------- ++ + private: + // Create a new implementation object. + // Always call Initialize() after creation. +-- +2.42.0 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0006-Add-a-method-to-check-if-the-agl-window-is-configure.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0006-Add-a-method-to-check-if-the-agl-window-is-configure.patch new file mode 100644 index 000000000..0f5c4c5fa --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0006-Add-a-method-to-check-if-the-agl-window-is-configure.patch @@ -0,0 +1,129 @@ +From 7eefab1c1a8938145f9fb3a5d7a8fa58ca7ad695 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Fri, 30 Jun 2023 10:27:03 +0200 +Subject: [PATCH 6/9] Add a method to check if the agl window is configured + +--- + include/views/cef_window.h | 6 ++++++ + libcef/browser/views/view_util.h | 1 + + libcef/browser/views/view_util_aura.cc | 20 +++++++++++++++----- + libcef/browser/views/window_impl.cc | 4 ++++ + libcef/browser/views/window_impl.h | 1 + + 5 files changed, 27 insertions(+), 5 deletions(-) + +diff --git a/include/views/cef_window.h b/include/views/cef_window.h +index 22fe2e2a1..c34963302 100644 +--- a/include/views/cef_window.h ++++ b/include/views/cef_window.h +@@ -399,6 +399,12 @@ class CefWindow : public CefPanel { + /*--cef()--*/ + virtual void AglSetPanelApp(uint32_t edge) = 0; + ++ /// ++ /// Tells if the window wayland surface is configured ++ /// ++ /*--cef()--*/ ++ virtual bool IsSurfaceConfigured() = 0; ++ + // ----------------- + }; + +diff --git a/libcef/browser/views/view_util.h b/libcef/browser/views/view_util.h +index bc12a9ddc..bf657fd39 100644 +--- a/libcef/browser/views/view_util.h ++++ b/libcef/browser/views/view_util.h +@@ -172,6 +172,7 @@ void AglSetAppId(views::Widget* widget, const std::string& app_id); + void AglSetAppReady(views::Widget* widget); + void AglSetBackGroundApp(views::Widget* widget); + void AglSetPanelApp(views::Widget* widget, uint32_t edge); ++bool IsSurfaceConfigured(views::Widget* widget); + + // ----------------- + +diff --git a/libcef/browser/views/view_util_aura.cc b/libcef/browser/views/view_util_aura.cc +index 2dabf5eae..2946a2d81 100644 +--- a/libcef/browser/views/view_util_aura.cc ++++ b/libcef/browser/views/view_util_aura.cc +@@ -66,7 +66,7 @@ void AglActivateApp(views::Widget* widget, const std::string& app) { + } + aura::Window* window = widget->GetNativeWindow(); + if (window && window->GetRootWindow()) { +- return window->GetHost()->SetAglActivateApp(app); ++ window->GetHost()->SetAglActivateApp(app); + } + } + +@@ -76,7 +76,7 @@ void AglSetAppId(views::Widget* widget, const std::string& app_id) { + } + aura::Window* window = widget->GetNativeWindow(); + if (window && window->GetRootWindow()) { +- return window->GetHost()->SetAglAppId(app_id); ++ window->GetHost()->SetAglAppId(app_id); + } + } + +@@ -86,7 +86,7 @@ void AglSetAppReady(views::Widget* widget) { + } + aura::Window* window = widget->GetNativeWindow(); + if (window && window->GetRootWindow()) { +- return window->GetHost()->SetAglReady(); ++ window->GetHost()->SetAglReady(); + } + } + +@@ -96,7 +96,7 @@ void AglSetBackGroundApp(views::Widget* widget) { + } + aura::Window* window = widget->GetNativeWindow(); + if (window && window->GetRootWindow()) { +- return window->GetHost()->SetAglBackground(); ++ window->GetHost()->SetAglBackground(); + } + } + +@@ -106,7 +106,17 @@ void AglSetPanelApp(views::Widget* widget, uint32_t edge) { + } + aura::Window* window = widget->GetNativeWindow(); + if (window && window->GetRootWindow()) { +- return window->GetHost()->SetAglPanel(edge); ++ window->GetHost()->SetAglPanel(edge); ++ } ++} ++ ++bool IsSurfaceConfigured(views::Widget* widget) { ++ if (!widget) { ++ return false; ++ } ++ aura::Window* window = widget->GetNativeWindow(); ++ if (window && window->GetRootWindow()) { ++ return window->GetHost()->IsSurfaceConfigured(); + } + } + +diff --git a/libcef/browser/views/window_impl.cc b/libcef/browser/views/window_impl.cc +index 8b347bf4a..8edac98b5 100644 +--- a/libcef/browser/views/window_impl.cc ++++ b/libcef/browser/views/window_impl.cc +@@ -791,4 +791,8 @@ void CefWindowImpl::AglSetPanelApp(uint32_t edge) { + view_util::AglSetPanelApp(widget_, edge); + } + ++bool CefWindowImpl::IsSurfaceConfigured() { ++ return view_util::IsSurfaceConfigured(widget_); ++} ++ + // ----------------- +diff --git a/libcef/browser/views/window_impl.h b/libcef/browser/views/window_impl.h +index 20514fc32..7f7b47e1a 100644 +--- a/libcef/browser/views/window_impl.h ++++ b/libcef/browser/views/window_impl.h +@@ -141,6 +141,7 @@ class CefWindowImpl + void AglSetAppReady() override; + void AglSetBackGroundApp() override; + void AglSetPanelApp(uint32_t edge) override; ++ bool IsSurfaceConfigured() override; + + // ----------------- + +-- +2.42.0 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0007-Add-the-SetActivateRegion-method.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0007-Add-the-SetActivateRegion-method.patch new file mode 100644 index 000000000..e2d87065c --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0007-Add-the-SetActivateRegion-method.patch @@ -0,0 +1,101 @@ +From 6515114202a98f81950687b6656151fa7cfd5ab6 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Sun, 2 Jul 2023 12:08:59 +0200 +Subject: [PATCH 7/9] Add the SetActivateRegion method + +--- + include/views/cef_window.h | 6 ++++++ + libcef/browser/views/view_util.h | 1 + + libcef/browser/views/view_util_aura.cc | 17 +++++++++++++++++ + libcef/browser/views/window_impl.cc | 7 +++++++ + libcef/browser/views/window_impl.h | 1 + + 5 files changed, 32 insertions(+) + +diff --git a/include/views/cef_window.h b/include/views/cef_window.h +index c34963302..9f196a1e7 100644 +--- a/include/views/cef_window.h ++++ b/include/views/cef_window.h +@@ -405,6 +405,12 @@ class CefWindow : public CefPanel { + /*--cef()--*/ + virtual bool IsSurfaceConfigured() = 0; + ++ /// ++ /// A hint for the compositor to use a custom area, rather than inferring the activation area. ++ /// ++ /*--cef()--*/ ++ virtual void SetupActivationArea(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0; ++ + // ----------------- + }; + +diff --git a/libcef/browser/views/view_util.h b/libcef/browser/views/view_util.h +index bf657fd39..50037a198 100644 +--- a/libcef/browser/views/view_util.h ++++ b/libcef/browser/views/view_util.h +@@ -173,6 +173,7 @@ void AglSetAppReady(views::Widget* widget); + void AglSetBackGroundApp(views::Widget* widget); + void AglSetPanelApp(views::Widget* widget, uint32_t edge); + bool IsSurfaceConfigured(views::Widget* widget); ++void SetupActivationArea(views::Widget* widget, uint32_t x, uint32_t y, uint32_t width, uint32_t height); + + // ----------------- + +diff --git a/libcef/browser/views/view_util_aura.cc b/libcef/browser/views/view_util_aura.cc +index 2946a2d81..bf435078d 100644 +--- a/libcef/browser/views/view_util_aura.cc ++++ b/libcef/browser/views/view_util_aura.cc +@@ -120,6 +120,23 @@ bool IsSurfaceConfigured(views::Widget* widget) { + } + } + ++void SetupActivationArea(views::Widget* widget, ++ uint32_t x, ++ uint32_t y, ++ uint32_t width, ++ uint32_t height) { ++ if (!widget) { ++ return; ++ } ++ aura::Window* window = widget->GetNativeWindow(); ++ if (window && window->GetRootWindow()) { ++ window->GetHost()->SetupActivationArea(x, ++ y, ++ width, ++ height); ++ } ++} ++ + // ----------------- + + } // namespace view_util +diff --git a/libcef/browser/views/window_impl.cc b/libcef/browser/views/window_impl.cc +index 8edac98b5..12858364e 100644 +--- a/libcef/browser/views/window_impl.cc ++++ b/libcef/browser/views/window_impl.cc +@@ -795,4 +795,11 @@ bool CefWindowImpl::IsSurfaceConfigured() { + return view_util::IsSurfaceConfigured(widget_); + } + ++void CefWindowImpl::SetupActivationArea(uint32_t x, ++ uint32_t y, ++ uint32_t width, ++ uint32_t height) { ++ view_util::SetupActivationArea(widget_, x, y, width, height); ++} ++ + // ----------------- +diff --git a/libcef/browser/views/window_impl.h b/libcef/browser/views/window_impl.h +index 7f7b47e1a..aaca3c281 100644 +--- a/libcef/browser/views/window_impl.h ++++ b/libcef/browser/views/window_impl.h +@@ -142,6 +142,7 @@ class CefWindowImpl + void AglSetBackGroundApp() override; + void AglSetPanelApp(uint32_t edge) override; + bool IsSurfaceConfigured() override; ++ void SetupActivationArea(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; + + // ----------------- + +-- +2.42.0 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0008-Allow-passing-the-app_id-on-widget-creation.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0008-Allow-passing-the-app_id-on-widget-creation.patch new file mode 100644 index 000000000..e0a79b6c2 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0008-Allow-passing-the-app_id-on-widget-creation.patch @@ -0,0 +1,130 @@ +From 5a8d9996ee7b3ce77f7b3fd3c7839806a034ea16 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Tue, 4 Jul 2023 12:10:41 +0200 +Subject: [PATCH 08/10] Allow passing the app_id on widget creation + +--- + include/views/cef_window.h | 6 ++++++ + libcef/browser/views/window_impl.cc | 13 +++++++++---- + libcef/browser/views/window_impl.h | 6 ++++-- + libcef/browser/views/window_view.cc | 3 ++- + libcef/browser/views/window_view.h | 2 +- + 5 files changed, 22 insertions(+), 8 deletions(-) + +diff --git a/include/views/cef_window.h b/include/views/cef_window.h +index 9f196a1e7..16c854b09 100644 +--- a/include/views/cef_window.h ++++ b/include/views/cef_window.h +@@ -65,6 +65,12 @@ class CefWindow : public CefPanel { + CefRefPtr<CefWindowDelegate> delegate); + + /// ++ /// Create a new Window with the provided ID ++ /// ++ /*--cef()--*/ ++ static CefRefPtr<CefWindow> CreateTopLevelWindowWithId( ++ CefRefPtr<CefWindowDelegate> delegate, const CefString& app_id); ++ /// + /// Show the Window. + /// + /*--cef()--*/ +diff --git a/libcef/browser/views/window_impl.cc b/libcef/browser/views/window_impl.cc +index 12858364e..f0fe9dfb2 100644 +--- a/libcef/browser/views/window_impl.cc ++++ b/libcef/browser/views/window_impl.cc +@@ -110,14 +110,19 @@ CefRefPtr<CefWindow> CefWindow::CreateTopLevelWindow( + return CefWindowImpl::Create(delegate, gfx::kNullAcceleratedWidget); + } + ++CefRefPtr<CefWindow> CefWindow::CreateTopLevelWindowWithId( ++ CefRefPtr<CefWindowDelegate> delegate, const CefString& app_id) { ++ return CefWindowImpl::Create(delegate, gfx::kNullAcceleratedWidget, app_id); ++} ++ + // static + CefRefPtr<CefWindowImpl> CefWindowImpl::Create( + CefRefPtr<CefWindowDelegate> delegate, +- gfx::AcceleratedWidget parent_widget) { ++ gfx::AcceleratedWidget parent_widget, const CefString& app_id) { + CEF_REQUIRE_UIT_RETURN(nullptr); + CefRefPtr<CefWindowImpl> window = new CefWindowImpl(delegate); + window->Initialize(); +- window->CreateWidget(parent_widget); ++ window->CreateWidget(parent_widget, app_id); + return window; + } + +@@ -745,10 +750,10 @@ void CefWindowImpl::InitializeRootView() { + static_cast<CefWindowView*>(root_view())->Initialize(); + } + +-void CefWindowImpl::CreateWidget(gfx::AcceleratedWidget parent_widget) { ++void CefWindowImpl::CreateWidget(gfx::AcceleratedWidget parent_widget, const CefString& app_id) { + DCHECK(!widget_); + +- root_view()->CreateWidget(parent_widget); ++ root_view()->CreateWidget(parent_widget, app_id); + widget_ = root_view()->GetWidget(); + DCHECK(widget_); + +diff --git a/libcef/browser/views/window_impl.h b/libcef/browser/views/window_impl.h +index aaca3c281..1c5be736f 100644 +--- a/libcef/browser/views/window_impl.h ++++ b/libcef/browser/views/window_impl.h +@@ -36,7 +36,8 @@ class CefWindowImpl + // Create a new CefWindow instance. |delegate| may be nullptr. |parent_widget| + // will be used when creating a Chrome child window. + static CefRefPtr<CefWindowImpl> Create(CefRefPtr<CefWindowDelegate> delegate, +- gfx::AcceleratedWidget parent_widget); ++ gfx::AcceleratedWidget parent_widget, ++ const CefString& app_id = ""); + + // CefWindow methods: + void Show() override; +@@ -157,7 +158,8 @@ class CefWindowImpl + void InitializeRootView() override; + + // Initialize the Widget. +- void CreateWidget(gfx::AcceleratedWidget parent_widget); ++ void CreateWidget(gfx::AcceleratedWidget parent_widget, ++ const CefString& app_id = ""); + + views::Widget* widget_ = nullptr; + +diff --git a/libcef/browser/views/window_view.cc b/libcef/browser/views/window_view.cc +index 2331caaea..5e4cb6b53 100644 +--- a/libcef/browser/views/window_view.cc ++++ b/libcef/browser/views/window_view.cc +@@ -371,7 +371,7 @@ CefWindowView::CefWindowView(CefWindowDelegate* cef_delegate, + DCHECK(window_delegate_); + } + +-void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget) { ++void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget, const CefString& app_id) { + DCHECK(!GetWidget()); + + // |widget| is owned by the NativeWidget and will be destroyed in response to +@@ -381,6 +381,7 @@ void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget) { + + views::Widget::InitParams params; + params.delegate = this; ++ params.wayland_app_id = app_id; + + views::Widget* host_widget = nullptr; + +diff --git a/libcef/browser/views/window_view.h b/libcef/browser/views/window_view.h +index b065f3700..c15e75d65 100644 +--- a/libcef/browser/views/window_view.h ++++ b/libcef/browser/views/window_view.h +@@ -52,7 +52,7 @@ class CefWindowView + CefWindowView& operator=(const CefWindowView&) = delete; + + // Create the Widget. +- void CreateWidget(gfx::AcceleratedWidget parent_widget); ++ void CreateWidget(gfx::AcceleratedWidget parent_widget, const CefString& app_id); + + // Returns the CefWindow associated with this view. See comments on + // CefViewView::GetCefView. +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0009-Update-generated-api.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0009-Update-generated-api.patch new file mode 100644 index 000000000..aaf8dd143 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0009-Update-generated-api.patch @@ -0,0 +1,753 @@ +From c10306e9da62f9c36513b98affc4589ea5016677 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Mon, 6 Nov 2023 16:00:35 -0300 +Subject: [PATCH 09/10] Update generated api + +Command used: + +./translator.sh --classes CefWindow CefWindowDelegate CefView CefViewDeleate --root-dir +--- + include/capi/cef_cookie_capi.h | 6 +- + include/capi/cef_media_router_capi.h | 6 +- + include/capi/cef_scheme_capi.h | 10 +- + include/capi/views/cef_window_capi.h | 52 +++++++- + include/cef_api_hash.h | 8 +- + libcef_dll/cpptoc/views/window_cpptoc.cc | 153 ++++++++++++++++++++++- + libcef_dll/ctocpp/views/window_ctocpp.cc | 148 +++++++++++++++++++++- + libcef_dll/ctocpp/views/window_ctocpp.h | 12 +- + libcef_dll/wrapper/libcef_dll_dylib.cc | 72 +++++++---- + 9 files changed, 422 insertions(+), 45 deletions(-) + +diff --git a/include/capi/cef_cookie_capi.h b/include/capi/cef_cookie_capi.h +index 1be978bfd..f6f19ede2 100644 +--- a/include/capi/cef_cookie_capi.h ++++ b/include/capi/cef_cookie_capi.h +@@ -33,7 +33,7 @@ + // by hand. See the translator.README.txt file in the tools directory for + // more information. + // +-// $hash=598c6f530b2e2553197d8c6a72ad9e2bf72b5443$ ++// $hash=8093e45bcbd09f41f21c0cb7c8719166cc481529$ + // + + #ifndef CEF_INCLUDE_CAPI_CEF_COOKIE_CAPI_H_ +@@ -126,8 +126,8 @@ typedef struct _cef_cookie_manager_t { + /// cef_settings_t.cache_path if specified or in memory otherwise. If |callback| + /// is non-NULL it will be executed asnychronously on the UI thread after the + /// manager's storage has been initialized. Using this function is equivalent to +-/// calling cef_request_context_t::cef_request_context_get_global_context()->Get +-/// DefaultCookieManager(). ++/// calling cef_request_context_t::cef_request_context_get_global_context()- ++/// >GetDefaultCookieManager(). + /// + CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_get_global_manager( + struct _cef_completion_callback_t* callback); +diff --git a/include/capi/cef_media_router_capi.h b/include/capi/cef_media_router_capi.h +index 27f9d0e15..9df759013 100644 +--- a/include/capi/cef_media_router_capi.h ++++ b/include/capi/cef_media_router_capi.h +@@ -33,7 +33,7 @@ + // by hand. See the translator.README.txt file in the tools directory for + // more information. + // +-// $hash=de4a9b856c6951231f446991a9b1efb89096ad3b$ ++// $hash=d3f29de333c90768caac6aee2b7eb2db5f593515$ + // + + #ifndef CEF_INCLUDE_CAPI_CEF_MEDIA_ROUTER_CAPI_H_ +@@ -114,8 +114,8 @@ typedef struct _cef_media_router_t { + /// Returns the MediaRouter object associated with the global request context. + /// If |callback| is non-NULL it will be executed asnychronously on the UI + /// thread after the manager's storage has been initialized. Equivalent to +-/// calling cef_request_context_t::cef_request_context_get_global_context()->get +-/// _media_router(). ++/// calling cef_request_context_t::cef_request_context_get_global_context()- ++/// >get_media_router(). + /// + CEF_EXPORT cef_media_router_t* cef_media_router_get_global( + struct _cef_completion_callback_t* callback); +diff --git a/include/capi/cef_scheme_capi.h b/include/capi/cef_scheme_capi.h +index 5f8796287..bdcd6cc3b 100644 +--- a/include/capi/cef_scheme_capi.h ++++ b/include/capi/cef_scheme_capi.h +@@ -33,7 +33,7 @@ + // by hand. See the translator.README.txt file in the tools directory for + // more information. + // +-// $hash=6b6a7f754abc9ee5d6f775ba9eee802d3244faf5$ ++// $hash=794d4c01f06c656c425779b0189a3b52820498ed$ + // + + #ifndef CEF_INCLUDE_CAPI_CEF_SCHEME_CAPI_H_ +@@ -116,8 +116,8 @@ typedef struct _cef_scheme_handler_factory_t { + /// matches the specified |scheme_name| and optional |domain_name|. Returns + /// false (0) if an error occurs. This function may be called on any thread in + /// the browser process. Using this function is equivalent to calling cef_reques +-/// t_context_t::cef_request_context_get_global_context()->register_scheme_handl +-/// er_factory(). ++/// t_context_t::cef_request_context_get_global_context()- ++/// >register_scheme_handler_factory(). + /// + CEF_EXPORT int cef_register_scheme_handler_factory( + const cef_string_t* scheme_name, +@@ -128,8 +128,8 @@ CEF_EXPORT int cef_register_scheme_handler_factory( + /// Clear all scheme handler factories registered with the global request + /// context. Returns false (0) on error. This function may be called on any + /// thread in the browser process. Using this function is equivalent to calling +-/// cef_request_context_t::cef_request_context_get_global_context()->clear_schem +-/// e_handler_factories(). ++/// cef_request_context_t::cef_request_context_get_global_context()- ++/// >clear_scheme_handler_factories(). + /// + CEF_EXPORT int cef_clear_scheme_handler_factories(void); + +diff --git a/include/capi/views/cef_window_capi.h b/include/capi/views/cef_window_capi.h +index e5e04e83e..b0be32ad2 100644 +--- a/include/capi/views/cef_window_capi.h ++++ b/include/capi/views/cef_window_capi.h +@@ -33,7 +33,7 @@ + // by hand. See the translator.README.txt file in the tools directory for + // more information. + // +-// $hash=4b43fe0b493d860e8b28d7a6d892db49d1135b34$ ++// $hash=53e1bba9189f03819c0646670cab8f9caabc74d6$ + // + + #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_WINDOW_CAPI_H_ +@@ -353,6 +353,49 @@ typedef struct _cef_window_t { + /// Remove all keyboard accelerators. + /// + void(CEF_CALLBACK* remove_all_accelerators)(struct _cef_window_t* self); ++ ++ /// ++ /// Tells the agl compositor to activate the app ++ /// ++ void(CEF_CALLBACK* agl_activate_app)(struct _cef_window_t* self, ++ const cef_string_t* app); ++ ++ /// ++ /// Tells the agl compositor the application id ++ /// ++ void(CEF_CALLBACK* agl_set_app_id)(struct _cef_window_t* self, ++ const cef_string_t* app_id); ++ ++ /// ++ /// Tells the agl compositor that everything is set-up and good to go ++ /// ++ void(CEF_CALLBACK* agl_set_app_ready)(struct _cef_window_t* self); ++ ++ /// ++ /// Tells the agl compositor that the app is the background application ++ /// ++ void(CEF_CALLBACK* agl_set_back_ground_app)(struct _cef_window_t* self); ++ ++ /// ++ /// Tells the agl compositor that the app is a panel ++ /// ++ void(CEF_CALLBACK* agl_set_panel_app)(struct _cef_window_t* self, ++ uint32_t edge); ++ ++ /// ++ /// Tells if the window wayland surface is configured ++ /// ++ int(CEF_CALLBACK* is_surface_configured)(struct _cef_window_t* self); ++ ++ /// ++ /// A hint for the compositor to use a custom area, rather than inferring the ++ /// activation area. ++ /// ++ void(CEF_CALLBACK* setup_activation_area)(struct _cef_window_t* self, ++ uint32_t x, ++ uint32_t y, ++ uint32_t width, ++ uint32_t height); + } cef_window_t; + + /// +@@ -361,6 +404,13 @@ typedef struct _cef_window_t { + CEF_EXPORT cef_window_t* cef_window_create_top_level( + struct _cef_window_delegate_t* delegate); + ++/// ++/// Create a new Window with the provided ID ++/// ++CEF_EXPORT cef_window_t* cef_window_create_top_level_with_id( ++ struct _cef_window_delegate_t* delegate, ++ const cef_string_t* app_id); ++ + #ifdef __cplusplus + } + #endif +diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h +index 90142ccb0..6af07332a 100644 +--- a/include/cef_api_hash.h ++++ b/include/cef_api_hash.h +@@ -42,13 +42,13 @@ + // way that may cause binary incompatibility with other builds. The universal + // hash value will change if any platform is affected whereas the platform hash + // values will change only if that particular platform is affected. +-#define CEF_API_HASH_UNIVERSAL "4acea2e5c7a3e281d9652802ae1d24b25eef299b" ++#define CEF_API_HASH_UNIVERSAL "7d1351328f7aeb7db3ae74b6d687b115ceec7695" + #if defined(OS_WIN) +-#define CEF_API_HASH_PLATFORM "3a181fdfaa42d2214c77cd83f76886b0657b0b53" ++#define CEF_API_HASH_PLATFORM "70c2a3fee7a3f4a4f6d44d4a3b3699ad23cf6f67" + #elif defined(OS_MAC) +-#define CEF_API_HASH_PLATFORM "06bfe874ee215bde0a415bac7ac37ecf4969d4ca" ++#define CEF_API_HASH_PLATFORM "9d9d39318398a7efaf43406ae25967a33c9d9787" + #elif defined(OS_LINUX) +-#define CEF_API_HASH_PLATFORM "1615f7e7079d89e2e81f683d4a8480455b5f2a60" ++#define CEF_API_HASH_PLATFORM "f828859cd19052fd3dab4b9f50f530d7011642b6" + #endif + + #ifdef __cplusplus +diff --git a/libcef_dll/cpptoc/views/window_cpptoc.cc b/libcef_dll/cpptoc/views/window_cpptoc.cc +index 93ee5341f..cbb4bb1a4 100644 +--- a/libcef_dll/cpptoc/views/window_cpptoc.cc ++++ b/libcef_dll/cpptoc/views/window_cpptoc.cc +@@ -9,7 +9,7 @@ + // implementations. See the translator.README.txt file in the tools directory + // for more information. + // +-// $hash=23777aea864e9abf38c2e2c5d79a40d6bd22876d$ ++// $hash=53b37fbf82615184d8b259a2e476431a3e699eea$ + // + + #include "libcef_dll/cpptoc/views/window_cpptoc.h" +@@ -48,6 +48,32 @@ CEF_EXPORT cef_window_t* cef_window_create_top_level( + return CefWindowCppToC::Wrap(_retval); + } + ++CEF_EXPORT cef_window_t* cef_window_create_top_level_with_id( ++ struct _cef_window_delegate_t* delegate, ++ const cef_string_t* app_id) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ // Verify param: delegate; type: refptr_diff ++ DCHECK(delegate); ++ if (!delegate) { ++ return NULL; ++ } ++ // Verify param: app_id; type: string_byref_const ++ DCHECK(app_id); ++ if (!app_id) { ++ return NULL; ++ } ++ ++ // Execute ++ CefRefPtr<CefWindow> _retval = CefWindow::CreateTopLevelWindowWithId( ++ CefWindowDelegateCToCpp::Wrap(delegate), CefString(app_id)); ++ ++ // Return type: refptr_same ++ return CefWindowCppToC::Wrap(_retval); ++} ++ + namespace { + + // MEMBER FUNCTIONS - Body may be edited by hand. +@@ -717,6 +743,124 @@ void CEF_CALLBACK window_remove_all_accelerators(struct _cef_window_t* self) { + CefWindowCppToC::Get(self)->RemoveAllAccelerators(); + } + ++void CEF_CALLBACK window_agl_activate_app(struct _cef_window_t* self, ++ const cef_string_t* app) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ DCHECK(self); ++ if (!self) { ++ return; ++ } ++ // Verify param: app; type: string_byref_const ++ DCHECK(app); ++ if (!app) { ++ return; ++ } ++ ++ // Execute ++ CefWindowCppToC::Get(self)->AglActivateApp(CefString(app)); ++} ++ ++void CEF_CALLBACK window_agl_set_app_id(struct _cef_window_t* self, ++ const cef_string_t* app_id) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ DCHECK(self); ++ if (!self) { ++ return; ++ } ++ // Verify param: app_id; type: string_byref_const ++ DCHECK(app_id); ++ if (!app_id) { ++ return; ++ } ++ ++ // Execute ++ CefWindowCppToC::Get(self)->AglSetAppId(CefString(app_id)); ++} ++ ++void CEF_CALLBACK window_agl_set_app_ready(struct _cef_window_t* self) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ DCHECK(self); ++ if (!self) { ++ return; ++ } ++ ++ // Execute ++ CefWindowCppToC::Get(self)->AglSetAppReady(); ++} ++ ++void CEF_CALLBACK window_agl_set_back_ground_app(struct _cef_window_t* self) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ DCHECK(self); ++ if (!self) { ++ return; ++ } ++ ++ // Execute ++ CefWindowCppToC::Get(self)->AglSetBackGroundApp(); ++} ++ ++void CEF_CALLBACK window_agl_set_panel_app(struct _cef_window_t* self, ++ uint32_t edge) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ DCHECK(self); ++ if (!self) { ++ return; ++ } ++ ++ // Execute ++ CefWindowCppToC::Get(self)->AglSetPanelApp(edge); ++} ++ ++int CEF_CALLBACK window_is_surface_configured(struct _cef_window_t* self) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ DCHECK(self); ++ if (!self) { ++ return 0; ++ } ++ ++ // Execute ++ bool _retval = CefWindowCppToC::Get(self)->IsSurfaceConfigured(); ++ ++ // Return type: bool ++ return _retval; ++} ++ ++void CEF_CALLBACK window_setup_activation_area(struct _cef_window_t* self, ++ uint32_t x, ++ uint32_t y, ++ uint32_t width, ++ uint32_t height) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ DCHECK(self); ++ if (!self) { ++ return; ++ } ++ ++ // Execute ++ CefWindowCppToC::Get(self)->SetupActivationArea(x, y, width, height); ++} ++ + struct _cef_window_t* CEF_CALLBACK window_as_window(struct _cef_panel_t* self) { + shutdown_checker::AssertNotShutdown(); + +@@ -2031,6 +2175,13 @@ CefWindowCppToC::CefWindowCppToC() { + GetStruct()->set_accelerator = window_set_accelerator; + GetStruct()->remove_accelerator = window_remove_accelerator; + GetStruct()->remove_all_accelerators = window_remove_all_accelerators; ++ GetStruct()->agl_activate_app = window_agl_activate_app; ++ GetStruct()->agl_set_app_id = window_agl_set_app_id; ++ GetStruct()->agl_set_app_ready = window_agl_set_app_ready; ++ GetStruct()->agl_set_back_ground_app = window_agl_set_back_ground_app; ++ GetStruct()->agl_set_panel_app = window_agl_set_panel_app; ++ GetStruct()->is_surface_configured = window_is_surface_configured; ++ GetStruct()->setup_activation_area = window_setup_activation_area; + GetStruct()->base.as_window = window_as_window; + GetStruct()->base.set_to_fill_layout = window_set_to_fill_layout; + GetStruct()->base.set_to_box_layout = window_set_to_box_layout; +diff --git a/libcef_dll/ctocpp/views/window_ctocpp.cc b/libcef_dll/ctocpp/views/window_ctocpp.cc +index 3a0423d28..aee3d62f1 100644 +--- a/libcef_dll/ctocpp/views/window_ctocpp.cc ++++ b/libcef_dll/ctocpp/views/window_ctocpp.cc +@@ -9,7 +9,7 @@ + // implementations. See the translator.README.txt file in the tools directory + // for more information. + // +-// $hash=b6b0a2a563b475163aa71b20af6ec2ac8c1f0cae$ ++// $hash=61eb77c4622382d6dda0136187c6acbd093f2e83$ + // + + #include "libcef_dll/ctocpp/views/window_ctocpp.h" +@@ -49,6 +49,33 @@ CefRefPtr<CefWindow> CefWindow::CreateTopLevelWindow( + return CefWindowCToCpp::Wrap(_retval); + } + ++NO_SANITIZE("cfi-icall") ++CefRefPtr<CefWindow> CefWindow::CreateTopLevelWindowWithId( ++ CefRefPtr<CefWindowDelegate> delegate, ++ const CefString& app_id) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ // Verify param: delegate; type: refptr_diff ++ DCHECK(delegate.get()); ++ if (!delegate.get()) { ++ return nullptr; ++ } ++ // Verify param: app_id; type: string_byref_const ++ DCHECK(!app_id.empty()); ++ if (app_id.empty()) { ++ return nullptr; ++ } ++ ++ // Execute ++ cef_window_t* _retval = cef_window_create_top_level_with_id( ++ CefWindowDelegateCppToC::Wrap(delegate), app_id.GetStruct()); ++ ++ // Return type: refptr_same ++ return CefWindowCToCpp::Wrap(_retval); ++} ++ + // VIRTUAL METHODS - Body may be edited by hand. + + NO_SANITIZE("cfi-icall") void CefWindowCToCpp::Show() { +@@ -707,6 +734,125 @@ NO_SANITIZE("cfi-icall") void CefWindowCToCpp::RemoveAllAccelerators() { + _struct->remove_all_accelerators(_struct); + } + ++NO_SANITIZE("cfi-icall") ++void CefWindowCToCpp::AglActivateApp(const CefString& app) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ cef_window_t* _struct = GetStruct(); ++ if (CEF_MEMBER_MISSING(_struct, agl_activate_app)) { ++ return; ++ } ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ // Verify param: app; type: string_byref_const ++ DCHECK(!app.empty()); ++ if (app.empty()) { ++ return; ++ } ++ ++ // Execute ++ _struct->agl_activate_app(_struct, app.GetStruct()); ++} ++ ++NO_SANITIZE("cfi-icall") ++void CefWindowCToCpp::AglSetAppId(const CefString& app_id) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ cef_window_t* _struct = GetStruct(); ++ if (CEF_MEMBER_MISSING(_struct, agl_set_app_id)) { ++ return; ++ } ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ // Verify param: app_id; type: string_byref_const ++ DCHECK(!app_id.empty()); ++ if (app_id.empty()) { ++ return; ++ } ++ ++ // Execute ++ _struct->agl_set_app_id(_struct, app_id.GetStruct()); ++} ++ ++NO_SANITIZE("cfi-icall") void CefWindowCToCpp::AglSetAppReady() { ++ shutdown_checker::AssertNotShutdown(); ++ ++ cef_window_t* _struct = GetStruct(); ++ if (CEF_MEMBER_MISSING(_struct, agl_set_app_ready)) { ++ return; ++ } ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ // Execute ++ _struct->agl_set_app_ready(_struct); ++} ++ ++NO_SANITIZE("cfi-icall") void CefWindowCToCpp::AglSetBackGroundApp() { ++ shutdown_checker::AssertNotShutdown(); ++ ++ cef_window_t* _struct = GetStruct(); ++ if (CEF_MEMBER_MISSING(_struct, agl_set_back_ground_app)) { ++ return; ++ } ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ // Execute ++ _struct->agl_set_back_ground_app(_struct); ++} ++ ++NO_SANITIZE("cfi-icall") void CefWindowCToCpp::AglSetPanelApp(uint32_t edge) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ cef_window_t* _struct = GetStruct(); ++ if (CEF_MEMBER_MISSING(_struct, agl_set_panel_app)) { ++ return; ++ } ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ // Execute ++ _struct->agl_set_panel_app(_struct, edge); ++} ++ ++NO_SANITIZE("cfi-icall") bool CefWindowCToCpp::IsSurfaceConfigured() { ++ shutdown_checker::AssertNotShutdown(); ++ ++ cef_window_t* _struct = GetStruct(); ++ if (CEF_MEMBER_MISSING(_struct, is_surface_configured)) { ++ return false; ++ } ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ // Execute ++ int _retval = _struct->is_surface_configured(_struct); ++ ++ // Return type: bool ++ return _retval ? true : false; ++} ++ ++NO_SANITIZE("cfi-icall") ++void CefWindowCToCpp::SetupActivationArea(uint32_t x, ++ uint32_t y, ++ uint32_t width, ++ uint32_t height) { ++ shutdown_checker::AssertNotShutdown(); ++ ++ cef_window_t* _struct = GetStruct(); ++ if (CEF_MEMBER_MISSING(_struct, setup_activation_area)) { ++ return; ++ } ++ ++ // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING ++ ++ // Execute ++ _struct->setup_activation_area(_struct, x, y, width, height); ++} ++ + NO_SANITIZE("cfi-icall") CefRefPtr<CefWindow> CefWindowCToCpp::AsWindow() { + shutdown_checker::AssertNotShutdown(); + +diff --git a/libcef_dll/ctocpp/views/window_ctocpp.h b/libcef_dll/ctocpp/views/window_ctocpp.h +index bc797350c..9931a7a3e 100644 +--- a/libcef_dll/ctocpp/views/window_ctocpp.h ++++ b/libcef_dll/ctocpp/views/window_ctocpp.h +@@ -9,7 +9,7 @@ + // implementations. See the translator.README.txt file in the tools directory + // for more information. + // +-// $hash=2a7aaed7d4296e29dca74345cf2b2d4db221a738$ ++// $hash=10cca846f56124ef20cd769e018ccfdf0aba26f5$ + // + + #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_WINDOW_CTOCPP_H_ +@@ -86,6 +86,16 @@ class CefWindowCToCpp + bool alt_pressed) override; + void RemoveAccelerator(int command_id) override; + void RemoveAllAccelerators() override; ++ void AglActivateApp(const CefString& app) override; ++ void AglSetAppId(const CefString& app_id) override; ++ void AglSetAppReady() override; ++ void AglSetBackGroundApp() override; ++ void AglSetPanelApp(uint32_t edge) override; ++ bool IsSurfaceConfigured() override; ++ void SetupActivationArea(uint32_t x, ++ uint32_t y, ++ uint32_t width, ++ uint32_t height) override; + + // CefPanel methods. + CefRefPtr<CefWindow> AsWindow() override; +diff --git a/libcef_dll/wrapper/libcef_dll_dylib.cc b/libcef_dll/wrapper/libcef_dll_dylib.cc +index 21065db3b..b61ea0d4b 100644 +--- a/libcef_dll/wrapper/libcef_dll_dylib.cc ++++ b/libcef_dll/wrapper/libcef_dll_dylib.cc +@@ -9,7 +9,7 @@ + // implementations. See the translator.README.txt file in the tools directory + // for more information. + // +-// $hash=bcad216e5fef8b9c10a895524f8b1201608138f9$ ++// $hash=51d1746394ff61e17d4fbb3d1415a3b646004563$ + // + + #include <dlfcn.h> +@@ -249,6 +249,8 @@ struct libcef_pointers { + decltype(&cef_scroll_view_create) cef_scroll_view_create; + decltype(&cef_textfield_create) cef_textfield_create; + decltype(&cef_window_create_top_level) cef_window_create_top_level; ++ decltype(&cef_window_create_top_level_with_id) ++ cef_window_create_top_level_with_id; + decltype(&cef_api_hash) cef_api_hash; + decltype(&cef_version_info) cef_version_info; + decltype(&cef_get_min_log_level) cef_get_min_log_level; +@@ -463,6 +465,7 @@ int libcef_init_pointers(const char* path) { + INIT_ENTRY(cef_scroll_view_create); + INIT_ENTRY(cef_textfield_create); + INIT_ENTRY(cef_window_create_top_level); ++ INIT_ENTRY(cef_window_create_top_level_with_id); + INIT_ENTRY(cef_api_hash); + INIT_ENTRY(cef_version_info); + INIT_ENTRY(cef_get_min_log_level); +@@ -705,8 +708,8 @@ int cef_create_url(const struct _cef_urlparts_t* parts, cef_string_t* url) { + } + + NO_SANITIZE("cfi-icall") +-cef_string_userfree_t cef_format_url_for_security_display( +- const cef_string_t* origin_url) { ++cef_string_userfree_t ++ cef_format_url_for_security_display(const cef_string_t* origin_url) { + return g_libcef_pointers.cef_format_url_for_security_display(origin_url); + } + +@@ -978,9 +981,10 @@ void cef_server_create(const cef_string_t* address, + } + + NO_SANITIZE("cfi-icall") +-struct _cef_shared_process_message_builder_t* +-cef_shared_process_message_builder_create(const cef_string_t* name, +- size_t byte_size) { ++struct ++ _cef_shared_process_message_builder_t* cef_shared_process_message_builder_create( ++ const cef_string_t* name, ++ size_t byte_size) { + return g_libcef_pointers.cef_shared_process_message_builder_create(name, + byte_size); + } +@@ -1192,46 +1196,54 @@ struct _cef_translator_test_t* cef_translator_test_create() { + } + + NO_SANITIZE("cfi-icall") +-struct _cef_translator_test_ref_ptr_library_t* +-cef_translator_test_ref_ptr_library_create(int value) { ++struct ++ _cef_translator_test_ref_ptr_library_t* cef_translator_test_ref_ptr_library_create( ++ int value) { + return g_libcef_pointers.cef_translator_test_ref_ptr_library_create(value); + } + + NO_SANITIZE("cfi-icall") +-struct _cef_translator_test_ref_ptr_library_child_t* +-cef_translator_test_ref_ptr_library_child_create(int value, int other_value) { ++struct ++ _cef_translator_test_ref_ptr_library_child_t* cef_translator_test_ref_ptr_library_child_create( ++ int value, ++ int other_value) { + return g_libcef_pointers.cef_translator_test_ref_ptr_library_child_create( + value, other_value); + } + + NO_SANITIZE("cfi-icall") +-struct _cef_translator_test_ref_ptr_library_child_child_t* +-cef_translator_test_ref_ptr_library_child_child_create(int value, +- int other_value, +- int other_other_value) { ++struct ++ _cef_translator_test_ref_ptr_library_child_child_t* cef_translator_test_ref_ptr_library_child_child_create( ++ int value, ++ int other_value, ++ int other_other_value) { + return g_libcef_pointers + .cef_translator_test_ref_ptr_library_child_child_create( + value, other_value, other_other_value); + } + + NO_SANITIZE("cfi-icall") +-struct _cef_translator_test_scoped_library_t* +-cef_translator_test_scoped_library_create(int value) { ++struct ++ _cef_translator_test_scoped_library_t* cef_translator_test_scoped_library_create( ++ int value) { + return g_libcef_pointers.cef_translator_test_scoped_library_create(value); + } + + NO_SANITIZE("cfi-icall") +-struct _cef_translator_test_scoped_library_child_t* +-cef_translator_test_scoped_library_child_create(int value, int other_value) { ++struct ++ _cef_translator_test_scoped_library_child_t* cef_translator_test_scoped_library_child_create( ++ int value, ++ int other_value) { + return g_libcef_pointers.cef_translator_test_scoped_library_child_create( + value, other_value); + } + + NO_SANITIZE("cfi-icall") +-struct _cef_translator_test_scoped_library_child_child_t* +-cef_translator_test_scoped_library_child_child_create(int value, +- int other_value, +- int other_other_value) { ++struct ++ _cef_translator_test_scoped_library_child_child_t* cef_translator_test_scoped_library_child_child_create( ++ int value, ++ int other_value, ++ int other_other_value) { + return g_libcef_pointers + .cef_translator_test_scoped_library_child_child_create(value, other_value, + other_other_value); +@@ -1284,14 +1296,14 @@ void cef_display_get_alls(size_t* displaysCount, + } + + NO_SANITIZE("cfi-icall") +-cef_point_t cef_display_convert_screen_point_to_pixels( +- const cef_point_t* point) { ++cef_point_t ++ cef_display_convert_screen_point_to_pixels(const cef_point_t* point) { + return g_libcef_pointers.cef_display_convert_screen_point_to_pixels(point); + } + + NO_SANITIZE("cfi-icall") +-cef_point_t cef_display_convert_screen_point_from_pixels( +- const cef_point_t* point) { ++cef_point_t ++ cef_display_convert_screen_point_from_pixels(const cef_point_t* point) { + return g_libcef_pointers.cef_display_convert_screen_point_from_pixels(point); + } + +@@ -1342,6 +1354,14 @@ struct _cef_window_t* cef_window_create_top_level( + return g_libcef_pointers.cef_window_create_top_level(delegate); + } + ++NO_SANITIZE("cfi-icall") ++struct _cef_window_t* cef_window_create_top_level_with_id( ++ struct _cef_window_delegate_t* delegate, ++ const cef_string_t* app_id) { ++ return g_libcef_pointers.cef_window_create_top_level_with_id(delegate, ++ app_id); ++} ++ + NO_SANITIZE("cfi-icall") const char* cef_api_hash(int entry) { + return g_libcef_pointers.cef_api_hash(entry); + } +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0010-Make-patcher-work-outside-a-git-checkout.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0010-Make-patcher-work-outside-a-git-checkout.patch new file mode 100644 index 000000000..a59b4f3ca --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0010-Make-patcher-work-outside-a-git-checkout.patch @@ -0,0 +1,118 @@ +From 713ccd00a541ded20b20c84c7d985f87d3a88d00 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Wed, 18 Oct 2023 15:59:13 -0300 +Subject: [PATCH 10/11] Make patcher work outside a git checkout + +--- + tools/make_distrib.py | 21 +++++++++++---------- + tools/patch_util.py | 40 ++++++++++++++++++++++++++++++++++++++++ + tools/patcher.py | 3 +++ + 3 files changed, 54 insertions(+), 10 deletions(-) + create mode 100644 tools/patch_util.py + +diff --git a/tools/make_distrib.py b/tools/make_distrib.py +index 6ed748fe7..a8db7947e 100644 +--- a/tools/make_distrib.py ++++ b/tools/make_distrib.py +@@ -621,20 +621,21 @@ cef_url = git.get_url(cef_dir) + cef_rev = git.get_hash(cef_dir) + cef_commit_number = git.get_commit_number(cef_dir) + +-if not git.is_checkout(src_dir): +- raise Exception('Not a valid checkout: %s' % (src_dir)) +- +-# retrieve information for Chromium +-chromium_url = git.get_url(src_dir) +-chromium_rev = git.get_hash(src_dir) +- +-date = get_date() +- +-# format version strings + formatter = VersionFormatter() ++# format version strings + cef_ver = formatter.get_version_string() + chromium_ver = formatter.get_chromium_version_string() + ++if not git.is_checkout(src_dir): ++ chromium_url = git.get_url(src_dir) ++ chromium_rev = git.get_hash(src_dir) ++else: ++ # retrieve information for Chromium ++ chromium_rev = chromium_ver ++ chromium_url = 'https://commondatastorage.googleapis.com/chromium-browser-official/chromium-%s.tar.xz' % chromium_ver ++ ++date = get_date() ++ + # list of output directories to be archived + archive_dirs = [] + +diff --git a/tools/patch_util.py b/tools/patch_util.py +new file mode 100644 +index 000000000..2025e97e0 +--- /dev/null ++++ b/tools/patch_util.py +@@ -0,0 +1,40 @@ ++from __future__ import absolute_import ++from exec_util import exec_cmd ++import os ++import sys ++ ++def patch_apply_patch_file(patch_path, patch_dir): ++ """ Apply |patch_path| to files in |patch_dir|. """ ++ patch_name = os.path.basename(patch_path) ++ sys.stdout.write('\nApply %s in %s\n' % (patch_name, patch_dir)) ++ ++ if not os.path.isfile(patch_path): ++ sys.stdout.write('... patch file does not exist.\n') ++ return 'fail' ++ ++ # Apply the patch file. This should always succeed because the previous ++ # command succeeded. ++ ++ cmd = 'patch -p0 -N --dry-run --ignore-whitespace --input=%s' % patch_path ++ result = exec_cmd(cmd, patch_dir) ++ if result['ret'] != 0: ++ return 'skip' ++ ++ cmd = 'patch --ignore-whitespace -p0 --input=%s --verbose' % patch_path ++ result = exec_cmd(cmd, patch_dir) ++ ++ sys.stdout.write('Err: \t%s\n' % result['err']) ++ sys.stdout.write('Out: \t%s\n' % result['out']) ++ ++ if result['err'].find('FAILED') >= 0: ++ sys.stdout.write('... error applying patch.\n') ++ write_indented_output(result['err'].replace('<stdin>', patch_name)) ++ return 'fail' ++ ++ if result['err'] == '': ++ sys.stdout.write('... successfully applied.\n') ++ else: ++ sys.stdout.write('... successfully applied (with warnings):\n') ++ sys.stdout.write('\t%s\n' % result['err']) ++ return 'apply' ++ +diff --git a/tools/patcher.py b/tools/patcher.py +index 023e91d4b..fa6eb1946 100644 +--- a/tools/patcher.py ++++ b/tools/patcher.py +@@ -9,6 +9,7 @@ import os + import sys + from file_util import * + from git_util import git_apply_patch_file ++from patch_util import patch_apply_patch_file + + # Cannot be loaded as a module. + if __name__ != "__main__": +@@ -46,6 +47,8 @@ def apply_patch_file(patch_file, patch_dir): + return 'skip' + + result = git_apply_patch_file(patch_path, patch_dir) ++ if result == 'fail': ++ result = patch_apply_patch_file(patch_path, patch_dir) + if result == 'fail': + write_note('ERROR', + 'This patch failed to apply. Your build will not be correct.') +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/cef/0011-Avoid-the-RuntimeError-dictionary-changed-size-durin.patch b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0011-Avoid-the-RuntimeError-dictionary-changed-size-durin.patch new file mode 100644 index 000000000..32527b798 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/cef/0011-Avoid-the-RuntimeError-dictionary-changed-size-durin.patch @@ -0,0 +1,26 @@ +From db006bee47fd4cd5f9138a0b916b81dff9bab3d0 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Wed, 8 Nov 2023 13:37:27 -0300 +Subject: [PATCH 11/11] Avoid the RuntimeError: dictionary changed size during + iteration + +--- + tools/gn_args.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/gn_args.py b/tools/gn_args.py +index 80545da49..9e2e9c061 100644 +--- a/tools/gn_args.py ++++ b/tools/gn_args.py +@@ -486,7 +486,7 @@ def GetConfigArgs(args, is_debug, cpu, bypass_sysroot_check=False): + + if platform == 'linux' and not cpu.startswith('arm'): + # Remove any arm-related values from non-arm configs. +- for key in result.keys(): ++ for key, value in list(result.items()): + if key.startswith('arm_'): + del result[key] + +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0001-agl-compositor-Add-agl_shell_wrapper-AGL-wayland-ext.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0001-agl-compositor-Add-agl_shell_wrapper-AGL-wayland-ext.patch new file mode 100644 index 000000000..6ab4d5b82 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0001-agl-compositor-Add-agl_shell_wrapper-AGL-wayland-ext.patch @@ -0,0 +1,914 @@ +From 019d5dea79b9ac8ec17d5925546aab66473f67f5 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Mon, 15 May 2023 20:32:06 +0200 +Subject: [PATCH 01/33] [agl][compositor] Add agl_shell_wrapper / AGL wayland + extension + +This is a backport of the chages we did on top of chromium webosose to +be able to communicate with the agl-compositor + +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + ui/base/ui_base_switches.cc | 2 + + ui/base/ui_base_switches.h | 3 + + ui/ozone/platform/wayland/BUILD.gn | 7 + + .../platform/wayland/extensions/agl/BUILD.gn | 40 ++++ + .../agl/common/wayland_object_agl.cc | 26 +++ + .../agl/common/wayland_object_agl.h | 34 ++++ + .../extensions/agl/host/agl_shell_wrapper.cc | 113 +++++++++++ + .../extensions/agl/host/agl_shell_wrapper.h | 62 ++++++ + .../agl/host/wayland_extensions_agl.h | 37 ++++ + .../agl/host/wayland_extensions_agl_impl.cc | 93 +++++++++ + .../agl/host/wayland_extensions_agl_impl.h | 54 ++++++ + .../extensions/agl/protocol/agl-shell.xml | 179 ++++++++++++++++++ + .../wayland/host/wayland_connection.cc | 12 +- + .../wayland/host/wayland_connection.h | 4 + + .../wayland/host/wayland_extensions.h | 56 ++++++ + 15 files changed, 720 insertions(+), 2 deletions(-) + create mode 100644 ui/ozone/platform/wayland/extensions/agl/BUILD.gn + create mode 100644 ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.cc + create mode 100644 ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.h + create mode 100644 ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.cc + create mode 100644 ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h + create mode 100644 ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h + create mode 100644 ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc + create mode 100644 ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.h + create mode 100644 ui/ozone/platform/wayland/extensions/agl/protocol/agl-shell.xml + create mode 100644 ui/ozone/platform/wayland/host/wayland_extensions.h + +diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc +index 514bb3cdb580d..d94e2c5e78306 100644 +--- a/ui/base/ui_base_switches.cc ++++ b/ui/base/ui_base_switches.cc +@@ -112,4 +112,6 @@ const char kUIDisablePartialSwap[] = "ui-disable-partial-swap"; + // Enables the ozone x11 clipboard for linux-chromeos. + const char kUseSystemClipboard[] = "use-system-clipboard"; + ++const char kAglShellAppId[] = "agl-shell-appid"; ++ + } // namespace switches +diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h +index ec664b866c5d2..cf483e0339072 100644 +--- a/ui/base/ui_base_switches.h ++++ b/ui/base/ui_base_switches.h +@@ -53,6 +53,9 @@ COMPONENT_EXPORT(UI_BASE) extern const char kTopChromeTouchUiEnabled[]; + COMPONENT_EXPORT(UI_BASE) extern const char kUIDisablePartialSwap[]; + COMPONENT_EXPORT(UI_BASE) extern const char kUseSystemClipboard[]; + ++// Agl related ++COMPONENT_EXPORT(UI_BASE) extern const char kAglShellAppId[]; ++ + // Test related. + COMPONENT_EXPORT(UI_BASE) extern const char kDisallowNonExactResourceReuse[]; + COMPONENT_EXPORT(UI_BASE) extern const char kMangleLocalizedStrings[]; +diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn +index ae763d441d55c..8a436de0fafe3 100644 +--- a/ui/ozone/platform/wayland/BUILD.gn ++++ b/ui/ozone/platform/wayland/BUILD.gn +@@ -397,6 +397,13 @@ source_set("wayland") { + ] + + configs += [ "//third_party/khronos:khronos_headers" ] ++ ++ sources += [ ++ "host/wayland_extensions.h", ++ "host/wayland_extensions_stub.cc", ++ ] ++ ++ deps += [ "extensions/agl" ] + } + + source_set("test_support") { +diff --git a/ui/ozone/platform/wayland/extensions/agl/BUILD.gn b/ui/ozone/platform/wayland/extensions/agl/BUILD.gn +new file mode 100644 +index 0000000000000..ce289bc5dbbca +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/BUILD.gn +@@ -0,0 +1,40 @@ ++# Copyright 2021 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 ++ ++import("//third_party/wayland/wayland_protocol.gni") ++ ++visibility = [ "//ui/ozone/*" ] ++ ++wayland_protocol("agl_shell_protocol") { ++ sources = [ "protocol/agl-shell.xml" ] ++} ++ ++source_set("agl") { ++ sources = [ ++ "common/wayland_object_agl.cc", ++ "common/wayland_object_agl.h", ++ "host/agl_shell_wrapper.cc", ++ "host/agl_shell_wrapper.h", ++ "host/wayland_extensions_agl.h", ++ "host/wayland_extensions_agl_impl.cc", ++ "host/wayland_extensions_agl_impl.h", ++ ] ++ ++ deps = [ ++ ":agl_shell_protocol", ++ "//ui/ozone/platform/wayland/mojom", ++ ] ++} +diff --git a/ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.cc b/ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.cc +new file mode 100644 +index 0000000000000..9f3300766df2c +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.cc +@@ -0,0 +1,26 @@ ++// Copyright 2021 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 "ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.h" ++ ++#include <agl-shell-client-protocol.h> ++ ++namespace wl { ++ ++const wl_interface* ObjectTraits<agl_shell>::interface = &agl_shell_interface; ++void (*ObjectTraits<agl_shell>::deleter)(agl_shell*) = &agl_shell_destroy; ++ ++} // namespace wl +\ No newline at end of file +diff --git a/ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.h b/ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.h +new file mode 100644 +index 0000000000000..e91ac0da8d2fc +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.h +@@ -0,0 +1,34 @@ ++// Copyright 2021 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 UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_COMMON_WAYLAND_OBJECT_AGL_H_ ++#define UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_COMMON_WAYLAND_OBJECT_AGL_H_ ++ ++#include "ui/ozone/platform/wayland/common/wayland_object.h" ++ ++struct agl_shell; ++ ++namespace wl { ++ ++template <> ++struct ObjectTraits<agl_shell> { ++ static const wl_interface* interface; ++ static void (*deleter)(agl_shell*); ++}; ++ ++} // namespace wl ++ ++#endif // UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_COMMON_WAYLAND_OBJECT_AGL_H_ +\ No newline at end of file +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.cc b/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.cc +new file mode 100644 +index 0000000000000..c74fa5d9cd221 +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.cc +@@ -0,0 +1,113 @@ ++// Copyright 2021 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 "ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h" ++ ++#include "agl_shell_wrapper.h" ++#include "base/logging.h" ++#include "ui/base/ui_base_switches.h" ++#include "ui/ozone/platform/wayland/host/wayland_connection.h" ++#include "ui/ozone/platform/wayland/host/wayland_output_manager.h" ++#include "ui/ozone/platform/wayland/host/wayland_window.h" ++ ++namespace ui { ++ ++static const struct agl_shell_listener shell_listener = { ++ &AglShellWrapper::AglShellBoundOk, ++ &AglShellWrapper::AglShellBoundFail, ++#ifdef AGL_SHELL_APP_STATE_SINCE_VERSION ++ &AglShellWrapper::AglAppState, ++#endif ++}; ++ ++AglShellWrapper::AglShellWrapper(agl_shell* agl_shell, ++ WaylandConnection* wayland_connection) ++ : agl_shell_(agl_shell), connection_(wayland_connection) { ++ if (wl::get_version_of_object(agl_shell) >= AGL_SHELL_BOUND_OK_SINCE_VERSION) ++ agl_shell_add_listener(agl_shell, &shell_listener, this); ++} ++ ++AglShellWrapper::~AglShellWrapper() = default; ++ ++void AglShellWrapper::SetAglActivateApp(const std::string& app_id) { ++ wl_output* output = ++ connection_->wayland_output_manager()->GetPrimaryOutput()->get_output(); ++ agl_shell_activate_app(agl_shell_.get(), app_id.c_str(), output); ++} ++ ++void AglShellWrapper::SetAglPanel(WaylandWindow* window, uint32_t edge) { ++ wl_surface* surface = window->root_surface()->surface(); ++ wl_output* output = ++ connection_->wayland_output_manager()->GetPrimaryOutput()->get_output(); ++ ++ agl_shell_set_panel(agl_shell_.get(), surface, output, edge); ++} ++ ++void AglShellWrapper::SetAglBackground(WaylandWindow* window) { ++ wl_surface* surface = window->root_surface()->surface(); ++ wl_output* output = ++ connection_->wayland_output_manager()->GetPrimaryOutput()->get_output(); ++ ++ agl_shell_set_background(agl_shell_.get(), surface, output); ++} ++ ++void AglShellWrapper::SetAglReady() { ++ agl_shell_ready(agl_shell_.get()); ++} ++ ++// static ++void AglShellWrapper::AglShellBoundOk(void* data, struct agl_shell*) { ++ AglShellWrapper* wrapper = static_cast<AglShellWrapper*>(data); ++ wrapper->wait_for_bound_ = false; ++ wrapper->bound_ok_ = true; ++ LOG(INFO) << "Bound to agl_shell (bound_ok)"; ++} ++ ++// static ++void AglShellWrapper::AglShellBoundFail(void* data, struct agl_shell*) { ++ AglShellWrapper* wrapper = static_cast<AglShellWrapper*>(data); ++ wrapper->wait_for_bound_ = false; ++ wrapper->bound_ok_ = false; ++ LOG(INFO) << "Failed to bind to agl_shell (bound_fail)"; ++} ++ ++#ifdef AGL_SHELL_APP_STATE_SINCE_VERSION ++// static ++void AglShellWrapper::AglAppState(void* data, ++ struct agl_shell*, ++ const char* app_id, ++ uint32_t state) { ++ AglShellWrapper* wrapper = static_cast<AglShellWrapper*>(data); ++ ++ LOG(INFO) << "State for app " << app_id << " changed to " << state; ++ ++ if (state == AGL_SHELL_APP_STATE_STARTED) { ++ wrapper->SetAglActivateApp(app_id); ++ LOG(INFO) << "Activating app " << app_id; ++ } ++} ++#endif ++ ++bool AglShellWrapper::WaitUntilBoundOk() { ++ int ret = 0; ++ while (ret != -1 && wait_for_bound_) { ++ ret = wl_display_dispatch(connection_->display()); ++ } ++ ++ return bound_ok_; ++} ++ ++} // namespace ui +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h b/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h +new file mode 100644 +index 0000000000000..2ab765883057e +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h +@@ -0,0 +1,62 @@ ++// Copyright 2021 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 UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_AGL_SHELL_WRAPPER_H_ ++#define UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_AGL_SHELL_WRAPPER_H_ ++ ++#include <string> ++ ++#include <agl-shell-client-protocol.h> ++ ++#include "ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.h" ++ ++namespace ui { ++ ++class WaylandConnection; ++class WaylandWindow; ++ ++class AglShellWrapper { ++ public: ++ AglShellWrapper(agl_shell* agl_shell, WaylandConnection* wayland_connection); ++ AglShellWrapper(const AglShellWrapper&) = delete; ++ AglShellWrapper& operator=(const AglShellWrapper&) = delete; ++ ~AglShellWrapper(); ++ ++ void SetAglActivateApp(const std::string& app_id); ++ void SetAglPanel(WaylandWindow* window, uint32_t edge); ++ void SetAglBackground(WaylandWindow* window); ++ void SetAglReady(); ++ bool WaitUntilBoundOk(); ++ ++ static void AglShellBoundOk(void* data, struct agl_shell*); ++ static void AglShellBoundFail(void* data, struct agl_shell*); ++#ifdef AGL_SHELL_APP_STATE_SINCE_VERSION ++ static void AglAppState(void* data, ++ struct agl_shell*, ++ const char* app_id, ++ uint32_t state); ++#endif ++ ++ private: ++ wl::Object<agl_shell> agl_shell_; ++ WaylandConnection* connection_; ++ bool wait_for_bound_ = true; ++ bool bound_ok_ = false; ++}; ++ ++} // namespace ui ++ ++#endif // UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_AGL_SHELL_WRAPPER_H_ +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h +new file mode 100644 +index 0000000000000..df42fc00c84da +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h +@@ -0,0 +1,37 @@ ++// Copyright 2021 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 UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_EXTENSIONS_AGL_H_ ++#define UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_EXTENSIONS_AGL_H_ ++ ++namespace ui { ++ ++class AglShellWrapper; ++ ++// AGL extensions implementation for webOS/Lite ++class WaylandExtensionsAgl { ++ public: ++ WaylandExtensionsAgl() = default; ++ WaylandExtensionsAgl(const WaylandExtensionsAgl&) = delete; ++ WaylandExtensionsAgl& operator=(const WaylandExtensionsAgl&) = delete; ++ virtual ~WaylandExtensionsAgl() = default; ++ ++ virtual AglShellWrapper* GetAglShell() = 0; ++}; ++ ++} // namespace ui ++ ++#endif // UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_EXTENSIONS_AGL_H_ +\ No newline at end of file +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc +new file mode 100644 +index 0000000000000..26a5f0550c302 +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc +@@ -0,0 +1,93 @@ ++// Copyright 2021 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 "ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.h" ++ ++#include <cstring> ++ ++#include "base/command_line.h" ++#include "base/logging.h" ++#include "ui/base/ui_base_switches.h" ++#include "ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h" ++#include "ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.h" ++#include "ui/ozone/platform/wayland/host/wayland_connection.h" ++ ++namespace ui { ++ ++namespace { ++ ++constexpr uint32_t kMinAglShellExtensionVersion = 1; ++constexpr uint32_t kMaxAglShellExtensionVersion = 3; ++ ++} // namespace ++ ++WaylandExtensionsAglImpl::WaylandExtensionsAglImpl( ++ WaylandConnection* connection) ++ : connection_(connection) {} ++ ++WaylandExtensionsAglImpl::~WaylandExtensionsAglImpl() = default; ++ ++bool WaylandExtensionsAglImpl::Bind(wl_registry* registry, ++ uint32_t name, ++ const char* interface, ++ uint32_t version) { ++ bool should_use_agl_shell = base::CommandLine::ForCurrentProcess()->HasSwitch( ++ switches::kAglShellAppId); ++ bool can_bind = wl::CanBind(interface, version, kMinAglShellExtensionVersion, ++ kMaxAglShellExtensionVersion); ++ bool is_agl_shell_interface = (strcmp(interface, "agl_shell") == 0); ++ ++ if (!is_agl_shell_interface) { ++ return false; ++ } ++ ++ LOG(INFO) << "should_use_agl_shell: " << should_use_agl_shell << ++ " can_bind: " << can_bind; ++ ++ if (should_use_agl_shell && !agl_shell_ && ++ is_agl_shell_interface && can_bind) { ++ wl::Object<agl_shell> aglshell = wl::Bind<agl_shell>( ++ registry, name, std::min(version, kMaxAglShellExtensionVersion)); ++ if (!aglshell) { ++ LOG(ERROR) << "Failed to bind to agl_shell global"; ++ return false; ++ } ++ agl_shell_ = ++ std::make_unique<AglShellWrapper>(aglshell.release(), connection_); ++ ++ LOG(INFO) << "Waiting until bound..."; ++ return agl_shell_->WaitUntilBoundOk(); ++ } else { ++ LOG(INFO) << "Cant bind."; ++ } ++ ++ return false; ++} ++ ++bool WaylandExtensionsAglImpl::HasShellObject() const { ++ return !!agl_shell_; ++} ++ ++AglShellWrapper* WaylandExtensionsAglImpl::GetAglShell() { ++ return agl_shell_.get(); ++} ++ ++std::unique_ptr<WaylandExtensions> CreateWaylandExtensions( ++ WaylandConnection* connection) { ++ return std::make_unique<WaylandExtensionsAglImpl>(connection); ++} ++ ++} // namespace ui +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.h b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.h +new file mode 100644 +index 0000000000000..f6cbabe99ed0b +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.h +@@ -0,0 +1,54 @@ ++// Copyright 2021 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 UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_EXTENSIONS_AGL_IMPL_H_ ++#define UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_EXTENSIONS_AGL_IMPL_H_ ++ ++#include "ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h" ++#include "ui/ozone/platform/wayland/host/wayland_extensions.h" ++ ++namespace ui { ++ ++class AglShellWrapper; ++ ++// AGL extension implementation for webOS/Lite ++class WaylandExtensionsAglImpl : public WaylandExtensions, ++ public WaylandExtensionsAgl { ++ public: ++ explicit WaylandExtensionsAglImpl(WaylandConnection* connection); ++ WaylandExtensionsAglImpl(const WaylandExtensionsAglImpl&) = delete; ++ WaylandExtensionsAglImpl& operator=(const WaylandExtensionsAglImpl&) = delete; ++ ~WaylandExtensionsAglImpl() override; ++ ++ // WaylandExtensions overrides ++ bool Bind(wl_registry* registry, ++ uint32_t name, ++ const char* interface, ++ uint32_t version) override; ++ ++ bool HasShellObject() const override; ++ ++ // WaylandExtensionsAgl overrides ++ AglShellWrapper* GetAglShell() override; ++ ++ private: ++ std::unique_ptr<AglShellWrapper> agl_shell_; ++ WaylandConnection* connection_; ++}; ++ ++} // namespace ui ++ ++#endif // UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_EXTENSIONS_AGL_IMPL_H_ +diff --git a/ui/ozone/platform/wayland/extensions/agl/protocol/agl-shell.xml b/ui/ozone/platform/wayland/extensions/agl/protocol/agl-shell.xml +new file mode 100644 +index 0000000000000..ad5553d61f189 +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/protocol/agl-shell.xml +@@ -0,0 +1,179 @@ ++<?xml version="1.0" encoding="UTF-8"?> ++<protocol name="agl_shell"> ++ <copyright> ++ Copyright © 2019, 2022 Collabora, Ltd. ++ ++ Permission is hereby granted, free of charge, to any person obtaining a ++ copy of this software and associated documentation files (the "Software"), ++ to deal in the Software without restriction, including without limitation ++ the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ and/or sell copies of the Software, and to permit persons to whom the ++ Software is furnished to do so, subject to the following conditions: ++ ++ The above copyright notice and this permission notice (including the next ++ paragraph) shall be included in all copies or substantial portions of the ++ Software. ++ ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ DEALINGS IN THE SOFTWARE. ++ </copyright> ++ <interface name="agl_shell" version="3"> ++ <description summary="user interface for Automotive Grade Linux platform"> ++ Starting with version 2 of the protocol, the client is required to wait ++ for the 'bound_ok' or 'bound_fail' events in order to proceed further. ++ ++ In case the client gets a 'bound_fail' event then it should consider that ++ there's another client already bound to the agl_shell protocol. ++ A client that receives a 'bound_ok' event should consider that there's ++ no other client already bound to the interface and can proceed further. ++ ++ If the client uses an older version of the protocol it will receive ++ automatically an error and the compositor will terminate the connection, ++ if there's another client already bound the interface. ++ ++ If the client receives the 'bound_fail' event and attempts to use the ++ interface further it will receive an error and the compositor will ++ terminate the connection. After the 'bound_fail' event was received the ++ client should call the destructor, which has been added with version 2 ++ of the protocol. The client is free to try at a later point in time to ++ see if it will receive the 'bound_ok' event, but there's no explicit way ++ of finding out when that event will be delivered. ++ It is assumed that it can infer that information through other ++ means/other channels. ++ </description> ++ ++ <enum name="error"> ++ <entry name="invalid_argument" value="0"/> ++ <entry name="background_exists" value="1"/> ++ <entry name="panel_exists" value="2"/> ++ </enum> ++ ++ <enum name="edge"> ++ <entry name="top" value="0"/> ++ <entry name="bottom" value="1"/> ++ <entry name="left" value="2"/> ++ <entry name="right" value="3"/> ++ </enum> ++ ++ <enum name="app_state" since="3"> ++ <entry name="started" value="0"/> ++ <entry name="terminated" value="1"/> ++ <entry name="activated" value="2"/> ++ <entry name="deactivated" value="3"/> ++ </enum> ++ ++ <request name="ready"> ++ <description summary="client is ready to be shown"> ++ Tell the server that this client is ready to be shown. The server ++ will delay presentation during start-up until all shell clients are ++ ready to be shown, and will display a black screen instead. ++ This gives the client an opportunity to set up and configure several ++ surfaces into a coherent interface. ++ ++ The client that binds to this interface must send this request, otherwise ++ they may stall the compositor unnecessarily. ++ ++ If this request is called after the compositor has already finished ++ start-up, no operation is performed. ++ </description> ++ </request> ++ ++ <request name="set_background"> ++ <description summary="set surface as output's background"> ++ Set the surface to act as the background of an output. After this ++ request, the server will immediately send a configure event with ++ the dimensions the client should use to cover the entire output. ++ ++ The surface must have a "desktop" surface role, as supported by ++ libweston-desktop. ++ ++ Only a single surface may be the background for any output. If a ++ background surface already exists, a protocol error is raised. ++ </description> ++ <arg name="surface" type="object" interface="wl_surface"/> ++ <arg name="output" type="object" interface="wl_output"/> ++ </request> ++ ++ <request name="set_panel"> ++ <description summary="set surface as panel"> ++ Set the surface to act as a panel of an output. The 'edge' argument ++ says what edge of the output the surface will be anchored to. ++ After this request, the server will send a configure event with the ++ corresponding width/height that the client should use, and 0 for the ++ other dimension. E.g. if the edge is 'top', the width will be the ++ output's width, and the height will be 0. ++ ++ The surface must have a "desktop" surface role, as supported by ++ libweston-desktop. ++ ++ The compositor will take the panel's window geometry into account when ++ positioning other windows, so the panels are not covered. ++ ++ XXX: What happens if e.g. both top and left are used at the same time? ++ Who gets to have the corner? ++ ++ Only a single surface may be the panel for an output's edge. If a ++ surface already exists on an edge, a protocol error is raised. ++ </description> ++ <arg name="surface" type="object" interface="wl_surface"/> ++ <arg name="output" type="object" interface="wl_output"/> ++ <arg name="edge" type="uint" enum="edge"/> ++ </request> ++ ++ <request name="activate_app"> ++ <description summary="make client current window"> ++ Ask the compositor to make a toplevel to become the current/focused ++ window for window management purposes. ++ ++ See xdg_toplevel.set_app_id from the xdg-shell protocol for a ++ description of app_id. ++ ++ If multiple toplevels have the same app_id, the result is unspecified. ++ ++ XXX: Do we need feedback to say it didn't work? (e.g. client does ++ not exist) ++ </description> ++ <arg name="app_id" type="string"/> ++ <arg name="output" type="object" interface="wl_output"/> ++ </request> ++ ++ <event name="bound_ok" since="2"> ++ <description summary="event sent if binding was ok"> ++ Informs the client that it was able to bind the agl_shell ++ interface succesfully. Clients are required to wait for this ++ event before continuing further. ++ </description> ++ </event> ++ ++ <event name="bound_fail" since="2"> ++ <description summary="event sent if binding was nok"> ++ Informs the client that binding to the agl_shell interface was ++ unsuccesfull. Clients are required to wait for this event for ++ continuing further. ++ </description> ++ </event> ++ ++ <request name="destroy" type="destructor" since="2"> ++ <description summary="destroys the factory object"> ++ </description> ++ </request> ++ ++ <event name="app_state" since="3"> ++ <description summary="event sent when an application suffered state modification"> ++ Informs the client that an application has changed its state to another, ++ specified by the app_state enum. Client can use this event to track ++ current application state. For instance to know when the application has ++ started, or when terminated/stopped. ++ </description> ++ <arg name="app_id" type="string"/> ++ <arg name="state" type="uint" enum="app_state"/> ++ </event> ++ ++ ++ </interface> ++</protocol> +diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc +index ad3bbd6e37157..7a47d4a636998 100644 +--- a/ui/ozone/platform/wayland/host/wayland_connection.cc ++++ b/ui/ozone/platform/wayland/host/wayland_connection.cc +@@ -68,6 +68,8 @@ + #include "ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.h" + #include "ui/platform_window/common/platform_window_defaults.h" + ++#include "ui/ozone/platform/wayland/host/wayland_extensions.h" ++ + namespace ui { + + namespace { +@@ -212,6 +214,10 @@ bool WaylandConnection::Initialize(bool use_threaded_polling) { + use_threaded_polling = false; + } + ++ if (!extensions_) { ++ extensions_ = CreateWaylandExtensions(this); ++ } ++ + // Now that the connection with the display server has been properly + // estabilished, initialize the event source and input objects. + DCHECK(!event_source_); +@@ -243,7 +249,7 @@ bool WaylandConnection::Initialize(bool use_threaded_polling) { + LOG(ERROR) << "No wl_shm object"; + return false; + } +- if (!shell_) { ++ if (!shell_ && !(extensions_ && extensions_->HasShellObject())) { + LOG(ERROR) << "No Wayland shell found"; + return false; + } +@@ -538,7 +544,9 @@ void WaylandConnection::HandleGlobal(wl_registry* registry, + const char* interface, + uint32_t version) { + auto factory_it = global_object_factories_.find(interface); +- if (factory_it != global_object_factories_.end()) { ++ if (extensions_->Bind(registry, name, interface, version)) { ++ DVLOG(1) << "Successfully bound to " << interface; ++ } else if (factory_it != global_object_factories_.end()) { + (*factory_it->second)(this, registry, name, interface, version); + } else if (!compositor_ && strcmp(interface, "wl_compositor") == 0) { + compositor_ = wl::Bind<wl_compositor>( +diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h +index 6659bc54bd475..ba293e5bcd088 100644 +--- a/ui/ozone/platform/wayland/host/wayland_connection.h ++++ b/ui/ozone/platform/wayland/host/wayland_connection.h +@@ -50,6 +50,7 @@ class WaylandBufferManagerHost; + class WaylandCursor; + class WaylandCursorBufferListener; + class WaylandEventSource; ++class WaylandExtensions; + class WaylandOutputManager; + class WaylandSeat; + class WaylandZAuraShell; +@@ -201,6 +202,8 @@ class WaylandConnection { + + WaylandZAuraShell* zaura_shell() const { return zaura_shell_.get(); } + ++ WaylandExtensions* extensions() { return extensions_.get(); } ++ + WaylandZcrColorManager* zcr_color_manager() const { + return zcr_color_manager_.get(); + } +@@ -486,6 +489,7 @@ class WaylandConnection { + std::unique_ptr<OverlayPrioritizer> overlay_prioritizer_; + std::unique_ptr<SurfaceAugmenter> surface_augmenter_; + std::unique_ptr<SinglePixelBuffer> single_pixel_buffer_; ++ std::unique_ptr<WaylandExtensions> extensions_; + + // Clipboard-related objects. |clipboard_| must be declared after all + // DeviceManager instances it depends on, otherwise tests may crash with +diff --git a/ui/ozone/platform/wayland/host/wayland_extensions.h b/ui/ozone/platform/wayland/host/wayland_extensions.h +new file mode 100644 +index 0000000000000..3bd2fd7a211ae +--- /dev/null ++++ b/ui/ozone/platform/wayland/host/wayland_extensions.h +@@ -0,0 +1,56 @@ ++// Copyright 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 ++ ++#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_EXTENSIONS_H_ ++#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_EXTENSIONS_H_ ++ ++#include <memory> ++ ++#include "ui/ozone/platform/wayland/common/wayland_object.h" ++ ++namespace ui { ++ ++class ShellToplevelWrapper; ++class ShellPopupWrapper; ++class WaylandConnection; ++ ++// Wayland extensions abstract interface to support extending of the Wayland ++// protocol. Inherit it to provide your own Wayland extensions implementation. ++class WaylandExtensions { ++ public: ++ WaylandExtensions() = default; ++ WaylandExtensions(const WaylandExtensions&) = delete; ++ WaylandExtensions& operator=(const WaylandExtensions&) = delete; ++ virtual ~WaylandExtensions() = default; ++ ++ // Binds to the extensions interface(s). Can encapsulate binding of several ++ // interfaces, defined by |interface|. ++ virtual bool Bind(wl_registry* registry, ++ uint32_t name, ++ const char* interface, ++ uint32_t version) = 0; ++ ++ // Checks whether the extensions have bound shell object(s). ++ virtual bool HasShellObject() const = 0; ++}; ++ ++// Creates Wayland extensions. ++std::unique_ptr<WaylandExtensions> CreateWaylandExtensions( ++ WaylandConnection* connection); ++ ++} // namespace ui ++ ++#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_EXTENSIONS_H_ +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0002-agl-Add-waylandwindow-window-tree-host-essential-par.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0002-agl-Add-waylandwindow-window-tree-host-essential-par.patch new file mode 100644 index 000000000..488b398bb --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0002-agl-Add-waylandwindow-window-tree-host-essential-par.patch @@ -0,0 +1,1376 @@ +From d50bcc010ca2856979f58b2ffbd0015514c4231f Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Wed, 17 May 2023 21:25:53 +0200 +Subject: [PATCH 02/33] [agl] Add waylandwindow/window tree host essential + parts + +This is a backport of the work we did on top of chromium webosose to be +able to communicate with the agl compositor. + +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + ui/aura/BUILD.gn | 7 ++ + ui/aura/agl/window_tree_host_agl.h | 42 +++++++++ + ui/aura/agl/window_tree_host_platform_agl.cc | 50 +++++++++++ + ui/aura/agl/window_tree_host_platform_agl.h | 51 +++++++++++ + ui/aura/window_tree_host.h | 5 +- + ui/aura/window_tree_host_platform.cc | 4 +- + ui/aura/window_tree_host_platform.h | 4 +- + ui/ozone/platform/wayland/BUILD.gn | 1 - + .../platform/wayland/extensions/agl/BUILD.gn | 2 + + .../agl/host/wayland_extensions_agl.h | 10 ++- + .../agl/host/wayland_extensions_agl_impl.cc | 11 ++- + .../agl/host/wayland_extensions_agl_impl.h | 9 ++ + .../extensions/agl/host/wayland_window_agl.cc | 86 +++++++++++++++++++ + .../extensions/agl/host/wayland_window_agl.h | 49 +++++++++++ + .../wayland/gpu/gl_surface_wayland.cc | 9 +- + .../host/gtk_primary_selection_device.cc | 2 +- + .../gtk_primary_selection_device_manager.cc | 4 +- + .../wayland/host/proxy/wayland_proxy_impl.cc | 2 +- + .../wayland/host/wayland_connection.cc | 19 +++- + .../wayland/host/wayland_connection.h | 9 +- + .../platform/wayland/host/wayland_cursor.cc | 4 +- + .../wayland/host/wayland_data_device.cc | 10 +-- + .../wayland/host/wayland_data_device_base.cc | 2 +- + .../host/wayland_data_drag_controller.cc | 2 +- + .../wayland/host/wayland_data_source.cc | 6 +- + ui/ozone/platform/wayland/host/wayland_drm.cc | 6 +- + .../wayland/host/wayland_extensions.h | 6 ++ + .../platform/wayland/host/wayland_keyboard.cc | 4 +- + .../platform/wayland/host/wayland_popup.cc | 8 +- + .../platform/wayland/host/wayland_seat.cc | 2 +- + ui/ozone/platform/wayland/host/wayland_shm.cc | 2 +- + .../platform/wayland/host/wayland_surface.cc | 2 +- + .../wayland/host/wayland_toplevel_window.cc | 18 ++-- + .../platform/wayland/host/wayland_window.cc | 6 +- + .../platform/wayland/host/wayland_window.h | 2 + + .../host/wayland_window_drag_controller.cc | 2 +- + .../wayland/host/wayland_window_factory.cc | 14 +++ + .../wayland/host/wayland_zwp_linux_dmabuf.cc | 4 +- + .../wayland/host/xdg_foreign_wrapper.cc | 4 +- + .../wayland/host/xdg_popup_wrapper_impl.cc | 2 +- + .../wayland/host/xdg_surface_wrapper_impl.cc | 2 +- + .../wayland/host/xdg_toplevel_wrapper_impl.cc | 2 +- + .../host/zwp_primary_selection_device.cc | 2 +- + .../zwp_primary_selection_device_manager.cc | 4 +- + ui/platform_window/agl/platform_window_agl.h | 36 ++++++++ + ui/platform_window/platform_window.h | 4 +- + 46 files changed, 469 insertions(+), 63 deletions(-) + create mode 100644 ui/aura/agl/window_tree_host_agl.h + create mode 100644 ui/aura/agl/window_tree_host_platform_agl.cc + create mode 100644 ui/aura/agl/window_tree_host_platform_agl.h + create mode 100644 ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.cc + create mode 100644 ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h + create mode 100644 ui/platform_window/agl/platform_window_agl.h + +diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn +index 50ca856b9da18..8fa04492f69f7 100644 +--- a/ui/aura/BUILD.gn ++++ b/ui/aura/BUILD.gn +@@ -99,6 +99,13 @@ component("aura") { + "window_tree_host_platform.cc", + ] + ++ public += [ ++ "agl/window_tree_host_agl.h", ++ "agl/window_tree_host_platform_agl.h" ++ ] ++ ++ sources += [ "agl/window_tree_host_platform_agl.cc" ] ++ + friend = [ ":*" ] + + defines = [ "AURA_IMPLEMENTATION" ] +diff --git a/ui/aura/agl/window_tree_host_agl.h b/ui/aura/agl/window_tree_host_agl.h +new file mode 100644 +index 0000000000000..858a078d939d0 +--- /dev/null ++++ b/ui/aura/agl/window_tree_host_agl.h +@@ -0,0 +1,42 @@ ++// Copyright 2021 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 UI_AURA_AGL_WINDOW_TREE_HOST_AGL_H_ ++#define UI_AURA_AGL_WINDOW_TREE_HOST_AGL_H_ ++ ++#include <string> ++ ++#include "ui/aura/aura_export.h" ++ ++namespace aura { ++ ++class AURA_EXPORT WindowTreeHostAgl { ++ public: ++ WindowTreeHostAgl() = default; ++ WindowTreeHostAgl(const WindowTreeHostAgl&) = delete; ++ WindowTreeHostAgl& operator=(const WindowTreeHostAgl&) = delete; ++ ~WindowTreeHostAgl() = default; ++ ++ virtual void SetAglActivateApp(const std::string& app) {} ++ virtual void SetAglAppId(const std::string& title) {} ++ virtual void SetAglReady() {} ++ virtual void SetAglBackground() {} ++ virtual void SetAglPanel(uint32_t edge) {} ++}; ++ ++} // namespace aura ++ ++#endif // UI_AURA_AGL_WINDOW_TREE_HOST_AGL_H_ +diff --git a/ui/aura/agl/window_tree_host_platform_agl.cc b/ui/aura/agl/window_tree_host_platform_agl.cc +new file mode 100644 +index 0000000000000..e34595fe0ed9c +--- /dev/null ++++ b/ui/aura/agl/window_tree_host_platform_agl.cc +@@ -0,0 +1,50 @@ ++// Copyright 2021 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 "ui/aura/agl/window_tree_host_platform_agl.h" ++ ++#include "ui/aura/window_tree_host_platform.h" ++#include "ui/platform_window/platform_window.h" ++ ++namespace aura { ++ ++WindowTreeHostPlatformAgl::WindowTreeHostPlatformAgl( ++ std::unique_ptr<Window> window, ++ aura::WindowTreeHostPlatform* window_tree_host_platform) ++ : aura::WindowTreeHost(std::move(window)), ++ window_tree_host_platform_(window_tree_host_platform) {} ++ ++void WindowTreeHostPlatformAgl::SetAglActivateApp(const std::string& app) { ++ window_tree_host_platform_->platform_window()->SetAglActivateApp(app); ++} ++ ++void WindowTreeHostPlatformAgl::SetAglAppId(const std::string& title) { ++ window_tree_host_platform_->platform_window()->SetAglAppId(title); ++} ++ ++void WindowTreeHostPlatformAgl::SetAglReady() { ++ window_tree_host_platform_->platform_window()->SetAglReady(); ++} ++ ++void WindowTreeHostPlatformAgl::SetAglBackground() { ++ window_tree_host_platform_->platform_window()->SetAglBackground(); ++} ++ ++void WindowTreeHostPlatformAgl::SetAglPanel(uint32_t edge) { ++ window_tree_host_platform_->platform_window()->SetAglPanel(edge); ++} ++ ++} // namespace aura +diff --git a/ui/aura/agl/window_tree_host_platform_agl.h b/ui/aura/agl/window_tree_host_platform_agl.h +new file mode 100644 +index 0000000000000..181eefae346f7 +--- /dev/null ++++ b/ui/aura/agl/window_tree_host_platform_agl.h +@@ -0,0 +1,51 @@ ++// Copyright 2021 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 UI_AURA_AGL_WINDOW_TREE_HOST_PLATFORM_AGL_H_ ++#define UI_AURA_AGL_WINDOW_TREE_HOST_PLATFORM_AGL_H_ ++ ++#include <memory> ++ ++#include "ui/aura/aura_export.h" ++#include "ui/aura/window_tree_host.h" ++ ++namespace aura { ++ ++class Window; ++class WindowTreeHostPlatform; ++ ++class AURA_EXPORT WindowTreeHostPlatformAgl : public aura::WindowTreeHost { ++ public: ++ explicit WindowTreeHostPlatformAgl( ++ std::unique_ptr<Window> window, ++ aura::WindowTreeHostPlatform* window_tree_host_platform); ++ WindowTreeHostPlatformAgl(const WindowTreeHostPlatformAgl&) = delete; ++ WindowTreeHostPlatformAgl& operator=(const WindowTreeHostPlatformAgl&) = delete; ++ ~WindowTreeHostPlatformAgl() override = default; ++ ++ void SetAglActivateApp(const std::string& app) override; ++ void SetAglAppId(const std::string& title) override; ++ void SetAglReady() override; ++ void SetAglBackground() override; ++ void SetAglPanel(uint32_t edge) override; ++ ++ private: ++ aura::WindowTreeHostPlatform* window_tree_host_platform_; ++}; ++ ++} // namespace aura ++ ++#endif // UI_AURA_AGL_WINDOW_TREE_HOST_PLATFORM_AGL_H_ +diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h +index b4b6e7022ea34..afb37a3a3ed13 100644 +--- a/ui/aura/window_tree_host.h ++++ b/ui/aura/window_tree_host.h +@@ -30,6 +30,8 @@ + #include "ui/gfx/native_widget_types.h" + #include "ui/gfx/overlay_transform.h" + ++#include "ui/aura/agl/window_tree_host_agl.h" ++ + namespace gfx { + class Point; + class Rect; +@@ -66,7 +68,8 @@ class WindowTreeHostObserver; + class AURA_EXPORT WindowTreeHost : public ui::ImeKeyEventDispatcher, + public ui::EventSource, + public display::DisplayObserver, +- public ui::CompositorObserver { ++ public ui::CompositorObserver, ++ public WindowTreeHostAgl { + public: + // VideoCaptureLock ensures state necessary for capturing video remains in + // effect. For example, this may force keeping the compositor visible when +diff --git a/ui/aura/window_tree_host_platform.cc b/ui/aura/window_tree_host_platform.cc +index fd4a560f6cdd1..33b9e892c0212 100644 +--- a/ui/aura/window_tree_host_platform.cc ++++ b/ui/aura/window_tree_host_platform.cc +@@ -52,7 +52,7 @@ std::unique_ptr<WindowTreeHost> WindowTreeHost::Create( + WindowTreeHostPlatform::WindowTreeHostPlatform( + ui::PlatformWindowInitProperties properties, + std::unique_ptr<Window> window) +- : WindowTreeHost(std::move(window)) { ++ : WindowTreeHostPlatformAgl(std::move(window), this) { + size_in_pixels_ = properties.bounds.size(); + CreateCompositor(false, false, properties.enable_compositing_based_throttling, + properties.compositor_memory_limit_mb); +@@ -60,7 +60,7 @@ WindowTreeHostPlatform::WindowTreeHostPlatform( + } + + WindowTreeHostPlatform::WindowTreeHostPlatform(std::unique_ptr<Window> window) +- : WindowTreeHost(std::move(window)), ++ : WindowTreeHostPlatformAgl(std::move(window), this), + widget_(gfx::kNullAcceleratedWidget), + current_cursor_(ui::mojom::CursorType::kNull) {} + +diff --git a/ui/aura/window_tree_host_platform.h b/ui/aura/window_tree_host_platform.h +index 92ae0f0229e70..9c3f742c30ad3 100644 +--- a/ui/aura/window_tree_host_platform.h ++++ b/ui/aura/window_tree_host_platform.h +@@ -15,6 +15,8 @@ + #include "ui/gfx/native_widget_types.h" + #include "ui/platform_window/platform_window_delegate.h" + ++#include "ui/aura/agl/window_tree_host_platform_agl.h" ++ + namespace ui { + enum class DomCode; + class PlatformWindow; +@@ -26,7 +28,7 @@ namespace aura { + + // The unified WindowTreeHost implementation for platforms + // that implement PlatformWindow. +-class AURA_EXPORT WindowTreeHostPlatform : public WindowTreeHost, ++class AURA_EXPORT WindowTreeHostPlatform : public WindowTreeHostPlatformAgl, + public ui::PlatformWindowDelegate { + public: + explicit WindowTreeHostPlatform(ui::PlatformWindowInitProperties properties, +diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn +index 8a436de0fafe3..754cb123043a9 100644 +--- a/ui/ozone/platform/wayland/BUILD.gn ++++ b/ui/ozone/platform/wayland/BUILD.gn +@@ -400,7 +400,6 @@ source_set("wayland") { + + sources += [ + "host/wayland_extensions.h", +- "host/wayland_extensions_stub.cc", + ] + + deps += [ "extensions/agl" ] +diff --git a/ui/ozone/platform/wayland/extensions/agl/BUILD.gn b/ui/ozone/platform/wayland/extensions/agl/BUILD.gn +index ce289bc5dbbca..01c590e53df58 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/BUILD.gn ++++ b/ui/ozone/platform/wayland/extensions/agl/BUILD.gn +@@ -31,6 +31,8 @@ source_set("agl") { + "host/wayland_extensions_agl.h", + "host/wayland_extensions_agl_impl.cc", + "host/wayland_extensions_agl_impl.h", ++ "host/wayland_window_agl.cc", ++ "host/wayland_window_agl.h", + ] + + deps = [ +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h +index df42fc00c84da..295154dfb437d 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h +@@ -20,6 +20,9 @@ + namespace ui { + + class AglShellWrapper; ++class PlatformWindowDelegate; ++class WaylandConnection; ++class WaylandWindow; + + // AGL extensions implementation for webOS/Lite + class WaylandExtensionsAgl { +@@ -29,9 +32,14 @@ class WaylandExtensionsAgl { + WaylandExtensionsAgl& operator=(const WaylandExtensionsAgl&) = delete; + virtual ~WaylandExtensionsAgl() = default; + ++ virtual std::unique_ptr<WaylandWindow> CreateWaylandWindow( ++ PlatformWindowDelegate* delegate, ++ WaylandConnection* connection) = 0; ++ ++ + virtual AglShellWrapper* GetAglShell() = 0; + }; + + } // namespace ui + +-#endif // UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_EXTENSIONS_AGL_H_ +\ No newline at end of file ++#endif // UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_EXTENSIONS_AGL_H_ +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc +index 26a5f0550c302..87376cbb8a9d3 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc +@@ -22,6 +22,7 @@ + #include "base/logging.h" + #include "ui/base/ui_base_switches.h" + #include "ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h" ++#include "ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h" + #include "ui/ozone/platform/wayland/extensions/agl/common/wayland_object_agl.h" + #include "ui/ozone/platform/wayland/host/wayland_connection.h" + +@@ -68,8 +69,8 @@ bool WaylandExtensionsAglImpl::Bind(wl_registry* registry, + agl_shell_ = + std::make_unique<AglShellWrapper>(aglshell.release(), connection_); + +- LOG(INFO) << "Waiting until bound..."; +- return agl_shell_->WaitUntilBoundOk(); ++ //LOG(INFO) << "Waiting until bound..."; ++ //return agl_shell_->WaitUntilBoundOk(); + } else { + LOG(INFO) << "Cant bind."; + } +@@ -85,6 +86,12 @@ AglShellWrapper* WaylandExtensionsAglImpl::GetAglShell() { + return agl_shell_.get(); + } + ++std::unique_ptr<WaylandWindow> WaylandExtensionsAglImpl::CreateWaylandWindow( ++ PlatformWindowDelegate* delegate, ++ WaylandConnection* connection) { ++ return std::make_unique<WaylandWindowAgl>(delegate, connection, this); ++} ++ + std::unique_ptr<WaylandExtensions> CreateWaylandExtensions( + WaylandConnection* connection) { + return std::make_unique<WaylandExtensionsAglImpl>(connection); +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.h b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.h +index f6cbabe99ed0b..3218589f1a09a 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.h ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.h +@@ -17,12 +17,17 @@ + #ifndef UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_EXTENSIONS_AGL_IMPL_H_ + #define UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_EXTENSIONS_AGL_IMPL_H_ + ++#include <memory> ++ + #include "ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h" + #include "ui/ozone/platform/wayland/host/wayland_extensions.h" + + namespace ui { + + class AglShellWrapper; ++class PlatformWindowDelegate; ++class WaylandConnection; ++class WaylandWindow; + + // AGL extension implementation for webOS/Lite + class WaylandExtensionsAglImpl : public WaylandExtensions, +@@ -44,6 +49,10 @@ class WaylandExtensionsAglImpl : public WaylandExtensions, + // WaylandExtensionsAgl overrides + AglShellWrapper* GetAglShell() override; + ++ std::unique_ptr<WaylandWindow> CreateWaylandWindow( ++ PlatformWindowDelegate* delegate, ++ WaylandConnection* connection) override; ++ + private: + std::unique_ptr<AglShellWrapper> agl_shell_; + WaylandConnection* connection_; +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.cc b/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.cc +new file mode 100644 +index 0000000000000..97b21ae537658 +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.cc +@@ -0,0 +1,86 @@ ++// Copyright 2021 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 "ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h" ++ ++#include "base/logging.h" ++#include "ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h" ++#include "ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl.h" ++#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" ++#include "ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h" ++#include "ui/ozone/platform/wayland/host/wayland_connection.h" ++ ++namespace ui { ++ ++WaylandWindowAgl::WaylandWindowAgl(PlatformWindowDelegate* delegate, ++ WaylandConnection* connection, ++ WaylandExtensionsAgl* agl_extensions) ++ : WaylandToplevelWindow(delegate, connection), ++ agl_extensions_(agl_extensions) {} ++ ++WaylandWindowAgl::~WaylandWindowAgl() = default; ++ ++void WaylandWindowAgl::SetAglActivateApp(const std::string& app) { ++ if (!agl_extensions_->GetAglShell()) { ++ LOG(ERROR) << "Agl shell wrapper is not created"; ++ return; ++ } ++ ++ agl_extensions_->GetAglShell()->SetAglActivateApp(app); ++ connection()->ScheduleFlush(); ++} ++ ++void WaylandWindowAgl::SetAglAppId(const std::string& title) { ++ if (!shell_toplevel()) { ++ LOG(ERROR) << "Shell toplevel is not created"; ++ return; ++ } ++ ++ shell_toplevel()->SetAppId(title); ++ connection()->ScheduleFlush(); ++} ++ ++void WaylandWindowAgl::SetAglReady() { ++ if (!agl_extensions_->GetAglShell()) { ++ LOG(ERROR) << "Agl shell wrapper is not created"; ++ return; ++ } ++ ++ agl_extensions_->GetAglShell()->SetAglReady(); ++ connection()->ScheduleFlush(); ++} ++ ++void WaylandWindowAgl::SetAglBackground() { ++ if (!agl_extensions_->GetAglShell()) { ++ LOG(ERROR) << "Agl shell wrapper is not created"; ++ return; ++ } ++ ++ agl_extensions_->GetAglShell()->SetAglBackground(this); ++ connection()->ScheduleFlush(); ++} ++ ++void WaylandWindowAgl::SetAglPanel(uint32_t edge) { ++ if (!agl_extensions_->GetAglShell()) { ++ LOG(ERROR) << "Agl shell wrapper is not created"; ++ return; ++ } ++ ++ agl_extensions_->GetAglShell()->SetAglPanel(this, edge); ++ connection()->ScheduleFlush(); ++} ++ ++} // namespace ui +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h b/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h +new file mode 100644 +index 0000000000000..b2a922604c001 +--- /dev/null ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h +@@ -0,0 +1,49 @@ ++// Copyright 2021 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 UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_WINDOW_AGL_H_ ++#define UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_WINDOW_AGL_H_ ++ ++#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h" ++ ++namespace ui { ++ ++class WaylandExtensionsAgl; ++ ++class WaylandWindowAgl : public WaylandToplevelWindow { ++ public: ++ explicit WaylandWindowAgl(PlatformWindowDelegate* delegate, ++ WaylandConnection* connection, ++ WaylandExtensionsAgl* agl_extensions); ++ WaylandWindowAgl(const WaylandWindowAgl&) = delete; ++ WaylandWindowAgl& operator=(const WaylandWindowAgl&) = delete; ++ ~WaylandWindowAgl() override; ++ ++ // Overrides PlatformWindowAgl ++ void SetAglActivateApp(const std::string& app) override; ++ void SetAglAppId(const std::string& title) override; ++ void SetAglReady() override; ++ void SetAglBackground() override; ++ void SetAglPanel(uint32_t edge) override; ++ ++ private: ++ WaylandExtensionsAgl* agl_extensions_; ++}; ++ ++} // namespace ui ++ ++#endif // UI_OZONE_PLATFORM_WAYLAND_EXTENSIONS_AGL_HOST_WAYLAND_WINDOW_AGL_H_ +diff --git a/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc b/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc +index 1cda8aa671ddb..220f759ff30a1 100644 +--- a/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc ++++ b/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc +@@ -90,7 +90,14 @@ gfx::SwapResult GLSurfaceWayland::SwapBuffers(PresentationCallback callback, + return scoped_swap_buffers.result(); + } + window_->root_surface()->set_surface_buffer_scale(scale_factor_); +- return gl::NativeViewGLSurfaceEGL::SwapBuffers(std::move(callback), data); ++ ++ gfx::SwapResult result = gl::NativeViewGLSurfaceEGL::SwapBuffers(std::move(callback), data); ++ ++ if (window_) { ++ window_->OnSurfaceContentChanged(); ++ } ++ ++ return result; + } + + gfx::SwapResult GLSurfaceWayland::PostSubBuffer(int x, +diff --git a/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc b/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc +index c62dd62be4fbf..2959593cfeb5b 100644 +--- a/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc ++++ b/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc +@@ -32,7 +32,7 @@ void GtkPrimarySelectionDevice::SetSelectionSource( + auto* data_source = source ? source->data_source() : nullptr; + gtk_primary_selection_device_set_selection(data_device_.get(), data_source, + serial); +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + + // static +diff --git a/ui/ozone/platform/wayland/host/gtk_primary_selection_device_manager.cc b/ui/ozone/platform/wayland/host/gtk_primary_selection_device_manager.cc +index 2c39409808128..1e07ae6009776 100644 +--- a/ui/ozone/platform/wayland/host/gtk_primary_selection_device_manager.cc ++++ b/ui/ozone/platform/wayland/host/gtk_primary_selection_device_manager.cc +@@ -66,7 +66,7 @@ GtkPrimarySelectionDevice* GtkPrimarySelectionDeviceManager::GetDevice() { + connection_, + gtk_primary_selection_device_manager_get_device( + device_manager_.get(), connection_->seat()->wl_object())); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + DCHECK(device_); + return device_.get(); +@@ -77,7 +77,7 @@ GtkPrimarySelectionDeviceManager::CreateSource( + GtkPrimarySelectionSource::Delegate* delegate) { + auto* data_source = + gtk_primary_selection_device_manager_create_source(device_manager_.get()); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + return std::make_unique<GtkPrimarySelectionSource>(data_source, connection_, + delegate); + } +diff --git a/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc b/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc +index f2407d1c306ec..7a7868ded8a52 100644 +--- a/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc ++++ b/ui/ozone/platform/wayland/host/proxy/wayland_proxy_impl.cc +@@ -69,7 +69,7 @@ void WaylandProxyImpl::DestroyShmForWlBuffer(wl_buffer* buffer) { + } + + void WaylandProxyImpl::FlushForTesting() { +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + ui::PlatformWindowType WaylandProxyImpl::GetWindowType( +diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc +index 7a47d4a636998..8d9e8eea6fd79 100644 +--- a/ui/ozone/platform/wayland/host/wayland_connection.cc ++++ b/ui/ozone/platform/wayland/host/wayland_connection.cc +@@ -264,6 +264,20 @@ bool WaylandConnection::Initialize(bool use_threaded_polling) { + return true; + } + ++void WaylandConnection::ScheduleFlush() { ++ // When we are in tests, the message loop is set later when the ++ // initialization of the OzonePlatform complete. Thus, just ++ // flush directly. This doesn't happen in normal run. ++ if (!base::CurrentUIThread::IsSet()) { ++ Flush(); ++ } else if (!scheduled_flush_) { ++ base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( ++ FROM_HERE, ++ base::BindOnce(&WaylandConnection::Flush, base::Unretained(this))); ++ scheduled_flush_ = true; ++ } ++} ++ + void WaylandConnection::RoundTripQueue() { + if (roundtrip_closure_for_testing_) { + roundtrip_closure_for_testing_.Run(); +@@ -333,6 +347,7 @@ void WaylandConnection::RegisterGlobalObjectFactory( + + void WaylandConnection::Flush() { + wl_display_flush(display_.get()); ++ scheduled_flush_ = false; + } + + void WaylandConnection::UpdateInputDevices() { +@@ -526,7 +541,7 @@ void WaylandConnection::OnPing(void* data, + uint32_t serial) { + auto* connection = static_cast<WaylandConnection*>(data); + xdg_wm_base_pong(shell, serial); +- connection->Flush(); ++ connection->ScheduleFlush(); + } + + // static +@@ -707,7 +722,7 @@ void WaylandConnection::HandleGlobal(wl_registry* registry, + } + + available_globals_.emplace_back(interface, version); +- Flush(); ++ ScheduleFlush(); + } + + } // namespace ui +diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h +index ba293e5bcd088..641f36f13db35 100644 +--- a/ui/ozone/platform/wayland/host/wayland_connection.h ++++ b/ui/ozone/platform/wayland/host/wayland_connection.h +@@ -100,8 +100,8 @@ class WaylandConnection { + + bool Initialize(bool use_threaded_polling = false); + +- // Immediately flushes the Wayland display. +- void Flush(); ++ // Schedules a flush of the Wayland connection. ++ void ScheduleFlush(); + + // Calls wl_display_roundtrip_queue. Might be required during initialization + // of some objects that should block until they are initialized. +@@ -388,6 +388,9 @@ class WaylandConnection { + friend class ZwpIdleInhibitManager; + friend class ZwpPrimarySelectionDeviceManager; + ++ // Immediately flushes the Wayland display. ++ void Flush(); ++ + void RegisterGlobalObjectFactory(const char* interface_name, + wl::GlobalObjectFactory factory); + +@@ -535,6 +538,8 @@ class WaylandConnection { + // This is set if delegated composition should not be used. + bool overlay_delegation_disabled_ = false; + ++ bool scheduled_flush_ = false; ++ + wl::SerialTracker serial_tracker_; + + // Global Wayland interfaces available in the current session, with their +diff --git a/ui/ozone/platform/wayland/host/wayland_cursor.cc b/ui/ozone/platform/wayland/host/wayland_cursor.cc +index 1b7d303291cff..a384212c84134 100644 +--- a/ui/ozone/platform/wayland/host/wayland_cursor.cc ++++ b/ui/ozone/platform/wayland/host/wayland_cursor.cc +@@ -107,7 +107,7 @@ void WaylandCursor::HideCursor() { + wl_surface_attach(pointer_surface_.get(), nullptr, 0, 0); + wl_surface_commit(pointer_surface_.get()); + +- connection_->Flush(); ++ connection_->ScheduleFlush(); + + if (listener_) + listener_->OnCursorBufferAttached(nullptr); +@@ -166,7 +166,7 @@ void WaylandCursor::AttachAndCommit(wl_buffer* buffer, + wl_pointer_set_cursor(pointer_->wl_object(), pointer_enter_serial->value, + pointer_surface_.get(), hotspot_x_dip, hotspot_y_dip); + +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + } // namespace ui +diff --git a/ui/ozone/platform/wayland/host/wayland_data_device.cc b/ui/ozone/platform/wayland/host/wayland_data_device.cc +index a7adfd313188b..fe16d8577fd35 100644 +--- a/ui/ozone/platform/wayland/host/wayland_data_device.cc ++++ b/ui/ozone/platform/wayland/host/wayland_data_device.cc +@@ -51,7 +51,7 @@ void WaylandDataDevice::StartDrag(const WaylandDataSource& data_source, + origin_window.root_surface()->surface(), + icon_surface, serial); + drag_delegate_->DrawIcon(); +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + + void WaylandDataDevice::ResetDragDelegate() { +@@ -92,7 +92,7 @@ void WaylandDataDevice::SetSelectionSource(WaylandDataSource* source, + uint32_t serial) { + auto* data_source = source ? source->data_source() : nullptr; + wl_data_device_set_selection(data_device_.get(), data_source, serial); +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + + void WaylandDataDevice::ReadDragDataFromFD(base::ScopedFD fd, +@@ -146,7 +146,7 @@ void WaylandDataDevice::OnEnter(void* data, + gfx::PointF(wl_fixed_to_double(x), wl_fixed_to_double(y)), window); + self->drag_delegate_->OnDragEnter(window, point, serial); + +- self->connection()->Flush(); ++ self->connection()->ScheduleFlush(); + } + + void WaylandDataDevice::OnMotion(void* data, +@@ -167,7 +167,7 @@ void WaylandDataDevice::OnDrop(void* data, wl_data_device* data_device) { + auto* self = static_cast<WaylandDataDevice*>(data); + if (self->drag_delegate_) { + self->drag_delegate_->OnDragDrop(); +- self->connection()->Flush(); ++ self->connection()->ScheduleFlush(); + } + + // There are buggy Exo versions, which send 'drop' event (even for +@@ -184,7 +184,7 @@ void WaylandDataDevice::OnLeave(void* data, wl_data_device* data_device) { + auto* self = static_cast<WaylandDataDevice*>(data); + if (self->drag_delegate_) { + self->drag_delegate_->OnDragLeave(); +- self->connection()->Flush(); ++ self->connection()->ScheduleFlush(); + } + self->ResetDragDelegateIfNotDragSource(); + } +diff --git a/ui/ozone/platform/wayland/host/wayland_data_device_base.cc b/ui/ozone/platform/wayland/host/wayland_data_device_base.cc +index 203e907f92bfa..a0c72971ac567 100644 +--- a/ui/ozone/platform/wayland/host/wayland_data_device_base.cc ++++ b/ui/ozone/platform/wayland/host/wayland_data_device_base.cc +@@ -64,7 +64,7 @@ void WaylandDataDeviceBase::RegisterDeferredReadCallback() { + static constexpr wl_callback_listener kSyncCallbackListener = { + .done = &OnSyncDone}; + wl_callback_add_listener(sync_callback_.get(), &kSyncCallbackListener, this); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + void WaylandDataDeviceBase::RegisterDeferredReadClosure( +diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc +index 705bdec41a1b7..dfa5789e8d149 100644 +--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc ++++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc +@@ -256,7 +256,7 @@ void WaylandDataDragController::OnDragSurfaceFrame(void* data, + DCHECK(self); + self->DrawIconInternal(); + self->icon_frame_callback_.reset(); +- self->connection_->Flush(); ++ self->connection_->ScheduleFlush(); + } + + SkBitmap WaylandDataDragController::GetIconBitmap() { +diff --git a/ui/ozone/platform/wayland/host/wayland_data_source.cc b/ui/ozone/platform/wayland/host/wayland_data_source.cc +index c0e95c8a22e48..c294ffb8836aa 100644 +--- a/ui/ozone/platform/wayland/host/wayland_data_source.cc ++++ b/ui/ozone/platform/wayland/host/wayland_data_source.cc +@@ -130,7 +130,7 @@ void DataSource<wl_data_source>::Offer( + const std::vector<std::string>& mime_types) { + for (auto& mime_type : mime_types) + wl_data_source_offer(data_source_.get(), mime_type.c_str()); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + template <typename T> +@@ -165,7 +165,7 @@ void DataSource<gtk_primary_selection_source>::Offer( + const std::vector<std::string>& mime_types) { + for (const auto& mime_type : mime_types) + gtk_primary_selection_source_offer(data_source_.get(), mime_type.c_str()); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + template <> +@@ -185,7 +185,7 @@ void DataSource<zwp_primary_selection_source_v1>::Offer( + for (const auto& mime_type : mime_types) + zwp_primary_selection_source_v1_offer(data_source_.get(), + mime_type.c_str()); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + template class DataSource<gtk_primary_selection_source>; +diff --git a/ui/ozone/platform/wayland/host/wayland_drm.cc b/ui/ozone/platform/wayland/host/wayland_drm.cc +index 68570a9aacb2c..2b3b16e8859cb 100644 +--- a/ui/ozone/platform/wayland/host/wayland_drm.cc ++++ b/ui/ozone/platform/wayland/host/wayland_drm.cc +@@ -58,7 +58,7 @@ WaylandDrm::WaylandDrm(wl_drm* drm, WaylandConnection* connection) + .capabilities = &OnCapabilities, + }; + wl_drm_add_listener(wl_drm_.get(), &kDrmListener, this); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + + // A roundtrip after binding guarantees that the client has received all + // supported formats and capabilities of the device. +@@ -92,7 +92,7 @@ void WaylandDrm::CreateBuffer(const base::ScopedFD& fd, + wl::Object<wl_buffer> buffer(wl_drm_create_prime_buffer( + wl_drm_.get(), fd.get(), size.width(), size.height(), format, offset[0], + stride[0], offset[1], stride[1], offset[2], stride[2])); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + + std::move(callback).Run(std::move(buffer)); + } +@@ -146,7 +146,7 @@ void WaylandDrm::Authenticate(const char* drm_device_path) { + } + + wl_drm_authenticate(wl_drm_.get(), magic); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + + // Do the roundtrip to make sure the server processes this request and + // authenticates us. +diff --git a/ui/ozone/platform/wayland/host/wayland_extensions.h b/ui/ozone/platform/wayland/host/wayland_extensions.h +index 3bd2fd7a211ae..f6ed47507d217 100644 +--- a/ui/ozone/platform/wayland/host/wayland_extensions.h ++++ b/ui/ozone/platform/wayland/host/wayland_extensions.h +@@ -25,7 +25,9 @@ namespace ui { + + class ShellToplevelWrapper; + class ShellPopupWrapper; ++class PlatformWindowDelegate; + class WaylandConnection; ++class WaylandWindow; + + // Wayland extensions abstract interface to support extending of the Wayland + // protocol. Inherit it to provide your own Wayland extensions implementation. +@@ -45,6 +47,10 @@ class WaylandExtensions { + + // Checks whether the extensions have bound shell object(s). + virtual bool HasShellObject() const = 0; ++ ++ virtual std::unique_ptr<WaylandWindow> CreateWaylandWindow( ++ PlatformWindowDelegate* delegate, ++ WaylandConnection* connection) = 0; + }; + + // Creates Wayland extensions. +diff --git a/ui/ozone/platform/wayland/host/wayland_keyboard.cc b/ui/ozone/platform/wayland/host/wayland_keyboard.cc +index 2b7fc05d426e1..f24d6993b26ac 100644 +--- a/ui/ozone/platform/wayland/host/wayland_keyboard.cc ++++ b/ui/ozone/platform/wayland/host/wayland_keyboard.cc +@@ -114,7 +114,7 @@ class WaylandKeyboard::ZCRExtendedKeyboard { + + void AckKey(uint32_t serial, bool handled) { + zcr_extended_keyboard_v1_ack_key(obj_.get(), serial, handled); +- keyboard_->connection_->Flush(); ++ keyboard_->connection_->ScheduleFlush(); + } + + // Returns true if connected object will send zcr_extended_keyboard::peek_key. +@@ -373,7 +373,7 @@ void WaylandKeyboard::FlushInput(base::OnceClosure closure) { + .done = &OnSyncDone, + }; + wl_callback_add_listener(sync_callback_.get(), &kSyncCallbackListener, this); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + void WaylandKeyboard::DispatchKey(unsigned int key, +diff --git a/ui/ozone/platform/wayland/host/wayland_popup.cc b/ui/ozone/platform/wayland/host/wayland_popup.cc +index f1e886f8675fb..28903c031e6ce 100644 +--- a/ui/ozone/platform/wayland/host/wayland_popup.cc ++++ b/ui/ozone/platform/wayland/host/wayland_popup.cc +@@ -132,7 +132,7 @@ void WaylandPopup::Show(bool inactive) { + return; + } + +- connection()->Flush(); ++ connection()->ScheduleFlush(); + WaylandWindow::Show(inactive); + } + +@@ -158,7 +158,7 @@ void WaylandPopup::Hide() { + decorated_via_aura_popup_ = false; + } + +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + + bool WaylandPopup::IsVisible() const { +@@ -256,14 +256,14 @@ void WaylandPopup::ShowTooltip(const std::u16string& text, + if (zaura_surface && + zaura_surface->ShowTooltip(text, position, zaura_shell_trigger, + show_delay, hide_delay)) { +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + } + + void WaylandPopup::HideTooltip() { + auto* zaura_surface = GetZAuraSurface(); + if (zaura_surface && zaura_surface->HideTooltip()) { +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + } + +diff --git a/ui/ozone/platform/wayland/host/wayland_seat.cc b/ui/ozone/platform/wayland/host/wayland_seat.cc +index 3b05da49eb6b8..5f70725a9a9dd 100644 +--- a/ui/ozone/platform/wayland/host/wayland_seat.cc ++++ b/ui/ozone/platform/wayland/host/wayland_seat.cc +@@ -128,7 +128,7 @@ void WaylandSeat::HandleCapabilities(void* data, + + connection_->UpdateInputDevices(); + connection_->UpdateCursor(); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + } // namespace ui +diff --git a/ui/ozone/platform/wayland/host/wayland_shm.cc b/ui/ozone/platform/wayland/host/wayland_shm.cc +index b264ad88962bb..95c19d9962085 100644 +--- a/ui/ozone/platform/wayland/host/wayland_shm.cc ++++ b/ui/ozone/platform/wayland/host/wayland_shm.cc +@@ -62,7 +62,7 @@ wl::Object<wl_buffer> WaylandShm::CreateBuffer(const base::ScopedFD& fd, + with_alpha_channel ? WL_SHM_FORMAT_ARGB8888 : WL_SHM_FORMAT_XRGB8888; + wl::Object<wl_buffer> shm_buffer(wl_shm_pool_create_buffer( + pool.get(), 0, size.width(), size.height(), size.width() * 4, format)); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + return shm_buffer; + } + +diff --git a/ui/ozone/platform/wayland/host/wayland_surface.cc b/ui/ozone/platform/wayland/host/wayland_surface.cc +index 47dc846390898..2a04d28b05484 100644 +--- a/ui/ozone/platform/wayland/host/wayland_surface.cc ++++ b/ui/ozone/platform/wayland/host/wayland_surface.cc +@@ -305,7 +305,7 @@ void WaylandSurface::UpdateBufferDamageRegion(const gfx::Rect& damage_px) { + void WaylandSurface::Commit(bool flush) { + wl_surface_commit(surface_.get()); + if (flush) +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + void WaylandSurface::set_surface_buffer_scale(float scale) { +diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc +index 898113178a783..1b489b327fa29 100644 +--- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc ++++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc +@@ -127,7 +127,7 @@ void WaylandToplevelWindow::DispatchHostWindowDragMovement( + else + shell_toplevel_->SurfaceResize(connection(), hittest); + +- connection()->Flush(); ++ connection()->ScheduleFlush(); + #if !BUILDFLAG(IS_CHROMEOS_LACROS) + // TODO(crbug.com/1454893): Revisit to resolve the correct impl. + connection()->event_source()->ResetPointerFlags(); +@@ -176,7 +176,7 @@ void WaylandToplevelWindow::Hide() { + gtk_surface1_.reset(); + + shell_toplevel_.reset(); +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + + bool WaylandToplevelWindow::IsVisible() const { +@@ -193,7 +193,7 @@ void WaylandToplevelWindow::SetTitle(const std::u16string& title) { + + if (shell_toplevel_) { + shell_toplevel_->SetTitle(title); +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + } + +@@ -288,13 +288,13 @@ void WaylandToplevelWindow::Activate() { + // but nothing more happens (until the user moves the mouse over a Lacros + // window in which case events will start and the activation will come + // through). +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + + void WaylandToplevelWindow::Deactivate() { + if (shell_toplevel_ && shell_toplevel_->SupportsActivation()) { + shell_toplevel_->Deactivate(); +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + } + +@@ -722,14 +722,14 @@ void WaylandToplevelWindow::ShowTooltip( + if (zaura_surface && + zaura_surface->ShowTooltip(text, position, zaura_shell_trigger, + show_delay, hide_delay)) { +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + } + + void WaylandToplevelWindow::HideTooltip() { + auto* zaura_surface = GetZAuraSurface(); + if (zaura_surface && zaura_surface->HideTooltip()) { +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + } + +@@ -1001,7 +1001,7 @@ void WaylandToplevelWindow::TriggerStateChanges() { + } + + delegate()->OnWindowStateChanged(previous_state_, state_); +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + + void WaylandToplevelWindow::SetWindowState(PlatformWindowState state) { +@@ -1035,7 +1035,7 @@ void WaylandToplevelWindow::SetSizeConstraints() { + shell_toplevel_->SetCanMaximize(delegate()->CanMaximize()); + shell_toplevel_->SetCanFullscreen(delegate()->CanFullscreen()); + +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + + void WaylandToplevelWindow::SetOrResetRestoredBounds() { +diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc +index ad4366edfe4db..9a18c567bcbcc 100644 +--- a/ui/ozone/platform/wayland/host/wayland_window.cc ++++ b/ui/ozone/platform/wayland/host/wayland_window.cc +@@ -686,6 +686,10 @@ std::string WaylandWindow::WindowStates::ToString() const { + return states; + } + ++void WaylandWindow::OnSurfaceContentChanged() { ++ connection_->ScheduleFlush(); ++} ++ + void WaylandWindow::HandleToplevelConfigure(int32_t widht, + int32_t height, + const WindowStates& window_states) { +@@ -832,7 +836,7 @@ bool WaylandWindow::Initialize(PlatformWindowInitProperties properties) { + root_surface_->EnableTrustedDamageIfPossible(); + root_surface_->ApplyPendingState(); + +- connection_->Flush(); ++ connection_->ScheduleFlush(); + + return true; + } +diff --git a/ui/ozone/platform/wayland/host/wayland_window.h b/ui/ozone/platform/wayland/host/wayland_window.h +index d68d4d818f28f..2c5afbb3de99c 100644 +--- a/ui/ozone/platform/wayland/host/wayland_window.h ++++ b/ui/ozone/platform/wayland/host/wayland_window.h +@@ -230,6 +230,8 @@ class WaylandWindow : public PlatformWindow, + // currently bound to. + virtual void HandleSurfaceConfigure(uint32_t serial); + ++ void OnSurfaceContentChanged(); ++ + struct WindowStates { + bool is_maximized = false; + bool is_fullscreen = false; +diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc +index e38565635a583..ff201c038efb7 100644 +--- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc ++++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc +@@ -91,7 +91,7 @@ class WaylandWindowDragController::ExtendedDragSource { + auto* surface = window ? window->root_surface()->surface() : nullptr; + zcr_extended_drag_source_v1_drag(source_.get(), surface, offset.x(), + offset.y()); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + private: +diff --git a/ui/ozone/platform/wayland/host/wayland_window_factory.cc b/ui/ozone/platform/wayland/host/wayland_window_factory.cc +index 6f66c6654819c..e2bc045e4b3fb 100644 +--- a/ui/ozone/platform/wayland/host/wayland_window_factory.cc ++++ b/ui/ozone/platform/wayland/host/wayland_window_factory.cc +@@ -12,6 +12,8 @@ + #include "ui/ozone/platform/wayland/host/wayland_window.h" + #include "ui/platform_window/platform_window_init_properties.h" + ++#include "ui/ozone/platform/wayland/host/wayland_extensions.h" ++ + namespace ui { + + // static +@@ -29,6 +31,12 @@ std::unique_ptr<WaylandWindow> WaylandWindow::Create( + // toplevel window instead. + if (auto* parent = connection->window_manager()->GetWindow( + properties.parent_widget)) { ++ if (connection->extensions()) { ++ window = connection->extensions()->CreateWaylandWindow(delegate, ++ connection); ++ if (window) ++ break; ++ } + window = std::make_unique<WaylandPopup>(delegate, connection, parent); + } else { + DLOG(WARNING) << "Failed to determine parent for menu/popup window."; +@@ -40,6 +48,12 @@ std::unique_ptr<WaylandWindow> WaylandWindow::Create( + case PlatformWindowType::kDrag: + // TODO(crbug.com/1399419): Figure out what kind of surface we need to + // create for kBubble and kDrag windows. ++ if (connection->extensions()) { ++ window = ++ connection->extensions()->CreateWaylandWindow(delegate, connection); ++ if (window) ++ break; ++ } + window = std::make_unique<WaylandToplevelWindow>(delegate, connection); + break; + default: +diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc +index 33935db68eadd..15f600ed7a126 100644 +--- a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc ++++ b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc +@@ -104,7 +104,7 @@ void WaylandZwpLinuxDmabuf::CreateBuffer(const base::ScopedFD& fd, + // created buffer and notify the client about it via the |callback|. + pending_params_.emplace(std::move(params), std::move(callback)); + } +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + bool WaylandZwpLinuxDmabuf::CanCreateBufferImmed() const { +@@ -147,7 +147,7 @@ void WaylandZwpLinuxDmabuf::NotifyRequestCreateBufferDone( + DCHECK(it != pending_params_.end()); + std::move(it->second).Run(wl::Object<wl_buffer>(new_buffer)); + pending_params_.erase(it); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + // static +diff --git a/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc b/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc +index 293c09a7e35f2..d36db127ec057 100644 +--- a/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc ++++ b/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc +@@ -158,7 +158,7 @@ void XdgForeignWrapperImpl<zxdg_exporter_v1, zxdg_exported_v1>:: + &kXdgExportedListener, this); + + exported_surfaces_.emplace_back(std::move(exported_surface)); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + template <> +@@ -174,7 +174,7 @@ void XdgForeignWrapperImpl<zxdg_exporter_v2, zxdg_exported_v2>:: + &kXdgExportedListener, this); + + exported_surfaces_.emplace_back(std::move(exported_surface)); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + // static +diff --git a/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc +index 64c8f2663ae60..b0d8f27aebbf9 100644 +--- a/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc ++++ b/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc +@@ -239,7 +239,7 @@ bool XDGPopupWrapperImpl::SetBounds(const gfx::Rect& new_bounds) { + xdg_popup_reposition(xdg_popup_.get(), positioner.get(), + ++next_reposition_token_); + +- connection_->Flush(); ++ connection_->ScheduleFlush(); + return true; + } + +diff --git a/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc +index c4dd8c8e78ce4..67702ecc8fa4f 100644 +--- a/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc ++++ b/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc +@@ -39,7 +39,7 @@ bool XDGSurfaceWrapperImpl::Initialize() { + }; + xdg_surface_add_listener(xdg_surface_.get(), &kXdgSurfaceListener, this); + +- connection_->Flush(); ++ connection_->ScheduleFlush(); + return true; + } + +diff --git a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc +index 0673c59185348..b9462c60a2eee 100644 +--- a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc ++++ b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc +@@ -720,7 +720,7 @@ void XDGToplevelWrapperImpl::ShowSnapPreview( + + void XDGToplevelWrapperImpl::AckRotateFocus(uint32_t serial, uint32_t handled) { + zaura_toplevel_ack_rotate_focus(aura_toplevel_.get(), serial, handled); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + + XDGToplevelWrapperImpl* XDGToplevelWrapperImpl::AsXDGToplevelWrapper() { +diff --git a/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc b/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc +index 9057d1bea0116..97c1624e200ac 100644 +--- a/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc ++++ b/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc +@@ -32,7 +32,7 @@ void ZwpPrimarySelectionDevice::SetSelectionSource( + auto* data_source = source ? source->data_source() : nullptr; + zwp_primary_selection_device_v1_set_selection(data_device_.get(), data_source, + serial); +- connection()->Flush(); ++ connection()->ScheduleFlush(); + } + + // static +diff --git a/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.cc b/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.cc +index 9d5d79635b66d..2ca82ce6031ba 100644 +--- a/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.cc ++++ b/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.cc +@@ -66,7 +66,7 @@ ZwpPrimarySelectionDevice* ZwpPrimarySelectionDeviceManager::GetDevice() { + connection_, + zwp_primary_selection_device_manager_v1_get_device( + device_manager_.get(), connection_->seat()->wl_object())); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + } + DCHECK(device_); + return device_.get(); +@@ -77,7 +77,7 @@ ZwpPrimarySelectionDeviceManager::CreateSource( + ZwpPrimarySelectionSource::Delegate* delegate) { + auto* data_source = zwp_primary_selection_device_manager_v1_create_source( + device_manager_.get()); +- connection_->Flush(); ++ connection_->ScheduleFlush(); + return std::make_unique<ZwpPrimarySelectionSource>(data_source, connection_, + delegate); + } +diff --git a/ui/platform_window/agl/platform_window_agl.h b/ui/platform_window/agl/platform_window_agl.h +new file mode 100644 +index 0000000000000..4bc915d663e72 +--- /dev/null ++++ b/ui/platform_window/agl/platform_window_agl.h +@@ -0,0 +1,36 @@ ++// Copyright 2021 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 UI_PLATFORM_WINDOW_AGL_PLATFORM_WINDOW_AGL_H_ ++#define UI_PLATFORM_WINDOW_AGL_PLATFORM_WINDOW_AGL_H_ ++ ++#include <string> ++ ++namespace ui { ++ ++// AGL additions for platform window. ++class PlatformWindowAgl { ++ public: ++ virtual void SetAglActivateApp(const std::string& app) {} ++ virtual void SetAglAppId(const std::string& title) {} ++ virtual void SetAglReady() {} ++ virtual void SetAglBackground() {} ++ virtual void SetAglPanel(uint32_t edge) {} ++}; ++ ++} // namespace ui ++ ++#endif // UI_PLATFORM_WINDOW_AGL_PLATFORM_WINDOW_AGL_H_ +diff --git a/ui/platform_window/platform_window.h b/ui/platform_window/platform_window.h +index 845da9467d6a4..a9b28388ec649 100644 +--- a/ui/platform_window/platform_window.h ++++ b/ui/platform_window/platform_window.h +@@ -9,6 +9,7 @@ + #include <string> + #include <vector> + ++#include "agl/platform_window_agl.h" + #include "base/component_export.h" + #include "ui/base/class_property.h" + #include "ui/base/ui_base_types.h" +@@ -32,7 +33,8 @@ class PlatformCursor; + + // Generic PlatformWindow interface. + class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindow +- : public PropertyHandler { ++ : public PropertyHandler, ++ public PlatformWindowAgl { + public: + PlatformWindow(); + ~PlatformWindow() override; +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0003-agl-Only-bind-to-agl_shell-if-it-s-the-browser-proce.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0003-agl-Only-bind-to-agl_shell-if-it-s-the-browser-proce.patch new file mode 100644 index 000000000..4de7779f7 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0003-agl-Only-bind-to-agl_shell-if-it-s-the-browser-proce.patch @@ -0,0 +1,41 @@ +From ab07780e04f15b511967cd609b70fb97abcea96f Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Sat, 27 May 2023 15:55:17 +0200 +Subject: [PATCH 03/33] [agl] Only bind to agl_shell if it's the browser + process + +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + .../extensions/agl/host/wayland_extensions_agl_impl.cc | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc +index 87376cbb8a9d3..075b3010ea8a1 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc +@@ -20,6 +20,7 @@ + + #include "base/command_line.h" + #include "base/logging.h" ++#include "content/public/common/content_switches.h" + #include "ui/base/ui_base_switches.h" + #include "ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h" + #include "ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h" +@@ -45,8 +46,12 @@ bool WaylandExtensionsAglImpl::Bind(wl_registry* registry, + uint32_t name, + const char* interface, + uint32_t version) { +- bool should_use_agl_shell = base::CommandLine::ForCurrentProcess()->HasSwitch( +- switches::kAglShellAppId); ++ bool has_agl_shell_switch = base::CommandLine::ForCurrentProcess()->HasSwitch( ++ switches::kAglShellAppId); ++ bool is_browser_process = !base::CommandLine::ForCurrentProcess()->HasSwitch( ++ switches::kProcessType); ++ bool should_use_agl_shell = has_agl_shell_switch && is_browser_process; ++ + bool can_bind = wl::CanBind(interface, version, kMinAglShellExtensionVersion, + kMaxAglShellExtensionVersion); + bool is_agl_shell_interface = (strcmp(interface, "agl_shell") == 0); +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0004-agl-Add-a-method-to-check-if-the-agl-window-is-confi.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0004-agl-Add-a-method-to-check-if-the-agl-window-is-confi.patch new file mode 100644 index 000000000..398023ca0 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0004-agl-Add-a-method-to-check-if-the-agl-window-is-confi.patch @@ -0,0 +1,69 @@ +From 76cb42f0773ecff97710d7d5ea20cd16b8781d51 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Fri, 30 Jun 2023 10:25:10 +0200 +Subject: [PATCH 04/33] [agl] Add a method to check if the agl window is + configured + +This will be used on cef side to know the time when the window can be +displayed. + +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + ui/aura/agl/window_tree_host_agl.h | 1 + + ui/aura/agl/window_tree_host_platform_agl.cc | 4 ++++ + ui/aura/agl/window_tree_host_platform_agl.h | 1 + + ui/platform_window/agl/platform_window_agl.h | 1 + + 4 files changed, 7 insertions(+) + +diff --git a/ui/aura/agl/window_tree_host_agl.h b/ui/aura/agl/window_tree_host_agl.h +index 858a078d939d0..b9aa451c8332e 100644 +--- a/ui/aura/agl/window_tree_host_agl.h ++++ b/ui/aura/agl/window_tree_host_agl.h +@@ -35,6 +35,7 @@ class AURA_EXPORT WindowTreeHostAgl { + virtual void SetAglReady() {} + virtual void SetAglBackground() {} + virtual void SetAglPanel(uint32_t edge) {} ++ virtual bool IsSurfaceConfigured() const { return false; } + }; + + } // namespace aura +diff --git a/ui/aura/agl/window_tree_host_platform_agl.cc b/ui/aura/agl/window_tree_host_platform_agl.cc +index e34595fe0ed9c..67190e1da6973 100644 +--- a/ui/aura/agl/window_tree_host_platform_agl.cc ++++ b/ui/aura/agl/window_tree_host_platform_agl.cc +@@ -47,4 +47,8 @@ void WindowTreeHostPlatformAgl::SetAglPanel(uint32_t edge) { + window_tree_host_platform_->platform_window()->SetAglPanel(edge); + } + ++bool WindowTreeHostPlatformAgl::IsSurfaceConfigured() const { ++ return window_tree_host_platform_->platform_window()->IsSurfaceConfigured(); ++} ++ + } // namespace aura +diff --git a/ui/aura/agl/window_tree_host_platform_agl.h b/ui/aura/agl/window_tree_host_platform_agl.h +index 181eefae346f7..e5a29fa1bfca3 100644 +--- a/ui/aura/agl/window_tree_host_platform_agl.h ++++ b/ui/aura/agl/window_tree_host_platform_agl.h +@@ -41,6 +41,7 @@ class AURA_EXPORT WindowTreeHostPlatformAgl : public aura::WindowTreeHost { + void SetAglReady() override; + void SetAglBackground() override; + void SetAglPanel(uint32_t edge) override; ++ bool IsSurfaceConfigured() const override; + + private: + aura::WindowTreeHostPlatform* window_tree_host_platform_; +diff --git a/ui/platform_window/agl/platform_window_agl.h b/ui/platform_window/agl/platform_window_agl.h +index 4bc915d663e72..cab1f42272772 100644 +--- a/ui/platform_window/agl/platform_window_agl.h ++++ b/ui/platform_window/agl/platform_window_agl.h +@@ -29,6 +29,7 @@ class PlatformWindowAgl { + virtual void SetAglReady() {} + virtual void SetAglBackground() {} + virtual void SetAglPanel(uint32_t edge) {} ++ virtual bool IsSurfaceConfigured() { return false; } + }; + + } // namespace ui +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0005-agl-Start-using-agl-shell-version-4.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0005-agl-Start-using-agl-shell-version-4.patch new file mode 100644 index 000000000..8b5a38125 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0005-agl-Start-using-agl-shell-version-4.patch @@ -0,0 +1,348 @@ +From 98de96755da14f4cabf2447ce88a01cd3cdca770 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Sun, 2 Jul 2023 11:11:07 +0200 +Subject: [PATCH 05/33] [agl] Start using agl-shell version 4 + +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + ui/aura/agl/window_tree_host_agl.h | 1 + + ui/aura/agl/window_tree_host_platform_agl.cc | 4 + + ui/aura/agl/window_tree_host_platform_agl.h | 1 + + .../extensions/agl/host/agl_shell_wrapper.cc | 9 + + .../extensions/agl/host/agl_shell_wrapper.h | 1 + + .../agl/host/wayland_extensions_agl_impl.cc | 2 +- + .../extensions/agl/host/wayland_window_agl.cc | 10 + + .../extensions/agl/host/wayland_window_agl.h | 1 + + .../extensions/agl/protocol/agl-shell.xml | 185 +++++++++++++++++- + ui/platform_window/agl/platform_window_agl.h | 1 + + 10 files changed, 213 insertions(+), 2 deletions(-) + +diff --git a/ui/aura/agl/window_tree_host_agl.h b/ui/aura/agl/window_tree_host_agl.h +index b9aa451c8332e..c5213f75e623e 100644 +--- a/ui/aura/agl/window_tree_host_agl.h ++++ b/ui/aura/agl/window_tree_host_agl.h +@@ -36,6 +36,7 @@ class AURA_EXPORT WindowTreeHostAgl { + virtual void SetAglBackground() {} + virtual void SetAglPanel(uint32_t edge) {} + virtual bool IsSurfaceConfigured() const { return false; } ++ virtual void SetupActivationArea(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {} + }; + + } // namespace aura +diff --git a/ui/aura/agl/window_tree_host_platform_agl.cc b/ui/aura/agl/window_tree_host_platform_agl.cc +index 67190e1da6973..b9bae3f3b9bdc 100644 +--- a/ui/aura/agl/window_tree_host_platform_agl.cc ++++ b/ui/aura/agl/window_tree_host_platform_agl.cc +@@ -51,4 +51,8 @@ bool WindowTreeHostPlatformAgl::IsSurfaceConfigured() const { + return window_tree_host_platform_->platform_window()->IsSurfaceConfigured(); + } + ++void WindowTreeHostPlatformAgl::SetupActivationArea(uint32_t x, uint32_t y, uint32_t width, uint32_t height) { ++ window_tree_host_platform_->platform_window()->SetupActivationArea(x, y, width, height); ++} ++ + } // namespace aura +diff --git a/ui/aura/agl/window_tree_host_platform_agl.h b/ui/aura/agl/window_tree_host_platform_agl.h +index e5a29fa1bfca3..30e160736e327 100644 +--- a/ui/aura/agl/window_tree_host_platform_agl.h ++++ b/ui/aura/agl/window_tree_host_platform_agl.h +@@ -42,6 +42,7 @@ class AURA_EXPORT WindowTreeHostPlatformAgl : public aura::WindowTreeHost { + void SetAglBackground() override; + void SetAglPanel(uint32_t edge) override; + bool IsSurfaceConfigured() const override; ++ void SetupActivationArea(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; + + private: + aura::WindowTreeHostPlatform* window_tree_host_platform_; +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.cc b/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.cc +index c74fa5d9cd221..0d5d79c4738df 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.cc ++++ b/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.cc +@@ -110,4 +110,13 @@ bool AglShellWrapper::WaitUntilBoundOk() { + return bound_ok_; + } + ++void AglShellWrapper::SetupActivationArea(uint32_t x, uint32_t y, uint32_t width, uint32_t height) { ++#ifdef AGL_SHELL_SET_ACTIVATE_REGION_SINCE_VERSION ++ wl_output* output = ++ connection_->wayland_output_manager()->GetPrimaryOutput()->get_output(); ++ agl_shell_set_activate_region(agl_shell_.get(), output, x, y, ++ width, height); ++#endif ++} ++ + } // namespace ui +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h b/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h +index 2ab765883057e..1c2074e1b4306 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h ++++ b/ui/ozone/platform/wayland/extensions/agl/host/agl_shell_wrapper.h +@@ -39,6 +39,7 @@ class AglShellWrapper { + void SetAglPanel(WaylandWindow* window, uint32_t edge); + void SetAglBackground(WaylandWindow* window); + void SetAglReady(); ++ void SetupActivationArea(uint32_t x, uint32_t y, uint32_t width, uint32_t height); + bool WaitUntilBoundOk(); + + static void AglShellBoundOk(void* data, struct agl_shell*); +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc +index 075b3010ea8a1..8f9d938cdd1f6 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_extensions_agl_impl.cc +@@ -32,7 +32,7 @@ namespace ui { + namespace { + + constexpr uint32_t kMinAglShellExtensionVersion = 1; +-constexpr uint32_t kMaxAglShellExtensionVersion = 3; ++constexpr uint32_t kMaxAglShellExtensionVersion = 4; + + } // namespace + +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.cc b/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.cc +index 97b21ae537658..f92406d455de1 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.cc ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.cc +@@ -83,4 +83,14 @@ void WaylandWindowAgl::SetAglPanel(uint32_t edge) { + connection()->ScheduleFlush(); + } + ++void WaylandWindowAgl::SetupActivationArea(uint32_t x, uint32_t y, uint32_t width, uint32_t height) { ++ if (!agl_extensions_->GetAglShell()) { ++ LOG(ERROR) << "Agl shell wrapper is not created"; ++ return; ++ } ++ ++ agl_extensions_->GetAglShell()->SetupActivationArea(x, y, width, height); ++ connection()->ScheduleFlush(); ++} ++ + } // namespace ui +diff --git a/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h b/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h +index b2a922604c001..d21d2d9387215 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h ++++ b/ui/ozone/platform/wayland/extensions/agl/host/wayland_window_agl.h +@@ -39,6 +39,7 @@ class WaylandWindowAgl : public WaylandToplevelWindow { + void SetAglReady() override; + void SetAglBackground() override; + void SetAglPanel(uint32_t edge) override; ++ void SetupActivationArea(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; + + private: + WaylandExtensionsAgl* agl_extensions_; +diff --git a/ui/ozone/platform/wayland/extensions/agl/protocol/agl-shell.xml b/ui/ozone/platform/wayland/extensions/agl/protocol/agl-shell.xml +index ad5553d61f189..e010a80808c69 100644 +--- a/ui/ozone/platform/wayland/extensions/agl/protocol/agl-shell.xml ++++ b/ui/ozone/platform/wayland/extensions/agl/protocol/agl-shell.xml +@@ -22,7 +22,7 @@ + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + </copyright> +- <interface name="agl_shell" version="3"> ++ <interface name="agl_shell" version="8"> + <description summary="user interface for Automotive Grade Linux platform"> + Starting with version 2 of the protocol, the client is required to wait + for the 'bound_ok' or 'bound_fail' events in order to proceed further. +@@ -174,6 +174,189 @@ + <arg name="state" type="uint" enum="app_state"/> + </event> + ++ <request name="set_activate_region" since="4"> ++ <description summary="sets a specific region to activate"> ++ A hint for the compositor to use a custom area, rather than ++ inferring the activation area. If any panels are used ++ the compositor computes the activation area by subtracting the ++ panels geometry area. If no panels are used then the entire output ++ is being used. This request changes that as to hint the compositor ++ to use the supplied rectangle and ignore any potential panels ++ that might been set-up previously. + ++ In order for this request to take effect it will need to happen ++ before the 'ready' request in order for the compositor to make use of it. ++ Note that any 'set_panel' request be will not be honored, if this request ++ has been called. ++ ++ The x and y coordinates use the top-left corner as the origin. The ++ rectangle area shouldn't exceed the output area, while an area smaller ++ than the output, would basically result in showing up the background ++ surface. ++ </description> ++ <arg name="output" type="object" interface="wl_output"/> ++ <arg name="x" type="int" summary="x position of rectangle"/> ++ <arg name="y" type="int" summary="y position of rectangle"/> ++ <arg name="width" type="int" summary="width of rectangle"/> ++ <arg name="height" type="int" summary="height of rectangle"/> ++ </request> ++ ++ <request name="deactivate_app" since="5"> ++ <description summary="de-activate/hide window identified by app_id"> ++ Ask the compositor to hide the toplevel window for window ++ management purposes. Depending on the window role, this request ++ will either display the previously active window (or the background ++ in case there's no previously active surface) or temporarily (or ++ until a 'activate_app' is called upon) hide the surface. ++ ++ All the surfaces are identifiable by using the app_id, and no actions ++ are taken in case the app_id is not/was not present. ++ ++ See xdg_toplevel.set_app_id from the xdg-shell protocol for a ++ description of app_id. ++ </description> ++ <arg name="app_id" type="string"/> ++ </request> ++ ++ <request name="set_app_float" since="6"> ++ <description summary="set the window identified by app_id as float"> ++ Makes the application identified by app_id as floating. If the ++ application's window is already mapped, in a maximized, normal state, ++ it would transition to the float state. ++ ++ For applications that want to modify their own state, this request ++ must be done before the initial surface commit in order to take effect. ++ ++ If the application is already in floating state, this request wouldn't ++ do anything. ++ ++ There's no persistence of this request, once the application terminated ++ you'll to issue this request again for that particular app_id. ++ ++ The x, and y values would be initial position of the window where the ++ window surface will be placed. ++ ++ See xdg_toplevel.set_app_id from the xdg-shell protocol for a ++ description of app_id. ++ </description> ++ <arg name="app_id" type="string"/> ++ <arg name="x" type="int" summary="x position"/> ++ <arg name="y" type="int" summary="y position"/> ++ </request> ++ ++ <request name="set_app_normal" since="6"> ++ <description summary="set the window identified by app_id as normally started"> ++ Returns the application identified by app_id as it was in the normal state. ++ This is useful to come back from other states to the maximized state, the ++ normal state applications are started. ++ </description> ++ <arg name="app_id" type="string"/> ++ </request> ++ ++ <request name="set_app_fullscreen" since="7"> ++ <description summary=""> ++ Makes the application identified by app_id as fullscreen. If the ++ application's window is already mapped, in a maximized, normal state, ++ it would transition to the fullscreen state. ++ ++ For applications that want to modify their own state, this request ++ must be done before the initial surface commit in order to take effect. ++ ++ If the application is already in fullscreen state, this request wouldn't ++ do anything. ++ ++ There's no persistence of this request, once the application terminated ++ you'll to issue this request again for that particular app_id. ++ ++ See xdg_toplevel.set_app_id from the xdg-shell protocol for a ++ description of app_id. ++ </description> ++ <arg name="app_id" type="string"/> ++ </request> ++ ++ <request name="set_app_output" since="8"> ++ <description summary="Assign an application to a particular output"> ++ This would allow the compositor to place an application on a particular ++ output, if that output is indeed available. This can happen before ++ application is started which would make the application start on that ++ particular output. If the application is already started it would ++ move the application to that output. ++ ++ There's no persistence of this request, once the application terminated ++ you'll need to issue this request again for that particular app_id. ++ ++ See xdg_toplevel.set_app_id from the xdg-shell protocol for a ++ description of app_id. ++ </description> ++ <arg name="app_id" type="string"/> ++ <arg name="output" type="object" interface="wl_output"/> ++ </request> ++ ++ <event name="app_on_output" since="8"> ++ <description summary="Event sent as a reponse to set_app_output"> ++ Clients can use this event to be notified when an application ++ wants to be displayed on a certain output. This event is sent in ++ response to the set_app_output request. ++ ++ See xdg_toplevel.set_app_id from the xdg-shell protocol for a ++ description of app_id. ++ </description> ++ <arg name="app_id" type="string"/> ++ <arg name="output_name" type="string"/> ++ </event> ++ </interface> ++ ++ <interface name="agl_shell_ext" version="1"> ++ <description summary="extended user interface for Automotive Grade Linux platform"> ++ This interface allows another client bind to the agl_shell interface, ++ while there's another shell client already present. ++ ++ The client should first bind to this interface and then inform the ++ compositor with the 'doas_shell_client' request and it wants to bind to ++ the agl_shell interface. The client is still expected, if using a new ++ version of the agl_shell interface, to wait for the 'bound_ok' and ++ 'bound_fail' events before issueing any other requests/events. ++ ++ Note that this interface has its limitations, and the compositor would ++ still refuse the act for 'set_panel' or 'set_background' requests ++ of the agl_shell interface if there's already a client that used them. ++ ++ Any other requests or events should be delievered and handled as it would ++ a client bound to the agl_shell interface. ++ </description> ++ ++ <enum name="doas_shell_client_status"> ++ <entry name="success" value="0"/> ++ <entry name="failed" value="1"/> ++ </enum> ++ ++ <request name="destroy" type="destructor"> ++ <description summary="destroys the factory object"> ++ Call the destructor once you're ready with agl_shell_ext interface. ++ This would reset the state and would make any requests made ++ on the agl_shell interface be terminated. The client would need ++ to bind again the agl_shell_ext and issue a 'doas_shell_client' ++ request. ++ </description> ++ </request> ++ ++ <request name="doas_shell_client"> ++ <description summary="Informs the compositor it wants to bind to the ++ agl_shell interface"> ++ Prior to binding to agl_shell interface, this request would inform ++ the compositor that it wants to gain access the agl_shell interface. ++ The client is expected to wait for 'doas_shell_client_done' event and ++ check for a successful status before going further with binding to ++ the agl_shell interface. ++ </description> ++ </request> ++ ++ <event name="doas_done"> ++ <description summary="event sent as a reply to doas_shell_client"> ++ The client should check the status event to verify that the ++ compositor was able to handle the request. ++ </description> ++ <arg name="status" type="uint" enum="doas_shell_client_status"/> ++ </event> + </interface> + </protocol> +diff --git a/ui/platform_window/agl/platform_window_agl.h b/ui/platform_window/agl/platform_window_agl.h +index cab1f42272772..b1a6150fff950 100644 +--- a/ui/platform_window/agl/platform_window_agl.h ++++ b/ui/platform_window/agl/platform_window_agl.h +@@ -30,6 +30,7 @@ class PlatformWindowAgl { + virtual void SetAglBackground() {} + virtual void SetAglPanel(uint32_t edge) {} + virtual bool IsSurfaceConfigured() { return false; } ++ virtual void SetupActivationArea(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {} + }; + + } // namespace ui +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0006-agl-Don-t-use-DRI-for-renesas.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0006-agl-Don-t-use-DRI-for-renesas.patch new file mode 100644 index 000000000..1914661ed --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0006-agl-Don-t-use-DRI-for-renesas.patch @@ -0,0 +1,72 @@ +From e7b779035f0d7ff1ba5bf59ea2f314f364493928 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Thu, 4 May 2023 10:42:06 +0200 +Subject: [PATCH 06/33] [agl] Don't use DRI for renesas + +This adds the use_dri flag that defauls to true and +can be disabled if we are building CEF using ozone + wayland + +Upstream-Status: Inappropriate, specific to the renesas boards supported +by AGL. +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + content/gpu/BUILD.gn | 4 ++-- + media/gpu/sandbox/BUILD.gn | 5 +++-- + media/media_options.gni | 3 +++ + 3 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/content/gpu/BUILD.gn b/content/gpu/BUILD.gn +index 93559f6092c7a..cef8415be7ab1 100644 +--- a/content/gpu/BUILD.gn ++++ b/content/gpu/BUILD.gn +@@ -139,8 +139,8 @@ target(link_target_type, "gpu_sources") { + } + + # Use DRI on desktop Linux builds. +- if (current_cpu != "s390x" && current_cpu != "ppc64" && is_linux && +- !is_castos) { ++ if (use_dri && current_cpu != "s390x" && current_cpu != "ppc64" && ++ is_linux && !is_castos) { + configs += [ "//build/config/linux/dri" ] + } + } +diff --git a/media/gpu/sandbox/BUILD.gn b/media/gpu/sandbox/BUILD.gn +index cfcb7fa80ef89..6ba37d06b29c8 100644 +--- a/media/gpu/sandbox/BUILD.gn ++++ b/media/gpu/sandbox/BUILD.gn +@@ -4,6 +4,7 @@ + + import("//build/config/chromeos/ui_mode.gni") + import("//media/gpu/args.gni") ++import("//media/media_options.gni") + + source_set("sandbox") { + sources = [] +@@ -30,8 +31,8 @@ source_set("sandbox") { + if (use_v4l2_codec) { + deps += [ "//media/gpu/v4l2" ] + } +- if (current_cpu != "s390x" && current_cpu != "ppc64" && is_linux && +- !is_castos) { ++ if (use_dri && (current_cpu != "s390x" && current_cpu != "ppc64" && is_linux && ++ !is_castos)) { + # For DRI_DRIVER_DIR. + configs += [ "//build/config/linux/dri" ] + } +diff --git a/media/media_options.gni b/media/media_options.gni +index 61d5046d0cb0e..4898c9034d448 100644 +--- a/media/media_options.gni ++++ b/media/media_options.gni +@@ -117,6 +117,9 @@ declare_args() { + # Enable inclusion of VVC/H.266 parser/demuxer, and also enable VVC/H.266 decoding + # with hardware acceleration provided by platform. Disabled by default for all builds. + enable_platform_vvc = false ++ ++ # used to disable dri on renesas boards ++ use_dri = true + } + + # Use another declare_args() to allow dependence on args defined above. +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0007-meta-browser-Remove-the-GN-settings-done-for-clang-t.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0007-meta-browser-Remove-the-GN-settings-done-for-clang-t.patch new file mode 100644 index 000000000..75d37ab13 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0007-meta-browser-Remove-the-GN-settings-done-for-clang-t.patch @@ -0,0 +1,117 @@ +From 89705cfc3a4e677dd97db36c3dc9b0aa97515760 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Thu, 27 Apr 2023 16:16:28 +0200 +Subject: [PATCH 07/33] [meta-browser] Remove the GN settings done for clang + that conflict with OE + +clang cross compiler that is build with meta-clang has lot of these +settings built-in and specifying them here confuses the compiler + +--target option and -no-canonical-prefixes options result in clang + +finding the headers in target sysroot + +Upstream-Status: Inappropriate [OE-Specific] + +Signed-off-by: Khem Raj <raj.khem@gmail.com> +Rebased-by: Maksim Sisov <msisov@igalia.com> +Rebased-by: Randy MacLeod <randy.macleod@windriver.com> +Rebased-by: Roger Zanoni <rzanoni@igalia.com> +--- + build/config/compiler/BUILD.gn | 38 ---------------------------------- + 1 file changed, 38 deletions(-) + +diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn +index 06812fb9c2188..db763b998c4fb 100644 +--- a/build/config/compiler/BUILD.gn ++++ b/build/config/compiler/BUILD.gn +@@ -1112,11 +1112,6 @@ config("compiler_cpu_abi") { + ] + } + } else if (current_cpu == "arm") { +- if (is_clang && !is_android && !is_nacl && +- !(is_chromeos_lacros && is_chromeos_device)) { +- cflags += [ "--target=arm-linux-gnueabihf" ] +- ldflags += [ "--target=arm-linux-gnueabihf" ] +- } + if (!is_nacl) { + cflags += [ + "-march=$arm_arch", +@@ -1126,12 +1121,6 @@ config("compiler_cpu_abi") { + if (arm_tune != "") { + cflags += [ "-mtune=$arm_tune" ] + } +- } else if (current_cpu == "arm64") { +- if (is_clang && !is_android && !is_nacl && !is_fuchsia && +- !(is_chromeos_lacros && is_chromeos_device)) { +- cflags += [ "--target=aarch64-linux-gnu" ] +- ldflags += [ "--target=aarch64-linux-gnu" ] +- } + } else if (current_cpu == "mipsel" && !is_nacl) { + ldflags += [ "-Wl,--hash-style=sysv" ] + if (custom_toolchain == "") { +@@ -1139,9 +1128,6 @@ config("compiler_cpu_abi") { + if (is_android) { + cflags += [ "--target=mipsel-linux-android" ] + ldflags += [ "--target=mipsel-linux-android" ] +- } else { +- cflags += [ "--target=mipsel-linux-gnu" ] +- ldflags += [ "--target=mipsel-linux-gnu" ] + } + } else { + cflags += [ "-EL" ] +@@ -1221,8 +1207,6 @@ config("compiler_cpu_abi") { + ldflags += [ "-Wl,--hash-style=sysv" ] + if (custom_toolchain == "") { + if (is_clang) { +- cflags += [ "--target=mips-linux-gnu" ] +- ldflags += [ "--target=mips-linux-gnu" ] + } else { + cflags += [ "-EB" ] + ldflags += [ "-EB" ] +@@ -1270,9 +1254,6 @@ config("compiler_cpu_abi") { + if (is_android) { + cflags += [ "--target=mips64el-linux-android" ] + ldflags += [ "--target=mips64el-linux-android" ] +- } else { +- cflags += [ "--target=mips64el-linux-gnuabi64" ] +- ldflags += [ "--target=mips64el-linux-gnuabi64" ] + } + } else { + cflags += [ +@@ -1330,8 +1311,6 @@ config("compiler_cpu_abi") { + ldflags += [ "-Wl,--hash-style=sysv" ] + if (custom_toolchain == "") { + if (is_clang) { +- cflags += [ "--target=mips64-linux-gnuabi64" ] +- ldflags += [ "--target=mips64-linux-gnuabi64" ] + } else { + cflags += [ + "-EB", +@@ -1494,23 +1473,6 @@ config("compiler_deterministic") { + } + } + } +- +- # Tells the compiler not to use absolute paths when passing the default +- # paths to the tools it invokes. We don't want this because we don't +- # really need it and it can mess up the goma cache entries. +- if (is_clang && (!is_nacl || is_nacl_saigo)) { +- cflags += [ "-no-canonical-prefixes" ] +- +- # Same for links: Let the compiler driver invoke the linker +- # with a relative path and pass relative paths to built-in +- # libraries. Not needed on Windows because we call the linker +- # directly there, not through the compiler driver. +- # We don't link on goma, so this change is just for cleaner +- # internal linker invocations, for people who work on the build. +- if (!is_win) { +- ldflags += [ "-no-canonical-prefixes" ] +- } +- } + } + + config("clang_revision") { +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0008-meta-browser-Pass-no-static-libstdc-to-gen.py.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0008-meta-browser-Pass-no-static-libstdc-to-gen.py.patch new file mode 100644 index 000000000..a31d4242c --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0008-meta-browser-Pass-no-static-libstdc-to-gen.py.patch @@ -0,0 +1,31 @@ +From f4d754e203e4968f4c9f68f00321fa0f1c942139 Mon Sep 17 00:00:00 2001 +From: Maksim Sisov <msisov@igalia.com> +Date: Thu, 19 Dec 2019 15:47:53 +0200 +Subject: [PATCH 08/33] [meta-browser] Pass no-static-libstdc++ to gen.py + +Upstream-Status: Inappropriate + +GN requires libstdc++.a to be installed on host systems by default, +which is often not very common, for no particular reason. + +Signed-off-by: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com> +Signed-off-by: Maksim Sisov <msisov@igalia.com> +--- + tools/gn/bootstrap/bootstrap.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py +index caf736b28946d..c5d7c428ed68a 100755 +--- a/tools/gn/bootstrap/bootstrap.py ++++ b/tools/gn/bootstrap/bootstrap.py +@@ -113,6 +113,7 @@ def main(argv): + cmd = [ + sys.executable, + os.path.join(GN_ROOT, 'build', 'gen.py'), ++ '--no-static-libstdc++', + '--no-last-commit-position', + '--out-path=' + gn_build_dir, + ] +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0009-meta-browser-IWYU-Add-includes-for-size_t-and-int64_.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0009-meta-browser-IWYU-Add-includes-for-size_t-and-int64_.patch new file mode 100644 index 000000000..8e46c2c50 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0009-meta-browser-IWYU-Add-includes-for-size_t-and-int64_.patch @@ -0,0 +1,42 @@ +From 585854fa48a040fe31caa42e675f78c783be0098 Mon Sep 17 00:00:00 2001 +From: Ivan Murashov <ivan.murashov@lge.com> +Date: Wed, 6 Sep 2023 19:40:47 +0000 +Subject: [PATCH 09/33] [meta-browser] IWYU: Add includes for size_t and + int64_t usage into sensor_reading.h + +Otherwise build fails when building with use_custom_libcxx=false. +The errors example: +services/device/public/cpp/generic_sensor/sensor_reading.h:17:40: +error: use of undeclared identifier 'int64_t' +services/device/public/cpp/generic_sensor/sensor_reading.h:35:5: +error: unknown type name 'int64_t' +services/device/public/cpp/generic_sensor/sensor_reading.h:58:20: +error: unknown type name 'size_t'; did you mean 'std::size_t'? + +Bug: 957519 +Change-Id: Iec9bb821eb6284cf38d93c1cec90846e2f615fab +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4838935 +Reviewed-by: Reilly Grant <reillyg@chromium.org> +Commit-Queue: Ivan Murashov <ivan.murashov@lge.com> +Cr-Commit-Position: refs/heads/main@{#1193203} +--- + services/device/public/cpp/generic_sensor/sensor_reading.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/services/device/public/cpp/generic_sensor/sensor_reading.h b/services/device/public/cpp/generic_sensor/sensor_reading.h +index 7df8278649a23..c653bec632cc6 100644 +--- a/services/device/public/cpp/generic_sensor/sensor_reading.h ++++ b/services/device/public/cpp/generic_sensor/sensor_reading.h +@@ -5,6 +5,9 @@ + #ifndef SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_READING_H_ + #define SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_READING_H_ + ++#include <stddef.h> ++#include <stdint.h> ++ + #include <type_traits> + + namespace device { +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0010-meta-browser-BUILD-do-not-specify-march-on-arm.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0010-meta-browser-BUILD-do-not-specify-march-on-arm.patch new file mode 100644 index 000000000..5936248ec --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0010-meta-browser-BUILD-do-not-specify-march-on-arm.patch @@ -0,0 +1,43 @@ +From 5d216a0f4d6312531bc03ce8c878dc251b67c589 Mon Sep 17 00:00:00 2001 +From: Khem Raj <raj.khem@gmail.com> +Date: Tue, 22 Jan 2019 00:17:41 -0800 +Subject: [PATCH 10/33] [meta-browser] BUILD: do not specify march on arm + +Do not try to set the guessed values for march/mtune/float-abi +OE config machinary has computed these values already and fed it +via compiler cmdline to chromium build + +I think upstream should check for the values on compiler cmdline +before overriding these + +Upstream-Status: Inappropriate [OE-Specific] + +Signed-off-by: Khem Raj <raj.khem@gmail.com> +--- + build/config/compiler/BUILD.gn | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn +index db763b998c4fb..6d87a2b03fa04 100644 +--- a/build/config/compiler/BUILD.gn ++++ b/build/config/compiler/BUILD.gn +@@ -1111,16 +1111,6 @@ config("compiler_cpu_abi") { + "-msse3", + ] + } +- } else if (current_cpu == "arm") { +- if (!is_nacl) { +- cflags += [ +- "-march=$arm_arch", +- "-mfloat-abi=$arm_float_abi", +- ] +- } +- if (arm_tune != "") { +- cflags += [ "-mtune=$arm_tune" ] +- } + } else if (current_cpu == "mipsel" && !is_nacl) { + ldflags += [ "-Wl,--hash-style=sysv" ] + if (custom_toolchain == "") { +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0011-meta-browser-Avoid-parenthesized-initialization-of-a.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0011-meta-browser-Avoid-parenthesized-initialization-of-a.patch new file mode 100644 index 000000000..dbdda920b --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0011-meta-browser-Avoid-parenthesized-initialization-of-a.patch @@ -0,0 +1,164 @@ +From 03e9492ef563af17682683b6db5761d1c2ece8cc Mon Sep 17 00:00:00 2001 +From: Max Ihlenfeldt <max@igalia.com> +Date: Thu, 3 Aug 2023 13:31:15 +0000 +Subject: [PATCH 11/33] [meta-browser] Avoid parenthesized initialization of + aggregates + +clang < 16 doesn't support C++20's "Parenthesized initialization of +aggregates" [1]. To fix build errors with older clang versions, we need +to either explicitly define a constructor that does the initialization, +or initialize the aggregate using curly braces. + +[1] https://clang.llvm.org/cxx_status.html + +Upstream-Status: Inappropriate [specific to older versions of clang] +Signed-off-by: Max Ihlenfeldt <max@igalia.com> +--- + .../browser/content_settings/one_time_permission_provider.h | 1 + + chrome/browser/ui/omnibox/chrome_omnibox_client.cc | 4 ++-- + chrome/test/chromedriver/chrome/client_hints.h | 1 + + .../display_embedder/skia_output_surface_impl_on_gpu.cc | 2 +- + net/dns/host_resolver_cache.cc | 2 +- + .../blink/renderer/modules/canvas/canvas2d/canvas_style.cc | 4 ++-- + .../blink/renderer/platform/fonts/palette_interpolation.cc | 2 +- + ui/base/wayland/color_manager_util.h | 5 +++++ + 8 files changed, 14 insertions(+), 7 deletions(-) + +diff --git a/chrome/browser/content_settings/one_time_permission_provider.h b/chrome/browser/content_settings/one_time_permission_provider.h +index 839bec7daff97..2a000003507cf 100644 +--- a/chrome/browser/content_settings/one_time_permission_provider.h ++++ b/chrome/browser/content_settings/one_time_permission_provider.h +@@ -92,6 +92,7 @@ class OneTimePermissionProvider + ContentSettingsType type; + ContentSettingsPattern primary_pattern; + ContentSettingsPattern secondary_pattern; ++ ContentSettingEntry(ContentSettingsType t, ContentSettingsPattern p, ContentSettingsPattern s) : type(t), primary_pattern(p), secondary_pattern(s) {} + }; + + void DeleteEntriesAndNotify( +diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc +index 7ee2e0645e6c8..e036eeea4a5f9 100644 +--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc ++++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc +@@ -474,10 +474,10 @@ void ChromeOmniboxClient::OnAutocompleteAccept( + alternative_nav_match); + + // Store the details necessary to open the omnibox match via browser commands. +- location_bar_->set_navigation_params(LocationBar::NavigationParams( ++ location_bar_->set_navigation_params(LocationBar::NavigationParams { + destination_url, disposition, transition, match_selection_timestamp, + destination_url_entered_without_scheme, +- destination_url_entered_with_http_scheme)); ++ destination_url_entered_with_http_scheme}); + + if (browser_) { + auto navigation = chrome::OpenCurrentURL(browser_); +diff --git a/chrome/test/chromedriver/chrome/client_hints.h b/chrome/test/chromedriver/chrome/client_hints.h +index 8c13bd3321c5e..42dc1acf75ec5 100644 +--- a/chrome/test/chromedriver/chrome/client_hints.h ++++ b/chrome/test/chromedriver/chrome/client_hints.h +@@ -19,6 +19,7 @@ struct BrandVersion { + // * "major version" for "brands", + // * "full version" for "fullVersionList". + std::string version; ++ BrandVersion(std::string b, std::string v) : brand(b), version(v) {} + }; + + // User-Agent Client Hints +diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +index 9e04843c454e3..e4981a96bbb06 100644 +--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc ++++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +@@ -1521,7 +1521,7 @@ void SkiaOutputSurfaceImplOnGpu::CopyOutputNV12( + + // Issue readbacks from the surfaces: + for (size_t i = 0; i < CopyOutputResult::kNV12MaxPlanes; ++i) { +- SkISize size(plane_surfaces[i]->width(), plane_surfaces[i]->height()); ++ SkISize size {plane_surfaces[i]->width(), plane_surfaces[i]->height()}; + SkImageInfo dst_info = SkImageInfo::Make( + size, (i == 0) ? kAlpha_8_SkColorType : kR8G8_unorm_SkColorType, + kUnpremul_SkAlphaType); +diff --git a/net/dns/host_resolver_cache.cc b/net/dns/host_resolver_cache.cc +index e54ed00c913ba..7d1165e7fcacf 100644 +--- a/net/dns/host_resolver_cache.cc ++++ b/net/dns/host_resolver_cache.cc +@@ -161,7 +161,7 @@ void HostResolverCache::Set( + + std::string domain_name = result->domain_name(); + entries_.emplace( +- Key(std::move(domain_name), network_anonymization_key), ++ Key {std::move(domain_name), network_anonymization_key}, + Entry(std::move(result), source, secure, staleness_generation_)); + + if (entries_.size() > max_entries_) { +diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.cc +index 883d769ca4b24..3dcd0d73468fc 100644 +--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.cc ++++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.cc +@@ -83,12 +83,12 @@ void CanvasStyle::ApplyToFlags(cc::PaintFlags& flags, + case kGradient: + GetCanvasGradient()->GetGradient()->ApplyToFlags(flags, SkMatrix::I(), + ImageDrawOptions()); +- flags.setColor(SkColor4f(0.0f, 0.0f, 0.0f, global_alpha)); ++ flags.setColor(SkColor4f {0.0f, 0.0f, 0.0f, global_alpha}); + break; + case kImagePattern: + GetCanvasPattern()->GetPattern()->ApplyToFlags( + flags, AffineTransformToSkMatrix(GetCanvasPattern()->GetTransform())); +- flags.setColor(SkColor4f(0.0f, 0.0f, 0.0f, global_alpha)); ++ flags.setColor(SkColor4f {0.0f, 0.0f, 0.0f, global_alpha}); + break; + default: + NOTREACHED(); +diff --git a/third_party/blink/renderer/platform/fonts/palette_interpolation.cc b/third_party/blink/renderer/platform/fonts/palette_interpolation.cc +index 1ce08e956a7aa..d6521525a52f6 100644 +--- a/third_party/blink/renderer/platform/fonts/palette_interpolation.cc ++++ b/third_party/blink/renderer/platform/fonts/palette_interpolation.cc +@@ -31,7 +31,7 @@ Vector<FontPalette::FontPaletteOverride> PaletteInterpolation::MixColorRecords( + color_interpolation_space, hue_interpolation_method, start_color, + end_color, percentage, alpha_multiplier); + +- FontPalette::FontPaletteOverride result_color_record(i, result_color); ++ FontPalette::FontPaletteOverride result_color_record {static_cast<int>(i), result_color}; + result_color_records.push_back(result_color_record); + } + return result_color_records; +diff --git a/ui/base/wayland/color_manager_util.h b/ui/base/wayland/color_manager_util.h +index fa1dd422c0e60..c54ace574e52e 100644 +--- a/ui/base/wayland/color_manager_util.h ++++ b/ui/base/wayland/color_manager_util.h +@@ -23,26 +23,31 @@ constexpr uint32_t kDefaultSinceVersion = 1; + struct TransferFnVersion { + skcms_TransferFunction transfer_fn; + uint32_t version; ++ TransferFnVersion(skcms_TransferFunction t, uint32_t v) : transfer_fn(t), version(v) {} + }; + + struct TransferVersion { + gfx::ColorSpace::TransferID transfer; + uint32_t version; ++ TransferVersion(gfx::ColorSpace::TransferID t, uint32_t v) : transfer(t), version(v) {} + }; + + struct PrimaryVersion { + gfx::ColorSpace::PrimaryID primary; + uint32_t version; ++ PrimaryVersion(gfx::ColorSpace::PrimaryID p, uint32_t v) : primary(p), version(v) {} + }; + + struct MatrixVersion { + gfx::ColorSpace::MatrixID matrix; + uint32_t version; ++ MatrixVersion(gfx::ColorSpace::MatrixID m, uint32_t v) : matrix(m), version(v) {} + }; + + struct RangeVersion { + gfx::ColorSpace::RangeID range; + uint32_t version; ++ RangeVersion(gfx::ColorSpace::RangeID r, uint32_t v) : range(r), version(v) {} + }; + + // A map from the zcr_color_manager_v1 chromaticity_names enum values +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0012-meta-browser-Fix-constexpr-variable-cannot-have-non-.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0012-meta-browser-Fix-constexpr-variable-cannot-have-non-.patch new file mode 100644 index 000000000..3a91c1ddf --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0012-meta-browser-Fix-constexpr-variable-cannot-have-non-.patch @@ -0,0 +1,78 @@ +From dcc972ec3451eaf88c2289a6f4852b24e901f26d Mon Sep 17 00:00:00 2001 +From: Max Ihlenfeldt <max@igalia.com> +Date: Thu, 31 Aug 2023 10:27:47 +0000 +Subject: [PATCH 12/33] [meta-browser] Fix "constexpr variable cannot have + non-literal type" errors + +Something about Chromium's `base::flat_map` / +`base::internal::flat_tree` isn't considered a literal type by older +clang versions, meaning they can't be used in constexpr expressions. We +need to change them to be const instead. + +Upstream-Status: Inappropriate [specific to older versions of clang] +Signed-off-by: Max Ihlenfeldt <max@igalia.com> +--- + ui/base/wayland/color_manager_util.h | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/ui/base/wayland/color_manager_util.h b/ui/base/wayland/color_manager_util.h +index c54ace574e52e..e25abe8e5d722 100644 +--- a/ui/base/wayland/color_manager_util.h ++++ b/ui/base/wayland/color_manager_util.h +@@ -53,7 +53,7 @@ struct RangeVersion { + // A map from the zcr_color_manager_v1 chromaticity_names enum values + // representing well-known chromaticities, to their equivalent PrimaryIDs. + // See components/exo/wayland/protocol/chrome-color-management.xml +-constexpr auto kChromaticityMap = base::MakeFixedFlatMap< ++const auto kChromaticityMap = base::MakeFixedFlatMap< + zcr_color_manager_v1_chromaticity_names, + PrimaryVersion>( + {{ZCR_COLOR_MANAGER_V1_CHROMATICITY_NAMES_BT601_525_LINE, +@@ -108,7 +108,7 @@ constexpr auto kChromaticityMap = base::MakeFixedFlatMap< + // A map from the zcr_color_manager_v1 eotf_names enum values + // representing well-known EOTFs, to their equivalent TransferIDs. + // See components/exo/wayland/protocol/chrome-color-management.xml +-constexpr auto kEotfMap = base::MakeFixedFlatMap< ++const auto kEotfMap = base::MakeFixedFlatMap< + zcr_color_manager_v1_eotf_names, + TransferVersion>({ + {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_LINEAR, +@@ -176,7 +176,7 @@ constexpr auto kEotfMap = base::MakeFixedFlatMap< + // A map from the SDR zcr_color_manager_v1 eotf_names enum values + // representing well-known EOTFs, to their equivalent transfer functions. + // See components/exo/wayland/protocol/chrome-color-management.xml +-constexpr auto kTransferMap = ++const auto kTransferMap = + base::MakeFixedFlatMap<zcr_color_manager_v1_eotf_names, TransferFnVersion>({ + {ZCR_COLOR_MANAGER_V1_EOTF_NAMES_LINEAR, + TransferFnVersion(SkNamedTransferFn::kLinear, kDefaultSinceVersion)}, +@@ -196,7 +196,7 @@ constexpr auto kTransferMap = + // A map from the HDR zcr_color_manager_v1 eotf_names enum values + // representing well-known EOTFs, to their equivalent transfer functions. + // See components/exo/wayland/protocol/chrome-color-management.xml +-constexpr auto kHDRTransferMap = ++const auto kHDRTransferMap = + base::MakeFixedFlatMap<zcr_color_manager_v1_eotf_names, TransferFnVersion>( + {{ZCR_COLOR_MANAGER_V1_EOTF_NAMES_LINEAR, + TransferFnVersion(SkNamedTransferFn::kLinear, kDefaultSinceVersion)}, +@@ -214,7 +214,7 @@ constexpr auto kHDRTransferMap = + + // A map from zcr_color_manager_v1 matrix_names enum values to + // gfx::ColorSpace::MatrixIDs. +-constexpr auto kMatrixMap = ++const auto kMatrixMap = + base::MakeFixedFlatMap<zcr_color_manager_v1_matrix_names, MatrixVersion>( + {{ZCR_COLOR_MANAGER_V1_MATRIX_NAMES_RGB, + MatrixVersion(gfx::ColorSpace::MatrixID::RGB, kDefaultSinceVersion)}, +@@ -251,7 +251,7 @@ constexpr auto kMatrixMap = + + // A map from zcr_color_manager_v1 range_names enum values to + // gfx::ColorSpace::RangeIDs. +-constexpr auto kRangeMap = ++const auto kRangeMap = + base::MakeFixedFlatMap<zcr_color_manager_v1_range_names, RangeVersion>( + {{ZCR_COLOR_MANAGER_V1_RANGE_NAMES_LIMITED, + RangeVersion(gfx::ColorSpace::RangeID::LIMITED, +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0013-meta-browser-Add-missing-typename-s.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0013-meta-browser-Add-missing-typename-s.patch new file mode 100644 index 000000000..8740b81aa --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0013-meta-browser-Add-missing-typename-s.patch @@ -0,0 +1,105 @@ +From 210019ce23ea273a13c77fedb3e674a47c67214a Mon Sep 17 00:00:00 2001 +From: Max Ihlenfeldt <max@igalia.com> +Date: Mon, 12 Jun 2023 16:52:44 +0000 +Subject: [PATCH 13/33] [meta-browser] Add missing "typename"s + +This adds some `typename`s in locations where they are needed in older +versions of clang (probably < 16). + +Upstream-Status: Inappropriate [specific to older versions of clang] +Signed-off-by: Max Ihlenfeldt <max@igalia.com> +--- + .../download/bubble/download_bubble_update_service.cc | 6 +++--- + components/optimization_guide/core/tflite_model_executor.h | 2 +- + .../browser/web_ui_browser_interface_broker_registry.h | 6 +++--- + .../core/html/parser/html_document_parser_fastpath.cc | 2 +- + .../renderer/core/paint/object_paint_properties_sparse.h | 4 ++-- + 5 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/chrome/browser/download/bubble/download_bubble_update_service.cc b/chrome/browser/download/bubble/download_bubble_update_service.cc +index 93ec91e38b9b3..acd25f25d1579 100644 +--- a/chrome/browser/download/bubble/download_bubble_update_service.cc ++++ b/chrome/browser/download/bubble/download_bubble_update_service.cc +@@ -91,7 +91,7 @@ ItemSortKey GetSortKey(const Item& item) { + // Helper to get an iterator to the last element in the cache. The cache + // must not be empty. + template <typename Item> +-SortedItems<Item>::const_iterator GetLastIter(const SortedItems<Item>& cache) { ++typename SortedItems<Item>::const_iterator GetLastIter(const SortedItems<Item>& cache) { + CHECK(!cache.empty()); + auto it = cache.end(); + return std::prev(it); +@@ -967,9 +967,9 @@ bool DownloadBubbleUpdateService::CacheManager::RemoveItemFromCacheImpl( + } + + template <typename Id, typename Item> +-SortedItems<Item>::iterator ++typename SortedItems<Item>::iterator + DownloadBubbleUpdateService::CacheManager::RemoveItemFromCacheByIter( +- SortedItems<Item>::iterator iter, ++ typename SortedItems<Item>::iterator iter, + SortedItems<Item>& cache, + IterMap<Id, Item>& iter_map) { + CHECK(iter != cache.end()); +diff --git a/components/optimization_guide/core/tflite_model_executor.h b/components/optimization_guide/core/tflite_model_executor.h +index bbb5208aae904..027ae8e101634 100644 +--- a/components/optimization_guide/core/tflite_model_executor.h ++++ b/components/optimization_guide/core/tflite_model_executor.h +@@ -240,7 +240,7 @@ class TFLiteModelExecutor : public ModelExecutor<OutputType, InputType> { + void SendForBatchExecution( + BatchExecutionCallback callback_on_complete, + base::TimeTicks start_time, +- ModelExecutor<OutputType, InputType>::ConstRefInputVector inputs) ++ typename ModelExecutor<OutputType, InputType>::ConstRefInputVector inputs) + override { + DCHECK(execution_task_runner_->RunsTasksInCurrentSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +diff --git a/content/public/browser/web_ui_browser_interface_broker_registry.h b/content/public/browser/web_ui_browser_interface_broker_registry.h +index 0a419be66b325..7253c9680f722 100644 +--- a/content/public/browser/web_ui_browser_interface_broker_registry.h ++++ b/content/public/browser/web_ui_browser_interface_broker_registry.h +@@ -127,10 +127,10 @@ class CONTENT_EXPORT WebUIBrowserInterfaceBrokerRegistry { + // + // TODO(crbug.com/1407936): Point to WebUIJsBridge documentation. + template <typename ControllerType> +- JsBridgeTraits<ControllerType>::BinderInitializer& ForWebUIWithJsBridge() { ++ typename JsBridgeTraits<ControllerType>::BinderInitializer& ForWebUIWithJsBridge() { + using Traits = JsBridgeTraits<ControllerType>; +- using Interface = Traits::Interface; +- using JsBridgeBinderInitializer = Traits::BinderInitializer; ++ using Interface = typename Traits::Interface; ++ using JsBridgeBinderInitializer = typename Traits::BinderInitializer; + + // WebUIController::GetType() requires an instantiated WebUIController + // (because it's a virtual method and can't be static). Here we only have +diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.cc b/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.cc +index 4b5b6701a591b..59e1262a06e37 100644 +--- a/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.cc ++++ b/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.cc +@@ -169,7 +169,7 @@ class HTMLFastPathParser { + using Span = base::span<const Char>; + using USpan = base::span<const UChar>; + // 32 matches that used by HTMLToken::Attribute. +- typedef std::conditional<std::is_same_v<Char, UChar>, ++ typedef typename std::conditional<std::is_same_v<Char, UChar>, + UCharLiteralBuffer<32>, + LCharLiteralBuffer<32>>::type LiteralBufferType; + typedef UCharLiteralBuffer<32> UCharLiteralBufferType; +diff --git a/third_party/blink/renderer/core/paint/object_paint_properties_sparse.h b/third_party/blink/renderer/core/paint/object_paint_properties_sparse.h +index 9adc6dfac54db..be94e55af7cf6 100644 +--- a/third_party/blink/renderer/core/paint/object_paint_properties_sparse.h ++++ b/third_party/blink/renderer/core/paint/object_paint_properties_sparse.h +@@ -272,8 +272,8 @@ class CORE_EXPORT ObjectPaintPropertiesSparse : public ObjectPaintProperties { + NodeList& nodes, + NodeId node_id, + const ParentType& parent, +- NodeType::State&& state, +- const NodeType::AnimationState& animation_state = ++ typename NodeType::State&& state, ++ const typename NodeType::AnimationState& animation_state = + NodeType::AnimationState()) { + // First, check if we need to add a new node. + if (!nodes.HasField(node_id)) { +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0014-meta-browser-Avoid-std-ranges-find_if.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0014-meta-browser-Avoid-std-ranges-find_if.patch new file mode 100644 index 000000000..2bd12fae1 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0014-meta-browser-Avoid-std-ranges-find_if.patch @@ -0,0 +1,70 @@ +From a577e7a76e6002e50b5ab27514b7f49d4070499c Mon Sep 17 00:00:00 2001 +From: Max Ihlenfeldt <max@igalia.com> +Date: Wed, 30 Aug 2023 16:06:19 +0000 +Subject: [PATCH 14/33] [meta-browser] Avoid std::ranges::find_if() + +std::ranges::find_if() was introduced in C++20, and older versions of +clang don't support it. We can instead use Chromium's `base::ranges` +library, which is supported. + +Upstream-Status: Inappropriate [specific to older versions of clang] +Signed-off-by: Max Ihlenfeldt <max@igalia.com> +--- + .../password_manager/core/browser/ui/passwords_grouper.cc | 3 ++- + components/webauthn/core/browser/passkey_sync_bridge.cc | 5 +++-- + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/components/password_manager/core/browser/ui/passwords_grouper.cc b/components/password_manager/core/browser/ui/passwords_grouper.cc +index 1b016e0eb9561..d259c6accf246 100644 +--- a/components/password_manager/core/browser/ui/passwords_grouper.cc ++++ b/components/password_manager/core/browser/ui/passwords_grouper.cc +@@ -8,6 +8,7 @@ + #include "base/containers/flat_set.h" + #include "base/strings/escape.h" + #include "base/strings/string_util.h" ++#include "base/ranges/algorithm.h" + #include "components/password_manager/core/browser/affiliation/affiliation_service.h" + #include "components/password_manager/core/browser/affiliation/affiliation_utils.h" + #include "components/password_manager/core/browser/passkey_credential.h" +@@ -277,7 +278,7 @@ absl::optional<PasskeyCredential> PasswordsGrouper::GetPasskeyFor( + const std::vector<PasskeyCredential>& passkeys = + map_group_id_to_credentials_[group_id_iterator->second].passkeys; + const auto passkey_it = +- std::ranges::find_if(passkeys, [&credential](const auto& passkey) { ++ base::ranges::find_if(passkeys, [&credential](const auto& passkey) { + return credential.passkey_credential_id == passkey.credential_id(); + }); + if (passkey_it == passkeys.end()) { +diff --git a/components/webauthn/core/browser/passkey_sync_bridge.cc b/components/webauthn/core/browser/passkey_sync_bridge.cc +index 93129fed756aa..794c696fcff04 100644 +--- a/components/webauthn/core/browser/passkey_sync_bridge.cc ++++ b/components/webauthn/core/browser/passkey_sync_bridge.cc +@@ -16,6 +16,7 @@ + #include "base/containers/span.h" + #include "base/feature_list.h" + #include "base/functional/callback_helpers.h" ++#include "base/ranges/algorithm.h" + #include "base/strings/string_number_conversions.h" + #include "base/trace_event/trace_event.h" + #include "components/sync/base/features.h" +@@ -258,7 +259,7 @@ PasskeySyncBridge::GetPasskeysForRelyingPartyId( + bool PasskeySyncBridge::DeletePasskey(const std::string& credential_id) { + // Find the credential with the given |credential_id|. + const auto passkey_it = +- std::ranges::find_if(data_, [&credential_id](const auto& passkey) { ++ base::ranges::find_if(data_, [&credential_id](const auto& passkey) { + return passkey.second.credential_id() == credential_id; + }); + if (passkey_it == data_.end()) { +@@ -309,7 +310,7 @@ bool PasskeySyncBridge::UpdatePasskey(const std::string& credential_id, + PasskeyChange change) { + // Find the credential with the given |credential_id|. + const auto passkey_it = +- std::ranges::find_if(data_, [&credential_id](const auto& passkey) { ++ base::ranges::find_if(data_, [&credential_id](const auto& passkey) { + return passkey.second.credential_id() == credential_id; + }); + if (passkey_it == data_.end()) { +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0015-meta-browser-Avoid-capturing-structured-bindings.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0015-meta-browser-Avoid-capturing-structured-bindings.patch new file mode 100644 index 000000000..7b612b84f --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0015-meta-browser-Avoid-capturing-structured-bindings.patch @@ -0,0 +1,56 @@ +From a1c05a94dc5b999bf22f1beedf3e3a9468775775 Mon Sep 17 00:00:00 2001 +From: Max Ihlenfeldt <max@igalia.com> +Date: Tue, 13 Jun 2023 15:48:12 +0000 +Subject: [PATCH 15/33] [meta-browser] Avoid capturing structured bindings + +Similar to https://crrev.com/c/4526976, this patch removes some uses of +structured bindings that lead to compile errors when using older +versions of clang (observed with clang 15). + +Upstream-Status: Inappropriate [specific to older versions of clang] +Signed-off-by: Max Ihlenfeldt <max@igalia.com> +--- + .../service_worker/service_worker_context_wrapper.cc | 3 ++- + media/base/cdm_promise_adapter.cc | 8 ++++---- + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc +index 3267cdb340819..de88ef7e565cb 100644 +--- a/content/browser/service_worker/service_worker_context_wrapper.cc ++++ b/content/browser/service_worker/service_worker_context_wrapper.cc +@@ -1412,9 +1412,10 @@ void ServiceWorkerContextWrapper::MaybeProcessPendingWarmUpRequest() { + auto [document_url, key, callback] = std::move(*request); + + DCHECK(document_url.is_valid()); ++ auto document_url_spec = document_url.spec(); + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerContextWrapper::MaybeProcessPendingWarmUpRequest", +- "document_url", document_url.spec()); ++ "document_url", document_url_spec); + + context_core_->registry()->FindRegistrationForClientUrl( + ServiceWorkerRegistry::Purpose::kNotForNavigation, +diff --git a/media/base/cdm_promise_adapter.cc b/media/base/cdm_promise_adapter.cc +index f013809a62e25..144809b9696c3 100644 +--- a/media/base/cdm_promise_adapter.cc ++++ b/media/base/cdm_promise_adapter.cc +@@ -94,12 +94,12 @@ void CdmPromiseAdapter::RejectPromise(uint32_t promise_id, + void CdmPromiseAdapter::Clear(ClearReason reason) { + // Reject all outstanding promises. + DCHECK(thread_checker_.CalledOnValidThread()); +- for (auto& [promise_id, promise] : promises_) { ++ for (auto& promise : promises_) { + TRACE_EVENT_NESTABLE_ASYNC_END1( +- "media", "CdmPromise", TRACE_ID_WITH_SCOPE("CdmPromise", promise_id), ++ "media", "CdmPromise", TRACE_ID_WITH_SCOPE("CdmPromise", promise.first), + "status", "cleared"); +- promise->reject(CdmPromise::Exception::INVALID_STATE_ERROR, +- ToSystemCode(reason), "Operation aborted."); ++ promise.second->reject(CdmPromise::Exception::INVALID_STATE_ERROR, ++ ToSystemCode(reason), "Operation aborted."); + } + promises_.clear(); + } +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0016-meta-browser-Delete-compiler-options-not-available-i.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0016-meta-browser-Delete-compiler-options-not-available-i.patch new file mode 100644 index 000000000..0956f5f3c --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0016-meta-browser-Delete-compiler-options-not-available-i.patch @@ -0,0 +1,32 @@ +From 267609878c7f7472990ee5b480a9ab1c54dad8b2 Mon Sep 17 00:00:00 2001 +From: Khem Raj <raj.khem@gmail.com> +Date: Wed, 4 Dec 2019 19:06:54 -0800 +Subject: [PATCH 16/33] [meta-browser] Delete compiler options not available in + release versions of clang _yet_ + +Upstream-Status: Inappropriate [ clang/master already supports them ] +Signed-off-by: Khem Raj <raj.khem@gmail.com> +Signed-off-by: Randy MacLeod <Randy.MacLeod@windriver.com> +--- + build/config/compiler/BUILD.gn | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn +index 6d87a2b03fa04..5762f0b4e6b0a 100644 +--- a/build/config/compiler/BUILD.gn ++++ b/build/config/compiler/BUILD.gn +@@ -1725,6 +1725,11 @@ config("default_warnings") { + cflags += [ + "-Wenum-compare-conditional", + ++ # Disable unknown warnings, since system clang may not have ++ # backported newer warning yet unlike internal clang that ++ # chromium uses. ++ "-Wno-unknown-warning-option", ++ + # Ignore warnings about MSVC optimization pragmas. + # TODO(thakis): Only for no_chromium_code? http://crbug.com/912662 + "-Wno-ignored-pragma-optimize", +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0017-meta-browser-Don-t-pass-disable-auto-upgrade-debug-i.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0017-meta-browser-Don-t-pass-disable-auto-upgrade-debug-i.patch new file mode 100644 index 000000000..48f722e8c --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0017-meta-browser-Don-t-pass-disable-auto-upgrade-debug-i.patch @@ -0,0 +1,39 @@ +From a8243956b0fd410bf16143b3e781144ad8964244 Mon Sep 17 00:00:00 2001 +From: Max Ihlenfeldt <max@igalia.com> +Date: Tue, 13 Jun 2023 14:36:23 +0000 +Subject: [PATCH 17/33] [meta-browser] Don't pass + disable-auto-upgrade-debug-info to linker + +The version of aarch64-oe-linux-ld.lld we use on dunfell, kirkstone, and +mickledore doesn't support this flag. Thus, we mustn't pass it if we +want to avoid an "Unknown command line argument" linker error that stops +the build. + +Upstream-Status: Inappropriate +Signed-off-by: Max Ihlenfeldt <max@igalia.com> +--- + build/config/compiler/BUILD.gn | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn +index 5762f0b4e6b0a..c73b7ca6325d8 100644 +--- a/build/config/compiler/BUILD.gn ++++ b/build/config/compiler/BUILD.gn +@@ -767,14 +767,6 @@ config("compiler") { + } + + ldflags += [ "-Wl,-mllvm,-import-instr-limit=$import_instr_limit" ] +- +- if (!is_chromeos) { +- # TODO(https://crbug.com/972449): turn on for ChromeOS when that +- # toolchain has this flag. +- # We only use one version of LLVM within a build so there's no need to +- # upgrade debug info, which can be expensive since it runs the verifier. +- ldflags += [ "-Wl,-mllvm,-disable-auto-upgrade-debug-info" ] +- } + } + + # TODO(https://crbug.com/1211155): investigate why this isn't effective on +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0018-meta-browser-Fix-undefined-symbol-PaintOpWriter-Seri.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0018-meta-browser-Fix-undefined-symbol-PaintOpWriter-Seri.patch new file mode 100644 index 000000000..2c953d3b0 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0018-meta-browser-Fix-undefined-symbol-PaintOpWriter-Seri.patch @@ -0,0 +1,49 @@ +From 1b8ee706e8bb16a9b6c59c832d33b56915d1f410 Mon Sep 17 00:00:00 2001 +From: Max Ihlenfeldt <max@igalia.com> +Date: Tue, 5 Sep 2023 09:51:38 +0000 +Subject: [PATCH 18/33] [meta-browser] Fix "undefined symbol: + PaintOpWriter::SerializedSize<unsigned long>()" + +For some reason, clang 14 (currently used on dunfell and kirkstone) +seems to fail to correctly generate a needed instantiation of +`cc::PaintOpWriter::SerializedSize<T>()`, and thus the final linking +step fails with an "undefined symbol" error. + +We can fix this by explicitly providing a specialization, which does the +same thing as the generic implementation. + +Upstream-Status: Inappropriate [specific to older versions of clang] +Signed-off-by: Max Ihlenfeldt <max@igalia.com> +--- + cc/paint/paint_op_writer.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/cc/paint/paint_op_writer.h b/cc/paint/paint_op_writer.h +index 70153c0aa64ac..f47eb934c1eb1 100644 +--- a/cc/paint/paint_op_writer.h ++++ b/cc/paint/paint_op_writer.h +@@ -122,6 +122,9 @@ class CC_PAINT_EXPORT PaintOpWriter { + static size_t SerializedSize(const PaintRecord& record); + static size_t SerializedSize(const SkHighContrastConfig& config); + ++ template<> ++ constexpr size_t SerializedSize<size_t>(); ++ + // Serialization of raw/smart pointers is not supported by default. + template <typename T> + static inline size_t SerializedSize(const T* p); +@@ -385,6 +388,11 @@ constexpr size_t PaintOpWriter::SerializedSize<SkGainmapInfo>() { + SerializedSizeSimple<uint32_t>(); // fBaseImageType + } + ++template<> ++constexpr size_t PaintOpWriter::SerializedSize<size_t>() { ++ return SerializedSizeSimple<size_t>(); ++} ++ + template <typename T> + constexpr size_t PaintOpWriter::SerializedSize() { + static_assert(std::is_arithmetic_v<T> || std::is_enum_v<T>); +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0019-upstream-Initialize-ServerCvc-with-designated-initia.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0019-upstream-Initialize-ServerCvc-with-designated-initia.patch new file mode 100644 index 000000000..aba255028 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0019-upstream-Initialize-ServerCvc-with-designated-initia.patch @@ -0,0 +1,45 @@ +From 41653aae0a0de782bcfb8396a01aa1d3c98d3149 Mon Sep 17 00:00:00 2001 +From: Chisoon Jeong <chisoon.jeong@lge.com> +Date: Tue, 12 Sep 2023 08:35:43 +0000 +Subject: [PATCH 19/33] [upstream] Initialize ServerCvc with designated + initializers. + +Replace ServerCvc initialization using aggregates from a parenthesized +list of values, which is not a c++20 feature allowed for Chromium at +the moment, with designated initializers. + +Change-Id: Ifdeb78d0ebc804016c655683ad1369dd543d4204 +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4855865 +Reviewed-by: Florian Leimgruber <fleimgruber@google.com> +Reviewed-by: Dominic Battre <battre@chromium.org> +Commit-Queue: Dominic Battre <battre@chromium.org> +Cr-Commit-Position: refs/heads/main@{#1195267} +--- + .../core/browser/webdata/autofill_sync_bridge_util.cc | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc b/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc +index 634443fb4fe22..f67b90114f762 100644 +--- a/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc ++++ b/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc +@@ -553,11 +553,13 @@ ServerCvc AutofillWalletCvcStructDataFromWalletCredentialSpecifics( + base::StringToInt64(wallet_credential_specifics.instrument_id(), + &instrument_id); + +- return ServerCvc( +- instrument_id, base::UTF8ToUTF16(wallet_credential_specifics.cvc()), +- base::Time::UnixEpoch() + ++ return ServerCvc{ ++ .instrument_id = instrument_id, ++ .cvc = base::UTF8ToUTF16(wallet_credential_specifics.cvc()), ++ .last_updated_timestamp = ++ base::Time::UnixEpoch() + + base::Milliseconds(wallet_credential_specifics +- .last_updated_time_unix_epoch_millis())); ++ .last_updated_time_unix_epoch_millis())}; + } + + VirtualCardUsageData VirtualCardUsageDataFromUsageSpecifics( +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0020-M118-fix-Don-t-look-for-depot_tools-in-chrommium-s-t.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0020-M118-fix-Don-t-look-for-depot_tools-in-chrommium-s-t.patch new file mode 100644 index 000000000..a8c01ab00 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0020-M118-fix-Don-t-look-for-depot_tools-in-chrommium-s-t.patch @@ -0,0 +1,37 @@ +From 814421a53454a9d35cd9d0799f68eaae8b7cf440 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Fri, 7 Apr 2023 16:28:51 +0200 +Subject: [PATCH 20/33] [M118-fix] Don't look for depot_tools in chrommium's + third_party folder + +This caused an issue at the configure step before we starte using +tarballs, we need to check if it still needed. + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + build/find_depot_tools.py | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/build/find_depot_tools.py b/build/find_depot_tools.py +index f891a414837a5..592bba699c00d 100755 +--- a/build/find_depot_tools.py ++++ b/build/find_depot_tools.py +@@ -27,14 +27,6 @@ def IsRealDepotTools(path): + + def add_depot_tools_to_path(): + """Search for depot_tools and add it to sys.path.""" +- # First, check if we have a DEPS'd in "depot_tools". +- deps_depot_tools = os.path.join(SRC, 'third_party', 'depot_tools') +- if IsRealDepotTools(deps_depot_tools): +- # Put the pinned version at the start of the sys.path, in case there +- # are other non-pinned versions already on the sys.path. +- sys.path.insert(0, deps_depot_tools) +- return deps_depot_tools +- + # Then look if depot_tools is already in PYTHONPATH. + for i in sys.path: + if i.rstrip(os.sep).endswith('depot_tools') and IsRealDepotTools(i): +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0021-M118-fix-Add-multiple-missing-includes.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0021-M118-fix-Add-multiple-missing-includes.patch new file mode 100644 index 000000000..df307082a --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0021-M118-fix-Add-multiple-missing-includes.patch @@ -0,0 +1,69 @@ +From 99b897cb41f70222477ed55128b38ea78edc78ff Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Tue, 31 Oct 2023 10:29:32 -0300 +Subject: [PATCH 21/33] [M118-fix] Add multiple missing includes + +Fix build issues related to missing includes. + +Upstream-Status: Apparently the issue only happens on older versions of +clang, but it's worth checking if it's applicable. +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + chrome/browser/ui/views/dark_mode_manager_linux.h | 1 + + net/cert/pki/general_names.h | 1 + + net/filter/zstd_source_stream.cc | 1 + + ui/events/gesture_detection/motion_event_generic.h | 2 ++ + 4 files changed, 5 insertions(+) + +diff --git a/chrome/browser/ui/views/dark_mode_manager_linux.h b/chrome/browser/ui/views/dark_mode_manager_linux.h +index f9bcd034d141d..e98db21ef1767 100644 +--- a/chrome/browser/ui/views/dark_mode_manager_linux.h ++++ b/chrome/browser/ui/views/dark_mode_manager_linux.h +@@ -6,6 +6,7 @@ + #define CHROME_BROWSER_UI_VIEWS_DARK_MODE_MANAGER_LINUX_H_ + + #include <string> ++#include <vector> + + #include "base/gtest_prod_util.h" + #include "base/memory/scoped_refptr.h" +diff --git a/net/cert/pki/general_names.h b/net/cert/pki/general_names.h +index e35e410a2fba7..7704837970178 100644 +--- a/net/cert/pki/general_names.h ++++ b/net/cert/pki/general_names.h +@@ -6,6 +6,7 @@ + #define NET_CERT_PKI_GENERAL_NAMES_H_ + + #include <memory> ++#include <string_view> + #include <vector> + + #include "net/base/net_export.h" +diff --git a/net/filter/zstd_source_stream.cc b/net/filter/zstd_source_stream.cc +index bd337d14366bb..551729ac542b7 100644 +--- a/net/filter/zstd_source_stream.cc ++++ b/net/filter/zstd_source_stream.cc +@@ -5,6 +5,7 @@ + #include "net/filter/zstd_source_stream.h" + + #include <algorithm> ++#include <unordered_map> + #include <utility> + + #define ZSTD_STATIC_LINKING_ONLY +diff --git a/ui/events/gesture_detection/motion_event_generic.h b/ui/events/gesture_detection/motion_event_generic.h +index 5460f7f8adf46..e508335d47ae9 100644 +--- a/ui/events/gesture_detection/motion_event_generic.h ++++ b/ui/events/gesture_detection/motion_event_generic.h +@@ -5,6 +5,8 @@ + #ifndef UI_EVENTS_GESTURE_DETECTION_MOTION_EVENT_GENERIC_H_ + #define UI_EVENTS_GESTURE_DETECTION_MOTION_EVENT_GENERIC_H_ + ++#include <vector> ++ + #include <stddef.h> + #include <stdint.h> + +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0022-M118-fix-Fix-aggregate-initialization-in-trace_log.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0022-M118-fix-Fix-aggregate-initialization-in-trace_log.patch new file mode 100644 index 000000000..39e5c6054 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0022-M118-fix-Fix-aggregate-initialization-in-trace_log.patch @@ -0,0 +1,34 @@ +From a46e381a9007ab552d4551711611cd9d231a9f17 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Wed, 25 Oct 2023 15:59:23 -0300 +Subject: [PATCH 22/33] [M118-fix] Fix aggregate initialization in trace_log + +clang 14 doesn't parenthesized initialization of aggregates, so we are +explicitly defining the needed constructor. + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + base/trace_event/trace_log.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h +index 2778526e87b78..3b7e0f0306cf5 100644 +--- a/base/trace_event/trace_log.h ++++ b/base/trace_event/trace_log.h +@@ -420,6 +420,12 @@ class BASE_EXPORT TraceLog : + + #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + struct TrackEventSession { ++ TrackEventSession(uint32_t internal_instance_index, ++ perfetto::DataSourceConfig config, ++ perfetto::BackendType backend_type = perfetto::kUnspecifiedBackend) ++ : internal_instance_index{internal_instance_index} ++ , config{config} ++ , backend_type{backend_type} {} + uint32_t internal_instance_index; + perfetto::DataSourceConfig config; + perfetto::BackendType backend_type = perfetto::kUnspecifiedBackend; +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0023-M118-fix-Add-missing-typename-keyword-in-multiple-st.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0023-M118-fix-Add-missing-typename-keyword-in-multiple-st.patch new file mode 100644 index 000000000..ea0b2c59f --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0023-M118-fix-Add-missing-typename-keyword-in-multiple-st.patch @@ -0,0 +1,140 @@ +From a1077aa6d029f729143727ab8d25f85121f871a3 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Thu, 26 Oct 2023 07:43:26 -0300 +Subject: [PATCH 23/33] [M118-fix] Add missing 'typename' keyword in multiple + statements + +Add the typename keywork where it's needed as this causes build issues +in clang 14. + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + .../optimization_guide/core/tflite_model_executor.h | 8 ++++---- + components/supervised_user/core/browser/proto_fetcher.cc | 6 +++--- + components/supervised_user/core/browser/proto_fetcher.h | 4 ++-- + ui/base/interaction/interactive_test_internal.h | 6 +++--- + 4 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/components/optimization_guide/core/tflite_model_executor.h b/components/optimization_guide/core/tflite_model_executor.h +index 027ae8e101634..a256a85322e54 100644 +--- a/components/optimization_guide/core/tflite_model_executor.h ++++ b/components/optimization_guide/core/tflite_model_executor.h +@@ -262,7 +262,7 @@ class TFLiteModelExecutor : public ModelExecutor<OutputType, InputType> { + // Starts the synchronous execution of the model. Returns model outputs. + // Model needs to be loaded. Synchronous calls do not load or unload model. + std::vector<absl::optional<OutputType>> SendForBatchExecutionSync( +- ModelExecutor<OutputType, InputType>::ConstRefInputVector inputs) ++ typename ModelExecutor<OutputType, InputType>::ConstRefInputVector inputs) + override { + DCHECK(execution_task_runner_->RunsTasksInCurrentSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +@@ -417,7 +417,7 @@ class TFLiteModelExecutor : public ModelExecutor<OutputType, InputType> { + // executes it on the model execution thread. + void LoadModelFileAndBatchExecute( + BatchExecutionCallback callback_on_complete, +- ModelExecutor<OutputType, InputType>::ConstRefInputVector inputs) { ++ typename ModelExecutor<OutputType, InputType>::ConstRefInputVector inputs) { + DCHECK(execution_task_runner_->RunsTasksInCurrentSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + +@@ -434,7 +434,7 @@ class TFLiteModelExecutor : public ModelExecutor<OutputType, InputType> { + + // Batch executes the loaded model for inputs. + void BatchExecuteLoadedModel( +- ModelExecutor<OutputType, InputType>::ConstRefInputVector inputs, ++ typename ModelExecutor<OutputType, InputType>::ConstRefInputVector inputs, + std::vector<absl::optional<OutputType>>* outputs) { + DCHECK(execution_task_runner_->RunsTasksInCurrentSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +@@ -494,7 +494,7 @@ class TFLiteModelExecutor : public ModelExecutor<OutputType, InputType> { + // Unloads the model if needed. + void BatchExecuteLoadedModelAndRunCallback( + BatchExecutionCallback callback_on_complete, +- ModelExecutor<OutputType, InputType>::ConstRefInputVector inputs, ++ typename ModelExecutor<OutputType, InputType>::ConstRefInputVector inputs, + ExecutionStatus execution_status) { + DCHECK(execution_task_runner_->RunsTasksInCurrentSequence()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +diff --git a/components/supervised_user/core/browser/proto_fetcher.cc b/components/supervised_user/core/browser/proto_fetcher.cc +index 9c8e7b5cb88f4..92a614d75b579 100644 +--- a/components/supervised_user/core/browser/proto_fetcher.cc ++++ b/components/supervised_user/core/browser/proto_fetcher.cc +@@ -399,7 +399,7 @@ class RetryingFetcherImpl final : public DeferredFetcherImpl<Response> { + RetryingFetcherImpl(const RetryingFetcherImpl&) = delete; + RetryingFetcherImpl& operator=(const RetryingFetcherImpl&) = delete; + +- void Start(ProtoFetcher<Response>::Callback callback) override { ++ void Start(typename ProtoFetcher<Response>::Callback callback) override { + callback_ = std::move(callback); + Retry(); + } +@@ -435,7 +435,7 @@ class RetryingFetcherImpl final : public DeferredFetcherImpl<Response> { + } + + // Client callback. +- ProtoFetcher<Response>::Callback callback_; ++ typename ProtoFetcher<Response>::Callback callback_; + + // Retry controls. + base::OneShotTimer timer_; +@@ -578,7 +578,7 @@ ParallelFetchManager<Request, Response>::ParallelFetchManager( + template <typename Request, typename Response> + void ParallelFetchManager<Request, Response>::Fetch( + const Request& request, +- Fetcher::Callback callback) { ++ typename Fetcher::Callback callback) { + CHECK(callback) << "Use base::DoNothing() instead of empty callback."; + KeyType key = requests_in_flight_.Add(MakeFetcher(request)); + requests_in_flight_.Lookup(key)->Start( +diff --git a/components/supervised_user/core/browser/proto_fetcher.h b/components/supervised_user/core/browser/proto_fetcher.h +index 8266c99d78a7a..9c41978aea68e 100644 +--- a/components/supervised_user/core/browser/proto_fetcher.h ++++ b/components/supervised_user/core/browser/proto_fetcher.h +@@ -165,10 +165,10 @@ class ParallelFetchManager { + + // Starts the fetch. Underlying fetcher is stored internally, and will be + // cleaned up after finish or when this manager is destroyed. +- void Fetch(const Request& request, Fetcher::Callback callback); ++ void Fetch(const Request& request, typename Fetcher::Callback callback); + + private: +- using KeyType = base::IDMap<std::unique_ptr<Fetcher>>::KeyType; ++ using KeyType = typename base::IDMap<std::unique_ptr<Fetcher>>::KeyType; + + // Remove fetcher under key from requests_in_flight_. + void Remove(KeyType key); +diff --git a/ui/base/interaction/interactive_test_internal.h b/ui/base/interaction/interactive_test_internal.h +index 080152fa265cd..a3c9b22f79487 100644 +--- a/ui/base/interaction/interactive_test_internal.h ++++ b/ui/base/interaction/interactive_test_internal.h +@@ -108,7 +108,7 @@ class InteractiveTestPrivate { + + // Adds `state_observer` and associates it with an element with identifier + // `id` and context `context`. +- template <typename Observer, typename V = Observer::ValueType> ++ template <typename Observer, typename V = typename Observer::ValueType> + void AddStateObserver(ElementIdentifier id, + ElementContext context, + std::unique_ptr<Observer> state_observer); +@@ -457,7 +457,7 @@ struct ArgsExtractor<R(Args...)> { + }; + + template <typename F> +-using ReturnTypeOf = MaybeBindTypeHelper<F>::ReturnType; ++using ReturnTypeOf = typename MaybeBindTypeHelper<F>::ReturnType; + + template <size_t N, typename F> + using NthArgumentOf = std::tuple_element_t< +@@ -556,7 +556,7 @@ struct MatcherTypeHelper<const char16_t[]> { + }; + + template <typename T> +-using MatcherTypeFor = MatcherTypeHelper<std::remove_cvref_t<T>>::ActualType; ++using MatcherTypeFor = typename MatcherTypeHelper<std::remove_cvref_t<T>>::ActualType; + + template <typename T> + class IsMatcherHelper { +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0024-M118-fix-Fix-comparison-in-HostResolverCache.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0024-M118-fix-Fix-comparison-in-HostResolverCache.patch new file mode 100644 index 000000000..ab487339f --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0024-M118-fix-Fix-comparison-in-HostResolverCache.patch @@ -0,0 +1,34 @@ +From 590fdfc0339a2d82f30927b7c4e35b5e24d2dcc8 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Mon, 30 Oct 2023 08:14:34 -0300 +Subject: [PATCH 24/33] [M118-fix] Fix comparison in HostResolverCache + +Fixes the string_view/basic_strinc comparison: + +error: invalid operands to binary expression +('tuple<...basic_string_view<char> &, ...>' and 'tuple<const std::basic_string<char> &, ...') + return std::tie(lhs.domain_name, *lhs.network_anonymization_key) < + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + net/dns/host_resolver_cache.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/dns/host_resolver_cache.h b/net/dns/host_resolver_cache.h +index 934e0682c9864..2bb147de0ff19 100644 +--- a/net/dns/host_resolver_cache.h ++++ b/net/dns/host_resolver_cache.h +@@ -120,7 +120,7 @@ class NET_EXPORT HostResolverCache final { + struct Key { + ~Key(); + +- std::string domain_name; ++ base::StringPiece domain_name; + NetworkAnonymizationKey network_anonymization_key; + }; + +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0025-M118-fix-Avoid-using-std-ranges-any_of-find_if-none_.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0025-M118-fix-Avoid-using-std-ranges-any_of-find_if-none_.patch new file mode 100644 index 000000000..fff1423ed --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0025-M118-fix-Avoid-using-std-ranges-any_of-find_if-none_.patch @@ -0,0 +1,92 @@ +From ded11a971e690a00075c4f337fa09469b69b69a5 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Mon, 30 Oct 2023 15:03:04 -0300 +Subject: [PATCH 25/33] [M118-fix] Avoid using + std::ranges::any_of/find_if/none_of/all_of + +Those functions are available only in newer c++ standards(C++20). +Chromium defines those functions in base::ranges. + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + chrome/browser/ui/webauthn/sheet_models.cc | 2 +- + .../browser/webauthn/authenticator_request_dialog_model.cc | 2 +- + .../webauthn/chrome_authenticator_request_delegate.cc | 4 ++-- + device/fido/get_assertion_request_handler.cc | 5 +++-- + 4 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc +index e72087c22dc84..1d1999fdc49c3 100644 +--- a/chrome/browser/ui/webauthn/sheet_models.cc ++++ b/chrome/browser/ui/webauthn/sheet_models.cc +@@ -1499,7 +1499,7 @@ AuthenticatorMultiSourcePickerSheetModel:: + using ICloudKeychainMech = + AuthenticatorRequestDialogModel::Mechanism::ICloudKeychain; + bool has_local_passkeys = +- std::ranges::any_of(dialog_model->mechanisms(), [](const auto& mech) { ++ base::ranges::any_of(dialog_model->mechanisms(), [](const auto& mech) { + return absl::holds_alternative<CredentialMech>(mech.type) && + absl::get<CredentialMech>(mech.type).value().source != + device::AuthenticatorType::kPhone; +diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc +index 7695aa00f44a8..fa983ddf1a166 100644 +--- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc ++++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc +@@ -495,7 +495,7 @@ void AuthenticatorRequestDialogModel:: + // extra step. Jump to Windows instead. + if (base::FeatureList::IsEnabled(device::kWebAuthnNewPasskeyUI) && + transport_availability_.has_win_native_api_authenticator && +- std::ranges::all_of(mechanisms_, [](const auto& mech) { ++ base::ranges::all_of(mechanisms_, [](const auto& mech) { + return absl::holds_alternative<Mechanism::WindowsAPI>(mech.type) || + (absl::holds_alternative<Mechanism::Credential>(mech.type) && + absl::get<Mechanism::Credential>(mech.type).value().source == +diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc +index 15773fad86902..6ddd5cba1d6f3 100644 +--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc ++++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc +@@ -886,8 +886,8 @@ void ChromeAuthenticatorRequestDelegate::OnTransportAvailabilityEnumerated( + if (data.has_platform_authenticator_credential == + device::FidoRequestHandlerBase::RecognizedCredential:: + kHasRecognizedCredential && +- std::ranges::none_of(data.recognized_credentials, +- IsCredentialFromPlatformAuthenticator)) { ++ base::ranges::none_of(data.recognized_credentials, ++ IsCredentialFromPlatformAuthenticator)) { + data.has_platform_authenticator_credential = device:: + FidoRequestHandlerBase::RecognizedCredential::kNoRecognizedCredential; + } +diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc +index 507cc2b46ddb6..80b6da1799c33 100644 +--- a/device/fido/get_assertion_request_handler.cc ++++ b/device/fido/get_assertion_request_handler.cc +@@ -15,6 +15,7 @@ + #include "base/functional/bind.h" + #include "base/json/json_writer.h" + #include "base/metrics/histogram_functions.h" ++#include "base/ranges/algorithm.h" + #include "base/stl_util.h" + #include "base/strings/string_number_conversions.h" + #include "base/timer/elapsed_timer.h" +@@ -370,7 +371,7 @@ bool AllowListOnlyHybridOrInternal(const CtapGetAssertionRequest& request) { + + bool AllowListIncludedTransport(const CtapGetAssertionRequest& request, + FidoTransportProtocol transport) { +- return std::ranges::any_of( ++ return base::ranges::any_of( + request.allow_list, + [transport](const PublicKeyCredentialDescriptor& cred) { + return cred.transports.empty() || +@@ -441,7 +442,7 @@ void GetAssertionRequestHandler::PreselectAccount( + PublicKeyCredentialDescriptor credential) { + DCHECK(!preselected_credential_); + DCHECK(request_.allow_list.empty() || +- std::ranges::any_of( ++ base::ranges::any_of( + request_.allow_list, + [&credential](const PublicKeyCredentialDescriptor& desc) { + return desc.id == credential.id; +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0026-M118-fix-Add-deleted-constructors-operators.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0026-M118-fix-Add-deleted-constructors-operators.patch new file mode 100644 index 000000000..06106360f --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0026-M118-fix-Add-deleted-constructors-operators.patch @@ -0,0 +1,339 @@ +From 19a3339965f79f8ae8ab650850461cbd0a782bff Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Mon, 30 Oct 2023 15:28:20 -0300 +Subject: [PATCH 26/33] [M118-fix] Add deleted constructors/operators + +Apparently the rules for deleting the implicitly-defined move +constructor/operators is different in clang 14 and this causes build +issues where the constructors or operators are needed. + +So we explicitly declare all the needed constructors defined as deleted +by the compiler. + +Upstream-Status: Inappropriate, only affects older versions of clang +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + .../profile_management_navigation_throttle.cc | 22 +++++++++++++ + .../core/browser/profile_token_quality.cc | 12 +++---- + .../core/browser/profile_token_quality.h | 15 +++++++++ + .../public/common/download_save_item_data.h | 5 +++ + .../fenced_frame/fenced_frame_reporter.h | 25 +++++++++++++++ + .../header_direct_from_seller_signals.cc | 4 ++- + .../webid/idp_network_request_manager.h | 31 +++++++++++++++++++ + .../renderer/platform/fonts/font_palette.h | 1 + + .../gesture_detection/motion_event_generic.cc | 27 ++++++++++++++++ + .../gesture_detection/motion_event_generic.h | 6 ++-- + 10 files changed, 139 insertions(+), 9 deletions(-) + +diff --git a/chrome/browser/enterprise/profile_management/profile_management_navigation_throttle.cc b/chrome/browser/enterprise/profile_management/profile_management_navigation_throttle.cc +index aecaaf76762ee..3b02142d3e722 100644 +--- a/chrome/browser/enterprise/profile_management/profile_management_navigation_throttle.cc ++++ b/chrome/browser/enterprise/profile_management/profile_management_navigation_throttle.cc +@@ -5,6 +5,7 @@ + #include "chrome/browser/enterprise/profile_management/profile_management_navigation_throttle.h" + + #include <string> ++#include <utility> + + #include "base/command_line.h" + #include "base/containers/contains.h" +@@ -47,6 +48,27 @@ constexpr char kGoogleServiceLoginUrl[] = + // Utility struct used to store SAML attributes related to third-party profile + // management. + struct SAMLProfileAttributes { ++ SAMLProfileAttributes() {} ++ SAMLProfileAttributes(std::string n, std::string d, std::string t) ++ : name{n}, domain{d}, token{t} {} ++ SAMLProfileAttributes(const SAMLProfileAttributes& o) ++ : SAMLProfileAttributes(o.name, ++ o.domain, ++ o.token) {} ++ SAMLProfileAttributes(SAMLProfileAttributes&& o) ++ : name{std::move(o.name)} ++ , domain{std::move(o.domain)} ++ , token{std::move(o.token)} {} ++ SAMLProfileAttributes& operator=(const SAMLProfileAttributes& o) { ++ return *this = SAMLProfileAttributes(o); ++ } ++ SAMLProfileAttributes& operator=(SAMLProfileAttributes&& o) { ++ name = std::move(o.name); ++ domain = std::move(o.domain); ++ token = std::move(o.token); ++ return *this; ++ } ++ + std::string name; + std::string domain; + std::string token; +diff --git a/components/autofill/core/browser/profile_token_quality.cc b/components/autofill/core/browser/profile_token_quality.cc +index ff5f175372f39..e1c18eccb84b3 100644 +--- a/components/autofill/core/browser/profile_token_quality.cc ++++ b/components/autofill/core/browser/profile_token_quality.cc +@@ -241,10 +241,10 @@ bool ProfileTokenQuality::AddObservationsForFilledForm( + } + possible_observations.emplace_back( + stored_type, +- Observation{.type = base::to_underlying(GetObservationTypeFromField( ++ Observation(base::to_underlying(GetObservationTypeFromField( + field, form_data.fields[i].value, other_profiles, + pdm.app_locale())), +- .form_hash = hash}); ++ hash)); + } + return AddSubsetOfObservations(std::move(possible_observations)) > 0; + } +@@ -387,10 +387,10 @@ void ProfileTokenQuality::LoadSerializedObservationsForStoredType( + for (size_t i = 0; i + 1 < serialized_data.size(); i += 2) { + AddObservation( + type, +- Observation{ +- .type = std::min(serialized_data[i], +- base::to_underlying(ObservationType::kMaxValue)), +- .form_hash = FormSignatureHash(serialized_data[i + 1])}); ++ Observation( ++ std::min(serialized_data[i], ++ base::to_underlying(ObservationType::kMaxValue)), ++ FormSignatureHash(serialized_data[i + 1]))); + } + } + +diff --git a/components/autofill/core/browser/profile_token_quality.h b/components/autofill/core/browser/profile_token_quality.h +index 9dc16a1f98a13..2f726f04ab8d3 100644 +--- a/components/autofill/core/browser/profile_token_quality.h ++++ b/components/autofill/core/browser/profile_token_quality.h +@@ -211,6 +211,21 @@ class ProfileTokenQuality { + // For this reason, it is preferred to store the `ObservationType`s as their + // underlying type in the data model as well. + // Getters expose unknown values as `kUnknown`. ++ Observation(std::underlying_type_t<ObservationType> t, ++ FormSignatureHash h) : type{t}, form_hash{h} {} ++ Observation(const Observation &o) ++ : Observation(o.type, o.form_hash) {} ++ Observation(Observation &&o) : type{std::move(o.type)}, ++ form_hash{std::move(o.form_hash)} {} ++ Observation& operator=(const Observation& o) { ++ return *this = Observation(o); ++ } ++ Observation& operator=(Observation&& o) noexcept { ++ type = std::move(o.type); ++ form_hash = std::move(o.form_hash); ++ return *this; ++ } ++ + std::underlying_type_t<ObservationType> type; + FormSignatureHash form_hash = FormSignatureHash(0); + }; +diff --git a/components/download/public/common/download_save_item_data.h b/components/download/public/common/download_save_item_data.h +index 754aec2f64f6d..d49c3cd545b06 100644 +--- a/components/download/public/common/download_save_item_data.h ++++ b/components/download/public/common/download_save_item_data.h +@@ -20,6 +20,11 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadSaveItemData + : public base::SupportsUserData::Data { + public: + struct ItemInfo { ++ ItemInfo(base::FilePath f, GURL u, GURL r) ++ : file_path{f} ++ , url{u} ++ , referrer_url{r} {} ++ + // The final path where this file of the package will be saved. + base::FilePath file_path; + // The url this file was downloaded from. +diff --git a/content/browser/fenced_frame/fenced_frame_reporter.h b/content/browser/fenced_frame/fenced_frame_reporter.h +index 19ebadf3e14f7..8d2ee62847ced 100644 +--- a/content/browser/fenced_frame/fenced_frame_reporter.h ++++ b/content/browser/fenced_frame/fenced_frame_reporter.h +@@ -8,6 +8,7 @@ + #include <map> + #include <set> + #include <string> ++#include <utility> + #include <vector> + + #include "base/containers/flat_map.h" +@@ -40,6 +41,21 @@ class RenderFrameHostImpl; + // `type` is the key for the `ReportingUrlMap`, and `data` is sent with the + // request as a POST. + struct DestinationEnumEvent { ++ DestinationEnumEvent(std::string t, std::string d) ++ : type{std::move(t)} ++ , data{std::move(d)} {} ++ DestinationEnumEvent(const DestinationEnumEvent& o) ++ : DestinationEnumEvent(o.type, o.data) {} ++ DestinationEnumEvent(DestinationEnumEvent&& o) ++ : type{std::move(o.type)} ++ , data{std::move(o.data)} {} ++ DestinationEnumEvent& operator=(const DestinationEnumEvent& o) { ++ return *this = DestinationEnumEvent(o); ++ } ++ DestinationEnumEvent& operator=(DestinationEnumEvent&& o) { ++ std::swap(type, o.type); ++ std::swap(data, o.data); ++ } + std::string type; + std::string data; + }; +@@ -48,6 +64,15 @@ struct DestinationEnumEvent { + // `url` is the custom destination url, and the request is sent as a GET. + // Macros are substituted using the `ReportingMacros`. + struct DestinationURLEvent { ++ DestinationURLEvent(const GURL& u) : url{u} {} ++ DestinationURLEvent(const DestinationURLEvent& u) : url{u.url} {} ++ DestinationURLEvent(DestinationURLEvent&& u) : url{std::move(u.url)} {} ++ DestinationURLEvent& operator=(const DestinationURLEvent& o) { ++ return *this =DestinationURLEvent(o); ++ } ++ DestinationURLEvent& operator=(DestinationURLEvent&& o) { ++ std::swap(url, o.url); ++ } + GURL url; + }; + +diff --git a/content/browser/interest_group/header_direct_from_seller_signals.cc b/content/browser/interest_group/header_direct_from_seller_signals.cc +index fe59d11edf449..facbec80a203a 100644 +--- a/content/browser/interest_group/header_direct_from_seller_signals.cc ++++ b/content/browser/interest_group/header_direct_from_seller_signals.cc +@@ -16,6 +16,7 @@ + #include "base/strings/stringprintf.h" + #include "base/values.h" + #include "services/data_decoder/public/cpp/data_decoder.h" ++#include "third_party/abseil-cpp/absl/types/optional.h" + #include "url/gurl.h" + #include "url/origin.h" + #include "url/url_constants.h" +@@ -187,7 +188,8 @@ void OnJsonDecoded(std::unique_ptr<const std::set<std::string>> responses, + + } // namespace + +-HeaderDirectFromSellerSignals::HeaderDirectFromSellerSignals() = default; ++HeaderDirectFromSellerSignals::HeaderDirectFromSellerSignals() : seller_signals_{absl::nullopt} ++ , auction_signals_{absl::nullopt} {} + + HeaderDirectFromSellerSignals::~HeaderDirectFromSellerSignals() = default; + +diff --git a/content/browser/webid/idp_network_request_manager.h b/content/browser/webid/idp_network_request_manager.h +index 6a652e0a22b44..307e0f4a68f48 100644 +--- a/content/browser/webid/idp_network_request_manager.h ++++ b/content/browser/webid/idp_network_request_manager.h +@@ -75,6 +75,24 @@ class CONTENT_EXPORT IdpNetworkRequestManager { + kInvalidContentTypeError, + }; + struct FetchStatus { ++ FetchStatus(ParseStatus p, int r) ++ : parse_status{p} ++ , response_code{r} {} ++ FetchStatus(const FetchStatus& o) ++ : FetchStatus(o.parse_status, ++ o.response_code) {} ++ FetchStatus(FetchStatus&& o) ++ : parse_status{std::move(o.parse_status)} ++ , response_code{std::move(o.response_code)} {} ++ FetchStatus& operator=(const FetchStatus& o) { ++ return *this = FetchStatus(o); ++ } ++ FetchStatus& operator=(FetchStatus&& o) { ++ std::swap(parse_status, o.parse_status); ++ std::swap(response_code, o.response_code); ++ return *this; ++ } ++ + ParseStatus parse_status; + // The HTTP response code, if one was received, otherwise the net error. It + // is possible to distinguish which it is since HTTP response codes are +@@ -117,6 +135,19 @@ class CONTENT_EXPORT IdpNetworkRequestManager { + }; + + struct IdentityCredentialTokenError { ++ IdentityCredentialTokenError(int c, GURL u) : code{c}, url{u} {} ++ IdentityCredentialTokenError(const IdentityCredentialTokenError &o) ++ : IdentityCredentialTokenError(o.code, o.url) {} ++ IdentityCredentialTokenError(IdentityCredentialTokenError &&o) ++ : code{std::move(o.code)}, url{std::move(o.url)} {} ++ IdentityCredentialTokenError& operator=(const IdentityCredentialTokenError& o) { ++ return *this = IdentityCredentialTokenError(o); ++ } ++ IdentityCredentialTokenError& operator=(IdentityCredentialTokenError&& o) { ++ std::swap(code, o.code); ++ std::swap(url, o.url); ++ return *this; ++ } + int code; + GURL url; + }; +diff --git a/third_party/blink/renderer/platform/fonts/font_palette.h b/third_party/blink/renderer/platform/fonts/font_palette.h +index 01dac9c908e9e..9a1a167acf213 100644 +--- a/third_party/blink/renderer/platform/fonts/font_palette.h ++++ b/third_party/blink/renderer/platform/fonts/font_palette.h +@@ -60,6 +60,7 @@ class PLATFORM_EXPORT FontPalette : public RefCounted<FontPalette> { + }; + + struct NonNormalizedPercentages { ++ NonNormalizedPercentages(double s, double e) : start{s}, end{e} {} + double start; + double end; + bool operator==(const NonNormalizedPercentages& other) const { +diff --git a/ui/events/gesture_detection/motion_event_generic.cc b/ui/events/gesture_detection/motion_event_generic.cc +index 77c5edaa17ee4..a312c6d4de0cf 100644 +--- a/ui/events/gesture_detection/motion_event_generic.cc ++++ b/ui/events/gesture_detection/motion_event_generic.cc +@@ -348,6 +348,33 @@ MotionEventGeneric& MotionEventGeneric::operator=( + return *this; + } + ++MotionEventGeneric& MotionEventGeneric::operator=( ++ MotionEventGeneric&& other) { ++ action_ = std::move(other.action_); ++ event_time_ = std::move(other.event_time_); ++ unique_event_id_ = std::move(other.unique_event_id_); ++ action_index_ = std::move(other.action_index_); ++ button_state_ = std::move(other.button_state_); ++ flags_ = std::move(other.flags_); ++ pointers_ = std::move(other.pointers_); ++ const size_t history_size = std::move(other.GetHistorySize()); ++ for (size_t h = 0; h < history_size; ++h) ++ PushHistoricalEvent(other.historical_events_[h]->Clone()); ++} ++ ++MotionEventGeneric::MotionEventGeneric(MotionEventGeneric&& other) { ++ action_ = std::move(other.action_); ++ event_time_ = std::move(other.event_time_); ++ unique_event_id_ = std::move(other.unique_event_id_); ++ action_index_ = std::move(other.action_index_); ++ button_state_ = std::move(other.button_state_); ++ flags_ = std::move(other.flags_); ++ pointers_ = std::move(other.pointers_); ++ const size_t history_size = std::move(other.GetHistorySize()); ++ for (size_t h = 0; h < history_size; ++h) ++ PushHistoricalEvent(other.historical_events_[h]->Clone()); ++} ++ + void MotionEventGeneric::PopPointer() { + DCHECK_GT(pointers_.size(), 0U); + pointers_.pop_back(); +diff --git a/ui/events/gesture_detection/motion_event_generic.h b/ui/events/gesture_detection/motion_event_generic.h +index e508335d47ae9..ed87c6254412c 100644 +--- a/ui/events/gesture_detection/motion_event_generic.h ++++ b/ui/events/gesture_detection/motion_event_generic.h +@@ -55,6 +55,9 @@ class GESTURE_DETECTION_EXPORT MotionEventGeneric : public MotionEvent { + base::TimeTicks event_time, + const PointerProperties& pointer); + MotionEventGeneric(const MotionEventGeneric& other); ++ MotionEventGeneric(MotionEventGeneric&& other); ++ MotionEventGeneric& operator=(const MotionEventGeneric& other); ++ MotionEventGeneric& operator=(MotionEventGeneric&& other); + + ~MotionEventGeneric() override; + +@@ -124,8 +127,7 @@ class GESTURE_DETECTION_EXPORT MotionEventGeneric : public MotionEvent { + protected: + MotionEventGeneric(); + MotionEventGeneric(const MotionEvent& event, bool with_history); +- MotionEventGeneric& operator=(const MotionEventGeneric& other); +- ++ + void PopPointer(); + + private: +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0027-M118-fix-Initialize-percentages-member-on-blink-Font.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0027-M118-fix-Initialize-percentages-member-on-blink-Font.patch new file mode 100644 index 000000000..9d7e30eb0 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0027-M118-fix-Initialize-percentages-member-on-blink-Font.patch @@ -0,0 +1,52 @@ +From c206c886eabc8f03289802276f826baedf0e4e54 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Mon, 30 Oct 2023 21:20:48 -0300 +Subject: [PATCH 27/33] [M118-fix] Initialize percentages member on + blink::FontPalette + +Fixes the build issue: + +error: constructor for 'blink::FontPalette' must explicitly +initialize the member 'percentages_' + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + .../blink/renderer/platform/fonts/font_palette.h | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/third_party/blink/renderer/platform/fonts/font_palette.h b/third_party/blink/renderer/platform/fonts/font_palette.h +index 9a1a167acf213..8c9a9c02439b5 100644 +--- a/third_party/blink/renderer/platform/fonts/font_palette.h ++++ b/third_party/blink/renderer/platform/fonts/font_palette.h +@@ -202,11 +202,14 @@ class PLATFORM_EXPORT FontPalette : public RefCounted<FontPalette> { + + private: + explicit FontPalette(KeywordPaletteName palette_name) +- : palette_keyword_(palette_name), base_palette_({kNoBasePalette, 0}) {} ++ : palette_keyword_(palette_name), ++ base_palette_({kNoBasePalette, 0}), ++ percentages_{0.0, 0.0} {} + explicit FontPalette(AtomicString palette_values_name) + : palette_keyword_(kCustomPalette), + palette_values_name_(palette_values_name), +- base_palette_({kNoBasePalette, 0}) {} ++ base_palette_({kNoBasePalette, 0}), ++ percentages_{0.0, 0.0} {} + FontPalette( + scoped_refptr<FontPalette> start, + scoped_refptr<FontPalette> end, +@@ -224,7 +227,9 @@ class PLATFORM_EXPORT FontPalette : public RefCounted<FontPalette> { + color_interpolation_space_(color_interpoaltion_space), + hue_interpolation_method_(hue_interpolation_method) {} + FontPalette() +- : palette_keyword_(kNormalPalette), base_palette_({kNoBasePalette, 0}) {} ++ : palette_keyword_(kNormalPalette), ++ base_palette_({kNoBasePalette, 0}), ++ percentages_{0.0, 0.0} {} + + KeywordPaletteName palette_keyword_; + AtomicString palette_values_name_; +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0028-M118-fix-Don-t-delete-ZstdSourceStream-copy-move-cto.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0028-M118-fix-Don-t-delete-ZstdSourceStream-copy-move-cto.patch new file mode 100644 index 000000000..d387b67cc --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0028-M118-fix-Don-t-delete-ZstdSourceStream-copy-move-cto.patch @@ -0,0 +1,32 @@ +From f45fd7f3cd85c0d421c37202d0f4dff2f7925162 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Fri, 3 Nov 2023 15:53:09 -0300 +Subject: [PATCH 28/33] [M118-fix] Don't delete ZstdSourceStream copy/move + ctors + +std::unique_ptr requires the deleted ZstdSourceStream deleted +constructors and it causes a build issue. + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + net/filter/zstd_source_stream.cc | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/net/filter/zstd_source_stream.cc b/net/filter/zstd_source_stream.cc +index 551729ac542b7..81d4565608e7a 100644 +--- a/net/filter/zstd_source_stream.cc ++++ b/net/filter/zstd_source_stream.cc +@@ -64,9 +64,6 @@ class ZstdSourceStream : public FilterSourceStream { + } + } + +- ZstdSourceStream(const ZstdSourceStream&) = delete; +- ZstdSourceStream& operator=(const ZstdSourceStream&) = delete; +- + ~ZstdSourceStream() override { + if (ZSTD_isError(decoding_result_)) { + ZSTD_ErrorCode error_code = ZSTD_getErrorCode(decoding_result_); +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0029-M118-fix-Fix-issue-with-structured-bindinds-captured.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0029-M118-fix-Fix-issue-with-structured-bindinds-captured.patch new file mode 100644 index 000000000..fec15dd8c --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0029-M118-fix-Fix-issue-with-structured-bindinds-captured.patch @@ -0,0 +1,68 @@ +From f7581fa1a0c25d2b76407bb04fd77031f5108411 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Fri, 3 Nov 2023 21:08:22 -0300 +Subject: [PATCH 29/33] [M118-fix] Fix issue with structured bindinds captured + by nested lambdas + +In clang <=14 the build fails doesn't when lambdas capture +aliases created in structured bindinds, so we do a few init-captures to +fix that. + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + .../core/layout/ng/grid/ng_grid_layout_algorithm.cc | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc +index 64c7a7481dd15..71eb55954e253 100644 +--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc ++++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc +@@ -3494,7 +3494,7 @@ void NGGridLayoutAlgorithm::PlaceGridItems( + To<NGPhysicalBoxFragment>(result->PhysicalFragment()); + NGBoxFragment fragment(container_writing_direction, physical_fragment); + +- auto BaselineOffset = [&](GridTrackSizingDirection track_direction, ++ auto BaselineOffset = [&, &layout_data = layout_data](GridTrackSizingDirection track_direction, + LayoutUnit size) -> LayoutUnit { + if (!grid_item.IsBaselineAligned(track_direction)) { + return LayoutUnit(); +@@ -3700,7 +3700,7 @@ void NGGridLayoutAlgorithm::PlaceGridItemsForFragmentation( + if (BreakToken()) + child_break_tokens = BreakToken()->ChildBreakTokens(); + +- auto PlaceItems = [&]() { ++ auto PlaceItems = [&, &grid_items = grid_items, &layout_data = layout_data]() { + // Reset our state. + result_and_offsets.clear(); + out_of_fragmentainer_space_item_placement.clear(); +@@ -3933,7 +3933,7 @@ void NGGridLayoutAlgorithm::PlaceGridItemsForFragmentation( + + // Adjust by |delta| the pre-computed item-offset for all grid items with a + // row begin index greater or equal than |row_index|. +- auto AdjustItemOffsets = [&](wtf_size_t row_index, LayoutUnit delta) { ++ auto AdjustItemOffsets = [&, &grid_items = grid_items](wtf_size_t row_index, LayoutUnit delta) { + auto current_item = grid_items.begin(); + + for (auto& item_placement_data : *grid_items_placement_data) { +@@ -3944,7 +3944,7 @@ void NGGridLayoutAlgorithm::PlaceGridItemsForFragmentation( + + // Adjust our grid break-token data to accommodate the larger item in the row. + // Returns true if this function adjusted the break-token data in any way. +- auto ExpandRow = [&]() -> bool { ++ auto ExpandRow = [&, &layout_data = layout_data]() -> bool { + if (max_row_expansion == 0) + return false; + +@@ -3963,7 +3963,7 @@ void NGGridLayoutAlgorithm::PlaceGridItemsForFragmentation( + // Shifts the row where we wish to take a breakpoint (indicated by + // |breakpoint_row_set_index|) into the next fragmentainer. + // Returns true if this function adjusted the break-token data in any way. +- auto ShiftBreakpointIntoNextFragmentainer = [&]() -> bool { ++ auto ShiftBreakpointIntoNextFragmentainer = [&, &layout_data = layout_data]() -> bool { + if (breakpoint_row_set_index == kNotFound) + return false; + +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0030-M118-fix-Only-default-arm_use_neon-to-true-if-its-va.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0030-M118-fix-Only-default-arm_use_neon-to-true-if-its-va.patch new file mode 100644 index 000000000..08a2db602 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0030-M118-fix-Only-default-arm_use_neon-to-true-if-its-va.patch @@ -0,0 +1,107 @@ +From 55fe851951b11c30e010b5f3df618addf606e3d4 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Wed, 8 Nov 2023 14:35:21 -0300 +Subject: [PATCH 30/33] [M118-fix] Only default arm_use_neon to true if its + value wasn't already set + +arm_use_neon was always being set causing the build to fail. + +Upstream-Status: Needs checking +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + build/config/arm.gni | 58 +++++++++++++++++++++----------------------- + 1 file changed, 27 insertions(+), 31 deletions(-) + +diff --git a/build/config/arm.gni b/build/config/arm.gni +index 5b404c1ca94f0..575871c287c80 100644 +--- a/build/config/arm.gni ++++ b/build/config/arm.gni +@@ -9,36 +9,39 @@ import("//build/config/v8_target_cpu.gni") + # ARM code is being compiled. But they can also be relevant in the + # other contexts when the code will change its behavior based on the + # cpu it wants to generate code for. +-if (current_cpu == "arm" || v8_current_cpu == "arm") { +- declare_args() { +- # Version of the ARM processor when compiling on ARM. Ignored on non-ARM +- # platforms. +- arm_version = 7 ++declare_args() { ++ # Version of the ARM processor when compiling on ARM. Ignored on non-ARM ++ # platforms. ++ arm_version = 7 + +- # The ARM architecture. This will be a string like "armv6" or "armv7-a". +- # An empty string means to use the default for the arm_version. +- arm_arch = "" ++ # The ARM architecture. This will be a string like "armv6" or "armv7-a". ++ # An empty string means to use the default for the arm_version. ++ arm_arch = "" + +- # The ARM floating point hardware. This will be a string like "neon" or +- # "vfpv3". An empty string means to use the default for the arm_version. +- arm_fpu = "" ++ # The ARM floating point hardware. This will be a string like "neon" or ++ # "vfpv3". An empty string means to use the default for the arm_version. ++ arm_fpu = "" + +- # The ARM variant-specific tuning mode. This will be a string like "armv6" +- # or "cortex-a15". An empty string means to use the default for the +- # arm_version. +- arm_tune = "" ++ # The ARM variant-specific tuning mode. This will be a string like "armv6" ++ # or "cortex-a15". An empty string means to use the default for the ++ # arm_version. ++ arm_tune = "" + +- # Whether to use the neon FPU instruction set or not. +- arm_use_neon = "" ++ # Whether to use the neon FPU instruction set or not. ++ arm_use_neon = "" + +- # Whether to enable optional NEON code paths. +- arm_optionally_use_neon = false ++ # Whether to enable optional NEON code paths. ++ arm_optionally_use_neon = false + +- # Thumb is a reduced instruction set available on some ARM processors that +- # has increased code density. +- arm_use_thumb = true +- } ++ # Thumb is a reduced instruction set available on some ARM processors that ++ # has increased code density. ++ arm_use_thumb = true + ++ arm_control_flow_integrity = "none" ++ arm_float_abi = "" ++} ++ ++if (current_cpu == "arm" || v8_current_cpu == "arm") { + # For lacros build, we use ARM v8 by default. + if (is_chromeos_lacros && arm_arch == "") { + # TODO(crbug.com/1467681) Enable i8mm and dotprod instructions for ffmpeg +@@ -49,13 +52,6 @@ if (current_cpu == "arm" || v8_current_cpu == "arm") { + + if (current_os == "android" || target_os == "android") { + arm_float_abi = "softfp" +- } else { +- declare_args() { +- # The ARM floating point mode. This is either the string "hard", "soft", +- # or "softfp". An empty string means to use the default one for the +- # arm_version. +- arm_float_abi = "" +- } + } + assert(arm_float_abi == "" || arm_float_abi == "hard" || + arm_float_abi == "soft" || arm_float_abi == "softfp") +@@ -126,7 +122,7 @@ if (current_cpu == "arm" || v8_current_cpu == "arm") { + } + } + } +-} else if (current_cpu == "arm64" || v8_current_cpu == "arm64") { ++} else if (arm_use_neon == "" && (current_cpu == "arm64" || v8_current_cpu == "arm64")) { + # arm64 supports only "hard". + arm_float_abi = "hard" + arm_use_neon = true +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0031-M118-fix-Add-a-way-to-set-different-lib-paths-host-a.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0031-M118-fix-Add-a-way-to-set-different-lib-paths-host-a.patch new file mode 100644 index 000000000..fa049e1b8 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0031-M118-fix-Add-a-way-to-set-different-lib-paths-host-a.patch @@ -0,0 +1,134 @@ +From e376fd5fa64d34803e821e02c0d5199ca7244944 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Sun, 12 Nov 2023 19:41:07 -0300 +Subject: [PATCH 31/33] [M118-fix] Add a way to set different lib paths host + and target + +meta-clang on AGL defines a simplified path structure for clang's +runtime libraries and a different lib naming convention. + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + build/config/clang/BUILD.gn | 79 +++++++++++------------------------- + build/config/clang/clang.gni | 3 ++ + 2 files changed, 26 insertions(+), 56 deletions(-) + +diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn +index fe044e29e428b..81ec24d92da72 100644 +--- a/build/config/clang/BUILD.gn ++++ b/build/config/clang/BUILD.gn +@@ -3,6 +3,7 @@ + # found in the LICENSE file. + + import("//build/config/rust.gni") ++import("//v8/gni/snapshot_toolchain.gni") + import("clang.gni") + + if (is_ios) { +@@ -95,66 +96,32 @@ template("clang_lib") { + } + } else { + config(target_name) { +- _dir = "" ++ if (is_a_target_toolchain) { ++ _base_path = "$clang_base_path_target" ++ _cpu = target_cpu ++ } else { ++ _base_path = "$clang_base_path" ++ _cpu = host_cpu ++ } ++ ++ if (_cpu == "x64") { ++ _suffix = "-x86_64" ++ } else if (_cpu == "x86") { ++ _suffix = "-i386" ++ } else if (_cpu == "arm64") { ++ _suffix = "-aarch64" ++ } else if (_cpu == "arm") { ++ _suffix = "-arm" ++ } else { ++ assert(false) # Unhandled cpu type ++ } ++ ++ _dir = "linux" + _libname = invoker.libname + _prefix = "lib" +- _suffix = "" + _ext = "a" +- if (is_win) { +- _dir = "windows" +- _prefix = "" +- _ext = "lib" +- if (current_cpu == "x64") { +- _suffix = "-x86_64" +- } else if (current_cpu == "x86") { +- _suffix = "-i386" +- } else if (current_cpu == "arm64") { +- _suffix = "-aarch64" +- } else { +- assert(false) # Unhandled cpu type +- } +- } else if (is_apple) { +- _dir = "darwin" +- } else if (is_linux || is_chromeos) { +- if (current_cpu == "x64") { +- _dir = "x86_64-unknown-linux-gnu" +- } else if (current_cpu == "x86") { +- _dir = "i386-unknown-linux-gnu" +- } else if (current_cpu == "arm") { +- _dir = "armv7-unknown-linux-gnueabihf" +- } else if (current_cpu == "arm64") { +- _dir = "aarch64-unknown-linux-gnu" +- } else { +- assert(false) # Unhandled cpu type +- } +- } else if (is_fuchsia) { +- if (current_cpu == "x64") { +- _dir = "x86_64-unknown-fuchsia" +- } else if (current_cpu == "arm64") { +- _dir = "aarch64-unknown-fuchsia" +- } else { +- assert(false) # Unhandled cpu type +- } +- } else if (is_android) { +- _dir = "linux" +- if (current_cpu == "x64") { +- _suffix = "-x86_64-android" +- } else if (current_cpu == "x86") { +- _suffix = "-i686-android" +- } else if (current_cpu == "arm") { +- _suffix = "-arm-android" +- } else if (current_cpu == "arm64") { +- _suffix = "-aarch64-android" +- } else if (current_cpu == "riscv64") { +- _suffix = "-riscv64-android" +- } else { +- assert(false) # Unhandled cpu type +- } +- } else { +- assert(false) # Unhandled target platform +- } + +- _clang_lib_dir = "$clang_base_path/lib/clang/$clang_version/lib" ++ _clang_lib_dir = "$_base_path/lib/clang/$clang_version/lib" + _lib_file = "${_prefix}clang_rt.${_libname}${_suffix}.${_ext}" + libs = [ "$_clang_lib_dir/$_dir/$_lib_file" ] + } +diff --git a/build/config/clang/clang.gni b/build/config/clang/clang.gni +index 1a065b5e348b0..46fb56693b494 100644 +--- a/build/config/clang/clang.gni ++++ b/build/config/clang/clang.gni +@@ -26,6 +26,9 @@ declare_args() { + build_with_chromium && !is_official_build && is_linux && !is_castos + + clang_base_path = default_clang_base_path ++ ++ # used only for linking ++ clang_base_path_target = default_clang_base_path + + # Specifies whether or not bitcode should be embedded during compilation. + # This is used for creating a MLGO corpus from Chromium in the non-ThinLTO case. +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0032-M118-fix-zlib-Fix-arm-build.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0032-M118-fix-zlib-Fix-arm-build.patch new file mode 100644 index 000000000..3c2b3a775 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0032-M118-fix-zlib-Fix-arm-build.patch @@ -0,0 +1,48 @@ +From 9ae234968078366877a1f8027423644ae7bbfb89 Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Mon, 13 Nov 2023 11:07:15 -0300 +Subject: [PATCH 32/33] [M118-fix] zlib: Fix arm build + +Prevent inclusion of cpuid on arm builds. + +error: + +third_party/zlib/cpu_features.c:15: +cpuid.h:14:2: error: this header is for x86 only + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + third_party/zlib/adler32_simd.c | 2 +- + third_party/zlib/cpu_features.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/third_party/zlib/adler32_simd.c b/third_party/zlib/adler32_simd.c +index 58966eecf0b80..25867ace82bd2 100644 +--- a/third_party/zlib/adler32_simd.c ++++ b/third_party/zlib/adler32_simd.c +@@ -49,7 +49,7 @@ + /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + #define NMAX 5552 + +-#if defined(ADLER32_SIMD_SSSE3) ++#if (__x86_64__ || __i386__) && defined(ADLER32_SIMD_SSSE3) + + #include <tmmintrin.h> + +diff --git a/third_party/zlib/cpu_features.c b/third_party/zlib/cpu_features.c +index 64e0428cd2fc2..c26c619970c10 100644 +--- a/third_party/zlib/cpu_features.c ++++ b/third_party/zlib/cpu_features.c +@@ -11,7 +11,7 @@ + #include <stdint.h> + #if defined(_MSC_VER) + #include <intrin.h> +-#elif defined(ADLER32_SIMD_SSSE3) ++#elif (__x86_64__ || __i386__) && defined(ADLER32_SIMD_SSSE3) + #include <cpuid.h> + #endif + +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0033-M118-fix-Fix-skia-linker-issues-for-arm-neon.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0033-M118-fix-Fix-skia-linker-issues-for-arm-neon.patch new file mode 100644 index 000000000..57f713b2d --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0033-M118-fix-Fix-skia-linker-issues-for-arm-neon.patch @@ -0,0 +1,56 @@ +From 0c37732e8443882518b79ce50b9389d1218484ef Mon Sep 17 00:00:00 2001 +From: Roger Zanoni <rzanoni@igalia.com> +Date: Mon, 13 Nov 2023 22:10:25 -0300 +Subject: [PATCH 33/33] [M118-fix] Fix skia linker issues for arm neon + +Fixes the following linker issue: + +error: undefined symbol: skia::ConvolveHorizontally_Neon(...) + +Upstream-Status: Inappropriate +Signed-off-by: Roger Zanoni <rzanoni@igalia.com> +--- + build/config/arm.gni | 5 +++++ + skia/ext/convolver.cc | 2 +- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/build/config/arm.gni b/build/config/arm.gni +index 575871c287c80..ebf56196c2605 100644 +--- a/build/config/arm.gni ++++ b/build/config/arm.gni +@@ -122,10 +122,14 @@ if (current_cpu == "arm" || v8_current_cpu == "arm") { + } + } + } ++ if (arm_use_neon) { ++ defines += [ "USE_NEON" ] ++ } + } else if (arm_use_neon == "" && (current_cpu == "arm64" || v8_current_cpu == "arm64")) { + # arm64 supports only "hard". + arm_float_abi = "hard" + arm_use_neon = true ++ defines += [ "USE_NEON" ] + declare_args() { + # Enables the new Armv8 branch protection features. Valid strings are: + # - "pac": Enables Pointer Authentication Code (PAC, featured in Armv8.3) +@@ -146,3 +150,4 @@ if (current_cpu == "arm" || v8_current_cpu == "arm") { + arm_control_flow_integrity == "pac", + "Invalid branch protection option") + } ++ +diff --git a/skia/ext/convolver.cc b/skia/ext/convolver.cc +index 8b3bd070d168a..a7d99de48d398 100644 +--- a/skia/ext/convolver.cc ++++ b/skia/ext/convolver.cc +@@ -371,7 +371,7 @@ void SetupSIMD(ConvolveProcs *procs) { + procs->extra_horizontal_reads = 3; + procs->convolve_vertically = &ConvolveVertically_mips_dspr2; + procs->convolve_horizontally = &ConvolveHorizontally_mips_dspr2; +-#elif defined SIMD_NEON ++#elif defined USE_NEON && defined SIMD_NEON + procs->extra_horizontal_reads = 3; + procs->convolve_vertically = &ConvolveVertically_Neon; + procs->convolve_4rows_horizontally = &Convolve4RowsHorizontally_Neon; +-- +2.42.1 + diff --git a/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0034-v8-qemu-wrapper.patch b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0034-v8-qemu-wrapper.patch new file mode 100644 index 000000000..dec3db353 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/files/chromium/0034-v8-qemu-wrapper.patch @@ -0,0 +1,66 @@ +From 733559e6f2c26ccbce97354a2341b14c63563dab Mon Sep 17 00:00:00 2001 +From: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com> +Date: Tue, 7 Nov 2017 15:24:32 +0100 +Subject: [PATCH] v8: qemu wrapper + +The patch below makes the V8 binaries run during the build be invoked through +QEMU, as they are built for the target. + +Upstream-Status: Inappropriate [embedder specific] + +Signed-off-by: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com> +Signed-off-by: Maksim Sisov <msisov@igalia.com> + +--- + tools/v8_context_snapshot/BUILD.gn | 1 + + v8/BUILD.gn | 4 ++++ + 2 files changed, 5 insertions(+) + +diff --git a/tools/v8_context_snapshot/BUILD.gn b/tools/v8_context_snapshot/BUILD.gn +index 52504f4..40425d6 100644 +--- a/tools/v8_context_snapshot/BUILD.gn ++++ b/tools/v8_context_snapshot/BUILD.gn +@@ -44,6 +44,7 @@ if (use_v8_context_snapshot) { + output_path = rebase_path(output_file, root_build_dir) + + args = [ ++ "./v8-qemu-wrapper.sh", + "./" + rebase_path(get_label_info(":v8_context_snapshot_generator", + "root_out_dir") + + "/v8_context_snapshot_generator", +diff --git a/v8/BUILD.gn b/v8/BUILD.gn +index 025203d..0c196bb 100644 +--- a/v8/BUILD.gn ++++ b/v8/BUILD.gn +@@ -2134,6 +2134,7 @@ template("run_torque") { + } + + args = [ ++ "./v8-qemu-wrapper.sh", + "./" + rebase_path( + get_label_info(":torque($toolchain)", "root_out_dir") + "/torque", + root_build_dir), +@@ -2291,6 +2292,7 @@ action("generate_bytecode_builtins_list") { + outputs = [ "$target_gen_dir/builtins-generated/bytecodes-builtins-list.h" ] + deps = [ ":bytecode_builtins_list_generator($v8_generator_toolchain)" ] + args = [ ++ "./v8-qemu-wrapper.sh", + "./" + rebase_path( + get_label_info( + ":bytecode_builtins_list_generator($v8_generator_toolchain)", +@@ -2330,6 +2332,7 @@ template("run_mksnapshot") { + data = [] + + args = [ ++ "./v8-qemu-wrapper.sh", + "./" + rebase_path(get_label_info(":mksnapshot($v8_snapshot_toolchain)", + "root_out_dir") + "/mksnapshot", + root_build_dir), +@@ -6931,6 +6934,7 @@ if (v8_enable_i18n_support) { + outputs = [ output_file ] + + args = [ ++ "./v8-qemu-wrapper.sh", + "./" + rebase_path( + get_label_info( + ":gen-regexp-special-case($v8_generator_toolchain)", diff --git a/meta-agl-html5-demo/recipes-wam/cef/gn-utils.inc b/meta-agl-html5-demo/recipes-wam/cef/gn-utils.inc new file mode 100644 index 000000000..34f8a12cc --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/cef/gn-utils.inc @@ -0,0 +1,115 @@ +# GN host architecture helpers. +# +# Copied from https://github.com/OSSystems/meta-browser +# +# BUILD_ARCH's value corresponds to what uname returns as the machine name. +# The mapping in gn_host_arch_name() tries to match several possible values +# returned by the Linux kernel in uname(2) into the corresponding values GN +# understands. + +def gn_host_arch_name(d): + """Returns a GN architecture name corresponding to the build host's machine + architecture.""" + import re + arch_translations = { + r'aarch64.*': 'arm64', + r'arm.*': 'arm', + r'i[3456]86$': 'x86', + r'x86_64$': 'x64', + } + build_arch = d.getVar("BUILD_ARCH") + for arch_regexp, gn_arch_name in arch_translations.items(): + if re.match(arch_regexp, build_arch): + return gn_arch_name + bb.fatal('Unsuported BUILD_ARCH value: "%s"' % build_arch) + +# GN target architecture helpers. +# +# Determining the target architecture is more difficult, as there are many +# different values we can use on the Yocto side (e.g. TUNE_ARCH, TARGET_ARCH, +# MACHINEOVERRIDES etc). What we do is define the mapping with regular, +# non-Python variables with overrides that are generic enough (i.e. "x86" +# instead of "i586") and then use gn_target_arch_name() to return the right +# value with some validation. +GN_TARGET_ARCH_NAME:aarch64 = "arm64" +GN_TARGET_ARCH_NAME:arm = "arm" +GN_TARGET_ARCH_NAME:x86 = "x86" +GN_TARGET_ARCH_NAME:x86-64 = "x64" + +def clang_install_path(d): + """Return clang compiler install path.""" + return d.getVar("STAGING_BINDIR_NATIVE") + +def gn_target_arch_name(d): + """Returns a GN architecture name corresponding to the target machine's + architecture.""" + name = d.getVar("GN_TARGET_ARCH_NAME") + if name is None: + bb.fatal('Unsupported target architecture. A valid override for the ' + 'GN_TARGET_ARCH_NAME variable could not be found.') + return name + +def write_toolchain_file(d, file_path): + """Creates a complete GN toolchain file in |file_path|.""" + import string + # Even though we always use clang, the "clang_toolchain" GN template is too + # restrictive in the way it sets variables such as |cxx|. Since it is just + # a wrapper on top of the "gcc_toolchain" template, we keep using the + # latter directly to accommodate our cross-compilation needs. + toolchain_tmpl = string.Template( + 'gcc_toolchain("${toolchain_name}") {\n' + ' cc = "${cc}"\n' + ' cxx = "${cxx}"\n' + ' ar = "${ar}"\n' + ' ld = cxx # GN expects a compiler, not a linker.\n' + ' nm = "${nm}"\n' + ' readelf = "${readelf}"\n' + ' extra_cflags = "${extra_cflags}"\n' + ' extra_cppflags = "${extra_cppflags}"\n' + ' extra_cxxflags = "${extra_cxxflags}"\n' + ' extra_ldflags = "${extra_ldflags}"\n' + ' toolchain_args = {\n' + ' current_cpu = "${current_cpu}"\n' + ' current_os = "linux"\n' + ' is_clang = true\n' + ' }\n' + '}\n' + ) + + native_toolchain = { + 'toolchain_name': 'yocto_native', + 'current_cpu': gn_host_arch_name(d), + 'cc': d.expand('${BUILD_CC}'), + 'cxx': d.expand('${BUILD_CXX}'), + 'ar': d.expand('${BUILD_AR}'), + 'nm': d.expand('${BUILD_NM}'), + 'readelf': d.expand('${BUILD_PREFIX}readelf'), + 'extra_cflags': d.expand('${BUILD_CFLAGS}'), + 'extra_cppflags': d.expand('${BUILD_CPPFLAGS}'), + 'extra_cxxflags': d.expand('${BUILD_CXXFLAGS}'), + 'extra_ldflags': d.expand('${BUILD_LDFLAGS}'), + } + target_toolchain = { + 'toolchain_name': 'yocto_target', + 'current_cpu': gn_target_arch_name(d), + 'cc': d.expand('${CC}'), + 'cxx': d.expand('${CXX}'), + 'ar': d.expand('${AR}'), + 'nm': d.expand('${NM}'), + 'readelf': d.expand('${READELF}'), + 'extra_cflags': d.expand('${CFLAGS}'), + 'extra_cppflags': d.expand('${CPPFLAGS}'), + 'extra_cxxflags': d.expand('${CXXFLAGS}'), + 'extra_ldflags': d.expand('${LDFLAGS}'), + } + + with open(file_path, 'w') as toolchain_file: + toolchain_file.write( + '# This file has been generated automatically.\n' + '\n' + 'import("//build/toolchain/gcc_toolchain.gni")\n' + '\n' + ) + toolchain_file.write(toolchain_tmpl.substitute(native_toolchain)) + toolchain_file.write(toolchain_tmpl.substitute(target_toolchain)) + diff --git a/meta-agl-html5-demo/recipes-wam/depot_tools/depot-tools-wam-native_git.bb b/meta-agl-html5-demo/recipes-wam/depot_tools/depot-tools-wam-native_git.bb new file mode 100644 index 000000000..9a466bb36 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/depot_tools/depot-tools-wam-native_git.bb @@ -0,0 +1,32 @@ +SUMMARY = " A collection of tools for dealing with Chromium development" +DESCRIPTION = "The Chromium depot_tools suite contains many tools to assist/augment the Chromium development environment." +HOMEPAGE = "https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html" + +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://LICENSE;md5=c2c05f9bdd5fc0b458037c2d1fb8d95e" + +SRC_URI = "git://chromium.googlesource.com/chromium/tools/depot_tools.git;protocol=https;branch=main" +SRCREV = "64b61755572b1d03b3a43f1a29b617dcae3a3fe0" + +S = "${WORKDIR}/git" + +inherit native + +do_compile[network] = "1" +do_compile() { + export PATH=${S}:$PATH + ./ensure_bootstrap +} + +do_install() { + install -d ${D}${datadir}/depot_tools + cp -aR --no-dereference --no-preserve=owner ${WORKDIR}/git/. ${D}${datadir}/depot_tools +} + +INSANE_SKIP:${PN} += "already-stripped file-rdeps" + +BBCLASSEXTEND = "native" + +FILES:${PN}-dev += " \ + ${datadir}/depot_tools/* \ +" diff --git a/meta-agl-html5-demo/recipes-wam/grpc-web-proxy/files/databroker-grpc-web-proxy.env b/meta-agl-html5-demo/recipes-wam/grpc-web-proxy/files/databroker-grpc-web-proxy.env new file mode 100644 index 000000000..1435253d3 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/grpc-web-proxy/files/databroker-grpc-web-proxy.env @@ -0,0 +1,7 @@ +EXTRA_ARGS="--backend_addr=localhost:55555 \ + --backend_client_tls_key_file=/etc/kuksa-val/Client.key \ + --backend_client_tls_cert_file=/etc/kuksa-val/Client.pem \ + --server_tls_key_file=/etc/kuksa-val/Server.key \ + --server_tls_cert_file=/etc/kuksa-val/Server.pem \ + --backend_tls_ca_files=/etc/kuksa-val/CA.pem --backend_tls=true \ + --server_http_tls_port=8888 --run_tls_server=true --allowed_origins=true" diff --git a/meta-agl-html5-demo/recipes-wam/grpc-web-proxy/files/databroker-grpc-web-proxy.service b/meta-agl-html5-demo/recipes-wam/grpc-web-proxy/files/databroker-grpc-web-proxy.service new file mode 100644 index 000000000..ff6afe44d --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/grpc-web-proxy/files/databroker-grpc-web-proxy.service @@ -0,0 +1,13 @@ +[Unit] +Description=gRPC web reverse proxy to kuksa.val databroker +Requires=kuksa-databroker.service +After=kuksa-databroker.service + +[Service] +User=kuksa +EnvironmentFile=-/etc/default/databroker-grpc-web-proxy.env +ExecStart=/usr/bin/grpcwebproxy $EXTRA_ARGS +Restart=on-abort + +[Install] +WantedBy=multi-user.target diff --git a/meta-agl-html5-demo/recipes-wam/grpc-web-proxy/grpc-web-proxy_git.bb b/meta-agl-html5-demo/recipes-wam/grpc-web-proxy/grpc-web-proxy_git.bb new file mode 100644 index 000000000..dfb763b64 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/grpc-web-proxy/grpc-web-proxy_git.bb @@ -0,0 +1,34 @@ +SUMMARY = "A small reverse proxy that can front existing gRPC servers and expose their functionality using gRPC-Web protocol, allowing for the gRPC services to be consumed from browsers." +HOMEPAGE = "https://github.com/improbable-eng/grpc-web" + +inherit go-mod systemd + +RDEPENDS:${PN} = "bash" +RDEPENDS:${PN}-dev = "bash" + +GO_IMPORT = "github.com/improbable-eng/grpc-web" +GO_INSTALL = "${GO_IMPORT}/go/grpcwebproxy" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://src/${GO_IMPORT}/LICENSE.txt;md5=71a6955f3cd81a809549da266346dc59" + +SRCREV = "1d9bbb09a0990bdaff0e37499570dbc7d6e58ce8" +SRC_URI = "git://${GO_IMPORT};branch=master;protocol=https \ + file://databroker-grpc-web-proxy.env \ + file://databroker-grpc-web-proxy.service" + +do_compile[network] = "1" + +do_install:append() { + install -d ${D}${systemd_system_unitdir} + install -m 0644 ${WORKDIR}/databroker-grpc-web-proxy.service ${D}${systemd_system_unitdir} + + install -d ${D}${sysconfdir}/default + install -m 0644 ${WORKDIR}/databroker-grpc-web-proxy.env ${D}${sysconfdir}/default/databroker-grpc-web-proxy.env +} + +SYSTEMD_SERVICE:${PN} = "databroker-grpc-web-proxy.service" + +FILES:${PN} = "${bindir} \ + ${systemd_system_unitdir} \ + ${sysconfdir}/default " diff --git a/meta-agl-html5-demo/recipes-wam/wam/files/0001-agl-cef-Snapshot-with-all-patches-needed-to-enable-w.patch b/meta-agl-html5-demo/recipes-wam/wam/files/0001-agl-cef-Snapshot-with-all-patches-needed-to-enable-w.patch new file mode 100644 index 000000000..65c2e7c66 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/wam/files/0001-agl-cef-Snapshot-with-all-patches-needed-to-enable-w.patch @@ -0,0 +1,3702 @@ +From 54da26083a7a08b73fe617b683c3f3c8c895c4a2 Mon Sep 17 00:00:00 2001 +From: Jose Dapena Paz <jdapena@igalia.com> +Date: Fri, 9 Jun 2023 14:08:08 +0200 +Subject: [PATCH] [agl][cef] Snapshot with all patches needed to enable wam-cef + +--- + CMakeLists.txt | 18 +- + src/CMakeLists.txt | 58 ++- + src/agl-cef/CMakeLists.txt | 54 +++ + src/agl-cef/plugin/CMakeLists.txt | 59 +++ + src/agl-cef/plugin/agl_cef_context.cc | 4 + + src/agl-cef/plugin/agl_cef_context.h | 42 ++ + src/agl-cef/plugin/background_cef_app.cc | 33 ++ + src/agl-cef/plugin/background_cef_app.h | 20 + + src/agl-cef/plugin/homescreen_cef_app.cc | 25 ++ + src/agl-cef/plugin/homescreen_cef_app.h | 15 + + src/agl-cef/plugin/regular_cef_app.cc | 11 + + src/agl-cef/plugin/regular_cef_app.h | 12 + + src/agl-cef/plugin/web_app_factory_agl_cef.cc | 49 +++ + src/agl-cef/plugin/web_app_factory_agl_cef.h | 23 ++ + src/agl-cef/web_runtime_agl_cef.cc | 63 +++ + src/agl-cef/web_runtime_agl_cef.h | 11 + + src/agl/web_runtime_agl.cc | 16 +- + src/agl/web_runtime_agl.h | 20 +- + src/cef/cli/CMakeLists.txt | 17 + + src/cef/cli/wam_cli.cc | 171 ++++++++ + src/cef/device_info_cef.cc | 104 +++++ + src/cef/device_info_cef.h | 38 ++ + src/cef/handlers/wam_cef_browser_handler.cc | 31 ++ + src/cef/handlers/wam_cef_browser_handler.h | 23 ++ + src/cef/handlers/wam_cef_client.cc | 39 ++ + src/cef/handlers/wam_cef_client.h | 31 ++ + src/cef/handlers/wam_cef_render_handler.cc | 135 +++++++ + src/cef/handlers/wam_cef_render_handler.h | 54 +++ + src/cef/platform_module_factory_cef.cc | 31 ++ + src/cef/platform_module_factory_cef.h | 27 ++ + src/cef/plugin/web_app_cef.cc | 172 ++++++++ + src/cef/plugin/web_app_cef.h | 95 +++++ + src/cef/plugin/web_page_cef.cc | 48 +++ + src/cef/plugin/web_page_cef.h | 69 ++++ + src/cef/service/CMakeLists.txt | 64 +++ + src/cef/service/applauncher.proto | 50 +++ + src/cef/service/applauncher_client_grpc.cc | 58 +++ + src/cef/service/applauncher_client_grpc.h | 24 ++ + src/cef/service/wam_ipc.proto | 22 + + .../service/web_app_manager_client_grpc.cc | 42 ++ + src/cef/service/web_app_manager_client_grpc.h | 23 ++ + .../service/web_app_manager_service_grpc.cc | 382 ++++++++++++++++++ + .../service/web_app_manager_service_grpc.h | 85 ++++ + src/core/CMakeLists.txt | 4 + + src/core/application_description.cc | 37 ++ + src/core/application_installation_handler.h | 12 + + .../application_installation_handler_stub.cc | 4 + + src/core/memory_pressure_level.h | 6 + + src/core/web_app_manager.cc | 29 +- + src/core/web_app_manager.h | 4 +- + src/core/web_app_manager_service.cc | 4 +- + src/core/web_app_manager_service.h | 3 +- + src/core/web_page_base.h | 6 +- + src/core/web_process_manager.h | 1 + + src/core/web_runtime.h | 3 +- + src/desktop/CMakeLists.txt | 100 +++++ + src/desktop/README.md | 102 +++++ + src/desktop/web_runtime_desktop.cc | 28 ++ + src/desktop/web_runtime_desktop.h | 11 + + src/platform/CMakeLists.txt | 23 +- + src/platform/web_app_window.h | 6 +- + src/util/log_msg_id.h | 2 + + src/util/timer.h | 4 +- + src/wam_main.cc | 4 +- + src/webos/web_app_manager_service_luna.cc | 2 + + src/webos/web_runtime_webos.cc | 2 +- + src/webos/web_runtime_webos.h | 2 +- + 67 files changed, 2693 insertions(+), 74 deletions(-) + create mode 100644 src/agl-cef/CMakeLists.txt + create mode 100644 src/agl-cef/plugin/CMakeLists.txt + create mode 100644 src/agl-cef/plugin/agl_cef_context.cc + create mode 100644 src/agl-cef/plugin/agl_cef_context.h + create mode 100644 src/agl-cef/plugin/background_cef_app.cc + create mode 100644 src/agl-cef/plugin/background_cef_app.h + create mode 100644 src/agl-cef/plugin/homescreen_cef_app.cc + create mode 100644 src/agl-cef/plugin/homescreen_cef_app.h + create mode 100644 src/agl-cef/plugin/regular_cef_app.cc + create mode 100644 src/agl-cef/plugin/regular_cef_app.h + create mode 100644 src/agl-cef/plugin/web_app_factory_agl_cef.cc + create mode 100644 src/agl-cef/plugin/web_app_factory_agl_cef.h + create mode 100644 src/agl-cef/web_runtime_agl_cef.cc + create mode 100644 src/agl-cef/web_runtime_agl_cef.h + create mode 100644 src/cef/cli/CMakeLists.txt + create mode 100644 src/cef/cli/wam_cli.cc + create mode 100644 src/cef/device_info_cef.cc + create mode 100644 src/cef/device_info_cef.h + create mode 100644 src/cef/handlers/wam_cef_browser_handler.cc + create mode 100644 src/cef/handlers/wam_cef_browser_handler.h + create mode 100644 src/cef/handlers/wam_cef_client.cc + create mode 100644 src/cef/handlers/wam_cef_client.h + create mode 100644 src/cef/handlers/wam_cef_render_handler.cc + create mode 100644 src/cef/handlers/wam_cef_render_handler.h + create mode 100644 src/cef/platform_module_factory_cef.cc + create mode 100644 src/cef/platform_module_factory_cef.h + create mode 100644 src/cef/plugin/web_app_cef.cc + create mode 100644 src/cef/plugin/web_app_cef.h + create mode 100644 src/cef/plugin/web_page_cef.cc + create mode 100644 src/cef/plugin/web_page_cef.h + create mode 100644 src/cef/service/CMakeLists.txt + create mode 100644 src/cef/service/applauncher.proto + create mode 100644 src/cef/service/applauncher_client_grpc.cc + create mode 100644 src/cef/service/applauncher_client_grpc.h + create mode 100644 src/cef/service/wam_ipc.proto + create mode 100644 src/cef/service/web_app_manager_client_grpc.cc + create mode 100644 src/cef/service/web_app_manager_client_grpc.h + create mode 100644 src/cef/service/web_app_manager_service_grpc.cc + create mode 100644 src/cef/service/web_app_manager_service_grpc.h + create mode 100644 src/core/application_installation_handler.h + create mode 100644 src/core/application_installation_handler_stub.cc + create mode 100644 src/core/memory_pressure_level.h + create mode 100644 src/desktop/CMakeLists.txt + create mode 100644 src/desktop/README.md + create mode 100644 src/desktop/web_runtime_desktop.cc + create mode 100644 src/desktop/web_runtime_desktop.h + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 1e9f94f..073e326 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -18,22 +18,24 @@ cmake_minimum_required(VERSION 3.13.0) + + project(WebAppMgr VERSION 1.0.0 LANGUAGES CXX) + +-set(CMAKE_CXX_STANDARD 14) ++set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +-set(CMAKE_BUILD_TYPE Release) + + include(FindPkgConfig) + + set(OS_WEBOS FALSE) + set(OS_AGL FALSE) +-set(PLATFORM_NAME "WebOS" CACHE STRING "Target platform name (WebOS, POKY_AGL)") ++set(OS_DESKTOP FALSE) ++set(WEBENGINE_CEF TRUE) ++set(WEBENGINE_CBE FALSE) ++set(PLATFORM_NAME "Desktop" CACHE STRING "Target platform name (WebOS, POKY_AGL, Desktop)") + string(TOLOWER ${PLATFORM_NAME} PLATFORM) + if(${PLATFORM} STREQUAL "webos") + set(OS_WEBOS TRUE) + elseif(${PLATFORM} MATCHES ".*agl") + set(OS_AGL TRUE) + else() +- message(FATAL_ERROR "Unsupported platform: ${PLATFORM}") ++ set(OS_DESKTOP TRUE) + endif() + + if(OS_WEBOS) +@@ -45,4 +47,12 @@ if(OS_WEBOS) + webos_build_system_bus_files(${CMAKE_SOURCE_DIR}/files/sysbus) + endif() + ++message(STATUS "WAM Configuration:") ++message(STATUS "OS_WEBOS: ${OS_WEBOS}") ++message(STATUS "OS_AGL: ${OS_AGL}") ++message(STATUS "OS_DESKTOP: ${OS_DESKTOP}") ++message(STATUS "WEBENGINE_CEF: ${WEBENGINE_CEF}") ++message(STATUS "WEBENGINE_CBE: ${WEBENGINE_CBE}") ++message(STATUS "PLATFORM_NAME: ${PLATFORM_NAME}") ++ + add_subdirectory(src) +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 3cca138..173dafc 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -18,10 +18,12 @@ project(WebAppMgrExec VERSION 1.0.0 DESCRIPTION "WAM") + + set(WAM_ROOT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +-if(NOT DEFINED CHROMIUM_SRC_DIR) +- message(FATAL_ERROR "CHROMIUM_SRC_DIR was not set") ++if (WEBVIEW_CBE) ++ if(NOT DEFINED CHROMIUM_SRC_DIR) ++ message(FATAL_ERROR "CHROMIUM_SRC_DIR was not set") ++ endif() ++ set(CHROMIUM_LDFLAGS -lcbe) + endif() +-set(CHROMIUM_LDFLAGS -lcbe) + + find_package(PkgConfig REQUIRED) + find_package(Boost COMPONENTS filesystem REQUIRED) +@@ -39,6 +41,8 @@ elseif(OS_AGL) + find_package(gRPC REQUIRED) + find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED) + find_package(Threads) ++elseif(OS_DESKTOP) ++ set(DISABLE_PMLOG(true)) + endif() + + if(DISABLE_PMLOG) +@@ -58,7 +62,6 @@ set(WAM_COMPILER_FLAGS -fno-rtti + -Wall + -fpermissive + -funwind-tables +- -std=c++14 + -Wno-psabi + -Werror + ) +@@ -70,29 +73,68 @@ endif() + add_link_options(-Wl,--no-as-needed -Wno-psabi -rdynamic) + + add_subdirectory(core) +-add_subdirectory(platform) + + set(WAM_INCLUDE_DIRS + ${GLIB_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR}/core + ${CMAKE_CURRENT_SOURCE_DIR}/util +- ${CMAKE_CURRENT_SOURCE_DIR}/webos + ) + + set(WAM_LIBS + ${CHROMIUM_LDFLAGS} + ${PMLOGLIB_LDFLAGS} +- WebAppMgr + WebAppMgrCore + ) + ++if(WEBENGINE_CBE) ++ add_subdirectory(platform) ++ LIST(APPEND WAM_INCLUDE_DIRS ++ ${CMAKE_CURRENT_SOURCE_DIR}/webos ++ ) ++ LIST(APPEND WAM_LIBS ++ WebAppMgr ++ ) ++endif() ++ ++if(OS_DESKTOP OR WEBENGINE_CEF) ++ if(NOT DEFINED CEF_ROOT) ++ message(FATAL_ERROR "CEF_ROOT needs to point to the binary distribution directory") ++ endif() ++ ++ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CEF_ROOT}/cmake") ++ find_package(CEF REQUIRED) ++ message(STATUS "CEF lib location: ${CEF_LIB_RELEASE}") ++ print_cef_config() ++ ++ add_subdirectory(${CEF_LIBCEF_DLL_WRAPPER_PATH} libcef_dll_wrapper) ++ add_library(libcef_lib SHARED IMPORTED) ++ set_target_properties(libcef_lib PROPERTIES IMPORTED_LOCATION ${CEF_LIB_RELEASE}) ++ target_link_libraries(libcef_dll_wrapper libcef_lib) ++ ++ LIST(APPEND WAM_LIBS libcef_lib libcef_dll_wrapper) ++endif() ++ ++if(OS_DESKTOP) ++ add_subdirectory(desktop) ++ add_subdirectory(cef/service) ++ add_subdirectory(cef/cli) ++ LIST(APPEND WAM_LIBS WebAppMgrDesktop) ++endif() ++ + if(OS_WEBOS) + add_subdirectory(plugin) + add_subdirectory(tests) + add_subdirectory(testplugin) + LIST(APPEND WAM_LIBS ${LIBLUNAPREFS_LDFLAGS}) + elseif(OS_AGL) +- add_subdirectory(agl/plugin) ++ if(WEBENGINE_CEF) ++ add_subdirectory(agl-cef) ++ add_subdirectory(cef/service) ++ add_subdirectory(cef/cli) ++ LIST(APPEND WAM_LIBS WebAppMgrAGLCEF) ++ else() ++ add_subdirectory(agl/plugin) ++ endif() + LIST(APPEND WAM_INCLUDE_DIRS + ${Protobuf_INCLUDE_DIRS} + ${gRPC_INCLUDE_DIRS} +diff --git a/src/agl-cef/CMakeLists.txt b/src/agl-cef/CMakeLists.txt +new file mode 100644 +index 0000000..8d29004 +--- /dev/null ++++ b/src/agl-cef/CMakeLists.txt +@@ -0,0 +1,54 @@ ++project(WebAppMgrAGLCEF VERSION 1.0.0 DESCRIPTION "Web Application Manager library") ++ ++set(WAM_LIB_LIBS ++ ${JSONCPP_LDFLAGS} ++ WebAppMgrCore ++ WebAppMgrService ++ libcef_lib ++ libcef_dll_wrapper ++) ++ ++set(SOURCES ++ web_runtime_agl_cef.cc ++) ++ ++set(HEADERS ++ web_runtime_agl_cef.h ++) ++ ++set(WAM_LIB_CEF_DIR ${WAM_ROOT_SOURCE_DIR}/cef) ++ ++set(WAM_LIB_INCLUDE_DIRS ++ ${JSONCPP_INCLUDE_DIRS} ++ ${CEF_INCLUDE_PATH} ++) ++ ++LIST(APPEND SOURCES ++ ${WAM_LIB_CEF_DIR}/device_info_cef.cc ++ ${WAM_LIB_CEF_DIR}/platform_module_factory_cef.cc ++ ${WAM_LIB_CEF_DIR}/handlers/wam_cef_browser_handler.cc ++ ${WAM_LIB_CEF_DIR}/handlers/wam_cef_client.cc ++ ${WAM_LIB_CEF_DIR}/handlers/wam_cef_render_handler.cc ++) ++LIST(APPEND HEADERS ++ ${WAM_LIB_CEF_DIR}/device_info_cef.h ++ ${WAM_LIB_CEF_DIR}/platform_module_factory_cef.h ++ ${WAM_LIB_CEF_DIR}/handlers/wam_cef_browser_handler.h ++ ${WAM_LIB_CEF_DIR}/handlers/wam_cef_client.h ++ ${WAM_LIB_CEF_DIR}/handlers/wam_cef_render_handler.cc ++) ++LIST(APPEND WAM_LIB_INCLUDE_DIRS ++ ${WAM_LIB_CEF_DIR} ++ ${WAM_LIB_CEF_DIR}/handlers ++) ++ ++add_library(${PROJECT_NAME} SHARED ${HEADERS} ${SOURCES}) ++target_include_directories(${PROJECT_NAME} PUBLIC ${WAM_LIB_INCLUDE_DIRS}) ++set_target_properties(${PROJECT_NAME} PROPERTIES VERSION 1.0.0 SOVERSION 1.0) ++ ++install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/webappmanager) ++ ++target_link_libraries(${PROJECT_NAME} PUBLIC ${WAM_LIB_LIBS}) ++install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) ++ ++add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/plugin) +diff --git a/src/agl-cef/plugin/CMakeLists.txt b/src/agl-cef/plugin/CMakeLists.txt +new file mode 100644 +index 0000000..052c94e +--- /dev/null ++++ b/src/agl-cef/plugin/CMakeLists.txt +@@ -0,0 +1,59 @@ ++project(webappmgr-default-plugin VERSION 1.0.0 DESCRIPTION "Default WAM plugin") ++ ++set(CEF_PLUGINS_DIR ${WAM_ROOT_SOURCE_DIR}/cef/plugin) ++set(CEF_HANDLERS_DIR ${WAM_ROOT_SOURCE_DIR}/cef/handlers) ++ ++set (SOURCES ++ ${CEF_HANDLERS_DIR}/wam_cef_client.cc ++ ${CEF_PLUGINS_DIR}/web_app_cef.cc ++ ${CEF_PLUGINS_DIR}/web_page_cef.cc ++ agl_cef_context.cc ++ web_app_factory_agl_cef.cc ++ background_cef_app.cc ++ homescreen_cef_app.cc ++ regular_cef_app.cc ++) ++set (HEADERS ++ ${CEF_HANDLERS_DIR}/wam_cef_client.h ++ ${CEF_PLUGINS_DIR}/web_app_cef.h ++ ${CEF_PLUGINS_DIR}/web_page_cef.h ++ agl_cef_context.h ++ web_app_factory_agl_cef.h ++ background_cef_app.h ++ homescreen_cef_app.h ++ regular_cef_app.h ++) ++set (WAM_PLUGIN_INCLUDE_DIRS ++ ${CEF_HANDLERS_DIR} ++ ${CEF_PLUGINS_DIR} ++ ${WAM_ROOT_SOURCE_DIR} ++ ${WAM_ROOT_SOURCE_DIR}/core ++ ${WAM_ROOT_SOURCE_DIR}/platform ++ ${WAM_ROOT_SOURCE_DIR}/platform/webengine ++ ${WAM_ROOT_SOURCE_DIR}/util ++ ${CEF_INCLUDE_PATH} ++) ++set(WAM_PLUGIN_LIBS ++ WebAppMgrService ++ WebAppMgrService-grpc ++ libcef_lib ++ libcef_dll_wrapper ++) ++ ++if (OS_DESKTOP) ++ LIST(APPEND WAM_PLUGIN_LIBS ++ WebAppMgrDesktop ++ ) ++else() ++ LIST(APPEND WAM_PLUGIN_LIBS ++ WebAppMgrAGLCEF ++ ) ++endif() ++ ++add_library(${PROJECT_NAME} SHARED ${HEADERS} ${SOURCES}) ++add_dependencies(${PROJECT_NAME} libcef_lib libcef_dll_wrapper) ++ ++target_include_directories(${PROJECT_NAME} PRIVATE ${WAM_PLUGIN_INCLUDE_DIRS}) ++target_link_libraries(${PROJECT_NAME} PRIVATE ${WAM_PLUGIN_LIBS}) ++install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/webappmanager/plugins) ++install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webappmanager) +diff --git a/src/agl-cef/plugin/agl_cef_context.cc b/src/agl-cef/plugin/agl_cef_context.cc +new file mode 100644 +index 0000000..8c1a390 +--- /dev/null ++++ b/src/agl-cef/plugin/agl_cef_context.cc +@@ -0,0 +1,4 @@ ++#include "agl_cef_context.h" ++ ++AglCefContext* AglCefContext::instance_ = nullptr; ++ +diff --git a/src/agl-cef/plugin/agl_cef_context.h b/src/agl-cef/plugin/agl_cef_context.h +new file mode 100644 +index 0000000..a1e698f +--- /dev/null ++++ b/src/agl-cef/plugin/agl_cef_context.h +@@ -0,0 +1,42 @@ ++#ifndef AGL_CEF_PLUGIN_AGL_CEF_CONTEXT_H ++#define AGL_CEF_PLUGIN_AGL_CEF_CONTEXT_H ++ ++#include <memory> ++ ++class AglCefContext { ++ public: ++ AglCefContext(const AglCefContext&) = delete; ++ AglCefContext& operator=(const AglCefContext&) = delete; ++ ++ static AglCefContext* get() { ++ if (!instance_) { ++ instance_ = new AglCefContext(); ++ } ++ return instance_; ++ } ++ ++ uint32_t activation_area_width() const { return activation_area_width_; } ++ void set_activation_area_width(uint32_t activation_area_width) { ++ activation_area_width_ = activation_area_width; ++ } ++ ++ uint32_t activation_area_height() const { return activation_area_height_; } ++ void set_activation_area_height(uint32_t activation_area_height) { ++ activation_area_height_ = activation_area_height; ++ } ++ ++ uint32_t panel_offset() const { return panel_offset_; } ++ void set_panel_offset(uint32_t panel_offset) { ++ panel_offset_ = panel_offset; ++ } ++ ++ private: ++ AglCefContext() = default; ++ ++ static AglCefContext* instance_; ++ uint32_t activation_area_width_ = 0; ++ uint32_t activation_area_height_ = 0; ++ uint32_t panel_offset_ = 0; ++}; ++ ++#endif // AGL_CEF_PLUGIN_AGL_CEF_CONTEXT_H +diff --git a/src/agl-cef/plugin/background_cef_app.cc b/src/agl-cef/plugin/background_cef_app.cc +new file mode 100644 +index 0000000..c406641 +--- /dev/null ++++ b/src/agl-cef/plugin/background_cef_app.cc +@@ -0,0 +1,33 @@ ++#include "background_cef_app.h" ++ ++BackgroundCefApp::BackgroundCefApp(std::shared_ptr<ApplicationDescription> app_desc) ++ : WebAppCEF(app_desc) { ++ CefRect display_bounds = GetDisplayBounds(); ++ width_override_ = display_bounds.width; ++ height_override_ = display_bounds.height; ++} ++ ++BackgroundCefApp::~BackgroundCefApp() {} ++ ++void BackgroundCefApp::Init(int width, ++ int height, ++ AglShellSurfaceType surface_type, ++ AglShellPanelEdge panel_type) { ++ if (!IsReady()) { ++ return; ++ } ++ ++ /* ++ // TODO: change when in portrait mode ++ window_->SetupActivationArea(AglCefContext::get()->panel_offset(), ++ 0, ++ AglCefContext::get()->activation_area_width(), ++ AglCefContext::get()->activation_area_height()); ++ */ ++ ++ WebAppCEF::Init(width, height, surface_type, panel_type); ++} ++ ++bool BackgroundCefApp::IsReady() const { ++ return window_ != nullptr; ++} +diff --git a/src/agl-cef/plugin/background_cef_app.h b/src/agl-cef/plugin/background_cef_app.h +new file mode 100644 +index 0000000..6681b5d +--- /dev/null ++++ b/src/agl-cef/plugin/background_cef_app.h +@@ -0,0 +1,20 @@ ++#ifndef AGL_CEF_PLUGIN_BACKGROUND_CEF_APP_H ++#define AGL_CEF_PLUGIN_BACKGROUND_CEF_APP_H ++ ++#include "agl_cef_context.h" ++#include "web_app_cef.h" ++ ++class BackgroundCefApp : public WebAppCEF { ++ public: ++ BackgroundCefApp(std::shared_ptr<ApplicationDescription> app_desc); ++ ~BackgroundCefApp(); ++ ++ void Init(int width, ++ int height, ++ AglShellSurfaceType surface_type, ++ AglShellPanelEdge panel_type) override; ++ ++ bool IsReady() const override; ++}; ++ ++#endif // AGL_CEF_PLUGIN_BACKGROUND_CEF_APP_H +diff --git a/src/agl-cef/plugin/homescreen_cef_app.cc b/src/agl-cef/plugin/homescreen_cef_app.cc +new file mode 100644 +index 0000000..cc6af64 +--- /dev/null ++++ b/src/agl-cef/plugin/homescreen_cef_app.cc +@@ -0,0 +1,25 @@ ++#include "homescreen_cef_app.h" ++ ++#include "agl_cef_context.h" ++ ++HomescreenCefApp::HomescreenCefApp(std::shared_ptr<ApplicationDescription> app_desc) ++ : WebAppCEF(app_desc) { ++ CefRect display_bounds = GetDisplayBounds(); ++ uint32_t panel_offset = app_desc->WidthOverride(); // TODO: height when in portrait mode ++ uint32_t activation_width = display_bounds.width - panel_offset - 1; ++ uint32_t activation_height = display_bounds.height; ++ ++ // TODO: change when in portrait mode ++ width_override_ = panel_offset; ++ height_override_ = activation_height; ++ ++ AglCefContext::get()->set_panel_offset(panel_offset); ++ AglCefContext::get()->set_activation_area_width(activation_width); ++ AglCefContext::get()->set_activation_area_height(activation_height); ++} ++ ++HomescreenCefApp::~HomescreenCefApp() {} ++ ++bool HomescreenCefApp::IsReady() const { ++ return window_ && window_->IsSurfaceConfigured(); ++} +diff --git a/src/agl-cef/plugin/homescreen_cef_app.h b/src/agl-cef/plugin/homescreen_cef_app.h +new file mode 100644 +index 0000000..c4f86ab +--- /dev/null ++++ b/src/agl-cef/plugin/homescreen_cef_app.h +@@ -0,0 +1,15 @@ ++#ifndef AGL_CEF_PLUGIN_HOMESCREEN_CEF_APP_H ++#define AGL_CEF_PLUGIN_HOMESCREEN_CEF_APP_H ++ ++#include "web_app_cef.h" ++ ++class HomescreenCefApp : public WebAppCEF { ++ public: ++ HomescreenCefApp(std::shared_ptr<ApplicationDescription> app_desc); ++ ~HomescreenCefApp(); ++ ++ protected: ++ bool IsReady() const override; ++}; ++ ++#endif // AGL_CEF_PLUGIN_BACKGROUND_CEF_APP_H +diff --git a/src/agl-cef/plugin/regular_cef_app.cc b/src/agl-cef/plugin/regular_cef_app.cc +new file mode 100644 +index 0000000..a882314 +--- /dev/null ++++ b/src/agl-cef/plugin/regular_cef_app.cc +@@ -0,0 +1,11 @@ ++#include "regular_cef_app.h" ++ ++#include "agl_cef_context.h" ++ ++RegularCefApp::RegularCefApp(std::shared_ptr<ApplicationDescription> app_desc) ++ : WebAppCEF(app_desc) { ++ width_override_ = AglCefContext::get()->activation_area_width(); ++ height_override_ = AglCefContext::get()->activation_area_height(); ++} ++ ++RegularCefApp::~RegularCefApp() {} +diff --git a/src/agl-cef/plugin/regular_cef_app.h b/src/agl-cef/plugin/regular_cef_app.h +new file mode 100644 +index 0000000..ed4b34d +--- /dev/null ++++ b/src/agl-cef/plugin/regular_cef_app.h +@@ -0,0 +1,12 @@ ++#ifndef AGL_CEF_PLUGIN_REGULAR_CEF_APP_H ++#define AGL_CEF_PLUGIN_REGULAR_CEF_APP_H ++ ++#include "web_app_cef.h" ++ ++class RegularCefApp : public WebAppCEF { ++ public: ++ RegularCefApp(std::shared_ptr<ApplicationDescription> app_desc); ++ ~RegularCefApp(); ++}; ++ ++#endif // AGL_CEF_PLUGIN_REGULAR_CEF_APP_H +diff --git a/src/agl-cef/plugin/web_app_factory_agl_cef.cc b/src/agl-cef/plugin/web_app_factory_agl_cef.cc +new file mode 100644 +index 0000000..8ca2ba8 +--- /dev/null ++++ b/src/agl-cef/plugin/web_app_factory_agl_cef.cc +@@ -0,0 +1,49 @@ ++#include "web_app_factory_agl_cef.h" ++ ++#include "application_description.h" ++#include "plugin_interface.h" ++ ++#include "background_cef_app.h" ++#include "homescreen_cef_app.h" ++#include "regular_cef_app.h" ++ ++#include "web_page_cef.h" ++ ++#include "wam_cef_client.h" ++ ++const char* kPluginApplicationType = "default"; ++ ++WebAppFactoryInterface* CreateInstance() { ++ return new WebAppFactoryCEF(); ++} ++ ++void DeleteInstance(WebAppFactoryInterface* interface) { ++ delete interface; ++} ++ ++WebAppBase* WebAppFactoryCEF::CreateWebApp( ++ const std::string&, ++ std::shared_ptr<ApplicationDescription> app_desc) { ++ std::string app_id = app_desc->Id(); ++ ++ if (app_id == "homescreen") { ++ return new HomescreenCefApp(app_desc); ++ } else if (app_id == "webapps-html5-background") { ++ return new BackgroundCefApp(app_desc); ++ } ++ return new RegularCefApp(app_desc); ++} ++ ++WebAppBase* WebAppFactoryCEF::CreateWebApp( ++ const std::string& win_type, ++ WebPageBase*, ++ std::shared_ptr<ApplicationDescription> desc) { ++ return CreateWebApp(win_type, desc); ++} ++ ++WebPageBase* WebAppFactoryCEF::CreateWebPage( ++ const wam::Url& url, ++ std::shared_ptr<ApplicationDescription> app_desc, ++ const std::string&) { ++ return new WebPageCEF(app_desc, url.ToString()); ++} +diff --git a/src/agl-cef/plugin/web_app_factory_agl_cef.h b/src/agl-cef/plugin/web_app_factory_agl_cef.h +new file mode 100644 +index 0000000..eb4b7ba +--- /dev/null ++++ b/src/agl-cef/plugin/web_app_factory_agl_cef.h +@@ -0,0 +1,23 @@ ++#ifndef AGL_CEF_PLUGIN_WEB_APP_FACTORY_CEF_H ++#define AGL_CEF_PLUGIN_WEB_APP_FACTORY_CEF_H ++ ++#include <memory> ++#include <string> ++ ++#include "web_app_factory_interface.h" ++ ++class WebAppFactoryCEF : public WebAppFactoryInterface { ++ public: ++ WebAppBase* CreateWebApp( ++ const std::string& win_type, ++ std::shared_ptr<ApplicationDescription> desc = 0) override; ++ WebAppBase* CreateWebApp( ++ const std::string& win_type, ++ WebPageBase* page, ++ std::shared_ptr<ApplicationDescription> desc = 0) override; ++ WebPageBase* CreateWebPage(const wam::Url& url, ++ std::shared_ptr<ApplicationDescription> desc, ++ const std::string& launchParams = "") override; ++}; ++ ++#endif // AGL_CEF_PLUGIN_WEB_APP_FACTORY_CEF_H +diff --git a/src/agl-cef/web_runtime_agl_cef.cc b/src/agl-cef/web_runtime_agl_cef.cc +new file mode 100644 +index 0000000..9bc1bd6 +--- /dev/null ++++ b/src/agl-cef/web_runtime_agl_cef.cc +@@ -0,0 +1,63 @@ ++#include "web_runtime_agl_cef.h" ++ ++#include "include/cef_base.h" ++#include "include/cef_origin_whitelist.h" ++ ++#include "wam_cef_browser_handler.h" ++#include "wam_cef_render_handler.h" ++ ++const char kProcessType[] = "type"; ++const char kRendererProcess[] = "renderer"; ++const char kZygoteProcess[] = "zygote"; ++ ++class WamCefUtilityHandler : public CefApp { ++ public: ++ WamCefUtilityHandler () {} ++ ++ private: ++ IMPLEMENT_REFCOUNTING(WamCefUtilityHandler); ++ DISALLOW_COPY_AND_ASSIGN(WamCefUtilityHandler); ++}; ++ ++int WebRuntimeCEF::Run(int argc, char** argv) { ++ CefMainArgs main_args(argc, argv); ++ ++ CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine(); ++ command_line->InitFromArgv(main_args.argc, main_args.argv); ++ ++ std::string app_id = command_line->GetSwitchValue("appid"); ++ if (app_id.empty()) { ++ app_id = "WebAppMgr"; ++ } ++ ++ CefRefPtr<CefApp> app; ++ if (!command_line->HasSwitch(kProcessType)) { ++ app = new WamCefBrowserHandler(); ++ } else { ++ const std::string& process_type = command_line->GetSwitchValue(kProcessType); ++ if (process_type == kRendererProcess || process_type == kZygoteProcess) { ++ app = new WamCefRenderHandler(); ++ } else { ++ app = new WamCefUtilityHandler(); ++ } ++ } ++ ++ auto exit_code = CefExecuteProcess(main_args, app.get(), nullptr); ++ if (exit_code >= 0) { ++ return exit_code; ++ } ++ ++ CefSettings settings; ++ settings.remote_debugging_port = 9998; ++ CefInitialize(main_args, settings, app.get(), nullptr); ++ ++ CefRunMessageLoop(); ++ ++ CefShutdown(); ++ ++ return 0; ++} ++ ++std::unique_ptr<WebRuntime> WebRuntime::Create() { ++ return std::make_unique<WebRuntimeCEF>(); ++} +diff --git a/src/agl-cef/web_runtime_agl_cef.h b/src/agl-cef/web_runtime_agl_cef.h +new file mode 100644 +index 0000000..049e554 +--- /dev/null ++++ b/src/agl-cef/web_runtime_agl_cef.h +@@ -0,0 +1,11 @@ ++#ifndef AGL_CEF_WEB_RUNTIME_AGL_CEF_H_ ++#define AGL_CEF_WEB_RUNTIME_AGL_CEF_H_ ++ ++#include "web_runtime.h" ++ ++class WebRuntimeCEF : public WebRuntime { ++ public: ++ int Run(int argc, char** argv) override; ++}; ++ ++#endif // AGL_CEF_WEB_RUNTIME_CEF_H_ +diff --git a/src/agl/web_runtime_agl.cc b/src/agl/web_runtime_agl.cc +index ce8525b..c791c70 100644 +--- a/src/agl/web_runtime_agl.cc ++++ b/src/agl/web_runtime_agl.cc +@@ -128,7 +128,7 @@ void SingleBrowserProcessWebAppLauncher::Launch( + } + + int SingleBrowserProcessWebAppLauncher::Loop(int argc, +- const char** argv, ++ char** argv, + volatile sig_atomic_t& e_flag) { + AGLMainDelegateWAM delegate; + webos::WebOSMain webOSMain(&delegate); +@@ -154,7 +154,7 @@ void SharedBrowserProcessWebAppLauncher::Launch( + } + + int SharedBrowserProcessWebAppLauncher::Loop(int argc, +- const char** argv, ++ char** argv, + volatile sig_atomic_t& e_flag) { + // TODO: wait for a pid + while (e_flag) +@@ -173,7 +173,7 @@ static void AglShellActivateApp(const std::string& app_id) { + WebAppManagerServiceAGL::Instance()->SendEvent(kActivateEvent, app_id); + } + +-int WebAppLauncherRuntime::Run(int argc, const char** argv) { ++int WebAppLauncherRuntime::Run(int argc, char** argv) { + bool is_wait_host_service = IsWaitForHostService(); + std::string app_id = IsActivateApp(Args::Instance()); + +@@ -334,7 +334,7 @@ bool WebAppLauncherRuntime::ParseJsonConfig(const char* path_to_config) { + return true; + } + +-int SharedBrowserProcessRuntime::Run(int argc, const char** argv) { ++int SharedBrowserProcessRuntime::Run(int argc, char** argv) { + if (WebAppManagerServiceAGL::Instance()->InitializeAsHostService()) { + AGLMainDelegateWAM delegate; + webos::WebOSMain webOSMain(&delegate); +@@ -347,7 +347,7 @@ int SharedBrowserProcessRuntime::Run(int argc, const char** argv) { + } + } + +-int RenderProcessRuntime::Run(int argc, const char** argv) { ++int RenderProcessRuntime::Run(int argc, char** argv) { + AGLMainDelegateWAM delegate; + webos::WebOSMain webOSMain(&delegate); + return webOSMain.Run(argc, argv); +@@ -372,7 +372,7 @@ static void print_help(void) { + exit(EXIT_FAILURE); + } + +-void Args::parse_args(int argc, const char** argv) { ++void Args::parse_args(int argc, char** argv) { + int c; + int option_index; + opterr = 0; +@@ -427,7 +427,7 @@ void Args::parse_args(int argc, const char** argv) { + } + } + +-void Args::copy_cmdline(int argc, const char** argv) { ++void Args::copy_cmdline(int argc, char** argv) { + new_argc = argc; + new_argv = static_cast<char**>(calloc(new_argc + 1, sizeof(*new_argv))); + +@@ -446,7 +446,7 @@ void Args::clear_cmdline(void) { + free(new_argv); + } + +-int WebRuntimeAGL::Run(int argc, const char** argv) { ++int WebRuntimeAGL::Run(int argc, char** argv) { + int ret; + Args::Instance()->parse_args(argc, argv); + +diff --git a/src/agl/web_runtime_agl.h b/src/agl/web_runtime_agl.h +index ad045c2..14bc0ed 100644 +--- a/src/agl/web_runtime_agl.h ++++ b/src/agl/web_runtime_agl.h +@@ -39,7 +39,7 @@ class Args { + static Args* args = new Args(); + return args; + } +- void parse_args(int argc, const char** argv); ++ void parse_args(int argc, char** argv); + + inline void set_flag(unsigned int flag) { flags |= flag; } + +@@ -56,7 +56,7 @@ class Args { + + private: + uint32_t flags = FLAG_NONE; +- void copy_cmdline(int argc, const char** argv); ++ void copy_cmdline(int argc, char** argv); + char** new_argv; + int new_argc; + }; +@@ -69,9 +69,7 @@ class Launcher { + AglShellPanelEdge panel_edge, + int width, + int height) = 0; +- virtual int Loop(int argc, +- const char** argv, +- volatile sig_atomic_t& e_flag) = 0; ++ virtual int Loop(int argc, char** argv, volatile sig_atomic_t& e_flag) = 0; + }; + + class SharedBrowserProcessWebAppLauncher : public Launcher { +@@ -82,7 +80,7 @@ class SharedBrowserProcessWebAppLauncher : public Launcher { + AglShellPanelEdge panel_edge, + int width, + int height) override; +- int Loop(int argc, const char** argv, volatile sig_atomic_t& e_flag) override; ++ int Loop(int argc, char** argv, volatile sig_atomic_t& e_flag) override; + }; + + class SingleBrowserProcessWebAppLauncher : public Launcher { +@@ -93,12 +91,12 @@ class SingleBrowserProcessWebAppLauncher : public Launcher { + AglShellPanelEdge panel_edge, + int width, + int height) override; +- int Loop(int argc, const char** argv, volatile sig_atomic_t& e_flag) override; ++ int Loop(int argc, char** argv, volatile sig_atomic_t& e_flag) override; + }; + + class WebAppLauncherRuntime : public WebRuntime { + public: +- int Run(int argc, const char** argv) override; ++ int Run(int argc, char** argv) override; + + private: + bool Init(Args* args); +@@ -127,17 +125,17 @@ class WebAppLauncherRuntime : public WebRuntime { + + class SharedBrowserProcessRuntime : public WebRuntime { + public: +- int Run(int argc, const char** argv) override; ++ int Run(int argc, char** argv) override; + }; + + class RenderProcessRuntime : public WebRuntime { + public: +- int Run(int argc, const char** argv) override; ++ int Run(int argc, char** argv) override; + }; + + class WebRuntimeAGL : public WebRuntime { + public: +- int Run(int argc, const char** argv) override; ++ int Run(int argc, char** argv) override; + + private: + WebRuntime* runtime_; +diff --git a/src/cef/cli/CMakeLists.txt b/src/cef/cli/CMakeLists.txt +new file mode 100644 +index 0000000..1b5f04a +--- /dev/null ++++ b/src/cef/cli/CMakeLists.txt +@@ -0,0 +1,17 @@ ++project(WebAppMgrCli VERSION 1.0.0 DESCRIPTION "Web Application Manager cli helper") ++ ++set(CLI_EXE ${PROJECT_NAME}) ++set(CLI_EXE_INCLUDE_DIRS ++ ${WAM_ROOT_SOURCE_DIR}/util ++) ++ ++set(CLI_EXE_LIBS ++ WebAppMgrCore ++ WebAppMgrService ++ WebAppMgrService-grpc ++) ++ ++add_executable(${CLI_EXE} wam_cli.cc) ++target_include_directories(${CLI_EXE} PUBLIC ${CLI_EXE_INCLUDE_DIRS}) ++target_link_libraries(${CLI_EXE} PUBLIC ${CLI_EXE_LIBS}) ++install(TARGETS ${CLI_EXE} DESTINATION ${CMAKE_INSTALL_BINDIR}) +diff --git a/src/cef/cli/wam_cli.cc b/src/cef/cli/wam_cli.cc +new file mode 100644 +index 0000000..4775ce4 +--- /dev/null ++++ b/src/cef/cli/wam_cli.cc +@@ -0,0 +1,171 @@ ++// Copyright (c) 2018-2022 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 <getopt.h> ++#include <optional> ++ ++#include "web_app_manager_client_grpc.h" ++ ++#include "log_manager.h" ++ ++class Args { ++ public: ++ enum flags { ++ FLAG_NONE = 0, ++ FLAG_APP_TYPE = 1 << 0, ++ FLAG_ACTIVATE_APP = 1 << 1, ++ FLAG_HTTP_LINK = 1 << 2, ++ FLAG_APP_ID = 1 << 3, ++ FLAG_APP_DIR = 1 << 4, ++ }; ++ ++ static Args* Instance() { ++ static Args* args = new Args(); ++ return args; ++ } ++ void PrintHelp(void) { ++ fprintf(stderr, "WAM: Web Application Manager\n"); ++ fprintf(stderr, ++ "\t[--activate_app=appid] -- activate application. Interrnal " ++ "usage.\n\tNot needing for starting applications.\n"); ++ fprintf(stderr, ++ "\t[--appid=appid] name of an application id.\n\tRequired if " ++ "starting a " ++ "web application.\n"); ++ fprintf( ++ stderr, ++ "\t[--app-install-dir=/path/to/root_index] installation path for web " ++ "application.\n\tRequired if starting a web application.\n"); ++ fprintf(stderr, "\t-h -- this help message \n"); ++ exit(EXIT_FAILURE); ++ } ++ ++ void ParseArgs(int argc, char** argv) { ++ int c; ++ int option_index; ++ opterr = 0; ++ ++ CopyCmdLine(argc, argv); ++ ++ struct option long_opts[] = {{"help", no_argument, 0, 'h'}, ++ {"activate-app", required_argument, 0, 'x'}, ++ {"appid", required_argument, 0, 'a'}, ++ {"app-install-dir", required_argument, 0, 'd'}, ++ {0, 0, 0, 0}}; ++ ++ while ((c = getopt_long(new_argc, new_argv, "ht:a:i:d:", long_opts, ++ &option_index)) != -1) { ++ switch (c) { ++ case 'h': ++ PrintHelp(); ++ break; ++ case 'x': ++ activate_app_id_ = optarg; ++ break; ++ case 'a': ++ app_id_ = optarg; ++ break; ++ case 'd': ++ app_dir_ = optarg; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ if (optind < new_argc) { ++ // check for 'http://' ++ int p = optind; ++ while (p < new_argc) { ++ if (!strcmp(new_argv[p], "http://")) { ++ http_link_ = new_argv[p]; ++ break; ++ } ++ p++; ++ } ++ } ++ } ++ ++ void ClearCmdLine() { ++ for (int i = 0; i < new_argc; i++) ++ free(new_argv[i]); ++ free(new_argv); ++ } ++ ++ std::string GetAppId() const { ++ return app_id_.has_value() ? *app_id_ : std::string(); ++ } ++ ++ std::string GetAppUri() const { ++ if (http_link_.has_value()) ++ return *http_link_; ++ else if (app_dir_.has_value()) ++ return *app_dir_; ++ return std::string(); ++ } ++ ++ bool HasActivateAppId() const { return activate_app_id_.has_value(); } ++ std::string GetActivateAppId() const { ++ return activate_app_id_.has_value() ? *activate_app_id_ : std::string(); ++ } ++ ++ private: ++ void CopyCmdLine(int argc, char** argv) { ++ new_argc = argc; ++ new_argv = static_cast<char**>(calloc(new_argc + 1, sizeof(*new_argv))); ++ ++ for (int i = 0; i < new_argc; i++) { ++ size_t len = strlen(argv[i]) + 1; ++ new_argv[i] = static_cast<char*>(calloc(len, sizeof(char))); ++ memcpy(new_argv[i], argv[i], len); ++ } ++ ++ new_argv[argc] = nullptr; ++ } ++ char** new_argv; ++ int new_argc; ++ ++ std::optional<std::string> activate_app_id_; ++ std::optional<std::string> http_link_; ++ std::optional<std::string> app_id_; ++ std::optional<std::string> app_dir_; ++}; ++ ++WebAppManagerClientGRPC* GetGrpcClient() { ++ static std::unique_ptr<WebAppManagerClientGRPC> grpc_client; ++ if (!grpc_client) { ++ grpc_client = std::make_unique<WebAppManagerClientGRPC>(); ++ } ++ return grpc_client.get(); ++} ++ ++int main(int argc, char** argv) { ++ auto* args = Args::Instance(); ++ args->ParseArgs(argc, argv); ++ ++ // TODO: handle completed grpc calls ++ // and get the correct ok() result ++ if (args->HasActivateAppId()) { ++ GetGrpcClient()->Activate(args->GetActivateAppId()); ++ } else { ++ WebAppManagerClientGRPC::LaunchParams params; ++ params.app_id = args->GetAppId(); ++ params.uri = args->GetAppUri(); ++ GetGrpcClient()->Launch(params); ++ } ++ ++ return 0; ++} +diff --git a/src/cef/device_info_cef.cc b/src/cef/device_info_cef.cc +new file mode 100644 +index 0000000..f5fd681 +--- /dev/null ++++ b/src/cef/device_info_cef.cc +@@ -0,0 +1,104 @@ ++#include "device_info_cef.h" ++ ++#include <string> ++ ++#include <glib.h> ++#include <json/value.h> ++ ++#include "log_manager.h" ++#include "utils.h" ++ ++DeviceInfoCEF::DeviceInfoCEF() = default; ++ ++void DeviceInfoCEF::Initialize() { ++ const std::string& json_string = ++ util::ReadFile("/var/luna/preferences/localeInfo"); ++ if (json_string.empty()) { ++ return; ++ } ++ ++ Json::Value locale_json = util::StringToJson(json_string); ++ if (!locale_json.isObject() || locale_json.empty() || ++ !locale_json["localeInfo"].isObject() || ++ !locale_json["localeInfo"]["locales"].isObject() || ++ !locale_json["localeInfo"]["locales"]["UI"].isString() || ++ !locale_json["country"].isString() || ++ !locale_json["smartServiceCountryCode3"].isString()) { ++ LOG_ERROR(MSGID_LOCALEINFO_READ_FAIL, 1, ++ PMLOGKS("CONTENT", json_string.c_str()), ""); ++ return; ++ } ++ ++ Json::Value locale_info = locale_json["localeInfo"]; ++ ++ std::string language(locale_info["locales"]["UI"].asString()); ++ std::string localcountry(locale_json["country"].asString()); ++ std::string smartservicecountry( ++ locale_json["smartServiceCountryCode3"].asString()); ++ ++ SetSystemLanguage(language.c_str()); ++ SetDeviceInfo("LocalCountry", localcountry.c_str()); ++ SetDeviceInfo("SmartServiceCountry", smartservicecountry.c_str()); ++} ++ ++void DeviceInfoCEF::InitDisplayInfo() { ++ // Display information ++ // -------------------------------------------------------- ++ float screen_density_ = 1.0f; ++ int hardware_screen_width = 0; ++ int hardware_screen_height = 0; ++ ++ std::string hardware_screen_width_str; ++ std::string hardware_screen_height_str; ++ if (GetDeviceInfo("HardwareScreenWidth", hardware_screen_width_str) && ++ GetDeviceInfo("HardwareScreenHeight", hardware_screen_height_str)) { ++ hardware_screen_width = ++ util::StrToIntWithDefault(hardware_screen_width_str, 0); ++ hardware_screen_height = ++ util::StrToIntWithDefault(hardware_screen_height_str, 0); ++ } else { ++ GetDisplayWidth(hardware_screen_width); ++ GetDisplayHeight(hardware_screen_height); ++ } ++ ++ screen_width_ = static_cast<int>(hardware_screen_width / screen_density_); ++ screen_height_ = static_cast<int>(hardware_screen_height / screen_density_); ++} ++ ++void DeviceInfoCEF::InitPlatformInfo() { ++ // normally like this info ++ /* ++ "modelName": "WEBOS1", ++ "platformVersion": "00.00.00", ++ "platformVersionDot": 00, ++ "platformVersionMajor_pos": 00, ++ "platformVersionMinor": 00, ++ */ ++ ++ std::string value; ++ if (GetDeviceInfo("ModelName", value)) ++ model_name_ = value; ++ if (GetDeviceInfo("FirmwareVersion", value)) ++ platform_version_ = value; ++ ++ size_t major_pos = 0, minor_pos = 0; ++ major_pos = platform_version_.find_first_of('.'); ++ if (major_pos != std::string::npos && ++ major_pos <= platform_version_.size() - 1) ++ minor_pos = platform_version_.find_first_of('.', major_pos + 1); ++ if (major_pos == std::string::npos || minor_pos == std::string::npos) { ++ version_major_ = version_minor_ = version_dot_ = -1; ++ } else { ++ version_major_ = ++ util::StrToIntWithDefault(platform_version_.substr(0, major_pos), 0); ++ version_minor_ = util::StrToIntWithDefault( ++ platform_version_.substr(major_pos + 1, minor_pos), 0); ++ version_dot_ = ++ util::StrToIntWithDefault(platform_version_.substr(minor_pos + 1), 0); ++ } ++} ++ ++void DeviceInfoCEF::GatherInfo() { ++ InitDisplayInfo(); ++ InitPlatformInfo(); ++} +diff --git a/src/cef/device_info_cef.h b/src/cef/device_info_cef.h +new file mode 100644 +index 0000000..e2b3712 +--- /dev/null ++++ b/src/cef/device_info_cef.h +@@ -0,0 +1,38 @@ ++#ifndef CEF_DEVICE_INFO_CEF_H_ ++#define CEF_DEVICE_INFO_CEF_H_ ++ ++#include <string> ++ ++#include "device_info.h" ++ ++class DeviceInfoCEF : public DeviceInfo { ++ public: ++ DeviceInfoCEF(); ++ ++ void Initialize() override; ++ ++ private: ++ int screen_width_ = 0; ++ int screen_height_ = 0; ++ ++ float screen_density_ = 1.0f; ++ ++ std::string model_name_ = "webOS.Open.CEF"; ++ std::string platform_version_ = "00.00.00"; ++ ++ // platform versions are <major>.<minor>.<dot> ++ int version_major_ = 0; ++ int version_minor_ = 0; ++ int version_dot_ = 0; ++ ++ bool support_3d_ = false; ++ std::string ota_id_; ++ std::string hardware_version_ = "0x00000001"; ++ std::string firmware_version_ = "00.00.01"; ++ ++ void InitDisplayInfo(); ++ void InitPlatformInfo(); ++ void GatherInfo(); ++}; ++ ++#endif // CEF_DEVICE_INFO_IMPL_H_ +diff --git a/src/cef/handlers/wam_cef_browser_handler.cc b/src/cef/handlers/wam_cef_browser_handler.cc +new file mode 100644 +index 0000000..0708363 +--- /dev/null ++++ b/src/cef/handlers/wam_cef_browser_handler.cc +@@ -0,0 +1,31 @@ ++#include "wam_cef_browser_handler.h" ++ ++#include "log_manager.h" ++#include "log_msg_id.h" ++#include "platform_module_factory_cef.h" ++#include "wam_cef_client.h" ++#include "web_app_manager_service_grpc.h" ++ ++WamCefBrowserHandler::WamCefBrowserHandler() : ++ client_(new WamCefClient()) { ++ WebAppManager::Instance()->SetPlatformModules( ++ std::make_unique<PlatformModuleFactoryCEF>()); ++} ++ ++WamCefBrowserHandler::~WamCefBrowserHandler() {} ++ ++CefRefPtr<CefBrowserProcessHandler> WamCefBrowserHandler::GetBrowserProcessHandler() { ++ return this; ++} ++ ++CefRefPtr<CefClient> WamCefBrowserHandler::GetDefaultClient() { ++ return client_; ++} ++ ++void WamCefBrowserHandler::OnContextInitialized() { ++ if (!WebAppManagerServiceGRPC::Instance()->InitializeAsHostService()) { ++ LOG_ERROR(MSGID_ERROR_CANNOT_LOCK_SERVICE, 0, ++ "Cannot lock WAM GRPC service IPC"); ++ } ++ WebAppManagerServiceGRPC::Instance()->StartService(); ++} +diff --git a/src/cef/handlers/wam_cef_browser_handler.h b/src/cef/handlers/wam_cef_browser_handler.h +new file mode 100644 +index 0000000..58c7f20 +--- /dev/null ++++ b/src/cef/handlers/wam_cef_browser_handler.h +@@ -0,0 +1,23 @@ ++#ifndef CEF_HANDLERS_WAM_CEF_BROWSER_HANDLER_H ++#define CEF_HANDLERS_WAM_CEF_BROWSER_HANDLER_H ++ ++#include "include/cef_app.h" ++#include "include/cef_browser_process_handler.h" ++ ++#include "wam_cef_client.h" ++ ++class WamCefBrowserHandler : public CefApp, public CefBrowserProcessHandler { ++ public: ++ WamCefBrowserHandler(); ++ virtual ~WamCefBrowserHandler(); ++ ++ CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() override; ++ CefRefPtr<CefClient> GetDefaultClient() override; ++ void OnContextInitialized() override; ++ ++ private: ++ IMPLEMENT_REFCOUNTING(WamCefBrowserHandler); ++ CefRefPtr<WamCefClient> client_; ++}; ++ ++#endif // CEF_HANDLERS_WAM_CEF_BROWSER_HANDLER_H +diff --git a/src/cef/handlers/wam_cef_client.cc b/src/cef/handlers/wam_cef_client.cc +new file mode 100644 +index 0000000..5ba6201 +--- /dev/null ++++ b/src/cef/handlers/wam_cef_client.cc +@@ -0,0 +1,39 @@ ++#include "wam_cef_client.h" ++ ++#include "include/wrapper/cef_helpers.h" ++ ++WamCefClient* g_instance = nullptr; ++ ++WamCefClient::WamCefClient() { ++ DCHECK(!g_instance); ++ g_instance = this; ++} ++ ++// static ++WamCefClient* WamCefClient::GetInstance() { ++ return g_instance; ++} ++ ++bool WamCefClient::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, ++ CefRefPtr<CefFrame> frame, ++ CefProcessId source_process, ++ CefRefPtr<CefProcessMessage> message) { ++ std::string message_name = message->GetName(); ++ CefRefPtr<CefListValue> args = message->GetArgumentList(); ++ if (message_name == "start") { ++ if (args->GetSize() != 1) { ++ return false; ++ } ++ std::string app_id = args->GetString(0); ++ applauncher_.Start(app_id); ++ return true; ++ } else if (message_name == "get_applications") { ++ if (args->GetSize() != 1) { ++ return false; ++ } ++ bool only_graphical = args->GetBool(0); ++ applauncher_.GetApplications(browser, only_graphical); ++ return true; ++ } ++ return false; ++} +diff --git a/src/cef/handlers/wam_cef_client.h b/src/cef/handlers/wam_cef_client.h +new file mode 100644 +index 0000000..3189c42 +--- /dev/null ++++ b/src/cef/handlers/wam_cef_client.h +@@ -0,0 +1,31 @@ ++#ifndef CEF_HANDLERS_WAM_CEF_CLIENT_H ++#define CEF_HANDLERS_WAM_CEF_CLIENT_H ++ ++#include "include/cef_client.h" ++ ++#include "applauncher_client_grpc.h" ++ ++class WamCefClient : public CefClient, ++ public CefLifeSpanHandler { ++ public: ++ WamCefClient(); ++ ++ static WamCefClient* GetInstance(); ++ ++ CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { ++ return this; ++ } ++ ++ bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, ++ CefRefPtr<CefFrame> frame, ++ CefProcessId source_process, ++ CefRefPtr<CefProcessMessage> message) override; ++ ++ private: ++ AppLauncherClientGRPC applauncher_; ++ ++ IMPLEMENT_REFCOUNTING(WamCefClient); ++ DISALLOW_COPY_AND_ASSIGN(WamCefClient); ++}; ++ ++#endif // CEF_HANDLERS_WAM_CEF_CLIENT_H +diff --git a/src/cef/handlers/wam_cef_render_handler.cc b/src/cef/handlers/wam_cef_render_handler.cc +new file mode 100644 +index 0000000..48c881a +--- /dev/null ++++ b/src/cef/handlers/wam_cef_render_handler.cc +@@ -0,0 +1,135 @@ ++#include "wam_cef_render_handler.h" ++ ++#include "include/cef_parser.h" ++#include "include/cef_process_message.h" ++ ++WamCefRenderHandler::WamCefRenderHandler() {} ++ ++void WamCefRenderHandler::OnContextCreated(CefRefPtr<CefBrowser> browser, ++ CefRefPtr<CefFrame> frame, ++ CefRefPtr<CefV8Context> context) { ++ ++ CefRefPtr<CefV8Value> app_service = CefV8Value::CreateObject(nullptr, nullptr); ++ ++ CefRefPtr<CefV8Value> start = CefV8Value::CreateFunction("start", this); ++ app_service->SetValue("start", start, V8_PROPERTY_ATTRIBUTE_NONE); ++ ++ CefRefPtr<CefV8Value> get_applications = CefV8Value::CreateFunction("getApplications", this); ++ app_service->SetValue("getApplications", get_applications, V8_PROPERTY_ATTRIBUTE_NONE); ++ ++ CefRefPtr<CefV8Value> global = context->GetGlobal(); // window object ++ CefRefPtr<CefV8Value> navigator = global->GetValue("navigator"); ++ ++ navigator->SetValue("appService", app_service, V8_PROPERTY_ATTRIBUTE_NONE); ++} ++ ++void WamCefRenderHandler::OnContextReleased(CefRefPtr<CefBrowser> browser, ++ CefRefPtr<CefFrame> frame, ++ CefRefPtr<CefV8Context> context) { ++ if (callback_map_.empty()) { ++ return; ++ } ++ ++ CallbackMap::iterator it = callback_map_.begin(); ++ for (; it != callback_map_.end();) { ++ if (it->second.first->IsSame(context)) { ++ callback_map_.erase(it++); ++ } else { ++ ++it; ++ } ++ } ++} ++ ++void WamCefRenderHandler::Start(const std::string &app_id) { ++ CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create("start"); ++ CefRefPtr<CefListValue> args = message->GetArgumentList(); ++ args->SetString(0, app_id); ++ auto context = CefV8Context::GetCurrentContext(); ++ context->GetFrame()->SendProcessMessage(PID_BROWSER, message); ++} ++ ++void WamCefRenderHandler::GetApplications(bool only_graphical, CefRefPtr<CefV8Value> callback) { ++ std::string message_name = "get_applications"; ++ ++ // store the callback until we receive the browser's response ++ CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext(); ++ int browser_id = context->GetBrowser()->GetIdentifier(); ++ callback_map_.insert( ++ std::make_pair(std::make_pair(message_name, browser_id), ++ std::make_pair(context, callback))); ++ ++ CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(message_name); ++ CefRefPtr<CefListValue> args = message->GetArgumentList(); ++ args->SetBool(0, only_graphical); ++ context->GetFrame()->SendProcessMessage(PID_BROWSER, message); ++} ++ ++bool WamCefRenderHandler::Execute(const CefString& name, ++ CefRefPtr<CefV8Value> object, ++ const CefV8ValueList& arguments, ++ CefRefPtr<CefV8Value>& retval, ++ CefString& exception) { ++ if (name == "start") { ++ if (arguments.size() != 1 || !arguments[0]->IsString()) { ++ return false; ++ } ++ std::string app_id = arguments[0]->GetStringValue(); ++ Start(app_id); ++ return true; ++ } else if (name == "getApplications") { ++ if (arguments.size() != 2 || ++ !arguments[0]->IsBool() || ++ !arguments[1]->IsFunction()) { ++ return false; ++ } ++ GetApplications(arguments[0]->GetBoolValue(), arguments[1]); ++ return true; ++ } ++ ++ return false; ++} ++ ++bool WamCefRenderHandler::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, ++ CefRefPtr<CefFrame> frame, ++ CefProcessId source_process, ++ CefRefPtr<CefProcessMessage> message) { ++ std::string message_name = message->GetName(); ++ CefRefPtr<CefListValue> args = message->GetArgumentList(); ++ if (message_name == "get_applications") { ++ CallbackMap::const_iterator it = callback_map_.find( ++ std::make_pair(message_name, ++ browser->GetIdentifier())); ++ if (it == callback_map_.end()) { ++ return false; ++ } ++ ++ CefRefPtr<CefV8Context> context = it->second.first; ++ CefRefPtr<CefV8Value> callback = it->second.second; ++ ++ context->Enter(); ++ ++ CefRefPtr<CefValue> apps_list_value = CefParseJSON(args->GetString(0), JSON_PARSER_RFC); ++ ++ CefRefPtr<CefListValue> list = apps_list_value->GetList(); ++ int size = list->GetSize(); ++ CefRefPtr<CefV8Value> apps_list = CefV8Value::CreateArray(size); ++ for (int i = 0; i < size; i++) { ++ CefRefPtr<CefDictionaryValue> app_info_dict = list->GetDictionary(i); ++ CefRefPtr<CefV8Value> dict = CefV8Value::CreateObject(nullptr, nullptr); ++ dict->SetValue("id", CefV8Value::CreateString(app_info_dict->GetString("id")), V8_PROPERTY_ATTRIBUTE_NONE); ++ dict->SetValue("name", CefV8Value::CreateString(app_info_dict->GetString("name")), V8_PROPERTY_ATTRIBUTE_NONE); ++ dict->SetValue("icon", CefV8Value::CreateString(app_info_dict->GetString("icon")), V8_PROPERTY_ATTRIBUTE_NONE); ++ apps_list->SetValue(i, dict); ++ } ++ ++ CefV8ValueList arguments; ++ arguments.push_back(apps_list); ++ callback->ExecuteFunctionWithContext(context, nullptr, arguments); ++ ++ context->Exit(); ++ ++ return true; ++ } ++ ++ return false; ++} +diff --git a/src/cef/handlers/wam_cef_render_handler.h b/src/cef/handlers/wam_cef_render_handler.h +new file mode 100644 +index 0000000..4a05ed6 +--- /dev/null ++++ b/src/cef/handlers/wam_cef_render_handler.h +@@ -0,0 +1,54 @@ ++#ifndef CEF_HANDLERS_WAM_CEF_RENDER_HANDLER_H ++#define CEF_HANDLERS_WAM_CEF_RENDER_HANDLER_H ++ ++#include <map> ++#include <string> ++ ++#include "include/cef_app.h" ++#include "include/cef_render_process_handler.h" ++#include "include/cef_v8.h" ++ ++class WamCefRenderHandler : public CefApp, ++ public CefRenderProcessHandler, ++ public CefV8Handler { ++ public: ++ typedef std::map<std::pair<std::string, int>, ++ std::pair<CefRefPtr<CefV8Context>, CefRefPtr<CefV8Value>>> CallbackMap; ++ ++ WamCefRenderHandler(); ++ ++ CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override { ++ return this; ++ } ++ ++ void OnContextCreated(CefRefPtr<CefBrowser> browser, ++ CefRefPtr<CefFrame> frame, ++ CefRefPtr<CefV8Context> context) override; ++ ++ ++ void OnContextReleased(CefRefPtr<CefBrowser> browser, ++ CefRefPtr<CefFrame> frame, ++ CefRefPtr<CefV8Context> context) override; ++ ++ bool Execute(const CefString& name, ++ CefRefPtr<CefV8Value> object, ++ const CefV8ValueList& arguments, ++ CefRefPtr<CefV8Value>& retval, ++ CefString& exception) override; ++ ++ bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, ++ CefRefPtr<CefFrame> frame, ++ CefProcessId source_process, ++ CefRefPtr<CefProcessMessage> message) override; ++ ++ void Start(const std::string &app_id); ++ void GetApplications(bool only_graphical, CefRefPtr<CefV8Value> callback); ++ ++ private: ++ IMPLEMENT_REFCOUNTING(WamCefRenderHandler); ++ DISALLOW_COPY_AND_ASSIGN(WamCefRenderHandler); ++ ++ CallbackMap callback_map_; ++}; ++ ++#endif // CEF_HANDLERS_WAM_CEF_RENDER_HANDLER_H +diff --git a/src/cef/platform_module_factory_cef.cc b/src/cef/platform_module_factory_cef.cc +new file mode 100644 +index 0000000..e225b9d +--- /dev/null ++++ b/src/cef/platform_module_factory_cef.cc +@@ -0,0 +1,31 @@ ++#include "platform_module_factory_cef.h" ++ ++#include "device_info_cef.h" ++#include "service_sender.h" ++#include "web_app_manager_config.h" ++#include "web_process_manager.h" ++ ++PlatformModuleFactoryCEF::PlatformModuleFactoryCEF() { ++ PrepareRenderingContext(); ++} ++ ++std::unique_ptr<ServiceSender> ++PlatformModuleFactoryCEF::CreateServiceSender() { ++ return nullptr; ++} ++ ++std::unique_ptr<WebProcessManager> ++PlatformModuleFactoryCEF::CreateWebProcessManager() { ++ return nullptr; ++} ++ ++std::unique_ptr<DeviceInfo> PlatformModuleFactoryCEF::CreateDeviceInfo() { ++ return std::make_unique<DeviceInfoCEF>(); ++} ++ ++std::unique_ptr<WebAppManagerConfig> ++PlatformModuleFactoryCEF::CreateWebAppManagerConfig() { ++ return std::unique_ptr<WebAppManagerConfig>(new WebAppManagerConfig()); ++} ++ ++void PlatformModuleFactoryCEF::PrepareRenderingContext() {} +diff --git a/src/cef/platform_module_factory_cef.h b/src/cef/platform_module_factory_cef.h +new file mode 100644 +index 0000000..5015dda +--- /dev/null ++++ b/src/cef/platform_module_factory_cef.h +@@ -0,0 +1,27 @@ ++#ifndef CEF_PLATFORM_MODULE_FACTORY_CEF_H_ ++#define CEF_PLATFORM_MODULE_FACTORY_CEF_H_ ++ ++#include <memory> ++ ++#include "platform_module_factory.h" ++ ++class ServiceSender; ++class WebProcessManager; ++class DeviceInfo; ++class WebAppManagerConfig; ++ ++class PlatformModuleFactoryCEF : public PlatformModuleFactory { ++ public: ++ PlatformModuleFactoryCEF(); ++ ++ protected: ++ std::unique_ptr<ServiceSender> CreateServiceSender() override; ++ std::unique_ptr<WebProcessManager> CreateWebProcessManager() override; ++ std::unique_ptr<DeviceInfo> CreateDeviceInfo() override; ++ std::unique_ptr<WebAppManagerConfig> CreateWebAppManagerConfig() override; ++ ++ private: ++ void PrepareRenderingContext(); ++}; ++ ++#endif // CEF_PLATFORM_MODULE_FACTORY_CEF_H_ +diff --git a/src/cef/plugin/web_app_cef.cc b/src/cef/plugin/web_app_cef.cc +new file mode 100644 +index 0000000..f57212b +--- /dev/null ++++ b/src/cef/plugin/web_app_cef.cc +@@ -0,0 +1,172 @@ ++#include "web_app_cef.h" ++ ++#include "include/base/cef_callback.h" ++#include "include/views/cef_display.h" ++#include "include/wrapper/cef_closure_task.h" ++ ++#include "web_page_cef.h" ++ ++WebAppCEF::WebAppCEF(std::shared_ptr<ApplicationDescription> app_desc) { ++ SetAppDescription(app_desc); ++} ++ ++WebAppCEF::~WebAppCEF() {} ++ ++void WebAppCEF::Init(int width, ++ int height, ++ AglShellSurfaceType surface_type, ++ AglShellPanelEdge panel_type) { ++ ApplicationDescription* app_desc = GetAppDescription(); ++ std::string app_id = app_desc->Id(); ++ ++ if (!IsReady()) { ++ return; ++ } ++ ++ surface_type_ = surface_type; ++ panel_type_ = panel_type; ++ ++ switch (surface_type_) { ++ case AglShellSurfaceType::kBackground: ++ window_->AglSetBackGroundApp(); ++ window_->AglSetAppReady(); ++ break; ++ case AglShellSurfaceType::kPanel: ++ window_->AglSetPanelApp(static_cast<int>(panel_type_)); ++ break; ++ case AglShellSurfaceType::kNone: ++ surface_type_ = AglShellSurfaceType::kNone; ++ CefPostDelayedTask( ++ TID_UI, ++ base::BindOnce(&WebAppCEF::DelayedActivate, this), ++ 500); ++ break; ++ } ++} ++ ++void WebAppCEF::TryInitialize() { ++ ApplicationDescription* app_desc = GetAppDescription(); ++ ++ if (!IsReady()) { ++ CefPostDelayedTask( ++ TID_UI, ++ base::BindOnce(&WebAppCEF::TryInitialize, this), ++ 500); ++ return; ++ // TODO: add a maximum number of retries ++ } ++ ++ Init(app_desc->WidthOverride(), ++ app_desc->HeightOverride(), ++ app_desc->SurfaceType(), ++ app_desc->PanelType()); ++} ++ ++void WebAppCEF::Attach(WebPageBase* web_page) { ++ WebAppBase::Attach(web_page); ++ ++ WebPageCEF* web_page_cef = static_cast<WebPageCEF*>(Page()); ++ if (!web_page_cef) { ++ // TODO: handle error ++ return; ++ } ++ web_page_cef->SetWebApp(this); ++} ++ ++void WebAppCEF::OnWindowCreated(CefRefPtr<CefWindow> window) { ++ if (!browser_view_) { ++ return; ++ } ++ ++ window_ = window; ++ window_->AddChildView(browser_view_); ++ window_->Show(); ++ ++ TryInitialize(); ++} ++ ++CefRect WebAppCEF::GetDisplayBounds() const { ++ CefRefPtr<CefDisplay> display = CefDisplay::GetPrimaryDisplay(); ++ CefRect display_bounds; ++ if (display) { ++ display_bounds = display->GetBounds(); ++ } ++ return display_bounds; ++} ++ ++CefSize WebAppCEF::GetPreferredSize(CefRefPtr<CefView> view) { ++ return CefSize(width_override_, height_override_); ++} ++ ++CefRect WebAppCEF::GetInitialBounds(CefRefPtr<CefWindow> window) { ++ return CefRect(0, 0, width_override_, height_override_); ++} ++ ++void WebAppCEF::SendAglReady() { ++ // Empty because it's called on Init() ++} ++ ++void WebAppCEF::SetAglAppId(const char* app_id) { ++ if (!window_) { ++ return; ++ } ++ window_->SetTitle(app_id); ++ window_->AglSetAppId(app_id); ++} ++ ++void WebAppCEF::SendAglActivate(const char* app_id) { ++ if (!window_) { ++ return; ++ } ++ window_->AglActivateApp(app_id); ++} ++ ++void WebAppCEF::Resize(int width, int height) { ++ if (!window_) { ++ return; ++ } ++ window_->SetSize(CefSize(width, height)); ++} ++ ++bool WebAppCEF::IsReady() const { ++ return window_ != nullptr; ++} ++ ++void WebAppCEF::Hide(bool forced_hide) { ++ if (!window_) { ++ return; ++ } ++ window_->Hide(); ++} ++ ++bool WebAppCEF::HideWindow() { ++ if (!window_) { ++ return false; ++ } ++ window_->Hide(); ++ return true; ++} ++ ++void WebAppCEF::Raise() { ++ if (!window_) { ++ return; ++ } ++ window_->BringToTop(); ++} ++ ++void WebAppCEF::DelayedActivate() { ++ ApplicationDescription* app_desc = GetAppDescription(); ++ SendAglActivate(app_desc->Id().c_str()); ++} ++ ++void WebAppCEF::Relaunch(const std::string& args, ++ const std::string& launching_app_id) { ++ if (!window_) { ++ return; ++ } ++ ++ ApplicationDescription* app_desc = GetAppDescription(); ++ std::string app_id = app_desc->Id(); ++ ++ SendAglActivate(app_id.c_str()); ++} +diff --git a/src/cef/plugin/web_app_cef.h b/src/cef/plugin/web_app_cef.h +new file mode 100644 +index 0000000..57145cf +--- /dev/null ++++ b/src/cef/plugin/web_app_cef.h +@@ -0,0 +1,95 @@ ++#ifndef CEF_PLUGIN_WEB_APP_CEF_H ++#define CEF_PLUGIN_WEB_APP_CEF_H ++ ++#include <cstdint> ++#include <memory> ++ ++#include "web_app_base.h" ++ ++#include "include/views/cef_window.h" ++#include "include/views/cef_browser_view.h" ++#include "include/views/cef_window_delegate.h" ++ ++#include "application_description.h" ++ ++class WebAppCEF : public WebAppBase, public CefWindowDelegate { ++ public: ++ WebAppCEF(std::shared_ptr<ApplicationDescription> app_desc); ++ ++ ~WebAppCEF(); ++ ++ virtual void Init(int width, ++ int height, ++ AglShellSurfaceType surface_type, ++ AglShellPanelEdge panel_type) override; ++ ++ void SuspendAppRendering() override {} ++ void ResumeAppRendering() override {} ++ bool IsFocused() const override { return false; } ++ void Resize(int width, int height) override; ++ bool IsActivated() const override { return false; } ++ bool IsMinimized() override { return false; } ++ bool IsNormal() override { return true; } ++ void OnStageActivated() override {} ++ void OnStageDeactivated() override {} ++ void DoAttach() override {} ++ void ConfigureWindow(const std::string& type) override {} ++ void SetWindowProperty(const std::string& name, ++ const std::string& value) override {} ++ void PlatformBack() override {} ++ void SetCursor(const std::string& cursor_arg, ++ int hotspot_x, ++ int hotspot_y) override {} ++ void SetInputRegion(const Json::Value& json_doc) override {} ++ void SetKeyMask(const Json::Value& json_doc) override {} ++ void Hide(bool forced_hide = false) override; ++ void Focus() override {} ++ void Unfocus() override {} ++ void SetOpacity(float opacity) override {} ++ void Raise() override; ++ void GoBackground() override {} ++ void DoPendingRelaunch() override {} ++ void DeleteSurfaceGroup() override {} ++ void DoClose() override {} ++ void SetUseVirtualKeyboard(const bool enable) override {} ++ bool HideWindow() override; ++ ++ void SendAglReady() override; ++ void SendAglActivate(const char* app_id) override; ++ void SetAglAppId(const char* app_id) override; ++ ++ void Attach(WebPageBase* web_page) override; ++ ++ void Relaunch(const std::string& args, ++ const std::string& launching_app_id) override; ++ ++ void SetBrowserView(CefRefPtr<CefBrowserView> browser_view) { ++ browser_view_ = browser_view; ++ } ++ ++ virtual bool IsReady() const; ++ ++ // CEF overrides ++ void OnWindowCreated(CefRefPtr<CefWindow> window) override; ++ CefSize GetPreferredSize(CefRefPtr<CefView> view) override; ++ CefRect GetInitialBounds(CefRefPtr<CefWindow> window) override; ++ bool IsFrameless(CefRefPtr<CefWindow> window) override { return true; } ++ ++ protected: ++ void TryInitialize(); ++ void DelayedActivate(); ++ ++ CefRect GetDisplayBounds() const; ++ ++ CefRefPtr<CefBrowserView> browser_view_; ++ CefRefPtr<CefWindow> window_; ++ AglShellSurfaceType surface_type_; ++ AglShellPanelEdge panel_type_; ++ uint32_t width_override_ = 0; ++ uint32_t height_override_ = 0; ++ ++ private: ++ IMPLEMENT_REFCOUNTING(WebAppCEF); ++}; ++ ++#endif // CEF_PLUGIN_WEB_APP_CEF_H +diff --git a/src/cef/plugin/web_page_cef.cc b/src/cef/plugin/web_page_cef.cc +new file mode 100644 +index 0000000..32c6e89 +--- /dev/null ++++ b/src/cef/plugin/web_page_cef.cc +@@ -0,0 +1,48 @@ ++#include "web_page_cef.h" ++#include "application_description.h" ++ ++#include "include/views/cef_window.h" ++ ++#include "wam_cef_client.h" ++ ++WebPageCEF::WebPageCEF(std::shared_ptr<ApplicationDescription> app_desc, const std::string& url) ++ : url_{url} { ++ SetApplicationDescription(app_desc); ++} ++ ++WebPageCEF::~WebPageCEF() {} ++ ++void WebPageCEF::LoadUrl(const std::string& url) { ++ CefBrowserSettings browser_settings; ++ browser_view_ = CefBrowserView::CreateBrowserView( ++ WamCefClient::GetInstance(), url, browser_settings, nullptr, nullptr, this); ++ ++ web_app_->SetBrowserView(browser_view_); ++ ++ ApplicationDescription* app_desc = GetAppDescription(); ++ CefWindow::CreateTopLevelWindowWithId(web_app_, app_desc->Id()); ++} ++ ++void WebPageCEF::LoadDefaultUrl() { ++ LoadUrl(url_); ++} ++ ++bool WebPageCEF::HasBeenShown() const { ++ if (!web_app_) { ++ return false; ++ } ++ ++ return web_app_->IsReady(); ++} ++ ++ ++void WebPageCEF::EvaluateJavaScript(const std::string& jsCode) { ++ /*if (!browser_view_) { ++ return; ++ } ++ CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser(); ++ if (!browser) { ++ return; ++ } ++ browser->GetMainFrame()->ExecuteJavaScript(jsCode, url_, 0);*/ ++} +diff --git a/src/cef/plugin/web_page_cef.h b/src/cef/plugin/web_page_cef.h +new file mode 100644 +index 0000000..f62c223 +--- /dev/null ++++ b/src/cef/plugin/web_page_cef.h +@@ -0,0 +1,69 @@ ++#ifndef CEF_PLUGIN_WEB_PAGE_CEF_H ++#define CEF_PLUGIN_WEB_PAGE_CEF_H ++ ++#include <memory> ++ ++#include "web_page_base.h" ++#include "web_app_cef.h" ++ ++#include "include/views/cef_browser_view_delegate.h" ++ ++class WebPageCEF : public WebPageBase, ++ public CefBrowserViewDelegate { ++ public: ++ WebPageCEF(std::shared_ptr<ApplicationDescription> app_desc, const std::string& url); ++ ~WebPageCEF() override; ++ ++ void Init() override {} ++ void* GetWebContents() override { return nullptr; } ++ ++ wam::Url Url() const override { return wam::Url(""); } ++ std::string FailedUrl() const override { return ""; } ++ void LoadUrl(const std::string& url) override; ++ int Progress() const override { return 0; } ++ bool HasBeenShown() const override; ++ void SetPageProperties() override {} ++ void SetPreferredLanguages(const std::string& language) override {} ++ void SetDefaultFont(const std::string& font) override {} ++ void ReloadDefaultPage() override {} ++ void Reload() override {} ++ void SetVisibilityState(WebPageVisibilityState visibility_state) override {} ++ void SetFocus(bool focus) override {} ++ std::string Title() override { return ""; } ++ bool CanGoBack() override { return false; } ++ void CloseVkb() override {} ++ void HandleDeviceInfoChanged(const std::string& device_info) override {} ++ void EvaluateJavaScript(const std::string& jsCode) override; ++ void EvaluateJavaScriptInAllFrames(const std::string& js_code, ++ const char* method = {}) override {} ++ uint32_t GetWebProcessProxyID() override { return 0; } ++ uint32_t GetWebProcessPID() const override { return 0; } ++ void CreatePalmSystem(WebAppBase* app) override {} ++ ++ void SuspendWebPageAll() override {} ++ void ResumeWebPageAll() override {} ++ void SuspendWebPageMedia() override {} ++ void ResumeWebPageMedia() override {} ++ void ResumeWebPagePaintingAndJSExecution() override {} ++ void ForwardEvent(void* event) override {} ++ ++ void SuspendWebPagePaintingAndJSExecution() override {} ++ ++ void SetWebApp(CefRefPtr<WebAppCEF> web_app) { web_app_ = web_app; } ++ ++ protected: ++ void LoadDefaultUrl() override; ++ void AddUserScript(const std::string& script) override {} ++ void AddUserScriptUrl(const wam::Url& url) override {} ++ void LoadErrorPage(int error_code) override {} ++ void RecreateWebView() override {} ++ ++ private: ++ IMPLEMENT_REFCOUNTING(WebPageCEF); ++ ++ CefRefPtr<CefBrowserView> browser_view_; ++ CefRefPtr<WebAppCEF> web_app_; ++ std::string url_; ++}; ++ ++#endif // CEF_PLUGIN_WEB_PAGE_CEF_H +diff --git a/src/cef/service/CMakeLists.txt b/src/cef/service/CMakeLists.txt +new file mode 100644 +index 0000000..763b527 +--- /dev/null ++++ b/src/cef/service/CMakeLists.txt +@@ -0,0 +1,64 @@ ++project(WebAppMgrService VERSION 1.0.0 DESCRIPTION "Web Application Manager cli helper") ++ ++find_package(gRPC REQUIRED) ++find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED) ++find_package(Protobuf REQUIRED) ++find_package(Threads) ++ ++set(WAM_GRPC_LIB_NAME ${PROJECT_NAME}-grpc) ++set(APPLAUNCHER_LIB_NAME WamAppLauncher-grpc) ++ ++set(WAM_GRPC_LIBS ++ protobuf::libprotobuf ++ gRPC::grpc ++ gRPC::grpc++ ++ gRPC::grpc++_reflection ++) ++set(WAM_SERVICE_LIBS ++ ${WAM_GRPC_LIBS} ++ ${WAM_GRPC_LIB_NAME} ++ ${APPLAUNCHER_LIB_NAME} ++ libcef_lib ++ libcef_dll_wrapper ++) ++set(WAM_GRPC_INCLUDE_DIRS ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ ${CMAKE_CURRENT_BINARY_DIR} ++) ++set(WAM_SERVICE_INCLUDE_DIRS ++ ${CEF_INCLUDE_PATH} ++ ${WAM_ROOT_SOURCE_DIR}/core ++ ${WAM_ROOT_SOURCE_DIR}/util ++) ++set(SOURCES ++ applauncher_client_grpc.cc ++ web_app_manager_client_grpc.cc ++ web_app_manager_service_grpc.cc ++) ++set(HEADERS ++ applauncher_client_grpc.h ++ web_app_manager_client_grpc.h ++ web_app_manager_service_grpc.h ++) ++ ++ ++macro(add_wam_grpc_lib target proto) ++ add_library(${target} SHARED ${proto}) ++ target_include_directories(${target} PUBLIC ${WAM_GRPC_INCLUDE_DIRS}) ++ target_link_libraries(${target} PUBLIC ${WAM_GRPC_LIBS}) ++ set_target_properties(${target} PROPERTIES VERSION 1.0.0 SOVERSION 1.0) ++ protobuf_generate(TARGET ${target} LANGUAGE cpp APPEND_PATH) ++ protobuf_generate(TARGET ${target} LANGUAGE grpc APPEND_PATH GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=${GRPC_CPP_PLUGIN_EXECUTABLE}") ++ install(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}) ++endmacro(add_wam_grpc_lib) ++ ++add_wam_grpc_lib(${WAM_GRPC_LIB_NAME} wam_ipc.proto) ++add_wam_grpc_lib(${APPLAUNCHER_LIB_NAME} applauncher.proto) ++ ++add_library(${PROJECT_NAME} SHARED ${HEADERS} ${SOURCES}) ++set_target_properties(${PROJECT_NAME} PROPERTIES VERSION 1.0.0 SOVERSION 1.0) ++add_dependencies(${PROJECT_NAME} ${WAM_GRPC_LIB_NAME}) ++target_include_directories(${PROJECT_NAME} PUBLIC ${WAM_SERVICE_INCLUDE_DIRS}) ++target_link_libraries(${PROJECT_NAME} PUBLIC ${WAM_SERVICE_LIBS}) ++install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) ++install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +diff --git a/src/cef/service/applauncher.proto b/src/cef/service/applauncher.proto +new file mode 100644 +index 0000000..0b8e0fc +--- /dev/null ++++ b/src/cef/service/applauncher.proto +@@ -0,0 +1,50 @@ ++syntax = "proto3"; ++ ++package automotivegradelinux; ++ ++service AppLauncher { ++ rpc StartApplication(StartRequest) returns (StartResponse) {} ++ rpc ListApplications(ListRequest) returns (ListResponse) {} ++ rpc GetStatusEvents(StatusRequest) returns (stream StatusResponse) {} ++} ++ ++message StartRequest { ++ string id = 1; ++} ++ ++message StartResponse { ++ bool status = 1; ++ string message = 2; ++} ++ ++message ListRequest { ++} ++ ++message ListResponse { ++ repeated AppInfo apps = 1; ++} ++ ++message AppInfo { ++ string id = 1; ++ string name = 2; ++ string icon_path = 3; ++} ++ ++message StatusRequest { ++} ++ ++message AppStatus { ++ string id = 1; ++ string status = 2; ++} ++ ++// Future-proofing for e.g. potentially signaling a list refresh ++message LauncherStatus { ++} ++ ++message StatusResponse { ++ oneof status { ++ AppStatus app = 1; ++ LauncherStatus launcher = 2; ++ } ++} +diff --git a/src/cef/service/applauncher_client_grpc.cc b/src/cef/service/applauncher_client_grpc.cc +new file mode 100644 +index 0000000..f704742 +--- /dev/null ++++ b/src/cef/service/applauncher_client_grpc.cc +@@ -0,0 +1,58 @@ ++#include "applauncher_client_grpc.h" ++ ++#include <grpcpp/ext/proto_server_reflection_plugin.h> ++#include <grpcpp/grpcpp.h> ++#include <grpcpp/health_check_service_interface.h> ++ ++#include "include/cef_parser.h" ++ ++AppLauncherClientGRPC::AppLauncherClientGRPC() ++ : stub_{MakeStub()} { ++} ++ ++std::unique_ptr<automotivegradelinux::AppLauncher::Stub>AppLauncherClientGRPC::MakeStub() const { ++ return automotivegradelinux::AppLauncher::NewStub(grpc::CreateChannel("localhost:50052", ++ grpc::InsecureChannelCredentials())); ++} ++ ++void AppLauncherClientGRPC::Start(const std::string& app_id) { ++ automotivegradelinux::StartRequest request; ++ request.set_id(app_id); ++ ++ grpc::ClientContext context; ++ automotivegradelinux::StartResponse response; ++ ++ grpc::Status status = stub_->StartApplication(&context, request, &response); ++} ++ ++void AppLauncherClientGRPC::GetApplications(CefRefPtr<CefBrowser> browser, bool only_graphical) { ++ automotivegradelinux::ListRequest request; ++ automotivegradelinux::ListResponse response; ++ grpc::ClientContext context; ++ ++ grpc::Status status = stub_->ListApplications(&context, request, &response); ++ if (!status.ok()) { ++ return; ++ } ++ ++ CefRefPtr<CefListValue> apps_list = CefListValue::Create(); ++ for (int i = 0; i < response.apps_size(); i++) { ++ automotivegradelinux::AppInfo app_info = response.apps(i); ++ CefRefPtr<CefDictionaryValue> app_info_dict = CefDictionaryValue::Create(); ++ app_info_dict->SetString("id", app_info.id()); ++ app_info_dict->SetString("name", app_info.name()); ++ app_info_dict->SetString("icon", app_info.icon_path()); ++ apps_list->SetDictionary(i, app_info_dict); ++ } ++ ++ CefRefPtr<CefValue> apps_list_value = CefValue::Create(); ++ apps_list_value->SetList(apps_list); ++ std::string response_string = CefWriteJSON(apps_list_value, JSON_WRITER_DEFAULT); ++ ++ // send the response to renderer process ++ CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create("get_applications"); ++ CefRefPtr<CefListValue> args = message->GetArgumentList(); ++ args->SetString(0, response_string); ++ browser->GetMainFrame()->SendProcessMessage(PID_RENDERER, message); ++} ++ +diff --git a/src/cef/service/applauncher_client_grpc.h b/src/cef/service/applauncher_client_grpc.h +new file mode 100644 +index 0000000..4a3f289 +--- /dev/null ++++ b/src/cef/service/applauncher_client_grpc.h +@@ -0,0 +1,24 @@ ++#ifndef CEF_SERVICE_APPLAUNCHER_CLIENT_GRPC_H ++#define CEF_SERVICE_APPLAUNCHER_CLIENT_GRPC_H ++ ++#include <string> ++ ++#include "applauncher.grpc.pb.h" ++ ++#include "include/cef_browser.h" ++ ++class AppLauncherClientGRPC { ++ public: ++ ++ AppLauncherClientGRPC(); ++ ++ void Start(const std::string& app_id); ++ void GetApplications(CefRefPtr<CefBrowser> browser, bool only_graphical); ++ ++ private: ++ std::unique_ptr<automotivegradelinux::AppLauncher::Stub> MakeStub() const; ++ ++ std::unique_ptr<automotivegradelinux::AppLauncher::Stub> stub_; ++}; ++ ++#endif // CEF_SERVICE_APPLAUNCHER_CLIENT_GRPC_H +diff --git a/src/cef/service/wam_ipc.proto b/src/cef/service/wam_ipc.proto +new file mode 100644 +index 0000000..313de8f +--- /dev/null ++++ b/src/cef/service/wam_ipc.proto +@@ -0,0 +1,22 @@ ++syntax = "proto3"; ++import "google/protobuf/empty.proto"; ++package wam_ipc; ++ ++service WebAppManagerService { ++ rpc Launch(LaunchRequest) returns (google.protobuf.Empty) {} ++ rpc Activate(ActivateRequest) returns (google.protobuf.Empty) {} ++ rpc Kill(KillRequest) returns (google.protobuf.Empty) {} ++} ++ ++message LaunchRequest { ++ string app_id = 1; ++ string uri = 2; ++} ++ ++message ActivateRequest { ++ string app_id = 1; ++} ++ ++message KillRequest { ++ string app_id = 1; ++} +diff --git a/src/cef/service/web_app_manager_client_grpc.cc b/src/cef/service/web_app_manager_client_grpc.cc +new file mode 100644 +index 0000000..8529868 +--- /dev/null ++++ b/src/cef/service/web_app_manager_client_grpc.cc +@@ -0,0 +1,42 @@ ++#include "web_app_manager_client_grpc.h" ++ ++#include <grpcpp/ext/proto_server_reflection_plugin.h> ++#include <grpcpp/grpcpp.h> ++#include <grpcpp/health_check_service_interface.h> ++ ++const char kDefaultGrpcServiceAddress[] = "127.0.0.1:15000"; ++ ++WebAppManagerClientGRPC::WebAppManagerClientGRPC() { ++ auto channel = grpc::CreateChannel(kDefaultGrpcServiceAddress, ++ grpc::InsecureChannelCredentials()); ++ stub_ = wam_ipc::WebAppManagerService::NewStub(channel); ++} ++ ++bool WebAppManagerClientGRPC::Launch(const LaunchParams& params) { ++ wam_ipc::LaunchRequest request; ++ request.set_app_id(params.app_id); ++ request.set_uri(params.uri); ++ ++ grpc::ClientContext context; ++ google::protobuf::Empty reply; ++ grpc::Status status = stub_->Launch(&context, request, &reply); ++ return status.ok(); ++} ++ ++bool WebAppManagerClientGRPC::Activate(const std::string& app_id) { ++ grpc::ClientContext context; ++ google::protobuf::Empty reply; ++ wam_ipc::ActivateRequest request; ++ request.set_app_id(app_id); ++ grpc::Status status = stub_->Activate(&context, request, &reply); ++ return status.ok(); ++} ++ ++bool WebAppManagerClientGRPC::Kill(const std::string& app_id) { ++ grpc::ClientContext context; ++ google::protobuf::Empty reply; ++ wam_ipc::KillRequest request; ++ request.set_app_id(app_id); ++ grpc::Status status = stub_->Kill(&context, request, &reply); ++ return status.ok(); ++} +diff --git a/src/cef/service/web_app_manager_client_grpc.h b/src/cef/service/web_app_manager_client_grpc.h +new file mode 100644 +index 0000000..9c4be70 +--- /dev/null ++++ b/src/cef/service/web_app_manager_client_grpc.h +@@ -0,0 +1,23 @@ ++#ifndef CEF_SERVICE_WEB_APP_MANAGER_CLIENT_GRPC_H ++#define CEF_SERVICE_WEB_APP_MANAGER_CLIENT_GRPC_H ++ ++#include "wam_ipc.grpc.pb.h" ++ ++class WebAppManagerClientGRPC { ++ public: ++ struct LaunchParams { ++ std::string app_id; ++ std::string uri; ++ }; ++ ++ WebAppManagerClientGRPC(); ++ bool Launch(const LaunchParams& params); ++ bool Activate(const std::string& app_id); ++ bool Kill(const std::string& app_id); ++ ++ private: ++ std::unique_ptr<wam_ipc::WebAppManagerService::Stub> stub_; ++}; ++ ++#endif // CEF_SERVICE_WEB_APP_MANAGER_CLIENT_GRPC_H ++ +diff --git a/src/cef/service/web_app_manager_service_grpc.cc b/src/cef/service/web_app_manager_service_grpc.cc +new file mode 100644 +index 0000000..52de924 +--- /dev/null ++++ b/src/cef/service/web_app_manager_service_grpc.cc +@@ -0,0 +1,382 @@ ++// Copyright (c) 2018-2022 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 "web_app_manager_service_grpc.h" ++ ++#include <grpcpp/ext/proto_server_reflection_plugin.h> ++#include <grpcpp/grpcpp.h> ++#include <grpcpp/health_check_service_interface.h> ++#include <pthread.h> ++#include <sys/file.h> ++#include <sys/un.h> ++#include <unistd.h> ++#include <algorithm> ++#include <cassert> ++#include <climits> ++#include <cstdlib> ++#include <exception> ++#include <fstream> ++#include <iostream> ++#include <set> ++#include <sstream> ++ ++#include <json/value.h> ++ ++#include "log_manager.h" ++#include "utils.h" ++#include "wam_ipc.grpc.pb.h" ++#include "web_app_base.h" ++#include "web_app_manager.h" ++ ++namespace { ++const char kDefaultGrpcServiceAddress[] = "127.0.0.1:15000"; ++} // namespace ++ ++class WamIPCLockFile { ++ public: ++ WamIPCLockFile() { ++ 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("/wamipc.lock"); ++ } ++ ++ ~WamIPCLockFile() { ++ 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() const { 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 GrpcServiceImpl final ++ : public wam_ipc::WebAppManagerService::CallbackService { ++ grpc::ServerUnaryReactor* Launch(grpc::CallbackServerContext* context, ++ const ::wam_ipc::LaunchRequest* request, ++ google::protobuf::Empty* /*response*/) { ++ WebAppManagerServiceGRPC::LaunchParams launch_params; ++ launch_params.app_id = request->app_id(); ++ launch_params.uri = request->uri(); ++ launch_params.width = 0; ++ launch_params.height = 0; ++ ++ WebAppManagerServiceGRPC::Instance()->LaunchOnIdle(launch_params); ++ ++ grpc::ServerUnaryReactor* reactor = context->DefaultReactor(); ++ reactor->Finish(grpc::Status::OK); ++ return reactor; ++ } ++ grpc::ServerUnaryReactor* Activate(grpc::CallbackServerContext* context, ++ const ::wam_ipc::ActivateRequest* request, ++ google::protobuf::Empty* /*response*/) { ++ WebAppManagerServiceGRPC::Instance()->SendEventOnIdle(kActivateEvent, ++ request->app_id()); ++ grpc::ServerUnaryReactor* reactor = context->DefaultReactor(); ++ reactor->Finish(grpc::Status::OK); ++ return reactor; ++ } ++ grpc::ServerUnaryReactor* Kill(grpc::CallbackServerContext* context, ++ const ::wam_ipc::KillRequest* request, ++ google::protobuf::Empty* /*response*/) { ++ WebAppManagerServiceGRPC::Instance()->SendEventOnIdle(kKilledApp, ++ request->app_id()); ++ grpc::ServerUnaryReactor* reactor = context->DefaultReactor(); ++ reactor->Finish(grpc::Status::OK); ++ return reactor; ++ } ++}; ++ ++WebAppManagerServiceGRPC::WebAppManagerServiceGRPC() ++ : lock_file_(std::make_unique<WamIPCLockFile>()) {} ++ ++WebAppManagerServiceGRPC* WebAppManagerServiceGRPC::Instance() { ++ static WebAppManagerServiceGRPC* srv = new WebAppManagerServiceGRPC(); ++ return srv; ++} ++ ++bool WebAppManagerServiceGRPC::InitializeAsHostService() { ++ return lock_file_->CreateAndLock(); ++} ++ ++bool WebAppManagerServiceGRPC::IsHostServiceRunning() { ++ return !lock_file_->TryAcquireLock(); ++} ++ ++void* RunGrpcService(void*) { ++ std::string server_address(kDefaultGrpcServiceAddress); ++ GrpcServiceImpl service; ++ ++ grpc::EnableDefaultHealthCheckService(true); ++ grpc::reflection::InitProtoReflectionServerBuilderPlugin(); ++ ++ grpc::ServerBuilder builder; ++ builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); ++ builder.RegisterService(&service); ++ ++ std::unique_ptr<grpc::Server> server(builder.BuildAndStart()); ++ std::cout << "Server listening on " << server_address << std::endl; ++ server->Wait(); ++ ++ return nullptr; ++} ++ ++bool WebAppManagerServiceGRPC::StartService() { ++ if (lock_file_->OwnsLock()) { ++ pthread_t thread_id; ++ if (pthread_create(&thread_id, nullptr, RunGrpcService, nullptr) < 0) { ++ perror("Could not create thread"); ++ LOG_DEBUG("Could not create thread..."); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++void WebAppManagerServiceGRPC::LaunchOnIdle(const LaunchParams& params) { ++ auto launch_params = std::make_unique<LaunchParams>(params); ++ ++ auto* timer = ++ new OneShotTimerWithData<WebAppManagerServiceGRPC, LaunchParams>(); ++ timer->Start(0, this, &WebAppManagerServiceGRPC::OnLaunchApp, ++ std::move(launch_params)); ++} ++ ++void WebAppManagerServiceGRPC::SendEventOnIdle(const std::string& event, ++ const std::string& app_id) { ++ auto event_data = std::make_unique<EventData>(); ++ event_data->app_id = app_id; ++ auto* timer = new OneShotTimerWithData<WebAppManagerServiceGRPC, EventData>(); ++ if (event == kActivateEvent) ++ timer->Start(0, this, &WebAppManagerServiceGRPC::OnActivateEvent, ++ std::move(event_data)); ++ else if (event == kDeactivateEvent) ++ timer->Start(0, this, &WebAppManagerServiceGRPC::OnDeactivateEvent, ++ std::move(event_data)); ++ else if (event == kKilledApp) ++ timer->Start(1000, this, &WebAppManagerServiceGRPC::OnKillEvent, ++ std::move(event_data)); ++} ++ ++void WebAppManagerServiceGRPC::OnLaunchApp(LaunchParams* params) { ++ LOG_DEBUG("Triggering app start: %s", params->uri.c_str()); ++ if (!params->uri.empty()) { ++ if (params->uri.find("http://") == 0) { ++ LaunchStartupAppFromURL(params); ++ } else { ++ LaunchStartupAppFromJsonConfig(params); ++ } ++ } ++} ++ ++void WebAppManagerServiceGRPC::LaunchStartupAppFromJsonConfig( ++ LaunchParams* params) { ++ std::string configfile; ++ configfile.append(params->uri); ++ configfile.append("/appinfo.json"); ++ ++ Json::Value root; ++ Json::CharReaderBuilder builder; ++ JSONCPP_STRING errs; ++ ++ std::ifstream ifs; ++ ifs.open(configfile.c_str()); ++ ++ if (!parseFromStream(builder, ifs, &root, &errs)) { ++ LOG_DEBUG("Failed to parse %s configuration file", configfile.c_str()); ++ } ++ ++ root["folderPath"] = params->uri.c_str(); ++ ++ auto surface_obj = root["surface"]; ++ auto surface_type = surface_obj["type"].asString(); ++ if (surface_type == "background") { ++ root["surface_type"] = 1; // AglShellSurfaceType::kBackground; ++ } else if (surface_type == "panel") { ++ root["surface_type"] = 2; // AglShellSurfaceType::kPanel; ++ } else { ++ root["surface_type"] = 0; // AglShellSurfaceType::kNone; ++ } ++ ++ std::string app_desc = util::JsonToString(root); ++ std::string empty_params = "{}"; ++ std::string app_id = root["id"].asString(); ++ int err_code = 0; ++ std::string err_msg; ++ WebAppManagerService::OnLaunch(app_desc, empty_params, app_id, err_code, ++ err_msg); ++} ++ ++void WebAppManagerServiceGRPC::LaunchStartupAppFromURL(LaunchParams* params) { ++ LOG_DEBUG("WebAppManagerServiceGRPC::LaunchStartupAppFromURL"); ++ LOG_DEBUG(" url: %s", params->uri.c_str()); ++ Json::Value obj(Json::objectValue); ++ obj["id"] = params->app_id; ++ obj["version"] = "1.0"; ++ obj["vendor"] = "some vendor"; ++ obj["type"] = "web"; ++ obj["main"] = params->uri; ++ obj["title"] = "webapp"; ++ obj["uiRevision"] = "2"; ++ ++ obj["widthOverride"] = params->width; ++ obj["heightOverride"] = params->height; ++ ++ std::string app_desc = util::JsonToString(obj); ++ std::string app_id = params->app_id; ++ int err_code = 0; ++ std::string empty_params = "{}"; ++ std::string err_msg; ++ ++ LOG_DEBUG("Launching with appDesc=[%s]", app_desc.c_str()); ++ ++ WebAppManagerService::OnLaunch(app_desc, empty_params, app_id, err_code, ++ err_msg); ++ LOG_DEBUG("onLaunch: Done."); ++} ++ ++Json::Value WebAppManagerServiceGRPC::launchApp(const Json::Value& request) { ++ return Json::Value(Json::objectValue); ++} ++ ++Json::Value WebAppManagerServiceGRPC::killApp(const Json::Value& request) { ++ return Json::Value(Json::objectValue); ++} ++ ++Json::Value WebAppManagerServiceGRPC::pauseApp(const Json::Value& request) { ++ return Json::Value(Json::objectValue); ++} ++ ++Json::Value WebAppManagerServiceGRPC::logControl(const Json::Value& request) { ++ return Json::Value(Json::objectValue); ++} ++ ++Json::Value WebAppManagerServiceGRPC::setInspectorEnable( ++ const Json::Value& request) { ++ return Json::Value(Json::objectValue); ++} ++ ++Json::Value WebAppManagerServiceGRPC::closeAllApps(const Json::Value& request) { ++ return Json::Value(Json::objectValue); ++} ++ ++Json::Value WebAppManagerServiceGRPC::discardCodeCache( ++ const Json::Value& request) { ++ return Json::Value(Json::objectValue); ++} ++ ++Json::Value WebAppManagerServiceGRPC::listRunningApps( ++ const Json::Value& request, ++ bool subscribed) { ++ return Json::Value(Json::objectValue); ++} ++ ++Json::Value WebAppManagerServiceGRPC::getWebProcessSize( ++ const Json::Value& request) { ++ return Json::Value(Json::objectValue); ++} ++ ++Json::Value WebAppManagerServiceGRPC::clearBrowsingData( ++ const Json::Value& request) { ++ return Json::Value(Json::objectValue); ++} ++ ++Json::Value WebAppManagerServiceGRPC::webProcessCreated( ++ const Json::Value& request, ++ bool subscribed) { ++ return Json::Value(Json::objectValue); ++} ++ ++void WebAppManagerServiceGRPC::OnActivateEvent(EventData* event_data) { ++ LOG_DEBUG("Activate app=%s", event_data->app_id.c_str()); ++ WebAppBase* web_app = ++ WebAppManager::Instance()->FindAppById(event_data->app_id); ++ if (web_app) { ++ web_app->OnStageActivated(); ++ web_app->SendAglActivate(event_data->app_id.c_str()); ++ } else { ++ LOG_DEBUG("Not found app=%s running", event_data->app_id.c_str()); ++ } ++} ++ ++void WebAppManagerServiceGRPC::OnDeactivateEvent(EventData* event_data) { ++ LOG_DEBUG("Dectivate app=%s", event_data->app_id.c_str()); ++ WebAppBase* web_app = ++ WebAppManager::Instance()->FindAppById(event_data->app_id); ++ if (web_app) ++ web_app->OnStageDeactivated(); ++} ++ ++void WebAppManagerServiceGRPC::OnKillEvent(EventData* event_data) { ++ LOG_DEBUG("Kill app=%s", event_data->app_id.c_str()); ++ WebAppManager::Instance()->OnKillApp(event_data->app_id, event_data->app_id); ++} +diff --git a/src/cef/service/web_app_manager_service_grpc.h b/src/cef/service/web_app_manager_service_grpc.h +new file mode 100644 +index 0000000..69ea0ed +--- /dev/null ++++ b/src/cef/service/web_app_manager_service_grpc.h +@@ -0,0 +1,85 @@ ++// Copyright (c) 2018-2022 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 CEF_SERVICE_WEB_APP_MANAGER_SERVICE_GRPC_H ++#define CEF_SERVICE_WEB_APP_MANAGER_SERVICE_GRPC_H ++ ++#include <memory> ++ ++#include "timer.h" ++#include "web_app_manager_service.h" ++ ++constexpr char kStartApp[] = "start-app"; ++constexpr char kKilledApp[] = "killed-app"; ++constexpr char kActivateEvent[] = "activate-event"; ++constexpr char kDeactivateEvent[] = "deactivate-event"; ++ ++class GrpcClient; ++class WamIPCLockFile; ++ ++class WebAppManagerServiceGRPC : public WebAppManagerService, ++ public TimerReceiver { ++ public: ++ struct LaunchParams { ++ std::string app_id; ++ std::string uri; ++ int width = 0; ++ int height = 0; ++ }; ++ ++ static WebAppManagerServiceGRPC* Instance(); ++ ++ bool InitializeAsHostService(); ++ bool IsHostServiceRunning(); ++ ++ void LaunchOnIdle(const LaunchParams& params); ++ void SendEventOnIdle(const std::string& event, const std::string& app_id); ++ ++ // WebAppManagerService ++ bool StartService() override; ++ Json::Value launchApp(const Json::Value& request) override; ++ Json::Value killApp(const Json::Value& request) override; ++ Json::Value pauseApp(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 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(); ++ ++ private: ++ WebAppManagerServiceGRPC(); ++ ++ void OnLaunchApp(LaunchParams* launch_data); ++ void LaunchStartupAppFromJsonConfig(LaunchParams*); ++ void LaunchStartupAppFromURL(LaunchParams*); ++ struct EventData { ++ std::string app_id; ++ }; ++ void OnActivateEvent(EventData* event_data); ++ void OnDeactivateEvent(EventData* event_data); ++ void OnKillEvent(EventData* event_data); ++ ++ std::unique_ptr<WamIPCLockFile> lock_file_; ++}; ++ ++#endif // CEF_SERVICE_WEB_APP_MANAGER_SERVICE_GRPC_H +diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt +index 182f96a..41871b9 100644 +--- a/src/core/CMakeLists.txt ++++ b/src/core/CMakeLists.txt +@@ -18,6 +18,7 @@ project(WebAppMgrCore VERSION 1.0.0 DESCRIPTION "Core of the Web Application Man + + set(SOURCES + application_description.cc ++ application_installation_handler_stub.cc + device_info.cc + palm_system_base.cc + plugin_service.cc +@@ -44,7 +45,9 @@ set(SOURCES + set(HEADERS + agl_shell_types.h + application_description.h ++ application_installation_handler.h + device_info.h ++ memory_pressure_level.h + palm_system_base.h + platform_module_factory.h + plugin_service.h +@@ -95,6 +98,7 @@ set(CORE_INCLUDE_DIRS + set(CORE_LIBS + ${CHROMIUM_LDFLAGS} + ${GLIB_LDFLAGS} ++ ${JSONCPP_LDFLAGS} + ${PMLOGLIB_LDFLAGS} + Boost::filesystem + dl +diff --git a/src/core/application_description.cc b/src/core/application_description.cc +index 9b494fc..adbb7d8 100644 +--- a/src/core/application_description.cc ++++ b/src/core/application_description.cc +@@ -144,12 +144,49 @@ std::unique_ptr<ApplicationDescription> ApplicationDescription::FromJsonString( + auto app_desc = + std::unique_ptr<ApplicationDescription>(new ApplicationDescription()); + ++ + app_desc->surface_type_ = + static_cast<AglShellSurfaceType>(json_obj["surface_type"].asInt()); + app_desc->panel_type_ = + static_cast<AglShellPanelEdge>(json_obj["panel_type"].asInt()); + app_desc->width_override_ = json_obj["widthOverride"].asInt(); + app_desc->height_override_ = json_obj["heightOverride"].asInt(); ++ ++ // override previous values if the json config file contains ++ // a "surface" object with nested data ++ auto surface_obj = json_obj["surface"]; ++ if (!surface_obj.empty()) { ++ std::string surface_type = surface_obj["type"].asString(); ++ if (surface_type == "background") { ++ app_desc->surface_type_ = AglShellSurfaceType::kBackground; ++ } else if (surface_type == "panel") { ++ app_desc->surface_type_ = AglShellSurfaceType::kPanel; ++ } else { ++ app_desc->surface_type_ = AglShellSurfaceType::kNone; ++ } ++ ++ std::string panel_edge = surface_obj["panel_edge"].asString(); ++ if (panel_edge == "left") { ++ app_desc->panel_type_ = AglShellPanelEdge::kLeft; ++ } else if (panel_edge == "right") { ++ app_desc->panel_type_ = AglShellPanelEdge::kRight; ++ } else if (panel_edge == "top") { ++ app_desc->panel_type_ = AglShellPanelEdge::kTop; ++ } else if (panel_edge == "bottom") { ++ app_desc->panel_type_ = AglShellPanelEdge::kBottom; ++ } ++ ++ int width = 0; ++ if (!surface_obj["width"].empty()) ++ util::StrToInt(surface_obj["width"].asString(), width); ++ app_desc->width_override_ = width; ++ ++ int height = 0; ++ if (!surface_obj["height"].empty()) ++ util::StrToInt(surface_obj["height"].asString(), height); ++ app_desc->height_override_ = height; ++ } ++ + app_desc->transparency_ = json_obj["transparent"].asBool(); + auto vendor_extension = + json_obj.get("vendorExtension", Json::Value(Json::objectValue)); +diff --git a/src/core/application_installation_handler.h b/src/core/application_installation_handler.h +new file mode 100644 +index 0000000..054bc9d +--- /dev/null ++++ b/src/core/application_installation_handler.h +@@ -0,0 +1,12 @@ ++#ifndef CORE_APPLICATION_INSTALLATION_HANDLER_H_ ++#define CORE_APPLICATION_INSTALLATION_HANDLER_H_ ++ ++#include <string> ++ ++class ApplicationInstallationHandler { ++ public: ++ static void OnAppInstalled(const std::string& app_id); ++ static void OnAppRemoved(const std::string& app_id); ++}; ++ ++#endif // CORE_APPLICATION_INSTALLATION_HANDLER_H_ +\ No newline at end of file +diff --git a/src/core/application_installation_handler_stub.cc b/src/core/application_installation_handler_stub.cc +new file mode 100644 +index 0000000..016c7d2 +--- /dev/null ++++ b/src/core/application_installation_handler_stub.cc +@@ -0,0 +1,4 @@ ++#include "application_installation_handler.h" ++ ++void ApplicationInstallationHandler::OnAppInstalled(const std::string&) {} ++void ApplicationInstallationHandler::OnAppRemoved(const std::string&) {} +\ No newline at end of file +diff --git a/src/core/memory_pressure_level.h b/src/core/memory_pressure_level.h +new file mode 100644 +index 0000000..01c9316 +--- /dev/null ++++ b/src/core/memory_pressure_level.h +@@ -0,0 +1,6 @@ ++#ifndef CORE_MEMORY_PRESSURE_LEVEL_H_ ++#define CORE_MEMORY_PRESSURE_LEVEL_H_ ++ ++enum class MemoryPressureLevel { kNone, kLow, kCritical }; ++ ++#endif // CORE_MEMORY_PRESSURE_LEVEL_H_ +\ No newline at end of file +diff --git a/src/core/web_app_manager.cc b/src/core/web_app_manager.cc +index ca64ef1..42e8be7 100644 +--- a/src/core/web_app_manager.cc ++++ b/src/core/web_app_manager.cc +@@ -22,10 +22,9 @@ + #include <string> + + #include <json/value.h> +-#include "webos/application_installation_handler.h" +-#include "webos/public/runtime.h" + + #include "application_description.h" ++#include "application_installation_handler.h" + #include "base_check.h" + #include "device_info.h" + #include "log_manager.h" +@@ -63,8 +62,7 @@ WebAppManager::~WebAppManager() { + device_info_->Terminate(); + } + +-void WebAppManager::NotifyMemoryPressure( +- webos::WebViewBase::MemoryPressureLevel level) { ++void WebAppManager::NotifyMemoryPressure(MemoryPressureLevel level) { + std::list<const WebAppBase*> app_list = RunningApps(); + for (auto it = app_list.begin(); it != app_list.end(); ++it) { + const WebAppBase* app = *it; +@@ -72,15 +70,14 @@ void WebAppManager::NotifyMemoryPressure( + // critical (when system is on low or critical) because they will be killed + // anyway + if (app->IsActivated() && +- (!app->Page()->IsPreload() || +- level != webos::WebViewBase::MEMORY_PRESSURE_CRITICAL)) ++ (!app->Page()->IsPreload() || level != MemoryPressureLevel::kCritical)) + app->Page()->NotifyMemoryPressure(level); + else { + LOG_DEBUG( + "Skipping memory pressure handler for" + " instanceId(%s) appId(%s) isActivated(%d) isPreload(%d) Level(%d)", + app->InstanceId().c_str(), app->AppId().c_str(), app->IsActivated(), +- app->Page()->IsPreload(), level); ++ app->Page()->IsPreload(), static_cast<int>(level)); + } + } + } +@@ -341,8 +338,10 @@ WebAppBase* WebAppManager::OnLaunchUrl( + WebPageAdded(page); + + /* if the surface role is a background send ready to display them */ +- if (app_desc->SurfaceType() == AglShellSurfaceType::kBackground) ++ if (app_desc->SurfaceType() == AglShellSurfaceType::kBackground) { ++ LOG_DEBUG("Sending agl_ready from app %s", app_desc->Id().c_str()); + app->SendAglReady(); ++ } + + app_list_.push_back(app); + +@@ -831,8 +830,10 @@ void WebAppManager::UpdateNetworkStatus(const Json::Value& object) { + NetworkStatus status; + status.FromJsonObject(object); + ++#if defined(OS_WEBOS) + webos::Runtime::GetInstance()->SetNetworkConnected( + status.IsInternetConnectionAvailable()); ++#endif + network_status_manager_->UpdateNetworkStatus(status); + + if (status.IsInternetConnectionAvailable()) { +@@ -867,16 +868,12 @@ int WebAppManager::MaskForBrowsingDataType(const char* type) { + + void WebAppManager::AppInstalled(const std::string& app_id) { + LOG_INFO(MSGID_WAM_DEBUG, 0, "App installed; id=%s", app_id.c_str()); +- auto p = webos::ApplicationInstallationHandler::GetInstance(); +- if (p) +- p->OnAppInstalled(app_id); ++ ApplicationInstallationHandler::OnAppInstalled(app_id); + } + + void WebAppManager::AppRemoved(const std::string& app_id) { + LOG_INFO(MSGID_WAM_DEBUG, 0, "App removed; id=%s", app_id.c_str()); +- auto p = webos::ApplicationInstallationHandler::GetInstance(); +- if (p) +- p->OnAppRemoved(app_id); ++ ApplicationInstallationHandler::OnAppRemoved(app_id); + } + + std::string WebAppManager::IdentifierForSecurityOrigin( +@@ -889,5 +886,9 @@ std::string WebAppManager::IdentifierForSecurityOrigin( + LOG_WARNING(MSGID_APPID_HAS_UPPERCASE, 0, + "Application id should not contain capital letters"); + } ++#if defined(OS_WEBOS) + return (lowcase_identifier + webos::WebViewBase::kSecurityOriginPostfix); ++#else ++ return lowcase_identifier; ++#endif + } +diff --git a/src/core/web_app_manager.h b/src/core/web_app_manager.h +index b10f53d..0f30a85 100644 +--- a/src/core/web_app_manager.h ++++ b/src/core/web_app_manager.h +@@ -24,7 +24,7 @@ + #include <unordered_map> + #include <vector> + +-#include "webos/webview_base.h" ++#include "memory_pressure_level.h" + + class ApplicationDescription; + class DeviceInfo; +@@ -150,7 +150,7 @@ class WebAppManager { + const std::string& payload, + const std::string& app_id); + void UpdateNetworkStatus(const Json::Value& object); +- void NotifyMemoryPressure(webos::WebViewBase::MemoryPressureLevel level); ++ void NotifyMemoryPressure(MemoryPressureLevel level); + + bool IsEnyoApp(const std::string& app_id); + +diff --git a/src/core/web_app_manager_service.cc b/src/core/web_app_manager_service.cc +index 1770d02..90b880f 100644 +--- a/src/core/web_app_manager_service.cc ++++ b/src/core/web_app_manager_service.cc +@@ -19,6 +19,7 @@ + #include <json/value.h> + + #include "log_manager.h" ++#include "memory_pressure_level.h" + #include "web_app_base.h" + #include "web_app_manager_tracer.h" + +@@ -158,8 +159,7 @@ void WebAppManagerService::UpdateNetworkStatus(const Json::Value& object) { + WebAppManager::Instance()->UpdateNetworkStatus(object); + } + +-void WebAppManagerService::NotifyMemoryPressure( +- webos::WebViewBase::MemoryPressureLevel level) { ++void WebAppManagerService::NotifyMemoryPressure(MemoryPressureLevel level) { + WebAppManager::Instance()->NotifyMemoryPressure(level); + } + +diff --git a/src/core/web_app_manager_service.h b/src/core/web_app_manager_service.h +index 7ead117..c294e50 100644 +--- a/src/core/web_app_manager_service.h ++++ b/src/core/web_app_manager_service.h +@@ -22,7 +22,6 @@ + #include <vector> + + #include "web_app_manager.h" +-#include "webos/webview_base.h" + + namespace Json { + class Value; +@@ -114,7 +113,7 @@ class WebAppManagerService { + void KillCustomPluginProcess(const std::string& app_base_path); + void RequestKillWebProcess(uint32_t pid); + void UpdateNetworkStatus(const Json::Value& object); +- void NotifyMemoryPressure(webos::WebViewBase::MemoryPressureLevel level); ++ void NotifyMemoryPressure(MemoryPressureLevel level); + void SetAccessibilityEnabled(bool enable); + uint32_t GetWebProcessId(const std::string& app_id, + const std::string& instance_id); +diff --git a/src/core/web_page_base.h b/src/core/web_page_base.h +index 7bbca84..8a689a7 100644 +--- a/src/core/web_page_base.h ++++ b/src/core/web_page_base.h +@@ -20,8 +20,7 @@ + #include <memory> + #include <string> + +-#include "webos/webview_base.h" +- ++#include "memory_pressure_level.h" + #include "observer_list.h" + #include "util/url.h" + +@@ -58,8 +57,7 @@ class WebPageBase { + virtual void Init() = 0; + virtual void* GetWebContents() = 0; + virtual void SetLaunchParams(const std::string& params); +- virtual void NotifyMemoryPressure( +- webos::WebViewBase::MemoryPressureLevel level) {} ++ virtual void NotifyMemoryPressure(MemoryPressureLevel level) {} + + virtual std::string GetIdentifier() const; + virtual wam::Url Url() const = 0; +diff --git a/src/core/web_process_manager.h b/src/core/web_process_manager.h +index b63d270..c7ffde1 100644 +--- a/src/core/web_process_manager.h ++++ b/src/core/web_process_manager.h +@@ -17,6 +17,7 @@ + #ifndef CORE_WEB_PROCESS_MANAGER_H_ + #define CORE_WEB_PROCESS_MANAGER_H_ + ++#include <cstdint> + #include <list> + #include <string> + #include <unordered_map> +diff --git a/src/core/web_runtime.h b/src/core/web_runtime.h +index 69bc204..1ae6ca9 100644 +--- a/src/core/web_runtime.h ++++ b/src/core/web_runtime.h +@@ -21,8 +21,9 @@ + + class WebRuntime { + public: ++ virtual ~WebRuntime() = default; + static std::unique_ptr<WebRuntime> Create(); +- virtual int Run(int argc, const char** argv) = 0; ++ virtual int Run(int argc, char** argv) = 0; + }; + + #endif // CORE_WEB_RUNTIME_H_ +diff --git a/src/desktop/CMakeLists.txt b/src/desktop/CMakeLists.txt +new file mode 100644 +index 0000000..06078da +--- /dev/null ++++ b/src/desktop/CMakeLists.txt +@@ -0,0 +1,100 @@ ++project(WebAppMgrDesktop VERSION 1.0.0 DESCRIPTION "Web Application Manager library") ++ ++find_package(gRPC REQUIRED) ++find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED) ++find_package(Protobuf REQUIRED) ++find_package(Threads) ++ ++set(WAM_IPC_LIB_NAME ${PROJECT_NAME}IPC) ++set(WAM_IPC_PROTO_FILES ${WAM_ROOT_SOURCE_DIR}/cef/ipc/wam_ipc.proto) ++set(WAM_IPC_LIBS ++ protobuf::libprotobuf ++ gRPC::grpc ++ gRPC::grpc++ ++ gRPC::grpc++_reflection ++) ++set(WAM_IPC_INCLUDE_DIRS ++ ${CMAKE_CURRENT_BINARY_DIR} ++) ++ ++set(WAM_LIB_LIBS ++ ${JSONCPP_LDFLAGS} ++ WebAppMgrCore ++ ${WAM_IPC_LIB_NAME} ++ libcef_lib ++ libcef_dll_wrapper ++) ++ ++set(SOURCES ++ web_runtime_desktop.cc ++) ++ ++set(HEADERS ++ web_runtime_desktop.h ++) ++ ++set(WAM_LIB_CEF_DIR ${WAM_ROOT_SOURCE_DIR}/cef) ++ ++ ++set(WAM_LIB_INCLUDE_DIRS ++ ${JSONCPP_INCLUDE_DIRS} ++ ${CEF_INCLUDE_PATH} ++) ++ ++add_library(${WAM_IPC_LIB_NAME} SHARED ${WAM_IPC_PROTO_FILES}) ++target_include_directories(${WAM_IPC_LIB_NAME} PUBLIC ${WAM_IPC_INCLUDE_DIRS}) ++target_link_libraries(${WAM_IPC_LIB_NAME} PUBLIC ${WAM_IPC_LIBS}) ++set_target_properties(${WAM_IPC_LIB_NAME} PROPERTIES VERSION 1.0.0 SOVERSION 1.0) ++protobuf_generate(TARGET ${WAM_IPC_LIB_NAME} LANGUAGE cpp APPEND_PATH) ++protobuf_generate(TARGET ${WAM_IPC_LIB_NAME} LANGUAGE grpc APPEND_PATH GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=${GRPC_CPP_PLUGIN_EXECUTABLE}") ++install(TARGETS ${WAM_IPC_LIB_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) ++ ++ ++LIST(APPEND SOURCES ++ ${WAM_LIB_CEF_DIR}/device_info_cef.cc ++ ${WAM_LIB_CEF_DIR}/platform_module_factory_cef.cc ++ ${WAM_LIB_CEF_DIR}/ipc/web_app_manager_service_grpc.cc ++ ${WAM_LIB_CEF_DIR}/handlers/wam_cef_browser_handler.cc ++ ${WAM_LIB_CEF_DIR}/handlers/wam_cef_client.cc ++) ++LIST(APPEND HEADERS ++ ${WAM_LIB_CEF_DIR}/device_info_cef.h ++ ${WAM_LIB_CEF_DIR}/platform_module_factory_cef.h ++ ${WAM_LIB_CEF_DIR}/ipc/web_app_manager_service_grpc.h ++ ${WAM_LIB_CEF_DIR}/handlers/wam_cef_browser_handler.h ++ ${WAM_LIB_CEF_DIR}/handlers/wam_cef_client.h ++) ++LIST(APPEND WAM_LIB_INCLUDE_DIRS ++ ${WAM_LIB_CEF_DIR} ++ ${WAM_LIB_CEF_DIR}/ipc ++ ${WAM_LIB_CEF_DIR}/webapp ++) ++ ++add_library(${PROJECT_NAME} SHARED ${HEADERS} ${SOURCES}) ++target_include_directories(${PROJECT_NAME} PUBLIC ${WAM_LIB_INCLUDE_DIRS}) ++set_target_properties(${PROJECT_NAME} PROPERTIES VERSION 1.0.0 SOVERSION 1.0) ++ ++install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/webappmanager) ++ ++macro(INSTALL_CEF_FILES file_list source_dir target_dir) ++ foreach(FILENAME ${file_list}) ++ set(source_file ${source_dir}/${FILENAME}) ++ ++ # Remove the target file path component. ++ get_filename_component(target_name ${FILENAME} NAME) ++ set(target_file ${target_dir}/${target_name}) ++ ++ if (IS_DIRECTORY ${source_file}) ++ install(DIRECTORY ${source_file} DESTINATION ${target_dir}) ++ else() ++ install(FILES ${source_file} DESTINATION ${target_dir}) ++ endif() ++ endforeach() ++endmacro() ++ ++# Copy CEF dependencies ++install_cef_files("${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CMAKE_INSTALL_PREFIX}") ++install_cef_files("${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CMAKE_INSTALL_PREFIX}") ++ ++target_link_libraries(${PROJECT_NAME} PUBLIC ${WAM_LIB_LIBS}) ++install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) +diff --git a/src/desktop/README.md b/src/desktop/README.md +new file mode 100644 +index 0000000..2d32b39 +--- /dev/null ++++ b/src/desktop/README.md +@@ -0,0 +1,102 @@ ++# CEF backend ++ ++This is an experimental CEF backend for WAM. ++ ++## Compilation ++ ++### Preparations ++ ++First prepare a workspace: ++``` ++mkdir wam-cef ++cd wam-cef ++``` ++ ++Now clone WAM repository: ++``` ++git clone ssh://git@gitlab.igalia.com:4429/dape/wam.git ++``` ++ ++Fetch latest stable CEF binary distribution (standard) for your system, from [CEF binary download](https://cef-builds.spotifycdn.com/index.html). Then uncompress the tarball: ++``` ++tar xvf ...path...to...binary/cef_binary...tar.bz2 ++``` ++ ++### Compilation of CEF DLL wrapper ++ ++Create a folder to compile the CEF DLL wrapper `.a` file: ++``` ++mkdir build-cef-dll ++cd build-cef-dll ++``` ++ ++Prepare compilation scripts: ++``` ++cmake ../cef_binary_... ++``` ++ ++Then compile the DLL wrapper: ++``` ++make libcef_dll_wrapper ++``` ++ ++Finally go back to the top directory: ++``` ++cd .. ++``` ++ ++After this, you can see the wrapper at `build-cef-dll/libcef_dll_wrapper/libcef_dll_wrapper.a`. ++ ++### Test applications ++ ++You can just use webOS `test-apps` repository: ++``` ++git clone https://github.com/webosose/test-apps.git ++``` ++ ++### Compilation of WAM ++ ++Prepare build folder: ++ ++``` ++mkdir build-wam ++cd build-wam ++mkdir wam-install ++``` ++ ++Then call *CMake* to generate the compilation scripts. You will need to pass several variables: ++* `CEF_ROOT`: full path to the CEF dist directory. ++* `CMAKE_INSTALL_PREFIX`: base install directory. ++* `CMAKE_INSTALL_BINDIR`: where executables will go. ++* `CMAKE_INSTALL_LIBDIR`: libraries. ++* `CMAKE_INSTALL_INCLUDEDIR`: path for includes. ++ ++You can also use `CMAKE_BUILD_TYPE` to set `Debug` or `Release` builds. ++ ++An example of the *CMake* invokation: ++``` ++cmake -DCMAKE_INSTALL_PREFIX=$PWD/wam-install -DCMAKE_INSTALL_BINDIR=$PWD/wam-install/bin -DCMAKE_INSTALL_LIBDIR=$PWD/wam-install/lib -DCMAKE_INSTALL_INCLUDEDIR=$PWD/wam-install/include -DCEF_ROOT=$WAM_BASE_PATH/cef_binary_114.2.10+g398e3c3+chromium-114.0.5735.110_linux64/Debug/ -DCMAKE_BUILD_TYPE=Debug ++``` ++ ++And finally compilation of WAM: ++``` ++make ++``` ++ ++And installation: ++``` ++make install ++``` ++ ++## Running ++ ++To run the daemon, you can do: ++``` ++cd wam-install/bin ++WEBAPPFACTORY_PLUGIN_PATH=../lib/webappmanager/plugins/ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../lib:$WAM_BASE_PATH/cef_binary_114.2.10+g398e3c3+chromium-114.0.5735.110_linux64/Release/ ./WebAppMgr & ++``` ++ ++Then, you can launch an application: ++``` ++LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../lib ../WebAppMgrDesktopCli --app-id=bareapp --app-install-dir=$WAM_BASE_PATH/test-apps/bareapp/ ++``` +diff --git a/src/desktop/web_runtime_desktop.cc b/src/desktop/web_runtime_desktop.cc +new file mode 100644 +index 0000000..49d1914 +--- /dev/null ++++ b/src/desktop/web_runtime_desktop.cc +@@ -0,0 +1,28 @@ ++#include "web_runtime_desktop.h" ++ ++#include "include/cef_base.h" ++ ++#include "wam_cef_browser_handler.h" ++ ++int WebRuntimeDesktop::Run(int argc, char** argv) { ++ CefMainArgs main_args(argc, argv); ++ ++ CefRefPtr<CefApp> app = new WamCefBrowserHandler; ++ auto exit_code = CefExecuteProcess(main_args, app.get(), nullptr); ++ if (exit_code >= 0) { ++ return exit_code; ++ } ++ ++ CefSettings settings; ++ CefInitialize(main_args, settings, app.get(), nullptr); ++ ++ CefRunMessageLoop(); ++ ++ CefShutdown(); ++ ++ return 0; ++} ++ ++std::unique_ptr<WebRuntime> WebRuntime::Create() { ++ return std::make_unique<WebRuntimeDesktop>(); ++} +diff --git a/src/desktop/web_runtime_desktop.h b/src/desktop/web_runtime_desktop.h +new file mode 100644 +index 0000000..e65f738 +--- /dev/null ++++ b/src/desktop/web_runtime_desktop.h +@@ -0,0 +1,11 @@ ++#ifndef DESKTOP_WEB_RUNTIME_CEF_H_ ++#define DESKTOP_WEB_RUNTIME_CEF_H_ ++ ++#include "web_runtime.h" ++ ++class WebRuntimeDesktop : public WebRuntime { ++ public: ++ int Run(int argc, char** argv) override; ++}; ++ ++#endif // DESKTOP_WEB_RUNTIME_CEF_H_ +diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt +index 876921b..b401dca 100644 +--- a/src/platform/CMakeLists.txt ++++ b/src/platform/CMakeLists.txt +@@ -17,10 +17,6 @@ + project(WebAppMgr VERSION 1.0.0 DESCRIPTION "Web Application Manager library") + + set(SOURCES +- palm_system_webos.cc +- web_app_wayland.cc +- web_app_wayland_window.cc +- web_app_window_impl.cc + webengine/blink_web_process_manager.cc + webengine/blink_web_view.cc + webengine/blink_web_view_profile_helper.cc +@@ -32,12 +28,8 @@ set(SOURCES + ) + + set(HEADERS +- palm_system_webos.h +- web_app_wayland.h +- web_app_wayland_window.h + web_app_window.h + web_app_window_factory.h +- web_app_window_impl.h + webengine/blink_web_process_manager.h + webengine/blink_web_view.h + webengine/blink_web_view_profile_helper.h +@@ -67,6 +59,21 @@ set(WAM_LIB_LIBS + WebAppMgrCore + ) + ++if (WEBENGINE_CBE) ++ LIST(APPEND SOURCES ++ web_app_window_impl.h ++ web_app_wayland_window.cc ++ palm_system_webos.cc ++ web_app_wayland.cc ++ ) ++ LIST(APPEND HEADERS ++ palm_system_webos.h ++ web_app_wayland.h ++ web_app_wayland_window.h ++ web_app_window_impl.h ++ ) ++endif() ++ + if (OS_WEBOS) + LIST(APPEND SOURCES + ${WAM_ROOT_SOURCE_DIR}/webos/palm_service_base.cc +diff --git a/src/platform/web_app_window.h b/src/platform/web_app_window.h +index 7381b0c..a90127f 100644 +--- a/src/platform/web_app_window.h ++++ b/src/platform/web_app_window.h +@@ -20,8 +20,6 @@ + #include <string> + #include <vector> + +-#include "webos/webapp_window_base.h" +- + class WebAppWayland; + + class WebAppWindow { +@@ -32,12 +30,14 @@ class WebAppWindow { + virtual int DisplayWidth() = 0; + virtual int DisplayHeight() = 0; + virtual void InitWindow(int width, int height) = 0; +- virtual void SetLocationHint(webos::WebAppWindowBase::LocationHint value) = 0; ++ virtual void SetLocationHint(const std::string& value) = 0; + virtual webos::NativeWindowState GetWindowHostState() const = 0; ++#if defined(OS_WEBOS) + virtual void CreateWindowGroup( + const webos::WindowGroupConfiguration& config) = 0; + virtual void AttachToWindowGroup(const std::string& name, + const std::string& layer) = 0; ++#endif + virtual bool IsKeyboardVisible() = 0; + virtual void SetKeyMask(webos::WebOSKeyMask key_mask) = 0; + virtual void SetKeyMask(webos::WebOSKeyMask key_mask, bool set) = 0; +diff --git a/src/util/log_msg_id.h b/src/util/log_msg_id.h +index 7d114cf..71d9621 100644 +--- a/src/util/log_msg_id.h ++++ b/src/util/log_msg_id.h +@@ -150,6 +150,8 @@ + + #define MSGID_DL_ERROR "DL_ERROR" /** Dinamic load library error **/ + ++#define MSGID_ERROR_CANNOT_LOCK_SERVICE "MSGID_CANNOT_LOCK_SERVICE" /** Cannot lock the GRPC IPC lock **/ ++ + // clang-format on + + #endif // LOGMSGID_H +diff --git a/src/util/timer.h b/src/util/timer.h +index 795a38c..6824fb8 100644 +--- a/src/util/timer.h ++++ b/src/util/timer.h +@@ -30,12 +30,12 @@ class Timer { + : source_id_(0), is_running_(false), is_repeating_(is_repeating) {} + virtual ~Timer() {} + +- // Timer + virtual void HandleCallback() = 0; +- virtual void Start(int delay_in_milli_seconds); + + bool IsRunning() { return is_running_; } + bool IsRepeating() { return is_repeating_; } ++ ++ void Start(int delay_in_milli_seconds); + void Stop(); + + protected: +diff --git a/src/wam_main.cc b/src/wam_main.cc +index 0c04a40..d559ee4 100644 +--- a/src/wam_main.cc ++++ b/src/wam_main.cc +@@ -14,11 +14,9 @@ + // + // SPDX-License-Identifier: Apache-2.0 + +-#include <webos/app/webos_main.h> +- + #include "web_runtime.h" + +-int main(int argc, const char** argv) { ++int main(int argc, char** argv) { + std::unique_ptr<WebRuntime> web_runtime(WebRuntime::Create()); + return web_runtime->Run(argc, argv); + } +diff --git a/src/webos/web_app_manager_service_luna.cc b/src/webos/web_app_manager_service_luna.cc +index 627cf31..b69635f 100644 +--- a/src/webos/web_app_manager_service_luna.cc ++++ b/src/webos/web_app_manager_service_luna.cc +@@ -632,6 +632,7 @@ void WebAppManagerServiceLuna::GetForegroundAppInfoCallback( + if (cleared_cache_) + cleared_cache_ = false; + ++#if defined(OS_WEBOS) + if (reply["returnValue"] == true) { + if (reply.isMember("appId") && reply["appId"].isString()) { + std::string appId = reply["appId"].asString(); +@@ -639,6 +640,7 @@ void WebAppManagerServiceLuna::GetForegroundAppInfoCallback( + WebAppManagerService::IsEnyoApp(appId.c_str())); + } + } ++#endif + } + + void WebAppManagerServiceLuna::BootdConnectCallback(const Json::Value& reply) { +diff --git a/src/webos/web_runtime_webos.cc b/src/webos/web_runtime_webos.cc +index 9dd2f72..cab7e5a 100644 +--- a/src/webos/web_runtime_webos.cc ++++ b/src/webos/web_runtime_webos.cc +@@ -70,7 +70,7 @@ class WebOSMainDelegateWAM : public webos::WebOSMainDelegate { + void AboutToCreateContentBrowserClient() override { StartWebAppManager(); } + }; + +-int WebRuntimeWebOS::Run(int argc, const char** argv) { ++int WebRuntimeWebOS::Run(int argc, char** argv) { + WebOSMainDelegateWAM delegate; + webos::WebOSMain webos_main(&delegate); + return webOSMain.Run(argc, argv); +diff --git a/src/webos/web_runtime_webos.h b/src/webos/web_runtime_webos.h +index eb52348..fa031a2 100644 +--- a/src/webos/web_runtime_webos.h ++++ b/src/webos/web_runtime_webos.h +@@ -21,7 +21,7 @@ + + class WebRuntimeWebOS : public WebRuntime { + public: +- int Run(int argc, const char** argv) override; ++ int Run(int argc, char** argv) override; + }; + + #endif // WEBOS_WEB_RUNTIME_WEBOS_H_ +-- +2.39.2 + diff --git a/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgr-cef.env b/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgr-cef.env new file mode 100644 index 000000000..adc18b94d --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgr-cef.env @@ -0,0 +1,81 @@ +# Set wam executable file path +HOOK_SEGV=NO + +# Set wam name for user-agent +WAM_NAME="WebAppManager" + +WAM_IS_CEF=true + +# Only allow UTF8 encoding for luna-service messages. +LS_ENABLE_UTF8=1 + +# suspending javascript execution delay for page visibility +WAM_SUSPEND_DELAY_IN_MS=250 + +WAM_DATA_PATH="/home/agl-driver/wamdata" + +# 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 +BLINK_NUM_RASTER_THREADS=1 + +# setup 6 Mb maximum for the program GPU cache +GPU_PROGRAM_CACHE_SIZE=6144 + +# Set location of all NPAPI plugins +NPAPI_PLUGIN_PATH=${HBBTV_PLUGIN_PATH}":"${NETCAST_PLUGIN_PATH}":"${PRIVILEGED_PLUGIN_PATH} + +# 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 + +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/share/wam + +WAM_SWITCHES="\ + --user-data-dir=\"$WAM_DATA_PATH\" \ + --use-gl=egl \ + --ozone-platform=wayland \ + --no-sandbox \ + --use-viz-fmp-with-timeout=0 \ + --remote-debugging-port=9998 \ + --webos-wam \ + --agl-shell-appid=homescreen \ + --disable-gpu-vsync \ + --ignore-gpu-blocklist \ + --allow-universal-access-from-files \ + --allow-file-access-from-files" diff --git a/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgr.env b/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgr.env new file mode 100644 index 000000000..f1d0f28f7 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgr.env @@ -0,0 +1,78 @@ +# Set wam executable file path +HOOK_SEGV=NO + +# Set wam name for user-agent +WAM_NAME="WebAppManager" + +WAM_IS_CEF=false + +# Only allow UTF8 encoding for luna-service messages. +LS_ENABLE_UTF8=1 + +# suspending javascript execution delay for page visibility +WAM_SUSPEND_DELAY_IN_MS=250 + +WAM_DATA_PATH="/home/agl-driver/wamdata" + +# 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 +BLINK_NUM_RASTER_THREADS=1 + +# setup 6 Mb maximum for the program GPU cache +GPU_PROGRAM_CACHE_SIZE=6144 +# Set location of all NPAPI plugins +NPAPI_PLUGIN_PATH=${HBBTV_PLUGIN_PATH}":"${NETCAST_PLUGIN_PATH}":"${PRIVILEGED_PLUGIN_PATH} + +# 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 + +WAM_SWITCHES="\ + --user-data-dir=$WAM_DATA_PATH \ + --use-gl=egl \ + --enable-features=UseOzonePlatform \ + --ozone-platform=wayland \ + --no-sandbox \ + --use-viz-fmp-with-timeout=0 \ + --in-process-gpu \ + --remote-debugging-port=9998 \ + --webos-wam \ + --agl-shell-appid=homescreen \ + --disable-gpu-vsync \ + --ignore-gpu-blocklist" diff --git a/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgr.service b/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgr.service new file mode 100644 index 000000000..5f025a18e --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgr.service @@ -0,0 +1,34 @@ +# @@@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=agl-compositor.service nss-agl-driver-db.service +Requires=agl-compositor.service nss-agl-driver-db.service +Before=graphical.target +BindTo=agl-compositor.service + +[Service] +User=agl-driver +WorkingDirectory=/home/agl-driver +Type=simple +UMask=0077 +OOMScoreAdjust=-1000 +EnvironmentFile=-/etc/default/WebAppMgr.env +Environment=XDG_RUNTIME_DIR=/run/user/1001/ +ExecStart=@WAM_EXE_DIR@/WebAppMgr $WAM_SWITCHES +ExecStop=pkill -U %U WebAppMgr +Restart=on-failure +RestartSec=50 + +[Install] +WantedBy=graphical.target diff --git a/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgrCli b/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgrCli new file mode 100755 index 000000000..4312e0472 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/wam/files/WebAppMgrCli @@ -0,0 +1,9 @@ +#!/bin/bash + +WAM_CLI_EXE="/usr/bin/WebAppMgr" + +if [ "$WAM_IS_CEF" = true ] ; then + WAM_CLI_EXE="/usr/share/wam/WebAppMgrCli" +fi + +exec $WAM_CLI_EXE $@ diff --git a/meta-agl-html5-demo/recipes-wam/wam/wam-cef.inc b/meta-agl-html5-demo/recipes-wam/wam/wam-cef.inc new file mode 100644 index 000000000..f0fdcd35d --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/wam/wam-cef.inc @@ -0,0 +1,40 @@ +SRC_URI:append = " file://0001-agl-cef-Snapshot-with-all-patches-needed-to-enable-w.patch" + +do_configure[depends] += "cef:do_populate_sysroot" + +CEF_ROOT = "${STAGING_DATADIR}/cef" +WAM_OUT_DIR = "${datadir}/wam" + +RUNTIME = "llvm" +TOOLCHAIN = "clang" + +DEPENDS:append:toolchain-clang = " clang-cross-${TARGET_ARCH}" + +PREFERRED_PROVIDER_libgcc = "compiler-rt" + +COMPATIBLE_MACHINE = "(-)" +COMPATIBLE_MACHINE:aarch64 = "(.*)" +COMPATIBLE_MACHINE:armv7 = "(.*)" +COMPATIBLE_MACHINE:armv7a = "(.*)" +COMPATIBLE_MACHINE:armv7ve = "(.*)" +COMPATIBLE_MACHINE:x86 = "(.*)" +COMPATIBLE_MACHINE:x86-64 = "(.*)" + +EXTRA_OECMAKE = "\ + -DPROJECT_ARCH=${TUNE_ARCH} \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=${prefix} \ + -DPLATFORM_NAME=${@'${DISTRO}'.upper().replace('-', '_')} \ + -DCEF_ROOT=${CEF_ROOT} \ + -DCMAKE_INSTALL_BINDIR=${WAM_OUT_DIR}" + +do_install:append() { + cp -R --no-dereference --preserve=mode,links -v ${CEF_ROOT}/Release/* ${D}${WAM_OUT_DIR} + cp -R --no-dereference --preserve=mode,links -v ${CEF_ROOT}/Resources/* ${D}${WAM_OUT_DIR} + install -v -D -m 644 ${WORKDIR}/WebAppMgr-cef.env ${D}${sysconfdir}/default/WebAppMgr.env + sed -i -e 's#@WAM_EXE_DIR@#${WAM_OUT_DIR}#g' ${D}${systemd_system_unitdir}/WebAppMgr.service +} + +INSANE_SKIP:${PN} += "already-stripped file-rdeps libdir" + +FILES:${PN} += "${WAM_OUT_DIR}" diff --git a/meta-agl-html5-demo/recipes-wam/wam/wam_git.bb b/meta-agl-html5-demo/recipes-wam/wam/wam_git.bb new file mode 100644 index 000000000..f76641e51 --- /dev/null +++ b/meta-agl-html5-demo/recipes-wam/wam/wam_git.bb @@ -0,0 +1,55 @@ +SUMMARY = "WAM" +AUTHOR = "Jani Hautakangas <jani.hautakangas@lge.com>" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +DEPENDS = "glib-2.0 jsoncpp boost protobuf protobuf-native grpc grpc-native" + +SRC_URI = "\ + git://github.com/igalia/${BPN}.git;branch=@58.agl;protocol=https \ + file://WebAppMgrCli \ + file://WebAppMgr.service \ + file://WebAppMgr.env \ + file://WebAppMgr-cef.env \ +" + +SRCREV = "4fbd6e648913bcf0fba63e4460eb44242c11f71b" + +PV = "ose58.agl" + +S = "${WORKDIR}/git" + +inherit cmake pkgconfig systemd + +# Disable some of security flags +# Disable D_FORTIFY_SOURCE=2 and -fstack-protector-strong +# Refer conf/distro/include/security_flags.inc in meta-webos/conf/distro/include/webos.inc +lcl_maybe_fortify = "" +SECURITY_STACK_PROTECTOR = "" + +SYSTEMD_SERVICE:${PN} = "WebAppMgr.service" + +do_install:append() { + install -v -d ${D}${sysconfdir}/wam + install -v -m 644 ${S}/files/launch/security_policy.conf ${D}${sysconfdir}/wam/security_policy.conf + install -v -D -m 644 ${WORKDIR}/WebAppMgr.service ${D}${systemd_system_unitdir}/WebAppMgr.service + install -v -D -m 755 ${WORKDIR}/WebAppMgrCli ${D}${bindir}/WebAppMgrCli +} + +CXXFLAGS:append:agl-devel = " -DAGL_DEVEL" + +do_install:append:agl-devel() { + # Enable remote inspector and dev mode + install -d ${D}${localstatedir}/agl-devel/preferences + touch ${D}${localstatedir}/agl-devel/preferences/debug_system_apps + touch ${D}${localstatedir}/agl-devel/preferences/devmode_enabled +} + +require wam-cef.inc + +FILES:${PN} += "${sysconfdir}/init \ + ${sysconfdir}/wam \ + ${bindir} \ + ${libdir}/webappmanager/plugins/*.so" + +RDEPENDS:${PN} += " bash grpc-web-proxy" |