mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 09:52:37 +02:00
Work on changing the WaitingWidget to check for Docker
This commit is contained in:
parent
d1c33bfcf5
commit
42ce884419
8 changed files with 83 additions and 158 deletions
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -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
|
|
@ -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":
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
|
@ -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
vendor/hyperkit
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 09fe9202a29a56a532d07505fd91831989b9afeb
|
1
vendor/vpnkit
vendored
1
vendor/vpnkit
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 16ed722e6dc24307e99aee931ffd0eb80a9487d0
|
Loading…
Reference in a new issue