Initial work on new private browsing
This commit is contained in:
parent
1d4c9d3b3f
commit
1c50377c0a
@ -195,7 +195,7 @@ def _process_args(args):
|
||||
session_manager = objreg.get('session-manager')
|
||||
if not session_manager.did_load:
|
||||
log.init.debug("Initializing main window...")
|
||||
window = mainwindow.MainWindow()
|
||||
window = mainwindow.MainWindow(private=None)
|
||||
if not args.nowindow:
|
||||
window.show()
|
||||
qApp.setActiveWindow(window)
|
||||
|
@ -35,11 +35,12 @@ from qutebrowser.browser import mouse, hints
|
||||
tab_id_gen = itertools.count(0)
|
||||
|
||||
|
||||
def create(win_id, parent=None):
|
||||
def create(win_id, private, parent=None):
|
||||
"""Get a QtWebKit/QtWebEngine tab object.
|
||||
|
||||
Args:
|
||||
win_id: The window ID where the tab will be shown.
|
||||
private: Whether the tab is a private/off the record tab.
|
||||
parent: The Qt parent to set.
|
||||
"""
|
||||
# Importing modules here so we don't depend on QtWebEngine without the
|
||||
@ -51,7 +52,8 @@ def create(win_id, parent=None):
|
||||
else:
|
||||
from qutebrowser.browser.webkit import webkittab
|
||||
tab_class = webkittab.WebKitTab
|
||||
return tab_class(win_id=win_id, mode_manager=mode_manager, parent=parent)
|
||||
return tab_class(win_id=win_id, mode_manager=mode_manager, private=private,
|
||||
parent=parent)
|
||||
|
||||
|
||||
def init():
|
||||
@ -542,6 +544,7 @@ class AbstractTab(QWidget):
|
||||
Attributes:
|
||||
history: The AbstractHistory for the current tab.
|
||||
registry: The ObjectRegistry associated with this tab.
|
||||
private: Whether private browsing is turned on for this tab.
|
||||
|
||||
_load_status: loading status of this page
|
||||
Accessible via load_status() method.
|
||||
@ -581,7 +584,8 @@ class AbstractTab(QWidget):
|
||||
fullscreen_requested = pyqtSignal(bool)
|
||||
renderer_process_terminated = pyqtSignal(TerminationStatus, int)
|
||||
|
||||
def __init__(self, win_id, mode_manager, parent=None):
|
||||
def __init__(self, *, win_id, mode_manager, private, parent=None):
|
||||
self.private = private
|
||||
self.win_id = win_id
|
||||
self.tab_id = next(tab_id_gen)
|
||||
super().__init__(parent)
|
||||
|
@ -67,10 +67,10 @@ class CommandDispatcher:
|
||||
def __repr__(self):
|
||||
return utils.get_repr(self)
|
||||
|
||||
def _new_tabbed_browser(self):
|
||||
def _new_tabbed_browser(self, private):
|
||||
"""Get a tabbed-browser from a new window."""
|
||||
from qutebrowser.mainwindow import mainwindow
|
||||
new_window = mainwindow.MainWindow()
|
||||
new_window = mainwindow.MainWindow(private=private)
|
||||
new_window.show()
|
||||
return new_window.tabbed_browser
|
||||
|
||||
@ -110,7 +110,7 @@ class CommandDispatcher:
|
||||
return widget
|
||||
|
||||
def _open(self, url, tab=False, background=False, window=False,
|
||||
explicit=True):
|
||||
explicit=True, private=None):
|
||||
"""Helper function to open a page.
|
||||
|
||||
Args:
|
||||
@ -118,12 +118,17 @@ class CommandDispatcher:
|
||||
tab: Whether to open in a new tab.
|
||||
background: Whether to open in the background.
|
||||
window: Whether to open in a new window
|
||||
private: If opening a new window, open it in private browsing mode.
|
||||
If not given, inherit the current window's mode.
|
||||
"""
|
||||
urlutils.raise_cmdexc_if_invalid(url)
|
||||
tabbed_browser = self._tabbed_browser
|
||||
cmdutils.check_exclusive((tab, background, window), 'tbw')
|
||||
if private is None:
|
||||
private = self._tabbed_browser.private
|
||||
|
||||
if window:
|
||||
tabbed_browser = self._new_tabbed_browser()
|
||||
tabbed_browser = self._new_tabbed_browser(private)
|
||||
tabbed_browser.tabopen(url)
|
||||
elif tab:
|
||||
tabbed_browser.tabopen(url, background=False, explicit=explicit)
|
||||
@ -228,7 +233,8 @@ class CommandDispatcher:
|
||||
@cmdutils.argument('url', completion=usertypes.Completion.url)
|
||||
@cmdutils.argument('count', count=True)
|
||||
def openurl(self, url=None, implicit=False,
|
||||
bg=False, tab=False, window=False, count=None, secure=False):
|
||||
bg=False, tab=False, window=False, count=None, secure=False,
|
||||
private=False):
|
||||
"""Open a URL in the current/[count]th tab.
|
||||
|
||||
If the URL contains newlines, each line gets opened in its own tab.
|
||||
@ -242,12 +248,25 @@ class CommandDispatcher:
|
||||
clicking on a link).
|
||||
count: The tab index to open the URL in, or None.
|
||||
secure: Force HTTPS.
|
||||
private: Open a new window in private browsing mode.
|
||||
"""
|
||||
if url is None:
|
||||
urls = [config.get('general', 'default-page')]
|
||||
else:
|
||||
urls = self._parse_url_input(url)
|
||||
|
||||
if private:
|
||||
try:
|
||||
from PyQt5.QtWebKit import qWebKitVersion
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
# WORKAROUND for https://github.com/annulen/webkit/issues/54
|
||||
if qtutils.is_qtwebkit_ng(qWebKitVersion()):
|
||||
message.warning("Private browsing is not fully "
|
||||
"implemented by QtWebKit-NG!")
|
||||
window = True
|
||||
|
||||
for i, cur_url in enumerate(urls):
|
||||
if secure:
|
||||
cur_url.setScheme('https')
|
||||
@ -255,7 +274,8 @@ class CommandDispatcher:
|
||||
tab = False
|
||||
bg = True
|
||||
if tab or bg or window:
|
||||
self._open(cur_url, tab, bg, window, not implicit)
|
||||
self._open(cur_url, tab, bg, window, explicit=not implicit,
|
||||
private=private)
|
||||
else:
|
||||
curtab = self._cntwidget(count)
|
||||
if curtab is None:
|
||||
@ -430,7 +450,8 @@ class CommandDispatcher:
|
||||
# The new tab could be in a new tabbed_browser (e.g. because of
|
||||
# tabs-are-windows being set)
|
||||
if window:
|
||||
new_tabbed_browser = self._new_tabbed_browser()
|
||||
new_tabbed_browser = self._new_tabbed_browser(
|
||||
private=self._tabbed_browser.private)
|
||||
else:
|
||||
new_tabbed_browser = self._tabbed_browser
|
||||
newtab = new_tabbed_browser.tabopen(background=bg, explicit=True)
|
||||
|
@ -274,8 +274,7 @@ class WebHistory(QObject):
|
||||
(hidden in completion)
|
||||
atime: Override the atime used to add the entry
|
||||
"""
|
||||
if config.get('general', 'private-browsing'):
|
||||
return
|
||||
assert not config.get('general', 'private-browsing')
|
||||
if not url.isValid():
|
||||
log.misc.warning("Ignoring invalid URL being added to history")
|
||||
return
|
||||
|
@ -128,17 +128,19 @@ def prevnext(*, browsertab, win_id, baseurl, prev=False,
|
||||
return
|
||||
qtutils.ensure_valid(url)
|
||||
|
||||
cur_tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||
window=win_id)
|
||||
|
||||
if window:
|
||||
from qutebrowser.mainwindow import mainwindow
|
||||
new_window = mainwindow.MainWindow()
|
||||
new_window = mainwindow.MainWindow(
|
||||
private=cur_tabbed_browser.private)
|
||||
new_window.show()
|
||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||
window=new_window.win_id)
|
||||
tabbed_browser.tabopen(url, background=False)
|
||||
elif tab:
|
||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||
window=win_id)
|
||||
tabbed_browser.tabopen(url, background=background)
|
||||
cur_tabbed_browser.tabopen(url, background=background)
|
||||
else:
|
||||
browsertab.openurl(url)
|
||||
|
||||
|
@ -366,7 +366,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
|
||||
def __init__(self, win_id, parent=None):
|
||||
super().__init__(parent)
|
||||
self._networkmanager = networkmanager.NetworkManager(
|
||||
win_id, None, self)
|
||||
win_id=win_id, tab_id=None, private=False, parent=self)
|
||||
|
||||
@pyqtSlot('QUrl')
|
||||
def get(self, url, *, user_agent=None, **kwargs):
|
||||
|
@ -216,8 +216,10 @@ def get_tab(win_id, target):
|
||||
win_id = win_id
|
||||
bg_tab = True
|
||||
elif target == usertypes.ClickTarget.window:
|
||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||
window=win_id)
|
||||
from qutebrowser.mainwindow import mainwindow
|
||||
window = mainwindow.MainWindow()
|
||||
window = mainwindow.MainWindow(private=tabbed_browser.private)
|
||||
window.show()
|
||||
win_id = window.win_id
|
||||
bg_tab = False
|
||||
|
@ -379,15 +379,16 @@ class AbstractWebElement(collections.abc.MutableMapping):
|
||||
self._click_fake_event(click_target)
|
||||
return
|
||||
|
||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||
window=self._tab.win_id)
|
||||
|
||||
if click_target in [usertypes.ClickTarget.tab,
|
||||
usertypes.ClickTarget.tab_bg]:
|
||||
background = click_target == usertypes.ClickTarget.tab_bg
|
||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||
window=self._tab.win_id)
|
||||
tabbed_browser.tabopen(url, background=background)
|
||||
elif click_target == usertypes.ClickTarget.window:
|
||||
from qutebrowser.mainwindow import mainwindow
|
||||
window = mainwindow.MainWindow()
|
||||
window = mainwindow.MainWindow(private=tabbed_browser.private)
|
||||
window.show()
|
||||
window.tabbed_browser.tabopen(url)
|
||||
else:
|
||||
|
@ -521,9 +521,11 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
|
||||
"""A QtWebEngine tab in the browser."""
|
||||
|
||||
def __init__(self, win_id, mode_manager, parent=None):
|
||||
def __init__(self, *, win_id, mode_manager, private, parent=None):
|
||||
# FIXME
|
||||
assert not private
|
||||
super().__init__(win_id=win_id, mode_manager=mode_manager,
|
||||
parent=parent)
|
||||
private=private, parent=parent)
|
||||
widget = webview.WebEngineView(tabdata=self.data, win_id=win_id)
|
||||
self.history = WebEngineHistory(self)
|
||||
self.scroller = WebEngineScroller(self, parent=self)
|
||||
|
@ -21,8 +21,7 @@
|
||||
|
||||
import os.path
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot
|
||||
from PyQt5.QtNetwork import QNetworkDiskCache, QNetworkCacheMetaData
|
||||
from PyQt5.QtNetwork import QNetworkDiskCache
|
||||
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.utils import utils, objreg, qtutils
|
||||
@ -30,24 +29,21 @@ from qutebrowser.utils import utils, objreg, qtutils
|
||||
|
||||
class DiskCache(QNetworkDiskCache):
|
||||
|
||||
"""Disk cache which sets correct cache dir and size.
|
||||
|
||||
Attributes:
|
||||
_activated: Whether the cache should be used.
|
||||
_cache_dir: The base directory for cache files (standarddir.cache())
|
||||
"""
|
||||
"""Disk cache which sets correct cache dir and size."""
|
||||
|
||||
def __init__(self, cache_dir, parent=None):
|
||||
super().__init__(parent)
|
||||
self._cache_dir = cache_dir
|
||||
self._maybe_activate()
|
||||
objreg.get('config').changed.connect(self.on_config_changed)
|
||||
assert not config.get('general', 'private-browsing')
|
||||
self.setCacheDirectory(os.path.join(cache_dir, 'http'))
|
||||
self._set_cache_size()
|
||||
objreg.get('config').changed.connect(self._set_cache_size)
|
||||
|
||||
def __repr__(self):
|
||||
return utils.get_repr(self, size=self.cacheSize(),
|
||||
maxsize=self.maximumCacheSize(),
|
||||
path=self.cacheDirectory())
|
||||
|
||||
@config.change_filter('storage', 'cache-size')
|
||||
def _set_cache_size(self):
|
||||
"""Set the cache size based on the config."""
|
||||
size = config.get('storage', 'cache-size')
|
||||
@ -58,128 +54,3 @@ class DiskCache(QNetworkDiskCache):
|
||||
not qtutils.version_check('5.9')): # pragma: no cover
|
||||
size = 0
|
||||
self.setMaximumCacheSize(size)
|
||||
|
||||
def _maybe_activate(self):
|
||||
"""Activate/deactivate the cache based on the config."""
|
||||
if config.get('general', 'private-browsing'):
|
||||
self._activated = False
|
||||
else:
|
||||
self._activated = True
|
||||
self.setCacheDirectory(os.path.join(self._cache_dir, 'http'))
|
||||
self._set_cache_size()
|
||||
|
||||
@pyqtSlot(str, str)
|
||||
def on_config_changed(self, section, option):
|
||||
"""Update cache size/activated if the config was changed."""
|
||||
if (section, option) == ('storage', 'cache-size'):
|
||||
self._set_cache_size()
|
||||
elif (section, option) == ('general', # pragma: no branch
|
||||
'private-browsing'):
|
||||
self._maybe_activate()
|
||||
|
||||
def cacheSize(self):
|
||||
"""Return the current size taken up by the cache.
|
||||
|
||||
Return:
|
||||
An int.
|
||||
"""
|
||||
if self._activated:
|
||||
return super().cacheSize()
|
||||
else:
|
||||
return 0
|
||||
|
||||
def fileMetaData(self, filename):
|
||||
"""Return the QNetworkCacheMetaData for the cache file filename.
|
||||
|
||||
Args:
|
||||
filename: The file name as a string.
|
||||
|
||||
Return:
|
||||
A QNetworkCacheMetaData object.
|
||||
"""
|
||||
if self._activated:
|
||||
return super().fileMetaData(filename)
|
||||
else:
|
||||
return QNetworkCacheMetaData()
|
||||
|
||||
def data(self, url):
|
||||
"""Return the data associated with url.
|
||||
|
||||
Args:
|
||||
url: A QUrl.
|
||||
|
||||
return:
|
||||
A QIODevice or None.
|
||||
"""
|
||||
if self._activated:
|
||||
return super().data(url)
|
||||
else:
|
||||
return None
|
||||
|
||||
def insert(self, device):
|
||||
"""Insert the data in device and the prepared meta data into the cache.
|
||||
|
||||
Args:
|
||||
device: A QIODevice.
|
||||
"""
|
||||
if self._activated:
|
||||
super().insert(device)
|
||||
else:
|
||||
return None
|
||||
|
||||
def metaData(self, url):
|
||||
"""Return the meta data for the url url.
|
||||
|
||||
Args:
|
||||
url: A QUrl.
|
||||
|
||||
Return:
|
||||
A QNetworkCacheMetaData object.
|
||||
"""
|
||||
if self._activated:
|
||||
return super().metaData(url)
|
||||
else:
|
||||
return QNetworkCacheMetaData()
|
||||
|
||||
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 self._activated:
|
||||
return super().prepare(meta_data)
|
||||
else:
|
||||
return None
|
||||
|
||||
def remove(self, url):
|
||||
"""Remove the cache entry for url.
|
||||
|
||||
Return:
|
||||
True on success, False otherwise.
|
||||
"""
|
||||
if self._activated:
|
||||
return super().remove(url)
|
||||
else:
|
||||
return False
|
||||
|
||||
def updateMetaData(self, meta_data):
|
||||
"""Update the cache meta date for the meta_data's url to meta_data.
|
||||
|
||||
Args:
|
||||
meta_data: A QNetworkCacheMetaData object.
|
||||
"""
|
||||
if self._activated:
|
||||
super().updateMetaData(meta_data)
|
||||
else:
|
||||
return
|
||||
|
||||
def clear(self):
|
||||
"""Remove all items from the cache."""
|
||||
if self._activated:
|
||||
super().clear()
|
||||
else:
|
||||
return
|
||||
|
@ -128,6 +128,7 @@ class NetworkManager(QNetworkAccessManager):
|
||||
_tab_id: The tab ID this NetworkManager is associated with.
|
||||
_rejected_ssl_errors: A {QUrl: [SslError]} dict of rejected errors.
|
||||
_accepted_ssl_errors: A {QUrl: [SslError]} dict of accepted errors.
|
||||
_private: Whether we're in private browsing mode.
|
||||
|
||||
Signals:
|
||||
shutting_down: Emitted when the QNAM is shutting down.
|
||||
@ -135,7 +136,7 @@ class NetworkManager(QNetworkAccessManager):
|
||||
|
||||
shutting_down = pyqtSignal()
|
||||
|
||||
def __init__(self, win_id, tab_id, parent=None):
|
||||
def __init__(self, *, win_id, tab_id, private, parent=None):
|
||||
log.init.debug("Initializing NetworkManager")
|
||||
with log.disable_qt_msghandler():
|
||||
# WORKAROUND for a hang when a message is printed - See:
|
||||
@ -146,11 +147,12 @@ class NetworkManager(QNetworkAccessManager):
|
||||
self._win_id = win_id
|
||||
self._tab_id = tab_id
|
||||
self._requests = []
|
||||
self._private = private
|
||||
self._scheme_handlers = {
|
||||
'qute': webkitqutescheme.QuteSchemeHandler(win_id),
|
||||
'file': filescheme.FileSchemeHandler(win_id),
|
||||
}
|
||||
self._set_cookiejar(private=config.get('general', 'private-browsing'))
|
||||
self._set_cookiejar()
|
||||
self._set_cache()
|
||||
self.sslErrors.connect(self.on_ssl_errors)
|
||||
self._rejected_ssl_errors = collections.defaultdict(list)
|
||||
@ -158,15 +160,10 @@ class NetworkManager(QNetworkAccessManager):
|
||||
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:
|
||||
def _set_cookiejar(self):
|
||||
"""Set the cookie jar of the NetworkManager correctly."""
|
||||
if self._private:
|
||||
cookie_jar = objreg.get('ram-cookie-jar')
|
||||
else:
|
||||
cookie_jar = objreg.get('cookie-jar')
|
||||
@ -178,11 +175,9 @@ class NetworkManager(QNetworkAccessManager):
|
||||
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.
|
||||
"""
|
||||
"""Set the cache of the NetworkManager correctly."""
|
||||
if self._private:
|
||||
return
|
||||
# We have a shared cache - we restore its parent so we don't take
|
||||
# ownership of it.
|
||||
app = QCoreApplication.instance()
|
||||
@ -324,17 +319,6 @@ class NetworkManager(QNetworkAccessManager):
|
||||
authenticator.setPassword(answer.password)
|
||||
_proxy_auth_cache[proxy_id] = 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()
|
||||
|
||||
@pyqtSlot()
|
||||
def on_adopted_download_destroyed(self):
|
||||
"""Check if we can clean up if an adopted download was destroyed.
|
||||
|
@ -89,20 +89,19 @@ def _set_user_stylesheet():
|
||||
|
||||
|
||||
def _init_private_browsing():
|
||||
if config.get('general', 'private-browsing'):
|
||||
if qtutils.is_qtwebkit_ng():
|
||||
message.warning("Private browsing is not fully implemented by "
|
||||
"QtWebKit-NG!")
|
||||
# WORKAROUND for https://github.com/annulen/webkit/issues/54
|
||||
message.warning("Private browsing is not fully implemented by QtWebKit-NG!")
|
||||
elif not qtutils.version_check('5.4.2'):
|
||||
# WORKAROUND for https://codereview.qt-project.org/#/c/108936/
|
||||
# Won't work when private browsing is not enabled globally, but that's
|
||||
# the best we can do...
|
||||
QWebSettings.setIconDatabasePath('')
|
||||
else:
|
||||
QWebSettings.setIconDatabasePath(standarddir.cache())
|
||||
|
||||
|
||||
def update_settings(section, option):
|
||||
"""Update global settings when qwebsettings changed."""
|
||||
if (section, option) == ('general', 'private-browsing'):
|
||||
_init_private_browsing()
|
||||
elif section == 'ui' and option in ['hide-scrollbar', 'user-stylesheet']:
|
||||
if section == 'ui' and option in ['hide-scrollbar', 'user-stylesheet']:
|
||||
_set_user_stylesheet()
|
||||
|
||||
websettings.update_mappings(MAPPINGS, section, option)
|
||||
@ -113,8 +112,7 @@ def init(_args):
|
||||
cache_path = standarddir.cache()
|
||||
data_path = standarddir.data()
|
||||
|
||||
_init_private_browsing()
|
||||
|
||||
QWebSettings.setIconDatabasePath(standarddir.cache())
|
||||
QWebSettings.setOfflineWebApplicationCachePath(
|
||||
os.path.join(cache_path, 'application-cache'))
|
||||
QWebSettings.globalSettings().setLocalStoragePath(
|
||||
@ -122,6 +120,9 @@ def init(_args):
|
||||
QWebSettings.setOfflineStoragePath(
|
||||
os.path.join(data_path, 'offline-storage'))
|
||||
|
||||
if config.get('general', 'private-browsing'):
|
||||
_init_private_browsing()
|
||||
|
||||
websettings.init_mappings(MAPPINGS)
|
||||
_set_user_stylesheet()
|
||||
objreg.get('config').changed.connect(update_settings)
|
||||
@ -254,8 +255,6 @@ MAPPINGS = {
|
||||
setter=QWebSettings.setOfflineWebApplicationCacheQuota),
|
||||
},
|
||||
'general': {
|
||||
'private-browsing':
|
||||
Attribute(QWebSettings.PrivateBrowsingEnabled),
|
||||
'developer-extras':
|
||||
Attribute(QWebSettings.DeveloperExtrasEnabled),
|
||||
'print-element-backgrounds':
|
||||
|
@ -629,10 +629,13 @@ class WebKitTab(browsertab.AbstractTab):
|
||||
|
||||
"""A QtWebKit tab in the browser."""
|
||||
|
||||
def __init__(self, win_id, mode_manager, parent=None):
|
||||
def __init__(self, *, win_id, mode_manager, private, parent=None):
|
||||
super().__init__(win_id=win_id, mode_manager=mode_manager,
|
||||
parent=parent)
|
||||
widget = webview.WebView(win_id, self.tab_id, tab=self)
|
||||
private=private, parent=parent)
|
||||
widget = webview.WebView(win_id=win_id, tab_id=self.tab_id,
|
||||
private=private, tab=self)
|
||||
if private:
|
||||
self._make_private(widget)
|
||||
self.history = WebKitHistory(self)
|
||||
self.scroller = WebKitScroller(self, parent=self)
|
||||
self.caret = WebKitCaret(win_id=win_id, mode_manager=mode_manager,
|
||||
@ -649,6 +652,10 @@ class WebKitTab(browsertab.AbstractTab):
|
||||
def _install_event_filter(self):
|
||||
self._widget.installEventFilter(self._mouse_event_filter)
|
||||
|
||||
def _make_private(self, widget):
|
||||
settings = widget.settings()
|
||||
settings.setAttribute(QWebSettings.PrivateBrowsingEnabled, True)
|
||||
|
||||
def openurl(self, url):
|
||||
self._openurl_prepare(url)
|
||||
self._widget.openurl(url)
|
||||
|
@ -59,7 +59,7 @@ class BrowserPage(QWebPage):
|
||||
shutting_down = pyqtSignal()
|
||||
reloading = pyqtSignal(QUrl)
|
||||
|
||||
def __init__(self, win_id, tab_id, tabdata, parent=None):
|
||||
def __init__(self, win_id, tab_id, tabdata, private, parent=None):
|
||||
super().__init__(parent)
|
||||
self._win_id = win_id
|
||||
self._tabdata = tabdata
|
||||
@ -72,7 +72,7 @@ class BrowserPage(QWebPage):
|
||||
self.error_occurred = False
|
||||
self.open_target = usertypes.ClickTarget.normal
|
||||
self._networkmanager = networkmanager.NetworkManager(
|
||||
win_id, tab_id, self)
|
||||
win_id=win_id, tab_id=tab_id, private=private, parent=self)
|
||||
self.setNetworkAccessManager(self._networkmanager)
|
||||
self.setForwardUnsupportedContent(True)
|
||||
self.reloading.connect(self._networkmanager.clear_rejected_ssl_errors)
|
||||
|
@ -55,7 +55,7 @@ class WebView(QWebView):
|
||||
scroll_pos_changed = pyqtSignal(int, int)
|
||||
shutting_down = pyqtSignal()
|
||||
|
||||
def __init__(self, win_id, tab_id, tab, parent=None):
|
||||
def __init__(self, *, win_id, tab_id, tab, private, parent=None):
|
||||
super().__init__(parent)
|
||||
if sys.platform == 'darwin' and qtutils.version_check('5.4'):
|
||||
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-42948
|
||||
@ -71,7 +71,8 @@ class WebView(QWebView):
|
||||
self._set_bg_color()
|
||||
self._tab_id = tab_id
|
||||
|
||||
page = webpage.BrowserPage(self.win_id, self._tab_id, tab.data,
|
||||
page = webpage.BrowserPage(win_id=self.win_id, tab_id=self._tab_id,
|
||||
tabdata=tab.data, private=private,
|
||||
parent=self)
|
||||
|
||||
try:
|
||||
|
@ -1125,6 +1125,14 @@ def data(readonly=False):
|
||||
SettingValue(typ.QssColor(), 'black'),
|
||||
"Background color of the statusbar."),
|
||||
|
||||
('statusbar.fg.private',
|
||||
SettingValue(typ.QssColor(), '${statusbar.fg}'),
|
||||
"Foreground color of the statusbar in private browsing mode."),
|
||||
|
||||
('statusbar.bg.private',
|
||||
SettingValue(typ.QssColor(), 'grey'), # FIXME darker color
|
||||
"Background color of the statusbar in private browsing mode."),
|
||||
|
||||
('statusbar.fg.insert',
|
||||
SettingValue(typ.QssColor(), '${statusbar.fg}'),
|
||||
"Foreground color of the statusbar in insert mode."),
|
||||
|
@ -81,7 +81,7 @@ def get_window(via_ipc, force_window=False, force_tab=False,
|
||||
|
||||
# Otherwise, or if no window was found, create a new one
|
||||
if window is None:
|
||||
window = MainWindow()
|
||||
window = MainWindow(private=None)
|
||||
window.show()
|
||||
raise_window = True
|
||||
|
||||
@ -127,13 +127,15 @@ class MainWindow(QWidget):
|
||||
_vbox: The main QVBoxLayout.
|
||||
_commandrunner: The main CommandRunner instance.
|
||||
_overlays: Widgets shown as overlay for the current webpage.
|
||||
_private: Whether the window is in private browsing mode.
|
||||
"""
|
||||
|
||||
def __init__(self, geometry=None, parent=None):
|
||||
def __init__(self, *, private, geometry=None, parent=None):
|
||||
"""Create a new main window.
|
||||
|
||||
Args:
|
||||
geometry: The geometry to load, as a bytes-object (or None).
|
||||
private: Whether the window is in private browsing mode.
|
||||
parent: The parent the window should get.
|
||||
"""
|
||||
super().__init__(parent)
|
||||
@ -161,7 +163,14 @@ class MainWindow(QWidget):
|
||||
self._init_downloadmanager()
|
||||
self._downloadview = downloadview.DownloadView(self.win_id)
|
||||
|
||||
self.tabbed_browser = tabbedbrowser.TabbedBrowser(self.win_id)
|
||||
if config.get('general', 'private-browsing'):
|
||||
# This setting always trumps what's passed in.
|
||||
private = True
|
||||
else:
|
||||
private = bool(private)
|
||||
self._private = private
|
||||
self.tabbed_browser = tabbedbrowser.TabbedBrowser(win_id=self.win_id,
|
||||
private=private)
|
||||
objreg.register('tabbed-browser', self.tabbed_browser, scope='window',
|
||||
window=self.win_id)
|
||||
self._init_command_dispatcher()
|
||||
@ -169,7 +178,8 @@ class MainWindow(QWidget):
|
||||
# We need to set an explicit parent for StatusBar because it does some
|
||||
# show/hide magic immediately which would mean it'd show up as a
|
||||
# window.
|
||||
self.status = bar.StatusBar(self.win_id, parent=self)
|
||||
self.status = bar.StatusBar(win_id=self.win_id, private=private,
|
||||
parent=self)
|
||||
|
||||
self._add_widgets()
|
||||
self._downloadview.show()
|
||||
@ -446,17 +456,15 @@ class MainWindow(QWidget):
|
||||
message_bridge.s_maybe_reset_text.connect(status.txt.maybe_reset_text)
|
||||
|
||||
# statusbar
|
||||
tabs.current_tab_changed.connect(status.prog.on_tab_changed)
|
||||
tabs.current_tab_changed.connect(status.on_tab_changed)
|
||||
|
||||
tabs.cur_progress.connect(status.prog.setValue)
|
||||
tabs.cur_load_finished.connect(status.prog.hide)
|
||||
tabs.cur_load_started.connect(status.prog.on_load_started)
|
||||
|
||||
tabs.current_tab_changed.connect(status.percentage.on_tab_changed)
|
||||
tabs.cur_scroll_perc_changed.connect(status.percentage.set_perc)
|
||||
|
||||
tabs.tab_index_changed.connect(status.tabindex.on_tab_index_changed)
|
||||
|
||||
tabs.current_tab_changed.connect(status.url.on_tab_changed)
|
||||
tabs.cur_url_changed.connect(status.url.set_url)
|
||||
tabs.cur_link_hovered.connect(status.url.set_hover_url)
|
||||
tabs.cur_load_status_changed.connect(status.url.on_load_status_changed)
|
||||
|
@ -22,6 +22,7 @@
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty, Qt, QSize, QTimer
|
||||
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QStackedLayout, QSizePolicy
|
||||
|
||||
from qutebrowser.browser import browsertab
|
||||
from qutebrowser.config import config, style
|
||||
from qutebrowser.utils import usertypes, log, objreg, utils
|
||||
from qutebrowser.mainwindow.statusbar import (command, progress, keystring,
|
||||
@ -70,6 +71,11 @@ class StatusBar(QWidget):
|
||||
For some reason we need to have this as class attribute
|
||||
so pyqtProperty works correctly.
|
||||
|
||||
_private: Whether we're in private browsing mode.
|
||||
|
||||
For some reason we need to have this as class attribute
|
||||
so pyqtProperty works correctly.
|
||||
|
||||
Signals:
|
||||
resized: Emitted when the statusbar has resized, so the completion
|
||||
widget can adjust its size to it.
|
||||
@ -86,6 +92,7 @@ class StatusBar(QWidget):
|
||||
_insert_active = False
|
||||
_command_active = False
|
||||
_caret_mode = CaretMode.off
|
||||
_private = False
|
||||
|
||||
STYLESHEET = """
|
||||
|
||||
@ -97,6 +104,13 @@ class StatusBar(QWidget):
|
||||
color: {{ color['statusbar.fg'] }};
|
||||
}
|
||||
|
||||
QWidget#StatusBar[private="true"],
|
||||
QWidget#StatusBar[private="true"] QLabel,
|
||||
QWidget#StatusBar[private="true"] QLineEdit {
|
||||
color: {{ color['statusbar.fg.private'] }};
|
||||
background-color: {{ color['statusbar.bg.private'] }};
|
||||
}
|
||||
|
||||
QWidget#StatusBar[caret_mode="on"],
|
||||
QWidget#StatusBar[caret_mode="on"] QLabel,
|
||||
QWidget#StatusBar[caret_mode="on"] QLineEdit {
|
||||
@ -134,7 +148,7 @@ class StatusBar(QWidget):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, win_id, parent=None):
|
||||
def __init__(self, *, win_id, private, parent=None):
|
||||
super().__init__(parent)
|
||||
objreg.register('statusbar', self, scope='window', window=win_id)
|
||||
self.setObjectName(self.__class__.__name__)
|
||||
@ -146,6 +160,7 @@ class StatusBar(QWidget):
|
||||
self._win_id = win_id
|
||||
self._option = None
|
||||
self._page_fullscreen = False
|
||||
self._private = private
|
||||
|
||||
self._hbox = QHBoxLayout(self)
|
||||
self.set_hbox_padding()
|
||||
@ -156,7 +171,7 @@ class StatusBar(QWidget):
|
||||
self._hbox.addLayout(self._stack)
|
||||
self._stack.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.cmd = command.Command(win_id)
|
||||
self.cmd = command.Command(private=private, win_id=win_id)
|
||||
self._stack.addWidget(self.cmd)
|
||||
objreg.register('status-command', self.cmd, scope='window',
|
||||
window=win_id)
|
||||
@ -226,6 +241,11 @@ class StatusBar(QWidget):
|
||||
"""Getter for self._caret_mode, so it can be used as Qt property."""
|
||||
return self._caret_mode.name
|
||||
|
||||
@pyqtProperty(bool)
|
||||
def private(self):
|
||||
"""Getter for self.private so it can be used as Qt property."""
|
||||
return self._private
|
||||
|
||||
def set_mode_active(self, mode, val):
|
||||
"""Setter for self.{insert,command,caret}_active.
|
||||
|
||||
@ -314,6 +334,13 @@ class StatusBar(QWidget):
|
||||
self._page_fullscreen = on
|
||||
self.maybe_hide()
|
||||
|
||||
@pyqtSlot(browsertab.AbstractTab)
|
||||
def on_tab_changed(self, tab):
|
||||
self.url.on_tab_changed(tab)
|
||||
self.prog.on_tab_changed(tab)
|
||||
self.percentage.on_tab_changed(tab)
|
||||
assert tab.private == self._private
|
||||
|
||||
def resizeEvent(self, e):
|
||||
"""Extend resizeEvent of QWidget to emit a resized signal afterwards.
|
||||
|
||||
|
@ -54,12 +54,11 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
||||
show_cmd = pyqtSignal()
|
||||
hide_cmd = pyqtSignal()
|
||||
|
||||
def __init__(self, win_id, parent=None):
|
||||
misc.CommandLineEdit.__init__(self, parent)
|
||||
def __init__(self, *, win_id, private, parent=None):
|
||||
misc.CommandLineEdit.__init__(self, private=private, parent=parent)
|
||||
misc.MinimalLineEditMixin.__init__(self)
|
||||
self._win_id = win_id
|
||||
command_history = objreg.get('command-history')
|
||||
self.history.handle_private_mode = True
|
||||
self.history.history = command_history.data
|
||||
self.history.changed.connect(command_history.changed)
|
||||
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored)
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot
|
||||
|
||||
from qutebrowser.browser import browsertab
|
||||
from qutebrowser.mainwindow.statusbar import textbase
|
||||
|
||||
|
||||
@ -51,7 +50,6 @@ class Percentage(textbase.TextBase):
|
||||
else:
|
||||
self.setText('[{:2}%]'.format(y))
|
||||
|
||||
@pyqtSlot(browsertab.AbstractTab)
|
||||
def on_tab_changed(self, tab):
|
||||
"""Update scroll position when tab changed."""
|
||||
self.set_perc(*tab.scroller.pos_perc())
|
||||
|
@ -22,7 +22,6 @@
|
||||
from PyQt5.QtCore import pyqtSlot, QSize
|
||||
from PyQt5.QtWidgets import QProgressBar, QSizePolicy
|
||||
|
||||
from qutebrowser.browser import browsertab
|
||||
from qutebrowser.config import style
|
||||
from qutebrowser.utils import utils, usertypes
|
||||
|
||||
@ -60,7 +59,6 @@ class Progress(QProgressBar):
|
||||
self.setValue(0)
|
||||
self.show()
|
||||
|
||||
@pyqtSlot(browsertab.AbstractTab)
|
||||
def on_tab_changed(self, tab):
|
||||
"""Set the correct value when the current tab changed."""
|
||||
if self is None: # pragma: no branch
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, pyqtProperty, Qt, QUrl
|
||||
|
||||
from qutebrowser.browser import browsertab
|
||||
from qutebrowser.mainwindow.statusbar import textbase
|
||||
from qutebrowser.config import style
|
||||
from qutebrowser.utils import usertypes, urlutils
|
||||
@ -165,7 +164,6 @@ class UrlText(textbase.TextBase):
|
||||
self._hover_url = None
|
||||
self._update_url()
|
||||
|
||||
@pyqtSlot(browsertab.AbstractTab)
|
||||
def on_tab_changed(self, tab):
|
||||
"""Update URL if the tab changed."""
|
||||
self._hover_url = None
|
||||
|
@ -68,6 +68,7 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
_local_marks: Jump markers local to each page
|
||||
_global_marks: Jump markers used across all pages
|
||||
default_window_icon: The qutebrowser window icon
|
||||
private: Whether private browsing is on for this window.
|
||||
|
||||
Signals:
|
||||
cur_progress: Progress of the current tab changed (load_progress).
|
||||
@ -100,7 +101,7 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
new_tab = pyqtSignal(browsertab.AbstractTab, int)
|
||||
page_fullscreen_requested = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, win_id, parent=None):
|
||||
def __init__(self, *, win_id, private, parent=None):
|
||||
super().__init__(win_id, parent)
|
||||
self._win_id = win_id
|
||||
self._tab_insert_idx_left = 0
|
||||
@ -118,6 +119,7 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
self._local_marks = {}
|
||||
self._global_marks = {}
|
||||
self.default_window_icon = self.window().windowIcon()
|
||||
self.private = private
|
||||
objreg.get('config').changed.connect(self.update_favicons)
|
||||
objreg.get('config').changed.connect(self.update_window_title)
|
||||
objreg.get('config').changed.connect(self.update_tab_titles)
|
||||
@ -205,7 +207,9 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
tab.renderer_process_terminated.connect(
|
||||
functools.partial(self._on_renderer_process_terminated, tab))
|
||||
tab.new_tab_requested.connect(self.tabopen)
|
||||
tab.add_history_item.connect(objreg.get('web-history').add_from_tab)
|
||||
if not self.private:
|
||||
web_history = objreg.get('web-history')
|
||||
tab.add_history_item.connect(web_history.add_from_tab)
|
||||
tab.fullscreen_requested.connect(self.page_fullscreen_requested)
|
||||
tab.fullscreen_requested.connect(
|
||||
self.tabBar().on_page_fullscreen_requested)
|
||||
@ -399,13 +403,14 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
if (config.get('tabs', 'tabs-are-windows') and self.count() > 0 and
|
||||
not ignore_tabs_are_windows):
|
||||
from qutebrowser.mainwindow import mainwindow
|
||||
window = mainwindow.MainWindow()
|
||||
window = mainwindow.MainWindow(private=self.private)
|
||||
window.show()
|
||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||
window=window.win_id)
|
||||
return tabbed_browser.tabopen(url, background, explicit)
|
||||
|
||||
tab = browsertab.create(win_id=self._win_id, parent=self)
|
||||
tab = browsertab.create(win_id=self._win_id, private=self.private,
|
||||
parent=self)
|
||||
self._connect_tab_signals(tab)
|
||||
|
||||
if idx is None:
|
||||
|
@ -44,9 +44,9 @@ class History(QObject):
|
||||
"""Command history.
|
||||
|
||||
Attributes:
|
||||
handle_private_mode: Whether to ignore history in private mode.
|
||||
history: A list of executed commands, with newer commands at the end.
|
||||
_tmphist: Temporary history for history browsing (as NeighborList)
|
||||
_private: Whether this history is in private browsing mode.
|
||||
|
||||
Signals:
|
||||
changed: Emitted when an entry was added to the history.
|
||||
@ -54,15 +54,15 @@ class History(QObject):
|
||||
|
||||
changed = pyqtSignal()
|
||||
|
||||
def __init__(self, history=None, parent=None):
|
||||
def __init__(self, *, private=False, history=None, parent=None):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
history: The initial history to set.
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self.handle_private_mode = False
|
||||
self._tmphist = None
|
||||
self._private = private
|
||||
if history is None:
|
||||
self.history = []
|
||||
else:
|
||||
@ -129,8 +129,7 @@ class History(QObject):
|
||||
Args:
|
||||
text: The text to append.
|
||||
"""
|
||||
if (self.handle_private_mode and
|
||||
config.get('general', 'private-browsing')):
|
||||
if self._private:
|
||||
return
|
||||
if not self.history or text != self.history[-1]:
|
||||
self.history.append(text)
|
||||
|
@ -50,7 +50,7 @@ class ConsoleLineEdit(miscwidgets.CommandLineEdit):
|
||||
Args:
|
||||
_namespace: The local namespace of the interpreter.
|
||||
"""
|
||||
super().__init__(parent)
|
||||
super().__init__(parent=parent)
|
||||
self.update_font()
|
||||
objreg.get('config').changed.connect(self.update_font)
|
||||
self._history = cmdhistory.History(parent=self)
|
||||
|
@ -69,9 +69,9 @@ class CommandLineEdit(QLineEdit):
|
||||
_promptlen: The length of the current prompt.
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, *, private=False, parent=None):
|
||||
super().__init__(parent)
|
||||
self.history = cmdhistory.History(parent=self)
|
||||
self.history = cmdhistory.History(private=private, parent=self)
|
||||
self._validator = _CommandValidator(self)
|
||||
self.setValidator(self._validator)
|
||||
self.textEdited.connect(self.on_text_edited)
|
||||
|
@ -379,7 +379,8 @@ class SessionManager(QObject):
|
||||
raise SessionError(e)
|
||||
log.sessions.debug("Loading session {} from {}...".format(name, path))
|
||||
for win in data['windows']:
|
||||
window = mainwindow.MainWindow(geometry=win['geometry'])
|
||||
window = mainwindow.MainWindow(geometry=win['geometry'],
|
||||
private=win.get('private', False))
|
||||
window.show()
|
||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||
window=window.win_id)
|
||||
|
@ -146,7 +146,7 @@ def test_previtem_index_error(hist):
|
||||
|
||||
def test_append_private_mode(hist, config_stub):
|
||||
"""Test append in private mode."""
|
||||
hist.handle_private_mode = True
|
||||
hist._private = True
|
||||
# We want general.private-browsing set to True
|
||||
config_stub.data = CONFIG_PRIVATE
|
||||
hist.append('new item')
|
||||
|
Loading…
Reference in New Issue
Block a user