Go back to using one NetworkManager per tab

This commit is contained in:
Florian Bruhin 2014-07-10 06:42:52 +02:00
parent bde26c7a76
commit fad22c63d9
8 changed files with 40 additions and 37 deletions

View File

@ -45,7 +45,6 @@ import qutebrowser.utils.log as log
import qutebrowser.utils.version as version import qutebrowser.utils.version as version
import qutebrowser.utils.url as urlutils import qutebrowser.utils.url as urlutils
import qutebrowser.utils.message as message import qutebrowser.utils.message as message
from qutebrowser.network.networkmanager import NetworkManager
from qutebrowser.config.config import ConfigManager from qutebrowser.config.config import ConfigManager
from qutebrowser.keyinput.modeman import ModeManager from qutebrowser.keyinput.modeman import ModeManager
from qutebrowser.widgets.mainwindow import MainWindow from qutebrowser.widgets.mainwindow import MainWindow
@ -78,7 +77,6 @@ class Application(QApplication):
cmd_history: The "cmd_history" LineConfigParser instance. cmd_history: The "cmd_history" LineConfigParser instance.
messagebridge: The global MessageBridge instance. messagebridge: The global MessageBridge instance.
modeman: The global ModeManager instance. modeman: The global ModeManager instance.
networkmanager: The global NetworkManager instance.
cookiejar: The global CookieJar instance. cookiejar: The global CookieJar instance.
rl_bridge: The ReadlineBridge being used. rl_bridge: The ReadlineBridge being used.
args: ArgumentParser instance. args: ArgumentParser instance.
@ -106,7 +104,6 @@ class Application(QApplication):
self._quit_status = { self._quit_status = {
'crash': True, 'crash': True,
'tabs': False, 'tabs': False,
'networkmanager': False,
'main': False, 'main': False,
} }
self._timers = [] self._timers = []
@ -141,8 +138,6 @@ class Application(QApplication):
proxy.init() proxy.init()
log.init.debug("Initializing cookies...") log.init.debug("Initializing cookies...")
self.cookiejar = CookieJar(self) self.cookiejar = CookieJar(self)
log.init.debug("Initializing NetworkManager...")
self.networkmanager = NetworkManager(self.cookiejar)
log.init.debug("Initializing commands...") log.init.debug("Initializing commands...")
self.commandmanager = CommandManager() self.commandmanager = CommandManager()
log.init.debug("Initializing search...") log.init.debug("Initializing search...")
@ -681,16 +676,6 @@ class Application(QApplication):
log.destroy.warning("No mainwindow/tabs to shut down ({}).".format( log.destroy.warning("No mainwindow/tabs to shut down ({}).".format(
e)) e))
self._maybe_quit('tabs') 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 # Re-enable faulthandler to stdout, then remove crash log
self._destroy_crashlogfile() self._destroy_crashlogfile()
# If we don't kill our custom handler here we might get segfaults # If we don't kill our custom handler here we might get segfaults

View File

@ -698,7 +698,8 @@ class CommandDispatcher:
@cmdutils.register(instance='mainwindow.tabs.cmd') @cmdutils.register(instance='mainwindow.tabs.cmd')
def download_page(self): def download_page(self):
"""Download the current page.""" """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'], @cmdutils.register(instance='mainwindow.tabs.cmd', modes=['insert'],
hide=True) hide=True)

View File

@ -24,8 +24,7 @@ import os.path
from functools import partial from functools import partial
from collections import deque from collections import deque
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QObject, QCoreApplication, from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QTimer
QTimer)
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
import qutebrowser.config.config as config import qutebrowser.config.config as config
@ -342,16 +341,17 @@ class DownloadManager(QObject):
def __repr__(self): def __repr__(self):
return '<{}>'.format(self.__class__.__name__) return '<{}>'.format(self.__class__.__name__)
@pyqtSlot('QUrl') @pyqtSlot('QUrl', 'QWebPage')
def get(self, url): def get(self, url, page):
"""Start a download with a link URL. """Start a download with a link URL.
Args: Args:
url: The URL to get, as QUrl url: The URL to get, as QUrl
page: The QWebPage to get the download from.
""" """
qt_ensure_valid(url) qt_ensure_valid(url)
req = QNetworkRequest(url) req = QNetworkRequest(url)
reply = QCoreApplication.instance().networkmanager.get(req) reply = page.networkAccessManager().get(req)
self.fetch(reply) self.fetch(reply)
@cmdutils.register(instance='downloadmanager') @cmdutils.register(instance='downloadmanager')

View File

@ -91,7 +91,8 @@ class HintManager(QObject):
arg 1: True if it should be opened in a new tab, else False. 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. set_open_target: Set a new target to open the links in.
download_get: Download an URL. 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 = """ HINT_CSS = """
@ -125,7 +126,7 @@ class HintManager(QObject):
mouse_event = pyqtSignal('QMouseEvent') mouse_event = pyqtSignal('QMouseEvent')
openurl = pyqtSignal('QUrl', bool) openurl = pyqtSignal('QUrl', bool)
set_open_target = pyqtSignal(str) set_open_target = pyqtSignal(str)
download_get = pyqtSignal('QUrl') download_get = pyqtSignal('QUrl', 'QWebPage')
def __init__(self, parent=None): def __init__(self, parent=None):
"""Constructor. """Constructor.
@ -327,14 +328,19 @@ class HintManager(QObject):
message.set_cmd_text(':{} {}'.format(commands[self._context.target], message.set_cmd_text(':{} {}'.format(commands[self._context.target],
urlstr)) urlstr))
def _download(self, url): def _download(self, elem):
"""Download a hint URL. """Download a hint URL.
Args: 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) qt_ensure_valid(url)
self.download_get.emit(url) self.download_get.emit(url, elem.webFrame().page())
def _resolve_url(self, elem, baseurl=None): def _resolve_url(self, elem, baseurl=None):
"""Resolve a URL and check if we want to keep it. """Resolve a URL and check if we want to keep it.
@ -516,6 +522,8 @@ class HintManager(QObject):
Target.tab: self._click, Target.tab: self._click,
Target.tab_bg: self._click, Target.tab_bg: self._click,
Target.rapid: self._click, Target.rapid: self._click,
# _download needs a QWebElement to get the frame.
Target.download: self._download,
} }
# Handlers which take a QUrl # Handlers which take a QUrl
url_handlers = { url_handlers = {
@ -524,7 +532,6 @@ class HintManager(QObject):
Target.cmd: self._preset_cmd_text, Target.cmd: self._preset_cmd_text,
Target.cmd_tab: self._preset_cmd_text, Target.cmd_tab: self._preset_cmd_text,
Target.cmd_tab_bg: self._preset_cmd_text, Target.cmd_tab_bg: self._preset_cmd_text,
Target.download: self._download,
} }
elem = self._context.elems[keystr].elem elem = self._context.elems[keystr].elem
if self._context.target in elem_handlers: if self._context.target in elem_handlers:

View File

@ -20,8 +20,7 @@
"""The main browser widgets.""" """The main browser widgets."""
import sip import sip
from PyQt5.QtCore import (QCoreApplication, pyqtSignal, pyqtSlot, PYQT_VERSION, from PyQt5.QtCore import pyqtSignal, pyqtSlot, PYQT_VERSION, Qt
Qt)
from PyQt5.QtNetwork import QNetworkReply from PyQt5.QtNetwork import QNetworkReply
from PyQt5.QtWidgets import QFileDialog from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtPrintSupport import QPrintDialog from PyQt5.QtPrintSupport import QPrintDialog
@ -30,6 +29,7 @@ from PyQt5.QtWebKitWidgets import QWebPage
import qutebrowser.utils.message as message import qutebrowser.utils.message as message
import qutebrowser.config.config as config import qutebrowser.config.config as config
import qutebrowser.utils.log as log import qutebrowser.utils.log as log
from qutebrowser.network.networkmanager import NetworkManager
from qutebrowser.utils.misc import read_file from qutebrowser.utils.misc import read_file
from qutebrowser.utils.qt import check_print_compat from qutebrowser.utils.qt import check_print_compat
from qutebrowser.utils.usertypes import PromptMode, ClickTarget from qutebrowser.utils.usertypes import PromptMode, ClickTarget
@ -42,7 +42,7 @@ class BrowserPage(QWebPage):
Attributes: Attributes:
_extension_handlers: Mapping of QWebPage extensions to their handlers. _extension_handlers: Mapping of QWebPage extensions to their handlers.
_view: The QWebView associated with this page. _view: The QWebView associated with this page.
network_access_manager: The QNetworkAccessManager used. _networkmnager: The NetworkManager used.
Signals: Signals:
start_download: Emitted when a file should be downloaded. start_download: Emitted when a file should be downloaded.
@ -58,8 +58,8 @@ class BrowserPage(QWebPage):
QWebPage.ErrorPageExtension: self._handle_errorpage, QWebPage.ErrorPageExtension: self._handle_errorpage,
QWebPage.ChooseMultipleFilesExtension: self._handle_multiple_files, QWebPage.ChooseMultipleFilesExtension: self._handle_multiple_files,
} }
self.setNetworkAccessManager( self._networkmanager = NetworkManager(self)
QCoreApplication.instance().networkmanager) self.setNetworkAccessManager(self._networkmanager)
self.setForwardUnsupportedContent(True) self.setForwardUnsupportedContent(True)
self.printRequested.connect(self.on_print_requested) self.printRequested.connect(self.on_print_requested)
self.downloadRequested.connect(self.on_download_requested) self.downloadRequested.connect(self.on_download_requested)
@ -71,6 +71,12 @@ class BrowserPage(QWebPage):
# pylint: disable=invalid-name # pylint: disable=invalid-name
self.javaScriptPrompt = self._javascript_prompt 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): def _javascript_prompt(self, _frame, msg, default):
"""Override javaScriptPrompt to use the statusbar. """Override javaScriptPrompt to use the statusbar.

View File

@ -19,7 +19,7 @@
"""Our own QNetworkAccessManager.""" """Our own QNetworkAccessManager."""
from PyQt5.QtCore import pyqtSlot, PYQT_VERSION from PyQt5.QtCore import pyqtSlot, PYQT_VERSION, QCoreApplication
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply
try: try:
@ -54,8 +54,12 @@ class NetworkManager(QNetworkAccessManager):
self._scheme_handlers = { self._scheme_handlers = {
'qute': QuteSchemeHandler(), 'qute': QuteSchemeHandler(),
} }
if cookiejar is not None: cookiejar = QCoreApplication.instance().cookiejar
self.setCookieJar(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: if SSL_AVAILABLE:
self.sslErrors.connect(self.on_ssl_errors) self.sslErrors.connect(self.on_ssl_errors)
self.authenticationRequired.connect(self.on_authentication_required) self.authenticationRequired.connect(self.on_authentication_required)

View File

@ -91,7 +91,7 @@ class TabbedBrowser(TabWidget):
cur_scroll_perc_changed = pyqtSignal(int, int) cur_scroll_perc_changed = pyqtSignal(int, int)
cur_load_status_changed = pyqtSignal(str) cur_load_status_changed = pyqtSignal(str)
start_download = pyqtSignal('QNetworkReply*') start_download = pyqtSignal('QNetworkReply*')
download_get = pyqtSignal('QUrl') download_get = pyqtSignal('QUrl', 'QWebPage')
hint_strings_updated = pyqtSignal(list) hint_strings_updated = pyqtSignal(list)
shutdown_complete = pyqtSignal() shutdown_complete = pyqtSignal()
quit = pyqtSignal() quit = pyqtSignal()

View File

@ -339,7 +339,7 @@ class WebView(QWebView):
self._destroyed[self.page()] = False self._destroyed[self.page()] = False
self.page().destroyed.connect(functools.partial(self._on_destroyed, self.page().destroyed.connect(functools.partial(self._on_destroyed,
self.page())) self.page()))
self.page().deleteLater() self.page().shutdown()
self._destroyed[self] = False self._destroyed[self] = False
self.destroyed.connect(functools.partial(self._on_destroyed, self)) self.destroyed.connect(functools.partial(self._on_destroyed, self))