From 43c9d692953392a51d5b8e096ec59f76c98f763b Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 9 Feb 2015 15:41:08 +0100 Subject: [PATCH] Handle shutdown of page with prompt correctly. Before we didn't cancel javascript prompts when a page was closed, which lead to exceptions or segfaults. --- qutebrowser/browser/webpage.py | 28 +++++++++++++++++++++++++++- qutebrowser/browser/webview.py | 8 +------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/qutebrowser/browser/webpage.py b/qutebrowser/browser/webpage.py index 1dffb5270..b8cddfbf8 100644 --- a/qutebrowser/browser/webpage.py +++ b/qutebrowser/browser/webpage.py @@ -21,7 +21,7 @@ import functools -from PyQt5.QtCore import pyqtSlot, PYQT_VERSION, Qt, QUrl +from PyQt5.QtCore import pyqtSlot, pyqtSignal, PYQT_VERSION, Qt, QUrl from PyQt5.QtGui import QDesktopServices from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest from PyQt5.QtWidgets import QFileDialog @@ -45,11 +45,18 @@ class BrowserPage(QWebPage): _networkmnager: The NetworkManager used. _win_id: The window ID this BrowserPage is associated with. _ignore_load_started: Whether to ignore the next loadStarted signal. + _is_shutting_down: Whether the page is currently shutting down. + + Signals: + shutting_down: Emitted when the page is currently shutting down. """ + shutting_down = pyqtSignal() + def __init__(self, win_id, tab_id, parent=None): super().__init__(parent) self._win_id = win_id + self._is_shutting_down = False self._extension_handlers = { QWebPage.ErrorPageExtension: self._handle_errorpage, QWebPage.ChooseMultipleFilesExtension: self._handle_multiple_files, @@ -75,6 +82,8 @@ class BrowserPage(QWebPage): def javaScriptPrompt(self, _frame, msg, default): """Override javaScriptPrompt to use the statusbar.""" + if self._is_shutting_down: + return (False, "") answer = self._ask("js: {}".format(msg), usertypes.PromptMode.text, default) if answer is None: @@ -185,12 +194,25 @@ class BrowserPage(QWebPage): q.mode = mode q.default = default self.loadStarted.connect(q.abort) + self.shutting_down.connect(q.abort) bridge = objreg.get('message-bridge', scope='window', window=self._win_id) bridge.ask(q, blocking=True) q.deleteLater() return q.answer + def shutdown(self): + """Prepare the web page for being deleted.""" + self._is_shutting_down = True + self.shutting_down.emit() + download_manager = objreg.get('download-manager', scope='window', + window=self._win_id) + nam = self.networkAccessManager() + if download_manager.has_downloads_with_nam(nam): + nam.setParent(download_manager) + else: + nam.shutdown() + def display_content(self, reply, mimetype): """Display a QNetworkReply with an explicitely set mimetype.""" self.mainFrame().setContent(reply.readAll(), mimetype, reply.url()) @@ -348,10 +370,14 @@ class BrowserPage(QWebPage): def javaScriptAlert(self, _frame, msg): """Override javaScriptAlert to use the statusbar.""" + if self._is_shutting_down: + return self._ask("[js alert] {}".format(msg), usertypes.PromptMode.alert) def javaScriptConfirm(self, _frame, msg): """Override javaScriptConfirm to use the statusbar.""" + if self._is_shutting_down: + return False ans = self._ask("[js confirm] {}".format(msg), usertypes.PromptMode.yesno) return bool(ans) diff --git a/qutebrowser/browser/webview.py b/qutebrowser/browser/webview.py index 93984a9bd..f4cd6eea7 100644 --- a/qutebrowser/browser/webview.py +++ b/qutebrowser/browser/webview.py @@ -306,19 +306,13 @@ class WebView(QWebView): def shutdown(self): """Shut down the webview.""" self.shutting_down.emit() + self.page().shutdown() # We disable javascript because that prevents some segfaults when # quitting it seems. log.destroy.debug("Shutting down {!r}.".format(self)) settings = self.settings() settings.setAttribute(QWebSettings.JavascriptEnabled, False) self.stop() - download_manager = objreg.get('download-manager', scope='window', - window=self._win_id) - nam = self.page().networkAccessManager() - if download_manager.has_downloads_with_nam(nam): - nam.setParent(download_manager) - else: - nam.shutdown() def openurl(self, url): """Open a URL in the browser.