Implement private browsing for QtWebEngine

This commit is contained in:
Florian Bruhin 2017-04-24 22:24:04 +02:00
parent 1c50377c0a
commit f4d3f97cb7
4 changed files with 51 additions and 32 deletions

View File

@ -38,6 +38,12 @@ from qutebrowser.utils import (objreg, utils, standarddir, javascript, log,
qtutils)
# The default QWebEngineProfile
default_profile = None
# The QWebEngineProfile used for private (off-the-record) windows
private_profile = None
class Attribute(websettings.Attribute):
"""A setting set via QWebEngineSettings::setAttribute."""
@ -67,7 +73,7 @@ class StaticSetter(websettings.StaticSetter):
GLOBAL_SETTINGS = QWebEngineSettings.globalSettings
class ProfileSetter(websettings.Base):
class DefaultProfileSetter(websettings.Base):
"""A setting set on the QWebEngineProfile."""
@ -78,16 +84,16 @@ class ProfileSetter(websettings.Base):
def get(self, settings=None):
utils.unused(settings)
getter = getattr(QWebEngineProfile.defaultProfile(), self._getter)
getter = getattr(default_profile, self._getter)
return getter()
def _set(self, value, settings=None):
utils.unused(settings)
setter = getattr(QWebEngineProfile.defaultProfile(), self._setter)
setter = getattr(default_profile, self._setter)
setter(value)
class PersistentCookiePolicy(ProfileSetter):
class PersistentCookiePolicy(DefaultProfileSetter):
"""The cookies -> store setting is different from other settings."""
@ -141,19 +147,27 @@ def _init_stylesheet(profile):
profile.scripts().insert(script)
def _init_profile(profile):
"""Initialize settings set on the QWebEngineProfile."""
profile.setCachePath(os.path.join(standarddir.cache(), 'webengine'))
profile.setPersistentStoragePath(
os.path.join(standarddir.data(), 'webengine'))
def update_settings(section, option):
"""Update global settings when qwebsettings changed."""
websettings.update_mappings(MAPPINGS, section, option)
profile = QWebEngineProfile.defaultProfile()
if section == 'ui' and option in ['hide-scrollbar', 'user-stylesheet']:
_init_stylesheet(profile)
_init_stylesheet(default_profile)
_init_stylesheet(private_profile)
def _init_profiles():
"""Init the two used QWebEngineProfiles"""
global default_profile, private_profile
default_profile = QWebEngineProfile.defaultProfile()
default_profile.setCachePath(
os.path.join(standarddir.cache(), 'webengine'))
default_profile.setPersistentStoragePath(
os.path.join(standarddir.data(), 'webengine'))
_init_stylesheet(default_profile)
private_profile = QWebEngineProfile()
assert private_profile.isOffTheRecord()
_init_stylesheet(private_profile)
def init(args):
@ -173,9 +187,7 @@ def init(args):
else:
log.misc.debug("Imported PyOpenGL as workaround")
profile = QWebEngineProfile.defaultProfile()
_init_profile(profile)
_init_stylesheet(profile)
_init_profiles()
# We need to do this here as a WORKAROUND for
# https://bugreports.qt.io/browse/QTBUG-58650
if not qtutils.version_check('5.9'):
@ -282,7 +294,7 @@ MAPPINGS = {
'local-storage':
Attribute(QWebEngineSettings.LocalStorageEnabled),
'cache-size':
ProfileSetter(getter='httpCacheMaximumSize',
DefaultProfileSetter(getter='httpCacheMaximumSize',
setter='setHttpCacheMaximumSize')
},
'general': {

View File

@ -34,7 +34,8 @@ from PyQt5.QtWebEngineWidgets import (QWebEnginePage, QWebEngineScript,
from qutebrowser.browser import browsertab, mouse, shared
from qutebrowser.browser.webengine import (webview, webengineelem, tabhistory,
interceptor, webenginequtescheme,
webenginedownloads)
webenginedownloads,
webenginesettings)
from qutebrowser.misc import miscwidgets
from qutebrowser.utils import (usertypes, qtutils, log, javascript, utils,
objreg, jinja, debug)
@ -50,21 +51,23 @@ def init():
# https://www.riverbankcomputing.com/pipermail/pyqt/2016-September/038075.html
global _qute_scheme_handler
app = QApplication.instance()
profile = QWebEngineProfile.defaultProfile()
log.init.debug("Initializing qute://* handler...")
_qute_scheme_handler = webenginequtescheme.QuteSchemeHandler(parent=app)
_qute_scheme_handler.install(profile)
_qute_scheme_handler.install(webenginesettings.default_profile)
_qute_scheme_handler.install(webenginesettings.private_profile)
log.init.debug("Initializing request interceptor...")
host_blocker = objreg.get('host-blocker')
req_interceptor = interceptor.RequestInterceptor(
host_blocker, parent=app)
req_interceptor.install(profile)
req_interceptor.install(webenginesettings.default_profile)
req_interceptor.install(webenginesettings.private_profile)
log.init.debug("Initializing QtWebEngine downloads...")
download_manager = webenginedownloads.DownloadManager(parent=app)
download_manager.install(profile)
download_manager.install(webenginesettings.default_profile)
download_manager.install(webenginesettings.private_profile)
objreg.register('webengine-download-manager', download_manager)
@ -522,11 +525,10 @@ class WebEngineTab(browsertab.AbstractTab):
"""A QtWebEngine tab in the browser."""
def __init__(self, *, win_id, mode_manager, private, parent=None):
# FIXME
assert not private
super().__init__(win_id=win_id, mode_manager=mode_manager,
private=private, parent=parent)
widget = webview.WebEngineView(tabdata=self.data, win_id=win_id)
widget = webview.WebEngineView(tabdata=self.data, win_id=win_id,
private=private)
self.history = WebEngineHistory(self)
self.scroller = WebEngineScroller(self, parent=self)
self.caret = WebEngineCaret(win_id=win_id, mode_manager=mode_manager,

View File

@ -28,7 +28,7 @@ from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
# pylint: enable=no-name-in-module,import-error,useless-suppression
from qutebrowser.browser import shared
from qutebrowser.browser.webengine import certificateerror
from qutebrowser.browser.webengine import certificateerror, webenginesettings
from qutebrowser.config import config
from qutebrowser.utils import (log, debug, usertypes, jinja, urlutils, message,
objreg)
@ -38,13 +38,19 @@ class WebEngineView(QWebEngineView):
"""Custom QWebEngineView subclass with qutebrowser-specific features."""
def __init__(self, tabdata, win_id, parent=None):
def __init__(self, *, tabdata, win_id, private, parent=None):
super().__init__(parent)
self._win_id = win_id
self._tabdata = tabdata
theme_color = self.style().standardPalette().color(QPalette.Base)
page = WebEnginePage(theme_color=theme_color, parent=self)
if private:
profile = webenginesettings.private_profile
assert profile.isOffTheRecord()
else:
profile = webenginesettings.default_profile
page = WebEnginePage(theme_color=theme_color, profile=profile,
parent=self)
self.setPage(page)
def shutdown(self):
@ -124,8 +130,8 @@ class WebEnginePage(QWebEnginePage):
certificate_error = pyqtSignal()
shutting_down = pyqtSignal()
def __init__(self, theme_color, parent=None):
super().__init__(parent)
def __init__(self, *, theme_color, profile, parent=None):
super().__init__(profile, parent)
self._is_shutting_down = False
self.featurePermissionRequested.connect(
self._on_feature_permission_requested)

View File

@ -185,8 +185,7 @@ def data(readonly=False):
"Encoding to use for editor."),
('private-browsing',
SettingValue(typ.Bool(), 'false',
backends=[usertypes.Backend.QtWebKit]),
SettingValue(typ.Bool(), 'false'),
"Do not record visited pages in the history or store web page "
"icons."),