Work on changing the WaitingWidget to check for Docker

This commit is contained in:
Micah Lee 2021-11-22 14:06:31 -08:00
parent d1c33bfcf5
commit 42ce884419
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
8 changed files with 83 additions and 158 deletions

6
.gitmodules vendored
View file

@ -1,6 +0,0 @@
[submodule "vendor/hyperkit"]
path = vendor/hyperkit
url = https://github.com/moby/hyperkit.git
[submodule "vendor/vpnkit"]
path = vendor/vpnkit
url = https://github.com/moby/vpnkit.git

View file

@ -35,8 +35,8 @@ class GlobalCommon(object):
# App data folder
self.appdata_path = appdirs.user_config_dir("dangerzone")
# In case we have a custom container
self.custom_container = None
# Container name
self.container_name = "dangerzone.rocks/dangerzone"
# Languages supported by tesseract
self.ocr_languages = {
@ -380,12 +380,6 @@ class GlobalCommon(object):
)
print(Back.BLACK + Fore.YELLOW + Style.DIM + "╰──────────────────────────╯")
def get_container_name(self):
if self.custom_container:
return self.custom_container
else:
return "docker.io/flmcode/dangerzone"
def get_resource_path(self, filename):
if getattr(sys, "dangerzone_dev", False):
# Look for resources directory relative to python file
@ -414,17 +408,17 @@ class GlobalCommon(object):
def exec_dangerzone_container(self, input_filename, output_filename, ocr_lang):
convert(self, input_filename, output_filename, ocr_lang)
args = [self.dz_container_path] + args
args_str = " ".join(pipes.quote(s) for s in args)
print(Style.DIM + "> " + Style.NORMAL + Fore.CYAN + args_str)
# args = [self.dz_container_path] + args
# args_str = " ".join(pipes.quote(s) for s in args)
# print(Style.DIM + "> " + Style.NORMAL + Fore.CYAN + args_str)
# Execute dangerzone-container
return subprocess.Popen(
args,
startupinfo=self.get_subprocess_startupinfo(),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
# # Execute dangerzone-container
# return subprocess.Popen(
# args,
# startupinfo=self.get_subprocess_startupinfo(),
# stdout=subprocess.PIPE,
# stderr=subprocess.PIPE,
# )
def get_subprocess_startupinfo(self):
if platform.system() == "Windows":

View file

@ -9,12 +9,6 @@ from PySide2 import QtCore, QtWidgets
from .common import GuiCommon
from .main_window import MainWindow
from .systray import SysTray
from .docker_installer import (
is_docker_installed,
is_docker_ready,
DockerInstaller,
AuthorizationFailed,
)
from ..global_common import GlobalCommon
@ -86,15 +80,6 @@ def gui_main(filename):
# Allow Ctrl-C to smoothly quit the program instead of throwing an exception
signal.signal(signal.SIGINT, signal.SIG_DFL)
# See if we need to install Docker (Windows-only)
if (platform.system() == "Windows" or platform.system() == "Darwin") and (
not is_docker_installed() or not is_docker_ready(global_common)
):
click.echo("Docker is either not installed or not running")
docker_installer = DockerInstaller(gui_common)
docker_installer.start()
return
# Create the system tray
systray = SysTray(global_common, gui_common, app, app_wrapper)

View file

@ -14,7 +14,6 @@ elif platform.system() == "Linux":
import getpass
from xdg.DesktopEntry import DesktopEntry
from .docker_installer import is_docker_ready
from ..settings import Settings
@ -36,7 +35,7 @@ class GuiCommon(object):
# Preload list of PDF viewers on computer
self.pdf_viewers = self._find_pdf_viewers()
# Are we done waiting (for VM to start, or container to install)
# Are we done waiting (for Docker Desktop to be installed, or for container to install)
self.is_waiting_finished = False
def get_window_icon(self):

View file

@ -1,99 +0,0 @@
import os
import subprocess
import shutil
import platform
from PySide2 import QtCore, QtWidgets
class AuthorizationFailed(Exception):
pass
container_runtime = shutil.which("docker")
def is_docker_installed():
return container_runtime is not None
def is_docker_ready(global_common):
# Run `docker image ls` without an error
with subprocess.Popen([container_runtime, "image", "ls"]) as p:
outs, errs = p.communicate()
# The user canceled, or permission denied
if p.returncode == 126 or p.returncode == 127:
raise AuthorizationFailed
# Return true if it succeeds
if p.returncode == 0:
return True
else:
print(outs)
print(errs)
return False
def launch_docker_windows(global_common):
docker_desktop_path = "C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe"
subprocess.Popen(
[docker_desktop_path], startupinfo=global_common.get_subprocess_startupinfo()
)
class DockerInstaller(QtWidgets.QDialog):
def __init__(self, gui_common):
super(DockerInstaller, self).__init__()
self.setWindowTitle("Dangerzone")
self.setWindowIcon(gui_common.get_window_icon())
# self.setMinimumHeight(170)
label = QtWidgets.QLabel()
if platform.system() == "Darwin":
label.setText("Dangerzone for macOS requires Docker")
elif platform.system() == "Windows":
label.setText("Dangerzone for Windows requires Docker")
label.setStyleSheet("QLabel { font-weight: bold; }")
label.setAlignment(QtCore.Qt.AlignCenter)
self.task_label = QtWidgets.QLabel()
self.task_label.setAlignment(QtCore.Qt.AlignCenter)
self.task_label.setWordWrap(True)
self.task_label.setOpenExternalLinks(True)
self.ok_button = QtWidgets.QPushButton("OK")
self.ok_button.clicked.connect(self.ok_clicked)
buttons_layout = QtWidgets.QHBoxLayout()
buttons_layout.addStretch()
buttons_layout.addWidget(self.ok_button)
buttons_layout.addStretch()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(label)
layout.addWidget(self.task_label)
layout.addLayout(buttons_layout)
layout.addStretch()
self.setLayout(layout)
if platform.system() == "Darwin":
self.docker_path = "/Applications/Docker.app/Contents/Resources/bin/docker"
elif platform.system() == "Windows":
self.docker_path = shutil.which("docker.exe")
def ok_clicked(self):
self.accept()
def start(self):
if not os.path.exists(self.docker_path):
self.task_label.setText(
"<a href='https://www.docker.com/products/docker-desktop'>Download Docker Desktop</a>, install it, and then run Dangerzone again."
)
self.task_label.setTextFormat(QtCore.Qt.RichText)
else:
self.task_label.setText(
"Docker Desktop is installed, but you must launch it first. Open Docker, make sure it's running, and then open Dangerzone again."
)
return self.exec_() == QtWidgets.QDialog.Accepted

View file

@ -3,6 +3,7 @@ import platform
import tempfile
import subprocess
import json
import shutil
from PySide2 import QtCore, QtGui, QtWidgets
from colorama import Style, Fore
@ -43,7 +44,7 @@ class MainWindow(QtWidgets.QMainWindow):
header_layout.addWidget(header_label)
header_layout.addStretch()
# Waiting widget, replaces content widget while VM is booting
# Waiting widget, replaces content widget while container runtime isn't available
self.waiting_widget = WaitingWidget(self.global_common, self.gui_common)
self.waiting_widget.finished.connect(self.waiting_finished)
@ -53,7 +54,7 @@ class MainWindow(QtWidgets.QMainWindow):
)
self.content_widget.close_window.connect(self.close)
# Only use the waiting widget if we have a VM
# Only use the waiting widget if container runtime isn't available
if self.gui_common.is_waiting_finished:
self.waiting_widget.hide()
self.content_widget.show()
@ -101,6 +102,15 @@ class InstallContainerThread(QtCore.QThread):
class WaitingWidget(QtWidgets.QWidget):
# These are the possible states that the WaitingWidget can show.
#
# Windows and macOS states:
# - "not_installed"
# - "not_running"
# - "install_container"
#
# Linux states
# - "install_container"
finished = QtCore.Signal()
def __init__(self, global_common, gui_common):
@ -110,34 +120,78 @@ class WaitingWidget(QtWidgets.QWidget):
self.label = QtWidgets.QLabel()
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setTextFormat(QtCore.Qt.RichText)
self.label.setStyleSheet("QLabel { font-size: 20px; }")
# Buttons
check_button = QtWidgets.QPushButton("Check Again")
check_button.clicked.connect(self.check_state)
buttons_layout = QtWidgets.QHBoxLayout()
buttons_layout.addStretch()
buttons_layout.addWidget(check_button)
buttons_layout.addStretch()
self.buttons = QtWidgets.QWidget()
self.buttons.setLayout(buttons_layout)
# Layout
layout = QtWidgets.QVBoxLayout()
layout.addStretch()
layout.addWidget(self.label)
layout.addWidget(self.buttons)
layout.addStretch()
self.setLayout(layout)
if platform.system() == "Darwin":
self.label.setText("Waiting for the Dangerzone virtual machine to start...")
self.global_common.vm.vm_state_change.connect(self.vm_state_change)
# Check the state
self.check_state()
elif platform.system() == "Linux":
self.label.setText("Installing the Dangerzone container...")
def check_state(self):
state = None
# Can we find the container runtime binary binary
if platform.system() == "Linux":
container_runtime = shutil.which("podman")
else:
container_runtime = shutil.which("docker")
if container_runtime is None:
print("Docker is not installed")
state = "not_installed"
else:
# Can we run `docker image ls` without an error
with subprocess.Popen([container_runtime, "image", "ls"]) as p:
p.communicate()
if p.returncode != 0:
print("Docker is not running")
state = "not_running"
else:
# Always try installing the container
print("Ensuring the container is installed")
state = "install_container"
# Update the state
self.state_change(state)
def state_change(self, state):
if state == "not_installed":
self.label.setText(
"<strong>Dangerzone requires Docker</strong><br><br><a href='https://www.docker.com/products/docker-desktop'>Download Docker Desktop</a> and install it."
)
self.buttons.show()
elif state == "not_running":
self.label.setText(
"Docker Desktop is installed, but you must launch it first. Open Docker and make sure it's running in the background."
)
self.buttons.show()
else:
self.label.setText(
"Installing the Dangerzone container..."
)
self.buttons.hide()
self.install_container_t = InstallContainerThread(self.global_common)
self.install_container_t.finished.connect(self.finished)
self.install_container_t.start()
else:
self.label.setText("Platform not implemented yet")
def vm_state_change(self, state):
if state == self.global_common.vm.STATE_ON:
self.finished.emit()
elif state == self.global_common.vm.STATE_FAIL:
self.label.setText("Dangerzone virtual machine failed to start :(")
class ContentWidget(QtWidgets.QWidget):
close_window = QtCore.Signal()

1
vendor/hyperkit vendored

@ -1 +0,0 @@
Subproject commit 09fe9202a29a56a532d07505fd91831989b9afeb

1
vendor/vpnkit vendored

@ -1 +0,0 @@
Subproject commit 16ed722e6dc24307e99aee931ffd0eb80a9487d0