diff options
author | Dominik Holland <dominik.holland@qt.io> | 2023-06-22 14:44:20 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-06-30 15:34:14 +0000 |
commit | 96667d1cbecc81d6bf522d81a55ca9b2a2c637a9 (patch) | |
tree | 1774512ff7dd9e3a426a382b52a0a6f32b98b1f6 | |
parent | ca681d30049b7f95ae22d97daaf35dcab095cfc9 (diff) |
Add a bubblewrap-example
Change-Id: If8992fdf6306030c8c59cd83ec57b6704b1dc01f
Reviewed-by: Robert Griebl <robert.griebl@qt.io>
(cherry picked from commit 6dcafd4d51923e866ed093d0ddb7686a881286bb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
20 files changed, 537 insertions, 0 deletions
diff --git a/examples/applicationmanager/CMakeLists.txt b/examples/applicationmanager/CMakeLists.txt index 3bd88f16..4cd52f9c 100644 --- a/examples/applicationmanager/CMakeLists.txt +++ b/examples/applicationmanager/CMakeLists.txt @@ -12,4 +12,5 @@ add_subdirectory(intents) add_subdirectory(custom-appman) if(LINUX) add_subdirectory(softwarecontainer-plugin) + add_subdirectory(bubblewrap-example) endif() diff --git a/examples/applicationmanager/bubblewrap-example/CMakeLists.txt b/examples/applicationmanager/bubblewrap-example/CMakeLists.txt new file mode 100644 index 00000000..e37a9ce6 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/CMakeLists.txt @@ -0,0 +1,35 @@ + +cmake_minimum_required(VERSION 3.16) +project(bubblewrap-example LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/applicationmanager/bubblewrap-example") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS AppManMainPrivate) + +qt_am_add_systemui_wrapper(bubblewrap-example + INSTALL_DIR "${INSTALL_EXAMPLEDIR}" + EXTRA_FILES apps system-ui.qml bubblewrap-network-setup.sh + CONFIG_YAML am-config.yaml + EXTRA_ARGS --verbose +) + +qt_add_qml_module(networkhelper + URI "NetworkHelper" + SOURCES + networkhelper.cpp networkhelper.h + PLUGIN_TARGET networkhelper + OUTPUT_DIRECTORY + imports/NetworkHelper +) diff --git a/examples/applicationmanager/bubblewrap-example/am-config.yaml b/examples/applicationmanager/bubblewrap-example/am-config.yaml new file mode 100644 index 00000000..3e7c5318 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/am-config.yaml @@ -0,0 +1,57 @@ +formatVersion: 1 +formatType: am-configuration +--- +applications: + builtinAppsManifestDir: "${CONFIG_PWD}/apps" + +ui: + mainQml: "${CONFIG_PWD}/system-ui.qml" + +runtimes: + qml: + importPaths: "${CONFIG_PWD}/imports" + +quicklaunch: + runtimesPerContainer: 1 + +containers: + bubblewrap: + # 'no': host network, or 'yes': no network at all, or a path to a setup script + unshareNetwork: no + # You can use this script as a starting point. It has to be adapted to + # your network setup though. + # unshareNetwork: 'sudo "${CONFIG_PWD}/bubblewrap-network-setup.sh"' + + # set to yes, if you build against a system or Installer Qt and the launcher cannot be found + bindMountHome: yes + configuration: + symlink: + usr/lib: '/lib' + usr/lib64: '/lib64' + usr/bin: [ '/bin', '/sbin' ] + ro-bind: + /usr/bin: '/usr/bin' + /usr/lib: '/usr/lib' + /usr/lib64: '/usr/lib64' + /etc: '/etc' + /usr/share/fonts: '/usr/share/fonts' + /usr/share/fontconfig: '/usr/share/fontconfig' + /usr/share/ca-certificates: '/usr/share/ca-certificates' + /sys/dev/char: '/sys/dev/char' + ${CONFIG_PWD}/imports: '${CONFIG_PWD}/imports' + ro-bind-try: + '/sys/devices/pci0000:00': '/sys/devices/pci0000:00' + /usr/share/glvnd/egl_vendor.d: '/usr/share/glvnd/egl_vendor.d' + /usr/share/X11/xkb: '/usr/share/X11/xkb' + /run/resolvconf: '/run/resolvconf' + dev: '/dev' + dev-bind: + /dev/dri: '/dev/dri' + tmpfs: + /tmp + proc: + /proc + + selection: + - '*': bubblewrap + diff --git a/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/Browser.qml b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/Browser.qml new file mode 100644 index 00000000..4a9414ba --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/Browser.qml @@ -0,0 +1,9 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtWebEngine + +WebEngineView { + url: "https://www.qt.io" +} diff --git a/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/icon.svg b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/icon.svg new file mode 100644 index 00000000..905de132 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/icon.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 91.26" style="enable-background:new 0 0 122.88 91.26" xml:space="preserve"><style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;}</style><g><path class="st0" d="M14.85,45.46h6.65l2.39,12.65l3.5-12.65h6.6l3.53,12.67l2.41-12.67h6.62l-5,22.68h-6.87L30.7,53.86 l-3.95,14.28h-6.86L14.85,45.46L14.85,45.46z M8.32,0h106.24c4.58,0,8.32,3.74,8.32,8.32v74.62c0,4.57-3.74,8.32-8.32,8.32H8.32 C3.74,91.26,0,87.51,0,82.94V8.32C0,3.74,3.74,0,8.32,0L8.32,0z M117.97,23.29H5.29v60.46c0,0.64,0.25,1.2,0.67,1.63 c0.42,0.42,0.99,0.67,1.63,0.67h108.04c0.64,0,1.2-0.25,1.63-0.67c0.43-0.43,0.67-0.99,0.67-1.63V23.29H117.97L117.97,23.29z M106.64,9.35c2.27,0,4.11,1.84,4.11,4.11s-1.84,4.11-4.11,4.11c-2.27,0-4.11-1.84-4.11-4.11S104.38,9.35,106.64,9.35L106.64,9.35z M78.8,9.35c2.27,0,4.11,1.84,4.11,4.11s-1.84,4.11-4.11,4.11c-2.27,0-4.11-1.84-4.11-4.11S76.53,9.35,78.8,9.35L78.8,9.35z M92.72,9.35c2.27,0,4.11,1.84,4.11,4.11s-1.84,4.11-4.11,4.11c-2.27,0-4.11-1.84-4.11-4.11S90.45,9.35,92.72,9.35L92.72,9.35z M78.3,45.46h6.65l2.39,12.65l3.5-12.65h6.6l3.53,12.67l2.41-12.67h6.62l-5,22.68h-6.87l-3.98-14.28L90.2,68.14h-6.86L78.3,45.46 L78.3,45.46z M46.58,45.46h6.65l2.39,12.65l3.5-12.65h6.6l3.53,12.67l2.41-12.67h6.62l-5,22.68h-6.87l-3.98-14.28l-3.95,14.28 h-6.86L46.58,45.46L46.58,45.46z"/></g></svg> + diff --git a/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/info.yaml b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/info.yaml new file mode 100644 index 00000000..5675905d --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/info.yaml @@ -0,0 +1,9 @@ +formatVersion: 1 +formatType: am-application +--- +id: 'bubblewrap.browser' +icon: 'icon.svg' +code: 'main.qml' +runtime: 'qml' +name: + en: 'Browser' diff --git a/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/main.qml b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/main.qml new file mode 100644 index 00000000..d4f5dd7c --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/main.qml @@ -0,0 +1,25 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtApplicationManager.Application + +ApplicationManagerWindow { + Rectangle { + anchors.fill: parent + border.color: "green" + + Text { + visible: loader.status === Loader.Error + anchors.centerIn: parent + text: "Can't load QtWebEngine, please make sure it is installed." + } + + Loader { + id: loader + anchors.fill: parent + anchors.margins: 2 + source: "Browser.qml" + } + } +} diff --git a/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/icon.svg b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/icon.svg new file mode 100644 index 00000000..f06011d8 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/icon.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 94.72" style="enable-background:new 0 0 122.88 94.72" xml:space="preserve"><g><path d="M8.46,31.23c-1.08,0.92-2.42,1.32-3.72,1.22c-1.31-0.1-2.58-0.7-3.5-1.78l-0.02-0.03c-0.91-1.07-1.3-2.41-1.2-3.7 c0.1-1.31,0.7-2.58,1.78-3.5l0.01-0.01c9.06-7.77,18.73-13.65,28.73-17.58c10.08-3.96,20.5-5.93,31-5.84 c10.35,0.09,20.74,2.19,30.9,6.36c9.81,4.03,19.4,10,28.55,17.97c0.11,0.08,0.21,0.17,0.29,0.26c0.96,0.92,1.5,2.13,1.58,3.37 c0.08,1.24-0.29,2.51-1.12,3.55c-0.08,0.12-0.18,0.23-0.29,0.33c-0.92,0.96-2.13,1.5-3.37,1.58c-1.3,0.09-2.65-0.33-3.71-1.26 c-8.27-7.23-16.9-12.62-25.68-16.25c-8.99-3.72-18.14-5.58-27.23-5.66c-9.2-0.08-18.38,1.68-27.31,5.2 C25.25,18.97,16.6,24.25,8.46,31.23L8.46,31.23z M61.44,72.27c3.1,0,5.9,1.26,7.93,3.29c2.03,2.03,3.29,4.84,3.29,7.93 c0,3.1-1.26,5.9-3.29,7.93c-2.03,2.03-4.84,3.29-7.93,3.29c-3.1,0-5.9-1.26-7.94-3.29c-2.03-2.03-3.29-4.84-3.29-7.93 c0-3.09,1.26-5.9,3.29-7.93l0,0C55.54,73.53,58.34,72.27,61.44,72.27L61.44,72.27z M42.07,66.17c-1.1,0.89-2.46,1.26-3.76,1.12 c-1.24-0.13-2.44-0.71-3.32-1.71c-0.1-0.1-0.19-0.21-0.26-0.32c-0.8-1.07-1.12-2.35-0.99-3.59c0.13-1.24,0.71-2.44,1.71-3.32 c0.09-0.09,0.19-0.17,0.29-0.24c4-3.23,8.18-5.7,12.47-7.37c4.35-1.7,8.82-2.57,13.33-2.58c4.45-0.01,8.89,0.81,13.27,2.5 c4.25,1.64,8.44,4.11,12.48,7.41c1.1,0.89,1.73,2.15,1.87,3.45c0.13,1.3-0.23,2.66-1.12,3.76l-0.01,0.01 c-0.89,1.09-2.14,1.72-3.45,1.86c-1.3,0.13-2.66-0.23-3.76-1.12l0,0c-3.14-2.57-6.35-4.47-9.56-5.73c-3.25-1.28-6.5-1.9-9.72-1.89 c-3.25,0.01-6.52,0.67-9.77,1.96C48.46,61.67,45.21,63.62,42.07,66.17L42.07,66.17z M25.81,49.65c-0.08,0.08-0.17,0.16-0.26,0.22 c-1.03,0.84-2.3,1.21-3.53,1.14c-1.27-0.08-2.51-0.63-3.44-1.63c-0.09-0.08-0.16-0.17-0.23-0.26c-0.84-1.03-1.21-2.3-1.14-3.53 c0.08-1.31,0.66-2.59,1.72-3.53c6.81-6.03,13.85-10.59,21.01-13.61c7.18-3.02,14.49-4.51,21.85-4.38c7.27,0.12,14.53,1.8,21.69,5.1 c6.97,3.21,13.86,7.96,20.59,14.3l0.13,0.12c0.95,0.95,1.44,2.2,1.48,3.46c0.04,1.31-0.42,2.63-1.39,3.66l-0.12,0.13 c-0.96,0.95-2.2,1.45-3.46,1.49c-1.31,0.04-2.63-0.42-3.66-1.39c-5.83-5.5-11.73-9.59-17.62-12.35c-5.95-2.78-11.9-4.19-17.8-4.29 c-5.99-0.1-12,1.15-17.96,3.69C37.64,40.58,31.66,44.48,25.81,49.65L25.81,49.65z"/></g></svg> + diff --git a/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/info.yaml b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/info.yaml new file mode 100644 index 00000000..a5994189 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/info.yaml @@ -0,0 +1,9 @@ +formatVersion: 1 +formatType: am-application +--- +id: 'bubblewrap.networkinfo' +icon: 'icon.svg' +code: 'main.qml' +runtime: 'qml' +name: + en: 'Network Info' diff --git a/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/main.qml b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/main.qml new file mode 100644 index 00000000..9540e47a --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/main.qml @@ -0,0 +1,36 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtApplicationManager.Application +import NetworkHelper + +ApplicationManagerWindow { + Rectangle { + anchors.fill: parent + border.color: "red" + + ListView { + anchors.fill: parent + model: networkHelper.ipAddresses + header: Text { + anchors.horizontalCenter: parent.horizontalCenter + text: "IP ADDRESSES" + font.bold: true + height: 40 + } + delegate: Text { + anchors.horizontalCenter: parent.horizontalCenter + text: modelData + } + } + + NetworkHelper { + id: networkHelper + + Component.onCompleted: { + console.log("ip", networkHelper.ipAddresses) + } + } + } +} diff --git a/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/icon.svg b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/icon.svg new file mode 100644 index 00000000..5c534a3e --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/icon.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 84.91 122.88" style="enable-background:new 0 0 84.91 122.88" xml:space="preserve"><g><path d="M26.6,80.57c-0.11-0.06-0.25-0.14-0.37-0.23c-1.49-1.18-3.13-2.51-4.54-3.66c-2.06-1.69-4.43-3.64-6.09-5.02 c-1.13-0.93-2.42-1.58-3.63-1.83c-0.79-0.14-1.49-0.14-2.06,0.08c-0.45,0.2-0.85,0.56-1.1,1.13c-0.34,0.76-0.51,1.83-0.42,3.3 c0.08,1.3,0.54,2.71,1.13,4.09c0.87,2,2.09,3.86,2.99,5.04c0.06,0.08,0.11,0.14,0.14,0.23l17.84,25.48 c0.23,0.34,0.37,0.71,0.39,1.07c0.37,2.93,0.99,5.16,1.89,6.54c0.68,1.01,1.52,1.52,2.62,1.49h28.07c1.75-0.03,3.33-0.53,4.79-1.55 c1.61-1.1,3.04-2.82,4.37-5.13c0.03-0.03,0.06-0.08,0.08-0.11c0.51-0.87,1.18-2,1.83-3.07c2.85-4.68,5.33-8.77,5.61-14.57l-0.17-8 c-0.03-0.11-0.03-0.23-0.03-0.34s0-0.87,0.03-1.89c0.06-5.3,0.14-11.84-4.71-12.65h-3.13c-0.03,1.49-0.11,3.02-0.2,4.48 c-0.08,1.32-0.17,2.56-0.17,3.78c0,1.3-1.04,2.34-2.34,2.34c-1.3,0-2.34-1.04-2.34-2.34c0-1.21,0.08-2.62,0.17-4.09 c0.31-4.99,0.68-10.71-3.3-11.41h-3.1c-0.17,0-0.34-0.03-0.51-0.06c0.03,1.8-0.08,3.66-0.2,5.47C60.08,70.46,60,71.7,60,72.91 c0,1.3-1.04,2.34-2.34,2.34c-1.3,0-2.34-1.04-2.34-2.34c0-1.21,0.08-2.62,0.17-4.09c0.31-4.99,0.68-10.71-3.3-11.41h-3.1 c-0.23,0-0.42-0.03-0.62-0.08v9.1c0,1.3-1.04,2.34-2.34,2.34c-1.3,0-2.34-1.04-2.34-2.34V41.99c0-4.09-1.66-6.68-3.8-7.75 c-0.79-0.4-1.63-0.59-2.45-0.59c-0.82,0-1.66,0.2-2.45,0.59c-2.11,1.07-3.75,3.66-3.75,7.86v42.81c0,1.3-1.04,2.34-2.34,2.34 c-1.3,0-2.34-1.04-2.34-2.34v-4.34H26.6L26.6,80.57z M39.29,13.99c0,1.55-1.26,2.78-2.78,2.78c-1.55,0-2.78-1.26-2.78-2.78V2.78 c0-1.55,1.26-2.78,2.78-2.78c1.55,0,2.78,1.26,2.78,2.78V13.99L39.29,13.99L39.29,13.99z M13.99,36.95c1.55,0,2.78,1.26,2.78,2.78 c0,1.55-1.26,2.78-2.78,2.78H2.78C1.23,42.5,0,41.24,0,39.73c0-1.55,1.26-2.78,2.78-2.78H13.99L13.99,36.95z M21.92,20.33 c1.08,1.08,1.08,2.85,0,3.93c-1.08,1.08-2.85,1.08-3.93,0l-7.9-7.93c-1.08-1.08-1.08-2.85,0-3.93c1.08-1.08,2.85-1.08,3.93,0 L21.92,20.33L21.92,20.33z M58.47,42.5c-1.55,0-2.78-1.26-2.78-2.78c0-1.55,1.26-2.78,2.78-2.78h11.21c1.55,0,2.78,1.26,2.78,2.78 c0,1.55-1.26,2.78-2.78,2.78H58.47L58.47,42.5z M54.47,23.65c-1.08,1.08-2.85,1.08-3.93,0c-1.08-1.08-1.08-2.85,0-3.93l7.9-7.93 c1.08-1.08,2.85-1.08,3.93,0c1.08,1.08,1.08,2.85,0,3.93L54.47,23.65L54.47,23.65z M48.47,52.79c0.2-0.06,0.39-0.08,0.62-0.08h3.24 c0.17,0,0.37,0.03,0.53,0.06c4.31,0.68,6.26,3.19,7.05,6.45c0.31-0.14,0.65-0.23,0.99-0.23h3.24c0.17,0,0.37,0.03,0.53,0.06 c4.65,0.73,6.51,3.58,7.19,7.19c0.11-0.03,0.23-0.03,0.37-0.03h3.24c0.17,0,0.37,0.03,0.54,0.06c8.91,1.38,8.79,10.23,8.71,17.36 v1.86l0.2,8.23v0.25c-0.34,7.02-3.1,11.56-6.28,16.8c-0.54,0.87-1.07,1.77-1.8,3.02c-0.03,0.03-0.03,0.06-0.06,0.08 c-1.66,2.9-3.58,5.13-5.78,6.65c-2.23,1.55-4.71,2.34-7.41,2.37H35.53c-2.79,0.06-4.96-1.16-6.57-3.55c-1.3-1.92-2.14-4.62-2.59-8 L8.9,86.35l-0.09-0.08c-1.04-1.38-2.45-3.55-3.52-5.95c-0.79-1.8-1.38-3.75-1.52-5.67c-0.14-2.28,0.17-4.09,0.82-5.52 c0.79-1.78,2.09-2.93,3.64-3.55c1.44-0.59,3.07-0.68,4.71-0.34c1.97,0.4,4,1.38,5.72,2.82c1.41,1.18,3.78,3.1,6.09,4.99l1.92,1.58 V42.13c0-6.23,2.76-10.23,6.34-12.04c1.44-0.73,2.99-1.1,4.57-1.1c1.58,0,3.13,0.37,4.56,1.1c3.58,1.8,6.4,5.83,6.4,11.95v10.76 L48.47,52.79L48.47,52.79z"/></g></svg> + diff --git a/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/info.yaml b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/info.yaml new file mode 100644 index 00000000..733d6b7e --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/info.yaml @@ -0,0 +1,9 @@ +formatVersion: 1 +formatType: am-application +--- +id: 'bubblewrap.simple' +icon: 'icon.svg' +code: 'main.qml' +runtime: 'qml' +name: + en: 'Simple QML' diff --git a/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/main.qml b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/main.qml new file mode 100644 index 00000000..bc2c1807 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/main.qml @@ -0,0 +1,23 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls +import QtApplicationManager.Application + +ApplicationManagerWindow { + Rectangle { + anchors.fill: parent + border.color: "blue" + + Button { + width: 200 + height: 50 + + anchors.centerIn: parent + + text: "Click to exit with code 42" + onClicked: Qt.exit(42) + } + } +} diff --git a/examples/applicationmanager/bubblewrap-example/bubblewrap-network-setup.sh b/examples/applicationmanager/bubblewrap-example/bubblewrap-network-setup.sh new file mode 100755 index 00000000..8eecc7d8 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/bubblewrap-network-setup.sh @@ -0,0 +1,75 @@ +#!/bin/sh +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +# Parameters: +# $1 event The stage for which this script has been called: can be "quicklaunch", "start" or "stop". +# - "quicklaunch" is called when a new quicklauncher instance is started. +# - "start" is called when an applications starts or when an application is attached to +# an already running quicklaunch instance. +# - "stop" is called when an application (or unused quicklauncher instance) shuts down. +# $2 appid The application's id for both the "start" and "stop" events. It is simply "quicklaunch" +# for the "quicklaunch" event and also for "stop" events on unused quicklauncher instances. +# $3 pid The PID of the containerized application. Use /proc/<pid>/ns/net to access the +# corresponding network namespace. In case of the "stop" event, the process with the +# given PID is already dead and just acts as a reference. + +set -e +#set -x + +echo >&2 "Network setup script called: $@" + +####### + +HOST_BRIDGE="br0" +HOST_IF_PREFIX="qtam-" +CONT_IF="veth" +CONT_IP="10.1.1.111/24" +CONT_GW="10.1.1.1" + +####### + +EVENT="$1" +APPID="$2" +NETNS_PID="$3" +# network device names can be max 15 chars: "qtam-<10 chars>" +HASHED_APPID=$(echo $APPID | sha1sum -b | base64 | tr '/' '_' | cut -b 1-10) +HOST_IF="${HOST_IF_PREFIX}${HASHED_APPID}" +NETNS="qtam-$APPID" + +case "$EVENT" in +start) + # "ip netns" cannot use the special /proc/<pid>/ns/net symlinks directly. Instead, we need to + # create a second level link in /var/run/netns and then reference the network namespace by the + # name of the this symlink. + mkdir -p /var/run/netns + ln -sfT /proc/$NETNS_PID/ns/net "/var/run/netns/$NETNS" + + # create a virtual ethernet (veth) device pair + ip link add "$HOST_IF" type veth peer name "$CONT_IF" netns "$NETNS" + + # host side: bring it up and add it to an existing bridge + ip link set dev "$HOST_IF" up + + # for a bridged setup, add the host interface to your external bridge + # brctl addif "${HOST_BRIDGE}" "${HOST_IF}" + + # client side: bring it up, set a fixed IP and add a default route + ip -n "$NETNS" link set dev "$CONT_IF" up + ip -n "$NETNS" addr add "$CONT_IP" dev "$CONT_IF" + ip -n "$NETNS" route add default via "$CONT_GW" + ;; + +stop) + # the kernel cleans up our veth pair automatically + + # we could have removed this link at the end of "start" above already, but keeping it around + # makes debugging the network namespace easier during development + rm -f "/var/run/netns/$NETNS" + ;; + +quicklaunch) + # the quick launcher does not need network access + ;; +esac + diff --git a/examples/applicationmanager/bubblewrap-example/doc/images/bubblewrap-example.png b/examples/applicationmanager/bubblewrap-example/doc/images/bubblewrap-example.png Binary files differnew file mode 100644 index 00000000..6e5bac36 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/doc/images/bubblewrap-example.png diff --git a/examples/applicationmanager/bubblewrap-example/doc/src/bubblewrap-example.qdoc b/examples/applicationmanager/bubblewrap-example/doc/src/bubblewrap-example.qdoc new file mode 100644 index 00000000..6d995717 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/doc/src/bubblewrap-example.qdoc @@ -0,0 +1,108 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + +\example applicationmanager/bubblewrap-example +\brief Learn how to use Bubblewrap Containers with the Application Manager. +\ingroup applicationmanager-examples +\title Bubblewrap Container Example +\image bubblewrap-example.png Bubblewrap Container Example + +\section1 Introduction + +This example shows you how to launch applications within a \l{Bubblewrap Container}{bubblewrap +container} for extra security. + +\b Prerequisites: You're already familiar with the concepts and topics introduced in the + \l {System UI Example: "Hello World!"}. This example uses the same folder structure and can be + started in the same way. + +A Bubblewrap container uses the \l{bubblewrap}{bwrap} command-line utility to start a process in a +separate kernel namespace. This is similar to how Docker works, but has the benefit that no extra +daemon needs to be running. Bubblewrap is also used by \l{Flatpak} to sandbox applications. + +\section1 Configuration + +First we need to select which applications should use the bubblewrap container. In this example we +use it for all our examples by setting a wildcard for the \l {selection} key in the am-config.yaml + +\quotefromfile applicationmanager/bubblewrap-example/am-config.yaml +\skipto containers: +\printuntil containers: +\skipto selection: +\printto + +The next thing we need is the actual container configuration. Without this configuration our +applications would not start and stop with an error similar to this: + +\badcode +bwrap: execvp /usr/bin/appman-launcher-qml: No such file or directory +\endcode + +This happens because the default configuration of the bubblewrap container doesn't share any +directory into the newly created kernel namespace. That basically means we tried to start a +application without having any user-space libraries. + +A good starting point for the container configuration is shown here: +\quotefromfile applicationmanager/bubblewrap-example/am-config.yaml +\skipto containers: +\printuntil bubblewrap: +\skipto configuration: +\printto selection: + +We configure the container to use parts of our own rootfs and bind mount it into the kernel +namespace. In a similar way we also configure it to use its own \c tmpfs and \c procfs filesystem. + +\section1 Running the example + +When starting the example you should see a window similar to this: + +\image bubblewrap-example.png + +Once you press one of the icons on the left side, the corresponding application is started and its +window is shown on the right side, similar to the \l {System UI Example: "Hello World!"}. + +The first application is a browser and uses \l QtWebengine to show the Qt homepage. The second +application is network info, which shows all ip addresses of the system. Last but not least the +'Simple QML' application shows a button to exit the process with a specific exit code. + +\section1 Quick launch + +Right now all our applications are started when the corresponding button is pressed. This involves +starting a new container process and within this container process start the application process, +which then starts loading the application's QML code. + +When quick-launch is enabled, a container running the application managers's QML launcher is +started in the background. Once the application should be started the QML launcher just needs to +load the application QML code. For this to work correctly with the bubblewrap container, root +permissions are needed, in order to mount the correct application directory into the container. + +In the am-config.yaml the quick launch is enabled like this: +\quotefromfile applicationmanager/bubblewrap-example/am-config.yaml +\skipto quicklaunch: +\printuntil runtimesPerContainer: + +To see quick-launch in action, you need to start the example with "sudo". + +\section1 Network isolation + +Similar to quick-launch, another feature also needs root permissions: the network isolation. +Right now the container has full network acccess. The network access can be configured with the +following snippet in the am-config.yaml: + +\quotefromfile applicationmanager/bubblewrap-example/am-config.yaml +\skipto containers: +\printuntil unshareNetwork: +\printuntil unshareNetwork: + +If the applications shouldn't have any network access, you can change the \c unshareNetwork option +to \c yes. If you start the networkinfo application you will see that no ip address is available +inside the container anymore. Similar the browser application doesn't have a network. + +Another option is to set \c unshareNetwork to the path of a script. This script will be executed +for every container and can be used to setup the network devices accordingly. The script which is +provided with this example creates a new network device on the host and shares this device into the +container. The newly created network device can now be bridged and filtered on the host side +without any changes inside the container. +*/ diff --git a/examples/applicationmanager/bubblewrap-example/hello-world.pro b/examples/applicationmanager/bubblewrap-example/hello-world.pro new file mode 100644 index 00000000..840857f1 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/hello-world.pro @@ -0,0 +1,31 @@ +TEMPLATE = app +CONFIG += am-systemui + +OTHER_FILES += \ + *.qml \ + doc/images/*.png \ + doc/src/*.qdoc \ + apps/hello-world.blue/*.yaml \ + apps/hello-world.blue/*.qml \ + apps/hello-world.blue/*.png \ + apps/hello-world.green/*.yaml \ + apps/hello-world.green/*.qml \ + apps/hello-world.green/*.png \ + apps/hello-world.red/*.yaml \ + apps/hello-world.red/*.qml \ + apps/hello-world.red/*.png \ + +target.path = $$[QT_INSTALL_EXAMPLES]/applicationmanager/hello-world +INSTALLS += target + +AM_COPY_DIRECTORIES += apps +AM_COPY_FILES += system-ui.qml + +prefix_build:tpath = $$target.path +else:tpath = $$_PRO_FILE_PWD_ + +AM_DEFAULT_ARGS=--builtin-apps-manifest-dir $$tpath/apps $$tpath/system-ui.qml + +example_sources.path = $$target.path +example_sources.files = $$AM_COPY_FILES $$AM_COPY_DIRECTORIES +INSTALLS += example_sources diff --git a/examples/applicationmanager/bubblewrap-example/networkhelper.cpp b/examples/applicationmanager/bubblewrap-example/networkhelper.cpp new file mode 100644 index 00000000..2f607c6a --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/networkhelper.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "networkhelper.h" + +#include <QNetworkInterface> + +NetworkHelper::NetworkHelper(QObject *parent) + : QObject{parent} +{ + const auto addresses = QNetworkInterface::allAddresses(); + for (const auto &address : addresses) { + m_ipAddresses += address.toString(); + } + + qDebug() << "FOOOO" << addresses << m_ipAddresses; +} + +QStringList NetworkHelper::ipAddresses() const +{ + return m_ipAddresses; +} diff --git a/examples/applicationmanager/bubblewrap-example/networkhelper.h b/examples/applicationmanager/bubblewrap-example/networkhelper.h new file mode 100644 index 00000000..282af2a7 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/networkhelper.h @@ -0,0 +1,28 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef NETWORKHELPER_H +#define NETWORKHELPER_H + +#include <QtCore/QObject> +#include <QtQml/QQmlEngine> + +class NetworkHelper : public QObject +{ + Q_OBJECT + QML_ELEMENT + + Q_PROPERTY(QStringList ipAddresses READ ipAddresses CONSTANT) + +public: + explicit NetworkHelper(QObject *parent = nullptr); + + QStringList ipAddresses() const; + +signals: + +private: + QStringList m_ipAddresses; +}; + +#endif // NETWORKHELPER_H diff --git a/examples/applicationmanager/bubblewrap-example/system-ui.qml b/examples/applicationmanager/bubblewrap-example/system-ui.qml new file mode 100644 index 00000000..89668de9 --- /dev/null +++ b/examples/applicationmanager/bubblewrap-example/system-ui.qml @@ -0,0 +1,54 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick 2.4 +import QtApplicationManager.SystemUI 2.0 + +Item { + width: 800 + height: 600 + + // Show application names and icons + Column { + + Repeater { + model: ApplicationManager + Item { + width: 200 + height: 200 + + Image { + id: icon + source: model.icon + anchors.centerIn: parent + MouseArea { + anchors.fill: parent + onClicked: model.isRunning ? application.stop() : application.start() + } + } + Text { + font.pixelSize: 15 + text: model.name + anchors.top: icon.bottom + anchors.topMargin: 5 + anchors.horizontalCenter: icon.horizontalCenter + } + } + } + } + + // Show windows + Column { + anchors.right: parent.right + spacing: 1 + + Repeater { + model: WindowManager + WindowItem { + width: 600 + height: 200 + window: model.window + } + } + } +} |