summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Holland <dominik.holland@qt.io>2023-06-22 14:44:20 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-06-30 15:34:14 +0000
commit96667d1cbecc81d6bf522d81a55ca9b2a2c637a9 (patch)
tree1774512ff7dd9e3a426a382b52a0a6f32b98b1f6
parentca681d30049b7f95ae22d97daaf35dcab095cfc9 (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>
-rw-r--r--examples/applicationmanager/CMakeLists.txt1
-rw-r--r--examples/applicationmanager/bubblewrap-example/CMakeLists.txt35
-rw-r--r--examples/applicationmanager/bubblewrap-example/am-config.yaml57
-rw-r--r--examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/Browser.qml9
-rw-r--r--examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/icon.svg2
-rw-r--r--examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/info.yaml9
-rw-r--r--examples/applicationmanager/bubblewrap-example/apps/bubblewrap.browser/main.qml25
-rw-r--r--examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/icon.svg2
-rw-r--r--examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/info.yaml9
-rw-r--r--examples/applicationmanager/bubblewrap-example/apps/bubblewrap.networkinfo/main.qml36
-rw-r--r--examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/icon.svg2
-rw-r--r--examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/info.yaml9
-rw-r--r--examples/applicationmanager/bubblewrap-example/apps/bubblewrap.simple/main.qml23
-rwxr-xr-xexamples/applicationmanager/bubblewrap-example/bubblewrap-network-setup.sh75
-rw-r--r--examples/applicationmanager/bubblewrap-example/doc/images/bubblewrap-example.pngbin0 -> 41855 bytes
-rw-r--r--examples/applicationmanager/bubblewrap-example/doc/src/bubblewrap-example.qdoc108
-rw-r--r--examples/applicationmanager/bubblewrap-example/hello-world.pro31
-rw-r--r--examples/applicationmanager/bubblewrap-example/networkhelper.cpp22
-rw-r--r--examples/applicationmanager/bubblewrap-example/networkhelper.h28
-rw-r--r--examples/applicationmanager/bubblewrap-example/system-ui.qml54
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
new file mode 100644
index 00000000..6e5bac36
--- /dev/null
+++ b/examples/applicationmanager/bubblewrap-example/doc/images/bubblewrap-example.png
Binary files differ
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
+ }
+ }
+ }
+}