mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 09:52:37 +02:00
Order list of PDF viewers and return default application first (Linux).
This commit is contained in:
parent
f03bc71855
commit
54ab9ce98f
2 changed files with 131 additions and 5 deletions
|
@ -4,6 +4,7 @@ import platform
|
|||
import shlex
|
||||
import subprocess
|
||||
import typing
|
||||
from collections import OrderedDict
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional
|
||||
|
||||
|
@ -49,7 +50,7 @@ class DangerzoneGui(DangerzoneCore):
|
|||
# Preload font
|
||||
self.fixed_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont)
|
||||
|
||||
# Preload list of PDF viewers on computer
|
||||
# Preload ordered list of PDF viewers on computer, starting with default
|
||||
self.pdf_viewers = self._find_pdf_viewers()
|
||||
|
||||
# Are we done waiting (for Docker Desktop to be installed, or for container to install)
|
||||
|
@ -93,9 +94,22 @@ class DangerzoneGui(DangerzoneCore):
|
|||
log.info(Fore.YELLOW + "> " + Fore.CYAN + args_str)
|
||||
subprocess.Popen(args)
|
||||
|
||||
def _find_pdf_viewers(self) -> Dict[str, str]:
|
||||
pdf_viewers: Dict[str, str] = {}
|
||||
def _find_pdf_viewers(self) -> OrderedDict[str, str]:
|
||||
pdf_viewers: OrderedDict[str, str] = OrderedDict()
|
||||
if platform.system() == "Linux":
|
||||
# Opportunistically query for default pdf handler
|
||||
default_pdf_viewer = None
|
||||
try:
|
||||
default_pdf_viewer = subprocess.check_output(
|
||||
["xdg-mime", "query", "default", "application/pdf"]
|
||||
).decode()
|
||||
except (FileNotFoundError, subprocess.CalledProcessError) as e:
|
||||
# Log it and continue
|
||||
log.info(
|
||||
"xdg-mime query failed, default PDF handler could not be found."
|
||||
)
|
||||
log.debug(f"xdg-mime query failed: {e}")
|
||||
|
||||
# Find all .desktop files
|
||||
for search_path in [
|
||||
"/usr/share/applications",
|
||||
|
@ -108,14 +122,26 @@ class DangerzoneGui(DangerzoneCore):
|
|||
if os.path.splitext(filename)[1] == ".desktop":
|
||||
# See which ones can open PDFs
|
||||
desktop_entry = DesktopEntry(full_filename)
|
||||
desktop_entry_name = desktop_entry.getName()
|
||||
if (
|
||||
"application/pdf" in desktop_entry.getMimeTypes()
|
||||
and "dangerzone" not in desktop_entry.getName().lower()
|
||||
and "dangerzone" not in desktop_entry_name.lower()
|
||||
):
|
||||
pdf_viewers[desktop_entry.getName()] = (
|
||||
pdf_viewers[desktop_entry_name] = (
|
||||
desktop_entry.getExec()
|
||||
)
|
||||
|
||||
# Put the default entry first
|
||||
if filename == default_pdf_viewer:
|
||||
try:
|
||||
pdf_viewers.move_to_end(
|
||||
desktop_entry_name, last=False
|
||||
)
|
||||
except KeyError as e:
|
||||
# Should be unreachable
|
||||
log.error(
|
||||
f"Problem reordering applications: {e}"
|
||||
)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
|
|
100
tests/gui/test_logic.py
Normal file
100
tests/gui/test_logic.py
Normal file
|
@ -0,0 +1,100 @@
|
|||
import platform
|
||||
import subprocess
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from dangerzone.gui.logic import DangerzoneGui
|
||||
|
||||
if platform.system() == "Linux":
|
||||
from xdg.DesktopEntry import DesktopEntry
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.system() != "Linux", reason="Linux-only test")
|
||||
def test_order_mime_handers() -> None:
|
||||
"""
|
||||
Given a default mime handler returned by xdg-mime,
|
||||
ensure it is the first item available in the list
|
||||
of compatible applications.
|
||||
"""
|
||||
mock_app = mock.MagicMock()
|
||||
dummy = mock.MagicMock()
|
||||
|
||||
mock_desktop = mock.MagicMock(spec=DesktopEntry)
|
||||
mock_desktop.getMimeTypes.return_value = "application/pdf"
|
||||
mock_desktop.getExec.side_effect = [
|
||||
"/usr/bin/madeup-evince",
|
||||
"/usr/local/bin/madeup-mupdf",
|
||||
"/usr/local/bin/madeup-libredraw",
|
||||
]
|
||||
mock_desktop.getName.side_effect = [
|
||||
"Evince",
|
||||
"MuPDF",
|
||||
"LibreOffice",
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"subprocess.check_output", return_value=b"libreoffice-draw.desktop"
|
||||
) as mock_default_mime_hander, mock.patch(
|
||||
"os.listdir",
|
||||
side_effect=[
|
||||
["org.gnome.Evince.desktop"],
|
||||
["org.pwmt.zathura-pdf-mupdf.desktop"],
|
||||
["libreoffice-draw.desktop"],
|
||||
],
|
||||
) as mock_list, mock.patch(
|
||||
"dangerzone.gui.logic.DesktopEntry", return_value=mock_desktop
|
||||
):
|
||||
dz = DangerzoneGui(mock_app, dummy)
|
||||
|
||||
mock_default_mime_hander.assert_called_once_with(
|
||||
["xdg-mime", "query", "default", "application/pdf"]
|
||||
)
|
||||
mock_list.assert_called()
|
||||
assert len(dz.pdf_viewers) == 3
|
||||
assert dz.pdf_viewers.popitem(last=False)[0] == "LibreOffice"
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.system() != "Linux", reason="Linux-only test")
|
||||
def test_mime_handers_succeeds_no_default_found() -> None:
|
||||
"""
|
||||
Given a failure to return default mime handler,
|
||||
ensure compatible applications are still returned.
|
||||
"""
|
||||
mock_app = mock.MagicMock()
|
||||
dummy = mock.MagicMock()
|
||||
|
||||
mock_desktop = mock.MagicMock(spec=DesktopEntry)
|
||||
mock_desktop.getMimeTypes.return_value = "application/pdf"
|
||||
mock_desktop.getExec.side_effect = [
|
||||
"/usr/bin/madeup-evince",
|
||||
"/usr/local/bin/madeup-mupdf",
|
||||
"/usr/local/bin/madeup-libredraw",
|
||||
]
|
||||
mock_desktop.getName.side_effect = [
|
||||
"Evince",
|
||||
"MuPDF",
|
||||
"LibreOffice",
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"subprocess.check_output",
|
||||
side_effect=subprocess.CalledProcessError(1, "Oh no, xdg-mime error!)"),
|
||||
) as mock_default_mime_hander, mock.patch(
|
||||
"os.listdir",
|
||||
side_effect=[
|
||||
["org.gnome.Evince.desktop"],
|
||||
["org.pwmt.zathura-pdf-mupdf.desktop"],
|
||||
["libreoffice-draw.desktop"],
|
||||
],
|
||||
) as mock_list, mock.patch(
|
||||
"dangerzone.gui.logic.DesktopEntry", return_value=mock_desktop
|
||||
):
|
||||
dz = DangerzoneGui(mock_app, dummy)
|
||||
|
||||
mock_default_mime_hander.assert_called_once_with(
|
||||
["xdg-mime", "query", "default", "application/pdf"]
|
||||
)
|
||||
mock_list.assert_called()
|
||||
assert len(dz.pdf_viewers) == 3
|
||||
assert dz.pdf_viewers.popitem(last=False)[0] == "Evince"
|
Loading…
Reference in a new issue