Merge branch 'perdomainstylesheets' of https://github.com/jcjordyn130/qutebrowser into jcjordyn130/perdomainstylesheets

This commit is contained in:
reaysawa 2019-03-11 00:25:12 -03:00
commit 6313a74423
7 changed files with 125 additions and 64 deletions

View File

@ -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):

View File

@ -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'),

View File

@ -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():

View File

@ -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)

View File

@ -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:

View File

@ -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.

View File

@ -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)