diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index e56971426..283e5534f 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -797,14 +797,19 @@ class DownloadManager(QAbstractListModel): Return: A boolean. """ + assert nam.adopted_downloads == 0 for download in self.downloads: - if download.reply is not None and download.reply.manager() is nam: - return True - if (download.done and (not download.successful) and - download.retry_info.manager is nam): - # user could request retry after tab is closed. - return True - return False + running_download = (download.reply is not None and + download.reply.manager() is nam) + # user could request retry after tab is closed. + failed_download = (download.done and (not download.successful) and + download.retry_info.manager is nam) + if running_download or failed_download: + log.downloads.debug("Found running/failed downloads, " + "adopting the NAM.") + nam.adopted_downloads += 1 + download.destroyed.connect(nam.on_adopted_download_destroyed) + return nam.adopted_downloads def can_clear(self): """Check if there are finished downloads to clear.""" diff --git a/qutebrowser/browser/network/networkmanager.py b/qutebrowser/browser/network/networkmanager.py index 3bf9e4c0f..509554dbc 100644 --- a/qutebrowser/browser/network/networkmanager.py +++ b/qutebrowser/browser/network/networkmanager.py @@ -43,6 +43,11 @@ class NetworkManager(QNetworkAccessManager): """Our own QNetworkAccessManager. Attributes: + adopted_downloads: If downloads are running with this QNAM but the + associated tab gets closed already, the NAM gets + reparented to the DownloadManager. This counts the + still running downloads, so the QNAM can clean + itself up when this reaches zero again. _requests: Pending requests. _scheme_handlers: A dictionary (scheme -> handler) of supported custom schemes. @@ -62,6 +67,7 @@ class NetworkManager(QNetworkAccessManager): # http://www.riverbankcomputing.com/pipermail/pyqt/2014-November/035045.html super().__init__(parent) log.init.debug("NetworkManager init done") + self.adopted_downloads = 0 self._win_id = win_id self._tab_id = tab_id self._requests = [] @@ -207,6 +213,19 @@ class NetworkManager(QNetworkAccessManager): # switched from private mode to normal mode self._set_cookiejar() + @pyqtSlot() + def on_adopted_download_destroyed(self): + """Check if we can clean up if an adopted download was destroyed. + + See the description for adopted_downloads for details. + """ + self.adopted_downloads -= 1 + log.downloads.debug("Adopted download destroyed, {} left.".format( + self.adopted_downloads)) + assert self.adopted_downloads >= 0 + if self.adopted_downloads == 0: + self.deleteLater() + # WORKAROUND for: # http://www.riverbankcomputing.com/pipermail/pyqt/2014-September/034806.html #