From 81b3ef937ebf202670c1561429552874ed51d32a Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 25 Jun 2018 21:04:32 +0200 Subject: [PATCH] Move handling of certificate errors to webenginetab --- qutebrowser/browser/browsertab.py | 4 -- .../browser/webengine/certificateerror.py | 7 +++ qutebrowser/browser/webengine/webenginetab.py | 33 +++++++++++++- qutebrowser/browser/webengine/webview.py | 43 ++++--------------- qutebrowser/browser/webkit/webkittab.py | 4 ++ 5 files changed, 50 insertions(+), 41 deletions(-) diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index 7e78b2621..9f2e891c5 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -893,10 +893,6 @@ class AbstractTab(QWidget): self._progress = perc self.load_progress.emit(perc) - @pyqtSlot() - def _on_ssl_errors(self): - self._has_ssl_errors = True - def url(self, requested=False): raise NotImplementedError diff --git a/qutebrowser/browser/webengine/certificateerror.py b/qutebrowser/browser/webengine/certificateerror.py index 47953d4cc..768f54ec6 100644 --- a/qutebrowser/browser/webengine/certificateerror.py +++ b/qutebrowser/browser/webengine/certificateerror.py @@ -28,6 +28,10 @@ class CertificateErrorWrapper(usertypes.AbstractCertificateErrorWrapper): """A wrapper over a QWebEngineCertificateError.""" + def __init__(self, error): + super().__init__(error) + self.ignore = False + def __str__(self): return self._error.errorDescription() @@ -37,5 +41,8 @@ class CertificateErrorWrapper(usertypes.AbstractCertificateErrorWrapper): self._error.error()), string=str(self)) + def url(self): + return self._error.url() + def is_overridable(self): return self._error.isOverridable() diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 6739c2f66..185021bfa 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -31,14 +31,15 @@ from PyQt5.QtCore import (pyqtSignal, pyqtSlot, Qt, QEvent, QPoint, QPointF, from PyQt5.QtGui import QKeyEvent, QIcon from PyQt5.QtNetwork import QAuthenticator from PyQt5.QtWidgets import QApplication -from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineScript +from PyQt5.QtWebEngineWidgets import (QWebEnginePage, QWebEngineScript, + QWebEngineCertificateError) from qutebrowser.config import configdata, config from qutebrowser.browser import browsertab, mouse, shared from qutebrowser.browser.webengine import (webview, webengineelem, tabhistory, interceptor, webenginequtescheme, cookies, webenginedownloads, - webenginesettings) + webenginesettings, certificateerror) from qutebrowser.misc import miscwidgets from qutebrowser.utils import (usertypes, qtutils, log, javascript, utils, message, objreg, jinja, debug) @@ -1224,6 +1225,34 @@ class WebEngineTab(browsertab.AbstractTab): # the old icon is still displayed. self.icon_changed.emit(QIcon()) + @pyqtSlot(certificateerror.CertificateErrorWrapper) + def _on_ssl_errors(self, error): + self._has_ssl_errors = True + + url = error.url() + log.webview.debug("Certificate error: {}".format(error)) + + if error.is_overridable(): + error.ignore = shared.ignore_certificate_errors( + url, [error], abort_on=[self.shutting_down, self.load_started]) + else: + log.webview.error("Non-overridable certificate error: " + "{}".format(error)) + + log.webview.debug("ignore {}, URL {}, requested {}".format( + error.ignore, url, self.url(requested=True))) + + # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-56207 + # We can't really know when to show an error page, as the error might + # have happened when loading some resource. + # However, self.url() is not available yet and the requested URL + # might not match the URL we get from the error - so we just apply a + # heuristic here. + if (not qtutils.version_check('5.9') and + not error.ignore and + url.matches(self.url(requested=True), QUrl.RemoveScheme)): + self._show_error_page(url, str(error)) + @pyqtSlot(QUrl) def _on_predicted_navigation(self, url): """If we know we're going to visit an URL soon, change the settings. diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py index 11add368e..76007b9d9 100644 --- a/qutebrowser/browser/webengine/webview.py +++ b/qutebrowser/browser/webengine/webview.py @@ -24,10 +24,11 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, PYQT_VERSION from PyQt5.QtGui import QPalette from PyQt5.QtWidgets import QWidget from PyQt5.QtWebEngineWidgets import (QWebEngineView, QWebEnginePage, - QWebEngineScript) + QWebEngineScript, + QWebEngineCertificateError) from qutebrowser.browser import shared -from qutebrowser.browser.webengine import certificateerror, webenginesettings +from qutebrowser.browser.webengine import webenginesettings, certificateerror from qutebrowser.config import config from qutebrowser.utils import log, debug, usertypes, jinja, objreg, qtutils from qutebrowser.misc import miscwidgets @@ -152,11 +153,13 @@ class WebEnginePage(QWebEnginePage): Signals: certificate_error: Emitted on certificate errors. + Needs to be directly connected to a slot setting the + 'ignore' attribute. shutting_down: Emitted when the page is shutting down. navigation_request: Emitted on acceptNavigationRequest. """ - certificate_error = pyqtSignal() + certificate_error = pyqtSignal(certificateerror.CertificateErrorWrapper) shutting_down = pyqtSignal() navigation_request = pyqtSignal(usertypes.NavigationRequest) @@ -181,39 +184,9 @@ class WebEnginePage(QWebEnginePage): def certificateError(self, error): """Handle certificate errors coming from Qt.""" - self.certificate_error.emit() - url = error.url() error = certificateerror.CertificateErrorWrapper(error) - log.webview.debug("Certificate error: {}".format(error)) - - url_string = url.toDisplayString() - error_page = jinja.render( - 'error.html', title="Error loading page: {}".format(url_string), - url=url_string, error=str(error)) - - if error.is_overridable(): - ignore = shared.ignore_certificate_errors( - url, [error], abort_on=[self.loadStarted, self.shutting_down]) - else: - log.webview.error("Non-overridable certificate error: " - "{}".format(error)) - ignore = False - - log.webview.debug("ignore {}, URL {}, requested {}".format( - ignore, url, self.requestedUrl())) - - # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-56207 - # We can't really know when to show an error page, as the error might - # have happened when loading some resource. - # However, self.url() is not available yet and self.requestedUrl() - # might not match the URL we get from the error - so we just apply a - # heuristic here. - if (not qtutils.version_check('5.9') and - not ignore and - url.matches(self.requestedUrl(), QUrl.RemoveScheme)): - self.setHtml(error_page) - - return ignore + self.certificate_error.emit(error) + return error.ignore def javaScriptConfirm(self, url, js_msg): """Override javaScriptConfirm to use qutebrowser prompts.""" diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py index cf158ed2d..8039eb5eb 100644 --- a/qutebrowser/browser/webkit/webkittab.py +++ b/qutebrowser/browser/webkit/webkittab.py @@ -808,6 +808,10 @@ class WebKitTab(browsertab.AbstractTab): if navigation.is_main_frame: self.settings.update_for_url(navigation.url) + @pyqtSlot() + def _on_ssl_errors(self): + self._has_ssl_errors = True + def _connect_signals(self): view = self._widget page = view.page()