Merge branch 'perdomainstylesheets' of https://github.com/jcjordyn130/qutebrowser into jcjordyn130/perdomainstylesheets
This commit is contained in:
commit
6313a74423
@ -25,7 +25,7 @@ import netrc
|
|||||||
|
|
||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QUrl
|
||||||
|
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config, configutils
|
||||||
from qutebrowser.utils import usertypes, message, log, objreg, jinja, utils
|
from qutebrowser.utils import usertypes, message, log, objreg, jinja, utils
|
||||||
from qutebrowser.mainwindow import mainwindow
|
from qutebrowser.mainwindow import mainwindow
|
||||||
|
|
||||||
@ -273,20 +273,31 @@ def get_tab(win_id, target):
|
|||||||
return tabbed_browser.tabopen(url=None, background=bg_tab)
|
return tabbed_browser.tabopen(url=None, background=bg_tab)
|
||||||
|
|
||||||
|
|
||||||
def get_user_stylesheet(searching=False):
|
def _wrap_bar(css: str, searching: bool):
|
||||||
"""Get the combined user-stylesheet."""
|
"""Wrap the passed css in a bar if needed, depending on settings."""
|
||||||
|
if css is not configutils.UNSET and \
|
||||||
|
(config.val.scrolling.bar == 'never' or
|
||||||
|
config.val.scrolling.bar == 'when-searching' and not searching):
|
||||||
|
css += '\nhtml > ::-webkit-scrollbar { width: 0px; height: 0px; }'
|
||||||
|
return css
|
||||||
|
|
||||||
|
def get_user_stylesheet(searching=False, url=None):
|
||||||
|
"""Get the combined user-stylesheet.
|
||||||
|
|
||||||
|
If `url` is given and there's no overridden stylesheet, return
|
||||||
|
`configutils.UNSET`.
|
||||||
|
"""
|
||||||
css = ''
|
css = ''
|
||||||
stylesheets = config.val.content.user_stylesheets
|
stylesheets = config.instance.get('content.user_stylesheets', url,
|
||||||
|
fallback=url is None)
|
||||||
|
if stylesheets is configutils.UNSET:
|
||||||
|
return _wrap_bar(stylesheets, searching)
|
||||||
|
|
||||||
for filename in stylesheets:
|
for filename in stylesheets:
|
||||||
with open(filename, 'r', encoding='utf-8') as f:
|
with open(filename, 'r', encoding='utf-8') as f:
|
||||||
css += f.read()
|
css += f.read()
|
||||||
|
|
||||||
if (config.val.scrolling.bar == 'never' or
|
return _wrap_bar(css, searching)
|
||||||
config.val.scrolling.bar == 'when-searching' and not searching):
|
|
||||||
css += '\nhtml > ::-webkit-scrollbar { width: 0px; height: 0px; }'
|
|
||||||
|
|
||||||
return css
|
|
||||||
|
|
||||||
|
|
||||||
def netrc_authentication(url, authenticator):
|
def netrc_authentication(url, authenticator):
|
||||||
|
@ -31,7 +31,7 @@ from PyQt5.QtNetwork import QAuthenticator
|
|||||||
from PyQt5.QtWidgets import QApplication
|
from PyQt5.QtWidgets import QApplication
|
||||||
from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineScript
|
from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineScript
|
||||||
|
|
||||||
from qutebrowser.config import configdata, config
|
from qutebrowser.config import configdata, config, configutils
|
||||||
from qutebrowser.browser import browsertab, mouse, shared, webelem
|
from qutebrowser.browser import browsertab, mouse, shared, webelem
|
||||||
from qutebrowser.browser.webengine import (webview, webengineelem, tabhistory,
|
from qutebrowser.browser.webengine import (webview, webengineelem, tabhistory,
|
||||||
interceptor, webenginequtescheme,
|
interceptor, webenginequtescheme,
|
||||||
@ -863,21 +863,41 @@ class _WebEngineScripts(QObject):
|
|||||||
def connect_signals(self):
|
def connect_signals(self):
|
||||||
"""Connect signals to our private slots."""
|
"""Connect signals to our private slots."""
|
||||||
config.instance.changed.connect(self._on_config_changed)
|
config.instance.changed.connect(self._on_config_changed)
|
||||||
|
self._tab.url_changed.connect(self._update_stylesheet)
|
||||||
|
self._tab.load_finished.connect(self._on_load_finished)
|
||||||
|
|
||||||
self._tab.search.cleared.connect(functools.partial(
|
self._tab.search.cleared.connect(
|
||||||
self._update_stylesheet, searching=False))
|
lambda: self._update_stylesheet(self._tab.url(), searching=False, force=True))
|
||||||
self._tab.search.finished.connect(self._update_stylesheet)
|
self._tab.search.finished.connect(
|
||||||
|
lambda found: self._update_stylesheet(self._tab.url(), searching=found, force=True))
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def _on_config_changed(self, option):
|
def _on_config_changed(self, option):
|
||||||
if option in ['scrolling.bar', 'content.user_stylesheets']:
|
if option in ['scrolling.bar', 'content.user_stylesheets']:
|
||||||
self._init_stylesheet()
|
self._init_stylesheet()
|
||||||
self._update_stylesheet()
|
self._update_stylesheet(self._tab.url(), force=True)
|
||||||
|
|
||||||
@pyqtSlot(bool)
|
@pyqtSlot()
|
||||||
def _update_stylesheet(self, searching=False):
|
def _on_load_finished(self, searching=False):
|
||||||
"""Update the custom stylesheet in existing tabs."""
|
url = self._tab.url()
|
||||||
css = shared.get_user_stylesheet(searching=searching)
|
self._update_stylesheet(url, searching=searching)
|
||||||
|
|
||||||
|
@pyqtSlot(QUrl)
|
||||||
|
def _update_stylesheet(self, url, searching=False, force=False):
|
||||||
|
"""Update the custom stylesheet in existing tabs.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
url: The url to get the stylesheet for.
|
||||||
|
force: Also update the global stylesheet.
|
||||||
|
"""
|
||||||
|
if not url.isValid():
|
||||||
|
# FIXME should we be dropping this request completely?
|
||||||
|
url = None
|
||||||
|
css = shared.get_user_stylesheet(searching=searching, url=url)
|
||||||
|
if css is configutils.UNSET and force:
|
||||||
|
css = shared.get_user_stylesheet(searching=searching, url=None)
|
||||||
|
|
||||||
|
if css is not configutils.UNSET:
|
||||||
code = javascript.assemble('stylesheet', 'set_css', css)
|
code = javascript.assemble('stylesheet', 'set_css', css)
|
||||||
self._tab.run_js_async(code)
|
self._tab.run_js_async(code)
|
||||||
|
|
||||||
@ -952,7 +972,7 @@ class _WebEngineScripts(QObject):
|
|||||||
https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/app/mainapplication.cpp#L1063-L1101
|
https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/app/mainapplication.cpp#L1063-L1101
|
||||||
"""
|
"""
|
||||||
self._remove_early_js('stylesheet')
|
self._remove_early_js('stylesheet')
|
||||||
css = shared.get_user_stylesheet()
|
css = shared.get_user_stylesheet(url=None)
|
||||||
js_code = javascript.wrap_global(
|
js_code = javascript.wrap_global(
|
||||||
'stylesheet',
|
'stylesheet',
|
||||||
utils.read_file('javascript/stylesheet.js'),
|
utils.read_file('javascript/stylesheet.js'),
|
||||||
|
@ -29,7 +29,7 @@ import os.path
|
|||||||
from PyQt5.QtGui import QFont
|
from PyQt5.QtGui import QFont
|
||||||
from PyQt5.QtWebKit import QWebSettings
|
from PyQt5.QtWebKit import QWebSettings
|
||||||
|
|
||||||
from qutebrowser.config import config, websettings
|
from qutebrowser.config import config, websettings, configutils
|
||||||
from qutebrowser.config.websettings import AttributeInfo as Attr
|
from qutebrowser.config.websettings import AttributeInfo as Attr
|
||||||
from qutebrowser.utils import standarddir, urlutils
|
from qutebrowser.utils import standarddir, urlutils
|
||||||
from qutebrowser.browser import shared
|
from qutebrowser.browser import shared
|
||||||
@ -120,15 +120,16 @@ class WebKitSettings(websettings.AbstractSettings):
|
|||||||
QWebSettings.FantasyFont: QFont.Fantasy,
|
QWebSettings.FantasyFont: QFont.Fantasy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _set_user_stylesheet(self, url=None):
|
||||||
def _set_user_stylesheet(settings):
|
|
||||||
"""Set the generated user-stylesheet."""
|
"""Set the generated user-stylesheet."""
|
||||||
stylesheet = shared.get_user_stylesheet().encode('utf-8')
|
stylesheet = shared.get_user_stylesheet(url=url)
|
||||||
url = urlutils.data_url('text/css;charset=utf-8', stylesheet)
|
if stylesheet is configutils.UNSET:
|
||||||
settings.setUserStyleSheetUrl(url)
|
return
|
||||||
|
url = urlutils.data_url('text/css;charset=utf-8',
|
||||||
|
stylesheet.encode('utf-8'))
|
||||||
|
self._settings.setUserStyleSheetUrl(url)
|
||||||
|
|
||||||
|
def _set_cookie_accept_policy(self):
|
||||||
def _set_cookie_accept_policy(settings):
|
|
||||||
"""Update the content.cookies.accept setting."""
|
"""Update the content.cookies.accept setting."""
|
||||||
mapping = {
|
mapping = {
|
||||||
'all': QWebSettings.AlwaysAllowThirdPartyCookies,
|
'all': QWebSettings.AlwaysAllowThirdPartyCookies,
|
||||||
@ -137,26 +138,32 @@ def _set_cookie_accept_policy(settings):
|
|||||||
'no-unknown-3rdparty': QWebSettings.AllowThirdPartyWithExistingCookies,
|
'no-unknown-3rdparty': QWebSettings.AllowThirdPartyWithExistingCookies,
|
||||||
}
|
}
|
||||||
value = config.val.content.cookies.accept
|
value = config.val.content.cookies.accept
|
||||||
settings.setThirdPartyCookiePolicy(mapping[value])
|
self._settings.setThirdPartyCookiePolicy(mapping[value])
|
||||||
|
|
||||||
|
def _set_cache_maximum_pages(self):
|
||||||
def _set_cache_maximum_pages(settings):
|
|
||||||
"""Update the content.cache.maximum_pages setting."""
|
"""Update the content.cache.maximum_pages setting."""
|
||||||
value = config.val.content.cache.maximum_pages
|
value = config.val.content.cache.maximum_pages
|
||||||
settings.setMaximumPagesInCache(value)
|
self._settings.setMaximumPagesInCache(value)
|
||||||
|
|
||||||
|
def update_setting(self, option):
|
||||||
def _update_settings(option):
|
|
||||||
"""Update global settings when qwebsettings changed."""
|
|
||||||
global_settings.update_setting(option)
|
|
||||||
|
|
||||||
settings = QWebSettings.globalSettings()
|
|
||||||
if option in ['scrollbar.hide', 'content.user_stylesheets']:
|
if option in ['scrollbar.hide', 'content.user_stylesheets']:
|
||||||
_set_user_stylesheet(settings)
|
self._set_user_stylesheet()
|
||||||
elif option == 'content.cookies.accept':
|
elif option == 'content.cookies.accept':
|
||||||
_set_cookie_accept_policy(settings)
|
self._set_cookie_accept_policy()
|
||||||
elif option == 'content.cache.maximum_pages':
|
elif option == 'content.cache.maximum_pages':
|
||||||
_set_cache_maximum_pages(settings)
|
self._set_cache_maximum_pages()
|
||||||
|
else:
|
||||||
|
super().update_setting(option)
|
||||||
|
|
||||||
|
def update_for_url(self, url):
|
||||||
|
super().update_for_url(url)
|
||||||
|
self._set_user_stylesheet(url)
|
||||||
|
|
||||||
|
def init_settings(self):
|
||||||
|
super().init_settings()
|
||||||
|
self._set_user_stylesheet()
|
||||||
|
self._set_cookie_accept_policy()
|
||||||
|
self._set_cache_maximum_pages()
|
||||||
|
|
||||||
|
|
||||||
def init(_args):
|
def init(_args):
|
||||||
@ -172,16 +179,10 @@ def init(_args):
|
|||||||
QWebSettings.setOfflineStoragePath(
|
QWebSettings.setOfflineStoragePath(
|
||||||
os.path.join(data_path, 'offline-storage'))
|
os.path.join(data_path, 'offline-storage'))
|
||||||
|
|
||||||
settings = QWebSettings.globalSettings()
|
|
||||||
_set_user_stylesheet(settings)
|
|
||||||
_set_cookie_accept_policy(settings)
|
|
||||||
_set_cache_maximum_pages(settings)
|
|
||||||
|
|
||||||
config.instance.changed.connect(_update_settings)
|
|
||||||
|
|
||||||
global global_settings
|
global global_settings
|
||||||
global_settings = WebKitSettings(QWebSettings.globalSettings())
|
global_settings = WebKitSettings(QWebSettings.globalSettings())
|
||||||
global_settings.init_settings()
|
global_settings.init_settings()
|
||||||
|
config.instance.changed.connect(global_settings.update_setting)
|
||||||
|
|
||||||
|
|
||||||
def shutdown():
|
def shutdown():
|
||||||
|
@ -353,10 +353,15 @@ class Config(QObject):
|
|||||||
"""Get the given setting converted for Python code.
|
"""Get the given setting converted for Python code.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fallback: Use the global value if there's no URL-specific one.
|
name: The name of the setting to get.
|
||||||
|
url: The QUrl to get the setting for.
|
||||||
|
fallback: If False, return configutils.UNSET when there's no
|
||||||
|
override for this domain.
|
||||||
"""
|
"""
|
||||||
opt = self.get_opt(name)
|
opt = self.get_opt(name)
|
||||||
obj = self.get_obj(name, url=url, fallback=fallback)
|
obj = self.get_obj(name, url=url, fallback=fallback)
|
||||||
|
if obj is configutils.UNSET:
|
||||||
|
return obj
|
||||||
return opt.typ.to_py(obj)
|
return opt.typ.to_py(obj)
|
||||||
|
|
||||||
def _maybe_copy(self, value: Any) -> Any:
|
def _maybe_copy(self, value: Any) -> Any:
|
||||||
@ -378,6 +383,12 @@ class Config(QObject):
|
|||||||
|
|
||||||
Note that the returned values are not watched for mutation.
|
Note that the returned values are not watched for mutation.
|
||||||
If a URL is given, return the value which should be used for that URL.
|
If a URL is given, return the value which should be used for that URL.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: The name of the setting to get.
|
||||||
|
url: The QUrl to get the setting for.
|
||||||
|
fallback: If False, return configutils.UNSET when there's no
|
||||||
|
override for this domain.
|
||||||
"""
|
"""
|
||||||
self.get_opt(name) # To make sure it exists
|
self.get_opt(name) # To make sure it exists
|
||||||
value = self._values[name].get_for_url(url, fallback=fallback)
|
value = self._values[name].get_for_url(url, fallback=fallback)
|
||||||
|
@ -742,6 +742,7 @@ content.user_stylesheets:
|
|||||||
valtype: File
|
valtype: File
|
||||||
none_ok: True
|
none_ok: True
|
||||||
default: []
|
default: []
|
||||||
|
supports_pattern: true
|
||||||
desc: List of user stylesheet filenames to use.
|
desc: List of user stylesheet filenames to use.
|
||||||
|
|
||||||
content.webgl:
|
content.webgl:
|
||||||
|
@ -120,14 +120,19 @@ window._qutebrowser.stylesheet = (function() {
|
|||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (css_content === css) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
css_content = css;
|
||||||
|
|
||||||
if (style_elem) {
|
if (style_elem) {
|
||||||
style_elem.textContent = css;
|
style_elem.textContent = css;
|
||||||
// The browser seems to rewrite the document in same-origin frames
|
// The browser seems to rewrite the document in same-origin frames
|
||||||
// without notifying the mutation observer. Ensure that the
|
// without notifying the mutation observer. Ensure that the
|
||||||
// stylesheet is in the current document.
|
// stylesheet is in the current document.
|
||||||
watch_root();
|
watch_root();
|
||||||
} else {
|
|
||||||
css_content = css;
|
|
||||||
}
|
}
|
||||||
// Propagate the new CSS to all child frames.
|
// Propagate the new CSS to all child frames.
|
||||||
// FIXME:qtwebengine This does not work for cross-origin frames.
|
// FIXME:qtwebengine This does not work for cross-origin frames.
|
||||||
|
@ -479,6 +479,18 @@ class TestConfig:
|
|||||||
conf.set_obj(name, False, pattern=pattern)
|
conf.set_obj(name, False, pattern=pattern)
|
||||||
assert conf.get(name, url=QUrl('https://example.com/')) is False
|
assert conf.get(name, url=QUrl('https://example.com/')) is False
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('fallback', [True, False])
|
||||||
|
def test_get_for_url_unset(self, conf, fallback):
|
||||||
|
"""Test config.get() with falling back to a global object."""
|
||||||
|
name = 'content.javascript.enabled'
|
||||||
|
conf.set_obj(name, False)
|
||||||
|
val = conf.get(name,
|
||||||
|
url=QUrl('https://example.com/'),
|
||||||
|
fallback=fallback)
|
||||||
|
|
||||||
|
expected = False if fallback else configutils.UNSET
|
||||||
|
assert val == expected
|
||||||
|
|
||||||
@pytest.mark.parametrize('fallback, expected', [
|
@pytest.mark.parametrize('fallback, expected', [
|
||||||
(True, True),
|
(True, True),
|
||||||
(False, configutils.UNSET)
|
(False, configutils.UNSET)
|
||||||
|
Loading…
Reference in New Issue
Block a user