diff options
author | Ander Punnar <ander@kvlt.ee> | 2021-06-01 20:36:56 +0300 |
---|---|---|
committer | Ander Punnar <ander@kvlt.ee> | 2021-06-01 20:36:56 +0300 |
commit | 00a394506f149b600c9869a63dd37e847fe17cfe (patch) | |
tree | 58c1ba094a79fa537abada91426cf2f01610c9c2 /qutebrowser | |
parent | 4e47af21586aad3846c2458dc0c8243e9d6eb792 (diff) | |
parent | b34988055071522e72c73b0f3a0bd3a6b59c6b9a (diff) | |
download | qutebrowser-00a394506f149b600c9869a63dd37e847fe17cfe.tar.gz qutebrowser-00a394506f149b600c9869a63dd37e847fe17cfe.zip |
Merge remote-tracking branch 'origin/master' into 4nd3r/hostblock_subdomains
Diffstat (limited to 'qutebrowser')
-rw-r--r-- | qutebrowser/__init__.py | 2 | ||||
-rw-r--r-- | qutebrowser/browser/qutescheme.py | 5 | ||||
-rw-r--r-- | qutebrowser/browser/webengine/notification.py | 34 | ||||
-rw-r--r-- | qutebrowser/browser/webengine/webenginetab.py | 14 | ||||
-rw-r--r-- | qutebrowser/components/braveadblock.py | 10 | ||||
-rw-r--r-- | qutebrowser/config/configdata.yml | 2 | ||||
-rw-r--r-- | qutebrowser/config/configtypes.py | 41 | ||||
-rw-r--r-- | qutebrowser/misc/editor.py | 2 | ||||
-rw-r--r-- | qutebrowser/misc/quitter.py | 8 | ||||
-rw-r--r-- | qutebrowser/utils/log.py | 16 |
10 files changed, 86 insertions, 48 deletions
diff --git a/qutebrowser/__init__.py b/qutebrowser/__init__.py index 96062d9bd..812df63c8 100644 --- a/qutebrowser/__init__.py +++ b/qutebrowser/__init__.py @@ -26,7 +26,7 @@ __copyright__ = "Copyright 2014-2021 Florian Bruhin (The Compiler)" __license__ = "GPL" __maintainer__ = __author__ __email__ = "mail@qutebrowser.org" -__version__ = "2.2.2" +__version__ = "2.2.3" __version_info__ = tuple(int(part) for part in __version__.split('.')) __description__ = "A keyboard-driven, vim-like browser based on PyQt5." diff --git a/qutebrowser/browser/qutescheme.py b/qutebrowser/browser/qutescheme.py index 031b6fe06..68e36d249 100644 --- a/qutebrowser/browser/qutescheme.py +++ b/qutebrowser/browser/qutescheme.py @@ -41,7 +41,7 @@ from qutebrowser.browser import pdfjs, downloads, history from qutebrowser.config import config, configdata, configexc from qutebrowser.utils import (version, utils, jinja, log, message, docutils, resources, objreg, standarddir) -from qutebrowser.misc import guiprocess +from qutebrowser.misc import guiprocess, quitter from qutebrowser.qt import sip @@ -452,6 +452,9 @@ def qute_settings(url: QUrl) -> _HandlerRet: if url.password() != csrf_token: message.error("Invalid CSRF token for qute://settings!") raise RequestDeniedError("Invalid CSRF token!") + if quitter.instance.is_shutting_down: + log.config.debug("Ignoring /set request during shutdown") + return 'text/html', b'error: ignored' return _qute_settings_set(url) # Requests to qute://settings/set should only be allowed from diff --git a/qutebrowser/browser/webengine/notification.py b/qutebrowser/browser/webengine/notification.py index d8387e6d4..6b26157e6 100644 --- a/qutebrowser/browser/webengine/notification.py +++ b/qutebrowser/browser/webengine/notification.py @@ -65,12 +65,18 @@ if TYPE_CHECKING: from qutebrowser.config import config from qutebrowser.misc import objects -from qutebrowser.utils import qtutils, log, utils, debug, message +from qutebrowser.utils import qtutils, log, utils, debug, message, version bridge: Optional['NotificationBridgePresenter'] = None +def _notifications_supported() -> bool: + """Check whether the current QtWebEngine version has notification support.""" + versions = version.qtwebengine_versions(avoid_init=True) + return versions.webengine >= utils.VersionNumber(5, 14) + + def init() -> None: """Initialize the DBus notification presenter, if applicable. @@ -84,7 +90,8 @@ def init() -> None: # at a later point in time. However, doing so is probably too complex compared # to its usefulness. return - if not qtutils.version_check('5.14'): + + if not _notifications_supported(): return global bridge @@ -163,7 +170,7 @@ class NotificationBridgePresenter(QObject): def __init__(self, parent: QObject = None) -> None: super().__init__(parent) - assert qtutils.version_check('5.14') + assert _notifications_supported() self._active_notifications: Dict[int, 'QWebEngineNotification'] = {} self._adapter: Optional[AbstractNotificationAdapter] = None @@ -709,8 +716,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): def __init__(self, parent: QObject = None) -> None: super().__init__(bridge) - if not qtutils.version_check('5.14'): - raise Error("Notifications are not supported on Qt < 5.14") + assert _notifications_supported() if utils.is_windows: # The QDBusConnection destructor seems to cause error messages (and @@ -778,7 +784,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): self, name: str, vendor: str, - version: str, + ver: str, ) -> Optional[_ServerQuirks]: """Find quirks to use based on the server information.""" if (name, vendor) == ("notify-osd", "Canonical Ltd"): @@ -791,15 +797,15 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): # Still in active development but doesn't implement spec 1.2: # https://github.com/mate-desktop/mate-notification-daemon/issues/132 quirks = _ServerQuirks(spec_version="1.1") - if utils.VersionNumber.parse(version) <= utils.VersionNumber(1, 24): + if utils.VersionNumber.parse(ver) <= utils.VersionNumber(1, 24): # https://github.com/mate-desktop/mate-notification-daemon/issues/118 quirks.avoid_body_hyperlinks = True return quirks - elif (name, vendor) == ("naughty", "awesome") and version != "devel": + elif (name, vendor) == ("naughty", "awesome") and ver != "devel": # Still in active development but spec 1.0/1.2 support isn't # released yet: # https://github.com/awesomeWM/awesome/commit/e076bc664e0764a3d3a0164dabd9b58d334355f4 - parsed_version = utils.VersionNumber.parse(version.lstrip('v')) + parsed_version = utils.VersionNumber.parse(ver.lstrip('v')) if parsed_version <= utils.VersionNumber(4, 3): return _ServerQuirks(spec_version="1.0") elif (name, vendor) == ("twmnd", "twmnd"): @@ -810,7 +816,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): return _ServerQuirks(skip_capabilities=True) elif (name, vendor) == ("lxqt-notificationd", "lxqt.org"): quirks = _ServerQuirks() - parsed_version = utils.VersionNumber.parse(version) + parsed_version = utils.VersionNumber.parse(ver) if parsed_version <= utils.VersionNumber(0, 16): # https://github.com/lxqt/lxqt-notificationd/issues/253 quirks.escape_title = True @@ -843,13 +849,13 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): """Query notification server information and set quirks.""" reply = self.interface.call(QDBus.BlockWithGui, "GetServerInformation") self._verify_message(reply, "ssss", QDBusMessage.ReplyMessage) - name, vendor, version, spec_version = reply.arguments() + name, vendor, ver, spec_version = reply.arguments() log.misc.debug( - f"Connected to notification server: {name} {version} by {vendor}, " + f"Connected to notification server: {name} {ver} by {vendor}, " f"implementing spec {spec_version}") - quirks = self._find_quirks(name, vendor, version) + quirks = self._find_quirks(name, vendor, ver) if quirks is not None: log.misc.debug(f"Enabling quirks {quirks}") self._quirks = quirks @@ -857,7 +863,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): expected_spec_version = self._quirks.spec_version or self.SPEC_VERSION if spec_version != expected_spec_version: log.misc.warning( - f"Notification server ({name} {version} by {vendor}) implements " + f"Notification server ({name} {ver} by {vendor}) implements " f"spec {spec_version}, but {expected_spec_version} was expected. " f"If {name} is up to date, please report a qutebrowser bug.") diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index c793a1929..f9b636bde 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -401,6 +401,16 @@ class WebEngineCaret(browsertab.AbstractCaret): self._js_call('reverseSelection') def _follow_selected_cb_wrapped(self, js_elem, tab): + if sip.isdeleted(self): + # Sometimes, QtWebEngine JS callbacks seem to be stuck, and will + # later get executed when the tab is closed. However, at this point, + # the WebEngineCaret is already gone. + log.webview.warning( + "Got follow_selected callback for deleted WebEngineCaret. " + "This is most likely due to a QtWebEngine bug, please report a " + "qutebrowser issue if you know a way to reproduce this.") + return + try: self._follow_selected_cb(js_elem, tab) finally: @@ -1593,7 +1603,9 @@ class WebEngineTab(browsertab.AbstractTab): up doing it twice. """ super()._on_url_changed(url) - if url.isValid() and qtutils.version_check('5.13'): + if (url.isValid() and + qtutils.version_check('5.13') and + not qtutils.version_check('5.14')): self.settings.update_for_url(url) @pyqtSlot(usertypes.NavigationRequest) diff --git a/qutebrowser/components/braveadblock.py b/qutebrowser/components/braveadblock.py index 0a39d5491..bd30f5d29 100644 --- a/qutebrowser/components/braveadblock.py +++ b/qutebrowser/components/braveadblock.py @@ -211,7 +211,15 @@ class BraveAdBlocker: if cache_exists: logger.debug("Loading cached adblock data: %s", self._cache_path) - self._engine.deserialize_from_file(str(self._cache_path)) + try: + self._engine.deserialize_from_file(str(self._cache_path)) + except ValueError as e: + if str(e) != "DeserializationError": + # All Rust exceptions get turned into a ValueError by + # python-adblock + raise + message.error("Reading adblock filter data failed (corrupted data?). " + "Please run :adblock-update.") else: if ( config.val.content.blocking.adblock.lists diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 80732d43d..b85e84be2 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -582,6 +582,7 @@ content.headers.accept_language: type: name: String none_ok: true + encoding: ascii supports_pattern: true default: en-US,en;q=0.9 desc: >- @@ -643,6 +644,7 @@ content.headers.user_agent: Safari/{webkit_version}' type: name: FormatString + encoding: ascii fields: - os_info - webkit_version diff --git a/qutebrowser/config/configtypes.py b/qutebrowser/config/configtypes.py index c157fba41..d3d5e3fb8 100644 --- a/qutebrowser/config/configtypes.py +++ b/qutebrowser/config/configtypes.py @@ -86,6 +86,21 @@ _UnsetNone = Union[None, usertypes.Unset] _StrUnsetNone = Union[str, _UnsetNone] +def _validate_encoding(encoding: Optional[str], value: str) -> None: + """Check if the given value fits into the given encoding. + + Raises ValidationError if not. + """ + if encoding is None: + return + + try: + value.encode(encoding) + except UnicodeEncodeError as e: + msg = f"{value!r} contains non-{encoding} characters: {e}" + raise configexc.ValidationError(value, msg) + + class ValidValues: """Container for valid values for a given type. @@ -377,6 +392,7 @@ class String(BaseType): maxlen: Maximum length (inclusive). forbidden: Forbidden chars in the string. regex: A regex used to validate the string. + encoding: The encoding the value needs to fit in. completions: completions to be used, or None """ @@ -407,24 +423,6 @@ class String(BaseType): self.encoding = encoding self.regex = regex - def _validate_encoding(self, value: str) -> None: - """Check if the given value fits into the configured encoding. - - Raises ValidationError if not. - - Args: - value: The value to check. - """ - if self.encoding is None: - return - - try: - value.encode(self.encoding) - except UnicodeEncodeError as e: - msg = "{!r} contains non-{} characters: {}".format( - value, self.encoding, e) - raise configexc.ValidationError(value, msg) - def to_py(self, value: _StrUnset) -> _StrUnsetNone: self._basic_py_validation(value, str) if isinstance(value, usertypes.Unset): @@ -432,7 +430,7 @@ class String(BaseType): elif not value: return None - self._validate_encoding(value) + _validate_encoding(self.encoding, value) self._validate_valid_values(value) if self.forbidden is not None and any(c in value @@ -1544,6 +1542,7 @@ class FormatString(BaseType): Attributes: fields: Which replacements are allowed in the format string. + encoding: Which encoding the string should fit into. completions: completions to be used, or None """ @@ -1551,11 +1550,13 @@ class FormatString(BaseType): self, *, fields: Iterable[str], none_ok: bool = False, + encoding: str = None, completions: _Completions = None, ) -> None: super().__init__( none_ok=none_ok, completions=completions) self.fields = fields + self.encoding = encoding self._completions = completions def to_py(self, value: _StrUnset) -> _StrUnsetNone: @@ -1565,6 +1566,8 @@ class FormatString(BaseType): elif not value: return None + _validate_encoding(self.encoding, value) + try: value.format(**{k: '' for k in self.fields}) except (KeyError, IndexError, AttributeError) as e: diff --git a/qutebrowser/misc/editor.py b/qutebrowser/misc/editor.py index 5741c6b47..d561a7b96 100644 --- a/qutebrowser/misc/editor.py +++ b/qutebrowser/misc/editor.py @@ -131,7 +131,7 @@ class ExternalEditor(QObject): raise ValueError("Already editing a file!") try: self._filename = self._create_tempfile(text, 'qutebrowser-editor-') - except OSError as e: + except (OSError, UnicodeEncodeError) as e: message.error("Failed to create initial file: {}".format(e)) return diff --git a/qutebrowser/misc/quitter.py b/qutebrowser/misc/quitter.py index 7d84c57f2..a51891685 100644 --- a/qutebrowser/misc/quitter.py +++ b/qutebrowser/misc/quitter.py @@ -54,7 +54,7 @@ class Quitter(QObject): Attributes: quit_status: The current quitting status. - _is_shutting_down: Whether we're currently shutting down. + is_shutting_down: Whether we're currently shutting down. _args: The argparse namespace. """ @@ -69,7 +69,7 @@ class Quitter(QObject): 'tabs': False, 'main': False, } - self._is_shutting_down = False + self.is_shutting_down = False self._args = args def on_last_window_closed(self) -> None: @@ -214,9 +214,9 @@ class Quitter(QObject): closing. is_restart: If we're planning to restart. """ - if self._is_shutting_down: + if self.is_shutting_down: return - self._is_shutting_down = True + self.is_shutting_down = True log.destroy.debug("Shutting down with status {}, session {}...".format( status, session)) diff --git a/qutebrowser/utils/log.py b/qutebrowser/utils/log.py index b6f1f3e9b..9cd07e2e3 100644 --- a/qutebrowser/utils/log.py +++ b/qutebrowser/utils/log.py @@ -33,7 +33,7 @@ import json import inspect import argparse from typing import (TYPE_CHECKING, Any, Iterator, Mapping, MutableSequence, - Optional, Set, Tuple, Union, cast) + Optional, Set, Tuple, Union) from PyQt5 import QtCore # Optional imports @@ -363,12 +363,16 @@ def change_console_formatter(level: int) -> None: level: The numeric logging level """ assert console_handler is not None + old_formatter = console_handler.formatter - old_formatter = cast(ColoredFormatter, console_handler.formatter) - console_fmt = get_console_format(level) - console_formatter = ColoredFormatter(console_fmt, DATEFMT, '{', - use_colors=old_formatter.use_colors) - console_handler.setFormatter(console_formatter) + if isinstance(old_formatter, ColoredFormatter): + console_fmt = get_console_format(level) + console_formatter = ColoredFormatter( + console_fmt, DATEFMT, '{', use_colors=old_formatter.use_colors) + console_handler.setFormatter(console_formatter) + else: + # Same format for all levels + assert isinstance(old_formatter, JSONFormatter), old_formatter def qt_message_handler(msg_type: QtCore.QtMsgType, |