cookies/cache: Handle por^H^Hrivate browsing mode.

See #43.
This commit is contained in:
Florian Bruhin 2014-12-10 13:12:53 +01:00
parent 0b82fdb4d8
commit 76c5c8bf8e
3 changed files with 184 additions and 34 deletions

View File

@ -22,7 +22,7 @@
import os.path
from PyQt5.QtCore import QStandardPaths
from PyQt5.QtNetwork import QNetworkDiskCache
from PyQt5.QtNetwork import QNetworkDiskCache, QNetworkCacheMetaData
from qutebrowser.config import config
from qutebrowser.utils import utils, standarddir, objreg
@ -48,3 +48,110 @@ class DiskCache(QNetworkDiskCache):
def cache_size_changed(self):
"""Update cache size if the config was changed."""
self.setMaximumCacheSize(config.get('storage', 'cache-size'))
def cacheSize(self):
"""Return the current size taken up by the cache.
Return:
An int.
"""
if objreg.get('general', 'private-browsing'):
return 0
else:
return super().cacheSize()
def fileMetaData(self, filename):
"""Returns the QNetworkCacheMetaData for the cache file filename.
Args:
filename: The file name as a string.
Return:
A QNetworkCacheMetaData object.
"""
if objreg.get('general', 'private-browsing'):
return QNetworkCacheMetaData()
else:
return super().fileMetaData(filename)
def data(self, url):
"""Return the data associated with url.
Args:
url: A QUrl.
return:
A QIODevice or None.
"""
if objreg.get('general', 'private-browsing'):
return None
else:
return super().data(url)
def insert(self, device):
"""Insert the data in device and the prepared meta data into the cache.
Args:
device: A QIODevice.
"""
if objreg.get('general', 'private-browsing'):
return
else:
super().insert(device)
def metaData(self, url):
"""Return the meta data for the url url.
Args:
url: A QUrl.
Return:
A QNetworkCacheMetaData object.
"""
if objreg.get('general', 'private-browsing'):
return QNetworkCacheMetaData()
else:
return super().metaData(url)
def prepare(self, meta_data):
"""Return the device that should be populated with the data.
Args:
meta_data: A QNetworkCacheMetaData object.
Return:
A QIODevice or None.
"""
if objreg.get('general', 'private-browsing'):
return None
else:
return super().prepare(meta_data)
def remove(self, url):
"""Remove the cache entry for url.
Return:
True on success, False otherwise.
"""
if objreg.get('general', 'private-browsing'):
return False
else:
return super().remove(url)
def updateMetaData(self, meta_data):
"""Updates the cache meta date for the meta_data's url to meta_data.
Args:
meta_data: A QNetworkCacheMetaData object.
"""
if objreg.get('general', 'private-browsing'):
return
else:
super().updateMetaData(meta_data)
def clear(self):
"""Removes all items from the cache."""
if objreg.get('general', 'private-browsing'):
return
else:
super().clear()

View File

@ -26,33 +26,13 @@ from qutebrowser.config import config, lineparser
from qutebrowser.utils import utils, standarddir, objreg
class CookieJar(QNetworkCookieJar):
class RAMCookieJar(QNetworkCookieJar):
"""Our own cookie jar to save cookies to disk if desired."""
def __init__(self, parent=None):
super().__init__(parent)
datadir = standarddir.get(QStandardPaths.DataLocation)
self._linecp = lineparser.LineConfigParser(datadir, 'cookies',
binary=True)
cookies = []
for line in self._linecp:
cookies += QNetworkCookie.parseCookies(line)
self.setAllCookies(cookies)
objreg.get('config').changed.connect(self.cookies_store_changed)
"""An in-RAM cookie jar."""
def __repr__(self):
return utils.get_repr(self, count=len(self.allCookies()))
def purge_old_cookies(self):
"""Purge expired cookies from the cookie jar."""
# Based on:
# http://qt-project.org/doc/qt-5/qtwebkitexamples-webkitwidgets-browser-cookiejar-cpp.html
now = QDateTime.currentDateTime()
cookies = [c for c in self.allCookies()
if c.isSessionCookie() or c.expirationDate() >= now]
self.setAllCookies(cookies)
def setCookiesFromUrl(self, cookies, url):
"""Add the cookies in the cookies list to this cookie jar.
@ -68,6 +48,35 @@ class CookieJar(QNetworkCookieJar):
else:
return super().setCookiesFromUrl(cookies, url)
class CookieJar(RAMCookieJar):
"""A cookie jar saving cookies to disk.
Attributes:
_linecp: The LineConfigParser managing the cookies file.
"""
def __init__(self, parent=None):
super().__init__(parent)
datadir = standarddir.get(QStandardPaths.DataLocation)
self._linecp = lineparser.LineConfigParser(datadir, 'cookies',
binary=True)
cookies = []
for line in self._linecp:
cookies += QNetworkCookie.parseCookies(line)
self.setAllCookies(cookies)
objreg.get('config').changed.connect(self.cookies_store_changed)
def purge_old_cookies(self):
"""Purge expired cookies from the cookie jar."""
# Based on:
# http://qt-project.org/doc/qt-5/qtwebkitexamples-webkitwidgets-browser-cookiejar-cpp.html
now = QDateTime.currentDateTime()
cookies = [c for c in self.allCookies()
if c.isSessionCookie() or c.expirationDate() >= now]
self.setAllCookies(cookies)
def save(self):
"""Save cookies to disk."""
if not config.get('content', 'cookies-store'):

View File

@ -32,6 +32,7 @@ else:
from qutebrowser.config import config
from qutebrowser.utils import message, log, usertypes, utils, objreg
from qutebrowser.network import qutescheme, networkreply
from qutebrowser.browser import cookies
class NetworkManager(QNetworkAccessManager):
@ -62,22 +63,44 @@ class NetworkManager(QNetworkAccessManager):
self._scheme_handlers = {
'qute': qutescheme.QuteSchemeHandler(win_id),
}
# We have a shared cookie jar and cache - we restore their parents so
# we don't take ownership of them.
app = QCoreApplication.instance()
cookie_jar = objreg.get('cookie-jar')
self.setCookieJar(cookie_jar)
cookie_jar.setParent(app)
cache = objreg.get('cache')
self.setCache(cache)
cache.setParent(app)
self._set_cookiejar()
self._set_cache()
if SSL_AVAILABLE:
self.sslErrors.connect(self.on_ssl_errors)
self.authenticationRequired.connect(self.on_authentication_required)
self.proxyAuthenticationRequired.connect(
self.on_proxy_authentication_required)
objreg.get('config').changed.connect(self.on_config_changed)
def _set_cookiejar(self, private=False):
"""Set the cookie jar of the NetworkManager correctly.
Args:
private: Whether we're currently in private browsing mode.
"""
if private:
cookie_jar = cookies.RAMCookieJar(self)
self.setCookieJar(cookie_jar)
else:
# We have a shared cookie jar - we restore its parent so we don't
# take ownership of it.
app = QCoreApplication.instance()
cookie_jar = objreg.get('cookie-jar')
self.setCookieJar(cookie_jar)
cookie_jar.setParent(app)
def _set_cache(self):
"""Set the cache of the NetworkManager correctly.
We can't switch the whole cache in private mode because QNAM would
delete the old cache.
"""
# We have a shared cache - we restore its parent so we don't take
# ownership of it.
app = QCoreApplication.instance()
cache = objreg.get('cache')
self.setCache(cache)
cache.setParent(app)
def _ask(self, win_id, text, mode):
"""Ask a blocking question in the statusbar.
@ -160,6 +183,17 @@ class NetworkManager(QNetworkAccessManager):
authenticator.realm()), mode=usertypes.PromptMode.user_pwd)
self._fill_authenticator(authenticator, answer)
@config.change_filter('general', 'private-browsing')
def on_config_changed(self):
"""Set cookie jar when entering/leaving private browsing mode."""
private_browsing = config.get('general', 'private-browsing')
if private_browsing:
# switched from normal mode to private mode
self._set_cookiejar(private=True)
else:
# switched from private mode to normal mode
self._set_cookiejar()
# WORKAROUND for:
# http://www.riverbankcomputing.com/pipermail/pyqt/2014-September/034806.html
#