From fad22c63d9324ca9ee30d783cd32a1a3b2b4bae7 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 10 Jul 2014 06:42:52 +0200 Subject: [PATCH] Go back to using one NetworkManager per tab --- qutebrowser/app.py | 15 --------------- qutebrowser/browser/commands.py | 3 ++- qutebrowser/browser/downloads.py | 10 +++++----- qutebrowser/browser/hints.py | 19 +++++++++++++------ qutebrowser/browser/webpage.py | 16 +++++++++++----- qutebrowser/network/networkmanager.py | 10 +++++++--- qutebrowser/widgets/tabbedbrowser.py | 2 +- qutebrowser/widgets/webview.py | 2 +- 8 files changed, 40 insertions(+), 37 deletions(-) diff --git a/qutebrowser/app.py b/qutebrowser/app.py index 7266e8955..8e18b3adc 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -45,7 +45,6 @@ import qutebrowser.utils.log as log import qutebrowser.utils.version as version import qutebrowser.utils.url as urlutils import qutebrowser.utils.message as message -from qutebrowser.network.networkmanager import NetworkManager from qutebrowser.config.config import ConfigManager from qutebrowser.keyinput.modeman import ModeManager from qutebrowser.widgets.mainwindow import MainWindow @@ -78,7 +77,6 @@ class Application(QApplication): cmd_history: The "cmd_history" LineConfigParser instance. messagebridge: The global MessageBridge instance. modeman: The global ModeManager instance. - networkmanager: The global NetworkManager instance. cookiejar: The global CookieJar instance. rl_bridge: The ReadlineBridge being used. args: ArgumentParser instance. @@ -106,7 +104,6 @@ class Application(QApplication): self._quit_status = { 'crash': True, 'tabs': False, - 'networkmanager': False, 'main': False, } self._timers = [] @@ -141,8 +138,6 @@ class Application(QApplication): proxy.init() log.init.debug("Initializing cookies...") self.cookiejar = CookieJar(self) - log.init.debug("Initializing NetworkManager...") - self.networkmanager = NetworkManager(self.cookiejar) log.init.debug("Initializing commands...") self.commandmanager = CommandManager() log.init.debug("Initializing search...") @@ -681,16 +676,6 @@ class Application(QApplication): log.destroy.warning("No mainwindow/tabs to shut down ({}).".format( e)) self._maybe_quit('tabs') - # Shut down networkmanager - try: - self.networkmanager.abort_requests() - self.networkmanager.destroyed.connect(partial( - self._maybe_quit, 'networkmanager')) - self.networkmanager.deleteLater() - except AttributeError as e: - log.destroy.warning("No networkmanager to shut down ({}).".format( - e)) - self._maybe_quit('networkmanager') # Re-enable faulthandler to stdout, then remove crash log self._destroy_crashlogfile() # If we don't kill our custom handler here we might get segfaults diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 16bb201cd..3332ecf09 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -698,7 +698,8 @@ class CommandDispatcher: @cmdutils.register(instance='mainwindow.tabs.cmd') def download_page(self): """Download the current page.""" - self._tabs.download_get.emit(self._current_url()) + page = self._tabs.currentWidget().page() + self._tabs.download_get.emit(self._current_url(), page) @cmdutils.register(instance='mainwindow.tabs.cmd', modes=['insert'], hide=True) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index d8ec32a01..c7575a951 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -24,8 +24,7 @@ import os.path from functools import partial from collections import deque -from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QObject, QCoreApplication, - QTimer) +from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QTimer from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply import qutebrowser.config.config as config @@ -342,16 +341,17 @@ class DownloadManager(QObject): def __repr__(self): return '<{}>'.format(self.__class__.__name__) - @pyqtSlot('QUrl') - def get(self, url): + @pyqtSlot('QUrl', 'QWebPage') + def get(self, url, page): """Start a download with a link URL. Args: url: The URL to get, as QUrl + page: The QWebPage to get the download from. """ qt_ensure_valid(url) req = QNetworkRequest(url) - reply = QCoreApplication.instance().networkmanager.get(req) + reply = page.networkAccessManager().get(req) self.fetch(reply) @cmdutils.register(instance='downloadmanager') diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index cd0bbfbd7..3dc0704a9 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -91,7 +91,8 @@ class HintManager(QObject): arg 1: True if it should be opened in a new tab, else False. set_open_target: Set a new target to open the links in. download_get: Download an URL. - arg: The URL to download, as QUrl. + arg 0: The URL to download, as QUrl. + arg 1: The QWebPage to download the URL in. """ HINT_CSS = """ @@ -125,7 +126,7 @@ class HintManager(QObject): mouse_event = pyqtSignal('QMouseEvent') openurl = pyqtSignal('QUrl', bool) set_open_target = pyqtSignal(str) - download_get = pyqtSignal('QUrl') + download_get = pyqtSignal('QUrl', 'QWebPage') def __init__(self, parent=None): """Constructor. @@ -327,14 +328,19 @@ class HintManager(QObject): message.set_cmd_text(':{} {}'.format(commands[self._context.target], urlstr)) - def _download(self, url): + def _download(self, elem): """Download a hint URL. Args: - url: The URL to download, as a QUrl. + elem: The QWebElement to download. """ + url = self._resolve_url(elem) + if url is None: + message.error("No suitable link found for this element.", + immediately=True) + return qt_ensure_valid(url) - self.download_get.emit(url) + self.download_get.emit(url, elem.webFrame().page()) def _resolve_url(self, elem, baseurl=None): """Resolve a URL and check if we want to keep it. @@ -516,6 +522,8 @@ class HintManager(QObject): Target.tab: self._click, Target.tab_bg: self._click, Target.rapid: self._click, + # _download needs a QWebElement to get the frame. + Target.download: self._download, } # Handlers which take a QUrl url_handlers = { @@ -524,7 +532,6 @@ class HintManager(QObject): Target.cmd: self._preset_cmd_text, Target.cmd_tab: self._preset_cmd_text, Target.cmd_tab_bg: self._preset_cmd_text, - Target.download: self._download, } elem = self._context.elems[keystr].elem if self._context.target in elem_handlers: diff --git a/qutebrowser/browser/webpage.py b/qutebrowser/browser/webpage.py index 8934e8160..3f8ee7578 100644 --- a/qutebrowser/browser/webpage.py +++ b/qutebrowser/browser/webpage.py @@ -20,8 +20,7 @@ """The main browser widgets.""" import sip -from PyQt5.QtCore import (QCoreApplication, pyqtSignal, pyqtSlot, PYQT_VERSION, - Qt) +from PyQt5.QtCore import pyqtSignal, pyqtSlot, PYQT_VERSION, Qt from PyQt5.QtNetwork import QNetworkReply from PyQt5.QtWidgets import QFileDialog from PyQt5.QtPrintSupport import QPrintDialog @@ -30,6 +29,7 @@ from PyQt5.QtWebKitWidgets import QWebPage import qutebrowser.utils.message as message import qutebrowser.config.config as config import qutebrowser.utils.log as log +from qutebrowser.network.networkmanager import NetworkManager from qutebrowser.utils.misc import read_file from qutebrowser.utils.qt import check_print_compat from qutebrowser.utils.usertypes import PromptMode, ClickTarget @@ -42,7 +42,7 @@ class BrowserPage(QWebPage): Attributes: _extension_handlers: Mapping of QWebPage extensions to their handlers. _view: The QWebView associated with this page. - network_access_manager: The QNetworkAccessManager used. + _networkmnager: The NetworkManager used. Signals: start_download: Emitted when a file should be downloaded. @@ -58,8 +58,8 @@ class BrowserPage(QWebPage): QWebPage.ErrorPageExtension: self._handle_errorpage, QWebPage.ChooseMultipleFilesExtension: self._handle_multiple_files, } - self.setNetworkAccessManager( - QCoreApplication.instance().networkmanager) + self._networkmanager = NetworkManager(self) + self.setNetworkAccessManager(self._networkmanager) self.setForwardUnsupportedContent(True) self.printRequested.connect(self.on_print_requested) self.downloadRequested.connect(self.on_download_requested) @@ -71,6 +71,12 @@ class BrowserPage(QWebPage): # pylint: disable=invalid-name self.javaScriptPrompt = self._javascript_prompt + def shutdown(self,): + """Shutdown the page.""" + self._networkmanager.abort_requests() + self._networkmanager.destroyed.connect(self.deleteLater) + self._networkmanager.deleteLater() + def _javascript_prompt(self, _frame, msg, default): """Override javaScriptPrompt to use the statusbar. diff --git a/qutebrowser/network/networkmanager.py b/qutebrowser/network/networkmanager.py index 87bf68ea6..20f47f8b2 100644 --- a/qutebrowser/network/networkmanager.py +++ b/qutebrowser/network/networkmanager.py @@ -19,7 +19,7 @@ """Our own QNetworkAccessManager.""" -from PyQt5.QtCore import pyqtSlot, PYQT_VERSION +from PyQt5.QtCore import pyqtSlot, PYQT_VERSION, QCoreApplication from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply try: @@ -54,8 +54,12 @@ class NetworkManager(QNetworkAccessManager): self._scheme_handlers = { 'qute': QuteSchemeHandler(), } - if cookiejar is not None: - self.setCookieJar(cookiejar) + cookiejar = QCoreApplication.instance().cookiejar + parent = cookiejar.parent() + self.setCookieJar(cookiejar) + # We have a shared cookie jar, so we don't want the NetworkManager to + # take ownership of the CookieJar. + cookiejar.setParent(parent) if SSL_AVAILABLE: self.sslErrors.connect(self.on_ssl_errors) self.authenticationRequired.connect(self.on_authentication_required) diff --git a/qutebrowser/widgets/tabbedbrowser.py b/qutebrowser/widgets/tabbedbrowser.py index 557a4f5fa..f6c22b855 100644 --- a/qutebrowser/widgets/tabbedbrowser.py +++ b/qutebrowser/widgets/tabbedbrowser.py @@ -91,7 +91,7 @@ class TabbedBrowser(TabWidget): cur_scroll_perc_changed = pyqtSignal(int, int) cur_load_status_changed = pyqtSignal(str) start_download = pyqtSignal('QNetworkReply*') - download_get = pyqtSignal('QUrl') + download_get = pyqtSignal('QUrl', 'QWebPage') hint_strings_updated = pyqtSignal(list) shutdown_complete = pyqtSignal() quit = pyqtSignal() diff --git a/qutebrowser/widgets/webview.py b/qutebrowser/widgets/webview.py index 5d4d034a4..995c12949 100644 --- a/qutebrowser/widgets/webview.py +++ b/qutebrowser/widgets/webview.py @@ -339,7 +339,7 @@ class WebView(QWebView): self._destroyed[self.page()] = False self.page().destroyed.connect(functools.partial(self._on_destroyed, self.page())) - self.page().deleteLater() + self.page().shutdown() self._destroyed[self] = False self.destroyed.connect(functools.partial(self._on_destroyed, self))