diff --git a/modules/common/networking/hosts.nix b/modules/common/networking/hosts.nix index e672e50e8..a8ad1c0d6 100644 --- a/modules/common/networking/hosts.nix +++ b/modules/common/networking/hosts.nix @@ -63,7 +63,7 @@ let } { ip = 100; - name = "chromium-vm"; + name = "chrome-vm"; } { ip = 101; diff --git a/modules/common/services/desktop.nix b/modules/common/services/desktop.nix index ebbf81a18..5230afcca 100644 --- a/modules/common/services/desktop.nix +++ b/modules/common/services/desktop.nix @@ -52,24 +52,34 @@ in ''; in [ - { - # The SPKI fingerprint is calculated like this: - # $ openssl x509 -noout -in mitmproxy-ca-cert.pem -pubkey | openssl asn1parse -noout -inform pem -out public.key - # $ openssl dgst -sha256 -binary public.key | openssl enc -base64 - name = "Chromium"; - description = "Isolated General Browsing"; - vm = "Chromium"; - path = "${pkgs.givc-cli}/bin/givc-cli ${cliArgs} start chromium"; - icon = "${pkgs.icon-pack}/chromium.svg"; - } + # { + # # The SPKI fingerprint is calculated like this: + # # $ openssl x509 -noout -in mitmproxy-ca-cert.pem -pubkey | openssl asn1parse -noout -inform pem -out public.key + # # $ openssl dgst -sha256 -binary public.key | openssl enc -base64 + # name = "Chromium"; + # description = "Isolated General Browsing"; + # vm = "Chromium"; + # path = "${pkgs.givc-cli}/bin/givc-cli ${cliArgs} start chromium"; + # icon = "${pkgs.icon-pack}/chromium.svg"; + # } { name = "Trusted Browser"; description = "Isolated Trusted Browsing"; vm = "Business"; - path = "${pkgs.givc-cli}/bin/givc-cli ${cliArgs} start --vm business-vm chromium"; + path = "${pkgs.givc-cli}/bin/givc-cli ${cliArgs} start --vm business-vm google-chrome"; icon = "${pkgs.icon-pack}/thorium-browser.svg"; } + { + # The SPKI fingerprint is calculated like this: + # $ openssl x509 -noout -in mitmproxy-ca-cert.pem -pubkey | openssl asn1parse -noout -inform pem -out public.key + # $ openssl dgst -sha256 -binary public.key | openssl enc -base64 + name = "Google Chrome"; + description = "Isolated General Browsing"; + vm = "Chrome"; + path = "${pkgs.givc-cli}/bin/givc-cli ${cliArgs} start --vm chrome-vm google-chrome"; + icon = "${pkgs.icon-pack}/google-chrome.svg"; + } { name = "VPN"; @@ -127,7 +137,7 @@ in name = "PDF Viewer"; description = "Isolated PDF Viewer"; vm = "Zathura"; - path = "${pkgs.givc-cli}/bin/givc-cli ${cliArgs} start zathura"; + path = "${pkgs.givc-cli}/bin/givc-cli ${cliArgs} start --vm zathura-vm zathura"; icon = "${pkgs.icon-pack}/document-viewer.svg"; } diff --git a/modules/desktop/graphics/demo-apps.nix b/modules/desktop/graphics/demo-apps.nix index e1ee1bfe0..7763c3ed5 100644 --- a/modules/desktop/graphics/demo-apps.nix +++ b/modules/desktop/graphics/demo-apps.nix @@ -25,6 +25,7 @@ in { options.ghaf.graphics.demo-apps = { chromium = mkProgramOption "Chromium browser" false; + google-chrome = mkProgramOption "Google Chrome browser" false; firefox = mkProgramOption "Firefox browser" config.ghaf.graphics.enableDemoApplications; gala-app = mkProgramOption "Gala App" false; element-desktop = mkProgramOption "Element desktop" config.ghaf.graphics.enableDemoApplications; @@ -33,7 +34,13 @@ in config = lib.mkIf config.ghaf.profiles.graphics.enable { ghaf.graphics.launchers = - lib.optional cfg.chromium { + lib.optional cfg.google-chrome { + name = "Google Chrome"; + description = "Web Browser"; + path = "${pkgs.google-chrome}/bin/google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland"; + icon = "${pkgs.icon-pack}/google-chrome.svg"; + } + ++ lib.optional cfg.chromium { name = "Chromium"; description = "Web Browser"; path = "${pkgs.chromium}/bin/chromium --enable-features=UseOzonePlatform --ozone-platform=wayland"; diff --git a/modules/givc/common.nix b/modules/givc/common.nix index 6306376ec..191998bc9 100644 --- a/modules/givc/common.nix +++ b/modules/givc/common.nix @@ -12,7 +12,7 @@ let mitmEnabled = config.ghaf.virtualization.microvm.idsvm.enable && config.ghaf.virtualization.microvm.idsvm.mitmproxy.enable; - mitmExtraArgs = lib.optionalString mitmEnabled "--user-data-dir=/home/${config.ghaf.users.accounts.user}/.config/chromium/Default --test-type --ignore-certificate-errors-spki-list=Bq49YmAq1CG6FuBzp8nsyRXumW7Dmkp7QQ/F82azxGU="; + mitmExtraArgs = lib.optionalString mitmEnabled "--user-data-dir=/home/${config.ghaf.users.accounts.user}/.config/google-chrome/Default --test-type --ignore-certificate-errors-spki-list=Bq49YmAq1CG6FuBzp8nsyRXumW7Dmkp7QQ/F82azxGU="; in { options.ghaf.givc = { diff --git a/modules/hardware/common/usb/vhotplug.nix b/modules/hardware/common/usb/vhotplug.nix index 3e19c7393..4983cd494 100644 --- a/modules/hardware/common/usb/vhotplug.nix +++ b/modules/hardware/common/usb/vhotplug.nix @@ -68,9 +68,10 @@ let } ]; } + { - name = "ChromiumVM"; - qmpSocket = "/var/lib/microvms/chromium-vm/chromium-vm.sock"; + name = "ChromeVM"; + qmpSocket = "/var/lib/microvms/chrome-vm/chrome-vm.sock"; usbPassthrough = [ { class = 14; diff --git a/modules/reference/appvms/business.nix b/modules/reference/appvms/business.nix index 2eca771b1..e4b6344ae 100644 --- a/modules/reference/appvms/business.nix +++ b/modules/reference/appvms/business.nix @@ -30,12 +30,13 @@ in name = "${name}"; packages = [ - pkgs.chromium + pkgs.google-chrome pkgs.globalprotect-openconnect pkgs.losslesscut-bin pkgs.openconnect gnomeTextEditor pkgs.xarchiver + ] ++ lib.optionals config.ghaf.profiles.debug.enable [ pkgs.tcpdump ] ++ lib.optionals config.ghaf.givc.enable [ pkgs.open-normal-extension ]; @@ -49,7 +50,8 @@ in { pkgs, ... }: { imports = [ - ../programs/chromium.nix + # ../programs/chromium.nix + ../programs/google-chrome.nix ../services/globalprotect-vpn/default.nix ]; time.timeZone = config.time.timeZone; @@ -68,21 +70,21 @@ in name = lib.mkForce "business-vm"; applications = [ { - name = "chromium"; - command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/chromium --enable-features=UseOzonePlatform --ozone-platform=wayland ${config.ghaf.givc.idsExtraArgs} --load-extension=${pkgs.open-normal-extension}"; + name = "google-chrome"; + command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland ${config.ghaf.givc.idsExtraArgs} --load-extension=${pkgs.open-normal-extension}"; args = [ "url" ]; } { name = "outlook"; - command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/chromium --enable-features=UseOzonePlatform --ozone-platform=wayland --app=https://outlook.office.com/mail/ ${config.ghaf.givc.idsExtraArgs} --load-extension=${pkgs.open-normal-extension}"; + command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland --app=https://outlook.office.com/mail/ ${config.ghaf.givc.idsExtraArgs} --load-extension=${pkgs.open-normal-extension}"; } { name = "office"; - command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/chromium --enable-features=UseOzonePlatform --ozone-platform=wayland --app=https://microsoft365.com ${config.ghaf.givc.idsExtraArgs} --load-extension=${pkgs.open-normal-extension}"; + command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland --app=https://microsoft365.com ${config.ghaf.givc.idsExtraArgs} --load-extension=${pkgs.open-normal-extension}"; } { name = "teams"; - command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/chromium --enable-features=UseOzonePlatform --ozone-platform=wayland --app=https://teams.microsoft.com ${config.ghaf.givc.idsExtraArgs} --load-extension=${pkgs.open-normal-extension}"; + command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland --app=https://teams.microsoft.com ${config.ghaf.givc.idsExtraArgs} --load-extension=${pkgs.open-normal-extension}"; } { name = "gpclient"; @@ -104,7 +106,7 @@ in }; reference = { - programs.chromium.enable = true; + programs.google-chrome.enable = true; services.globalprotect = { enable = true; @@ -114,12 +116,17 @@ in services.xdghandlers.enable = true; }; - - environment.etc."chromium/native-messaging-hosts/fi.ssrc.open_normal.json" = + environment.etc."opt/chrome/native-messaging-hosts/fi.ssrc.open_normal.json" = mkIf config.ghaf.givc.enable { source = "${pkgs.open-normal-extension}/fi.ssrc.open_normal.json"; }; + + # environment.etc."chromium/native-messaging-hosts/fi.ssrc.open_normal.json" = + # mkIf config.ghaf.givc.enable + # { + # source = "${pkgs.open-normal-extension}/fi.ssrc.open_normal.json"; + # }; environment.etc."open-normal-extension.cfg" = mkIf config.ghaf.givc.enable { text = let diff --git a/modules/reference/appvms/comms.nix b/modules/reference/appvms/comms.nix index df8f3c2d2..54c6f8dd8 100644 --- a/modules/reference/appvms/comms.nix +++ b/modules/reference/appvms/comms.nix @@ -21,7 +21,7 @@ in name = "${name}"; packages = [ - pkgs.chromium + pkgs.google-chrome pkgs.element-desktop pkgs.element-gps pkgs.gpsd @@ -32,7 +32,11 @@ in cores = 4; extraModules = [ { - imports = [ ../programs/chromium.nix ]; + imports = [ + # ../programs/chromium.nix + ../programs/google-chrome.nix + + ]; systemd = { services = { @@ -93,15 +97,15 @@ in } { name = "slack"; - command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/chromium --enable-features=UseOzonePlatform --ozone-platform=wayland --app=https://app.slack.com/client ${config.ghaf.givc.idsExtraArgs}"; + command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland --app=https://app.slack.com/client ${config.ghaf.givc.idsExtraArgs}"; } { name = "zoom"; - command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/chromium --enable-features=UseOzonePlatform --ozone-platform=wayland --app=https://app.zoom.us/wc/home ${config.ghaf.givc.idsExtraArgs}"; + command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland --app=https://app.zoom.us/wc/home ${config.ghaf.givc.idsExtraArgs}"; } ]; }; - ghaf.reference.programs.chromium.enable = true; + ghaf.reference.programs.google-chrome.enable = true; ghaf.services.xdghandlers.enable = true; } ]; diff --git a/modules/reference/appvms/default.nix b/modules/reference/appvms/default.nix index e8bb8f307..293720326 100644 --- a/modules/reference/appvms/default.nix +++ b/modules/reference/appvms/default.nix @@ -15,6 +15,7 @@ in options.ghaf.reference.appvms = { enable = lib.mkEnableOption "Enable the Ghaf reference appvms module"; chromium-vm = lib.mkEnableOption "Enable the Chromium appvm"; + chrome-vm = lib.mkEnableOption "Enable the Google Chrome appvm"; gala-vm = lib.mkEnableOption "Enable the Gala appvm"; zathura-vm = lib.mkEnableOption "Enable the Zathura appvm"; comms-vm = lib.mkEnableOption '' @@ -37,6 +38,7 @@ in ghaf.reference.appvms = { enabled-app-vms = (lib.optionals cfg.chromium-vm [ (import ./chromium.nix { inherit pkgs lib config; }) ]) + ++ (lib.optionals cfg.chrome-vm [ (import ./google-chrome.nix { inherit pkgs lib config; }) ]) ++ (lib.optionals cfg.gala-vm [ (import ./gala.nix { inherit pkgs lib config; }) ]) ++ (lib.optionals cfg.zathura-vm [ (import ./zathura.nix { inherit pkgs lib config; }) ]) ++ (lib.optionals cfg.comms-vm [ (import ./comms.nix { inherit pkgs lib config; }) ]) diff --git a/modules/reference/appvms/google-chrome.nix b/modules/reference/appvms/google-chrome.nix new file mode 100644 index 000000000..4d6abaf4b --- /dev/null +++ b/modules/reference/appvms/google-chrome.nix @@ -0,0 +1,56 @@ +# Copyright 2024 TII (SSRC) and the Ghaf contributors +# SPDX-License-Identifier: Apache-2.0 +# +{ + pkgs, + lib, + config, + ... +}: +let + name = "chrome"; +in +{ + name = "${name}"; + packages = [ + pkgs.google-chrome + ] ++ lib.optional config.ghaf.development.debug.tools.enable pkgs.alsa-utils; + # TODO create a repository of mac addresses to avoid conflicts + macAddress = "02:00:00:03:11:01"; + ramMb = 6144; + cores = 4; + extraModules = [ + { + imports = [ ../programs/google-chrome.nix ]; + + time.timeZone = config.time.timeZone; + + # Disable camera for now, because, due to the bug, the camera is not accessable in BusinessVM + # microvm.qemu.extraArgs = optionals ( + # config.ghaf.hardware.usb.internal.enable + # && (hasAttr "cam0" config.ghaf.hardware.usb.internal.qemuExtraArgs) + # ) config.ghaf.hardware.usb.internal.qemuExtraArgs.cam0; + microvm.devices = [ ]; + + ghaf.givc.appvm = { + enable = true; + name = lib.mkForce "chrome-vm"; + applications = [ + { + name = "google-chrome"; + command = "${config.ghaf.givc.appPrefix}/run-waypipe ${config.ghaf.givc.appPrefix}/google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland ${config.ghaf.givc.idsExtraArgs}"; + args = [ + "url" + "flag" + ]; + } + ]; + }; + ghaf.reference.programs.google-chrome.enable = true; + ghaf.services.xdghandlers.enable = true; + } + ]; + borderColor = "#630505"; + ghafAudio.enable = true; + vtpm.enable = true; +} diff --git a/modules/reference/profiles/laptop-x86.nix b/modules/reference/profiles/laptop-x86.nix index 2e53a25e7..f55f2cf02 100644 --- a/modules/reference/profiles/laptop-x86.nix +++ b/modules/reference/profiles/laptop-x86.nix @@ -69,8 +69,8 @@ in enable = true; vms = [ "business-vm" - "chromium-vm" "comms-vm" + "chrome-vm" ]; }; }; diff --git a/modules/reference/profiles/mvp-user-trial.nix b/modules/reference/profiles/mvp-user-trial.nix index a5ce94fa5..6cdfaee7b 100644 --- a/modules/reference/profiles/mvp-user-trial.nix +++ b/modules/reference/profiles/mvp-user-trial.nix @@ -32,11 +32,12 @@ in reference = { appvms = { enable = true; - chromium-vm = true; + chrome-vm = true; gala-vm = true; zathura-vm = true; comms-vm = true; business-vm = true; + }; services = { diff --git a/modules/reference/programs/default.nix b/modules/reference/programs/default.nix index d10a53184..0fbb37c51 100644 --- a/modules/reference/programs/default.nix +++ b/modules/reference/programs/default.nix @@ -3,7 +3,8 @@ { imports = [ ./zathura.nix - ./chromium.nix + # ./chromium.nix + ./google-chrome.nix ./windows-launcher.nix ]; } diff --git a/modules/reference/programs/google-chrome.nix b/modules/reference/programs/google-chrome.nix new file mode 100644 index 000000000..9ef6ded39 --- /dev/null +++ b/modules/reference/programs/google-chrome.nix @@ -0,0 +1,70 @@ +# Copyright 2024 TII (SSRC) and the Ghaf contributors +# SPDX-License-Identifier: Apache-2.0 +{ config, lib, ... }: +let + cfg = config.ghaf.reference.programs.google-chrome; +in +{ + options.ghaf.reference.programs.google-chrome = { + enable = lib.mkEnableOption "Enable Google chrome program settings"; + useZathuraVM = lib.mkEnableOption "Open PDFs in Zathura VM"; + defaultPolicy = lib.mkOption { + type = lib.types.attrs; + description = '' + Google chrome policy options. A list of available policies + can be found in the Chrome Enterprise documentation: + + Make sure the selected policy is supported on Linux and your browser version. + ''; + default = { + PromptForDownloadLocation = true; + AlwaysOpenPdfExternally = true; + DefaultBrowserSettingEnabled = true; + StartupBrowserWindowLaunchSuppressed = true; + DeviceMetricsReportingEnabled = false; + MetricsReportingEnabled = false; + }; + example = lib.literalExpression '' + { + PromptForDownloadLocation=true; + } + ''; + }; + extraOpts = lib.mkOption { + type = lib.types.attrs; + description = '' + Extra google chrome policy options. A list of available policies + can be found in the Chrome Enterprise documentation: + + Make sure the selected policy is supported on Linux and your browser version. + ''; + default = { + + }; + example = lib.literalExpression '' + { + "BrowserSignin" = 0; + "SyncDisabled" = true; + "PasswordManagerEnabled" = false; + "SpellcheckEnabled" = true; + "SpellcheckLanguage" = [ + "de" + "en-US" + ]; + } + ''; + }; + }; + config = lib.mkIf cfg.enable { + + environment.etc = { + "opt/chrome/policies/managed/default.json" = lib.mkIf (cfg.defaultPolicy != { }) { + text = builtins.toJSON cfg.defaultPolicy; + }; + "opt/chrome/policies/managed/extra.json" = lib.mkIf (cfg.extraOpts != { }) { + text = builtins.toJSON cfg.extraOpts; + }; + + }; + }; +} diff --git a/packages/ghaf-xdg-open/default.nix b/packages/ghaf-xdg-open/default.nix index 92ec4f1cd..a732ba628 100644 --- a/packages/ghaf-xdg-open/default.nix +++ b/packages/ghaf-xdg-open/default.nix @@ -22,15 +22,19 @@ writeShellApplication { filename=$(basename "$sourcepath") zathurapath="/var/tmp/$filename" chromiumvmip=$(dig +short chromium-vm | head -1) + googlechromevmip=$(dig +short chrome-vm | head -1) + businessvmip=$(dig +short business-vm | head -1) commsvmip=$(dig +short comms-vm | head -1) guivmip=$(dig +short gui-vm | head -1) + if [[ "$chromiumvmip" != "$REMOTE_ADDR" && \ "$businessvmip" != "$REMOTE_ADDR" && \ + "$googlechromevmip" != "$REMOTE_ADDR" && \ "$commsvmip" != "$REMOTE_ADDR" && \ "$guivmip" != "$REMOTE_ADDR" ]]; then - echo "Open PDF request received from $REMOTE_ADDR, but it is only permitted for chromium-vm, business-vm, comms-vm, or gui-vm" + echo "Open PDF request received from $REMOTE_ADDR, but it is only permitted for chrome-vm,chromium-vm, business-vm, comms-vm, or gui-vm" exit 0 fi diff --git a/packages/icon-pack/default.nix b/packages/icon-pack/default.nix index 1ee75f4d4..08a1afcce 100644 --- a/packages/icon-pack/default.nix +++ b/packages/icon-pack/default.nix @@ -37,6 +37,7 @@ let "system-file-manager.svg" "utilities-tweak-tool.svg" "Zoom.svg" + "google-chrome.svg" ]; in runCommand "icon-pack" diff --git a/packages/mitmweb-ui/default.nix b/packages/mitmweb-ui/default.nix index 66c902303..1c07945b9 100644 --- a/packages/mitmweb-ui/default.nix +++ b/packages/mitmweb-ui/default.nix @@ -10,24 +10,24 @@ let waypipePort = 1100; # TODO: remove hardcoded port number idsvmIP = "ids-vm"; mitmwebUI = pkgs.writeShellScript "mitmweb-ui" '' - # Create ssh-tunnel between chromium-vm and ids-vm + # Create ssh-tunnel between chrome-vm and ids-vm ${pkgs.openssh}/bin/ssh -i /run/waypipe-ssh/id_ed25519 \ -o StrictHostKeyChecking=no \ - -t ghaf@chromium-vm \ + -t ghaf@chrome-vm \ ${pkgs.openssh}/bin/ssh -M -S /tmp/control_socket \ -f -N -L 8081:localhost:8081 ghaf@${idsvmIP} # TODO: check pipe creation failures - # Launch chromium application and open mitmweb page - ${pkgs.openssh}/bin/ssh -i /run/waypipe-ssh/id_ed25519 -o StrictHostKeyChecking=no chromium-vm \ + # Launch google-chrome application and open mitmweb page + ${pkgs.openssh}/bin/ssh -i /run/waypipe-ssh/id_ed25519 -o StrictHostKeyChecking=no chrome-vm \ ${pkgs.waypipe}/bin/waypipe --border=#ff5733,5 --vsock -s ${toString waypipePort} server \ - chromium --enable-features=UseOzonePlatform --ozone-platform=wayland \ + google-chrome-stable --enable-features=UseOzonePlatform --ozone-platform=wayland \ http://localhost:8081 - # Use the control socket to close the ssh tunnel between chromium-vm and ids-vm + # Use the control socket to close the ssh tunnel between chrome-vm and ids-vm ${pkgs.openssh}/bin/ssh -i /run/waypipe-ssh/id_ed25519 \ -o StrictHostKeyChecking=no \ - -t ghaf@chromium-vm \ + -t ghaf@chrome-vm \ ${pkgs.openssh}/bin/ssh -q -S /tmp/control_socket -O exit ghaf@${idsvmIP} ''; in @@ -42,7 +42,7 @@ stdenvNoCC.mkDerivation { ''; meta = with lib; { - description = "Script to launch Chromium to open mitmweb interface using ssh-tunneling and authentication."; + description = "Script to launch Google Chrome to open mitmweb interface using ssh-tunneling and authentication."; platforms = [ "x86_64-linux" "aarch64-linux" diff --git a/packages/open-normal-extension/open_normal.sh b/packages/open-normal-extension/open_normal.sh index 2a98e88a5..2e5c43228 100755 --- a/packages/open-normal-extension/open_normal.sh +++ b/packages/open-normal-extension/open_normal.sh @@ -2,7 +2,7 @@ # SPDX-FileCopyrightText: 2022-2024 TII (SSRC) and the Ghaf contributors # SPDX-License-Identifier: Apache-2.0 # -# Chromium browser extension action script to open a URL in normal browser +# Chrome browser extension action script to open a URL in normal browser # Uses stdin and stdout for communicating with browser extension API # First four bytes tell the size of payload, and rest is the payload, # which is standard json data. Same format is used for input and output. @@ -57,7 +57,7 @@ if [ -r "$CFGF" ]; then else # Do not complain about double quotes, $GIVC_OPTS is purposefully unquoted here # shellcheck disable=SC2086 - "${GIVC_PATH}/bin/givc-cli" $GIVC_OPTS start chromium -- "${URL}" > /dev/null 2>&1 + "${GIVC_PATH}/bin/givc-cli" $GIVC_OPTS start --vm chrome-vm google-chrome -- "${URL}" > /dev/null 2>&1 RES=$? # Just return the exit value of givc-cli back to the browser Msg "{\"status\":\"${RES}\"}"