diff options
author | Ander Punnar <ander@kvlt.ee> | 2021-06-13 21:00:40 +0300 |
---|---|---|
committer | Ander Punnar <ander@kvlt.ee> | 2021-06-13 21:00:40 +0300 |
commit | d5433702a5c5c8e2ac831929a304b21570366dba (patch) | |
tree | fb66db1e6c323e10b86b0f0e9beb1fd92fb26210 | |
parent | 00a394506f149b600c9869a63dd37e847fe17cfe (diff) | |
parent | c6cdd3f8440b22a294911ebed0492beea8913c49 (diff) | |
download | qutebrowser-d5433702a5c5c8e2ac831929a304b21570366dba.tar.gz qutebrowser-d5433702a5c5c8e2ac831929a304b21570366dba.zip |
Merge remote-tracking branch 'origin/master' into 4nd3r/hostblock_subdomains
24 files changed, 184 insertions, 33 deletions
diff --git a/README.asciidoc b/README.asciidoc index b12665b7a..80d8b3880 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -205,6 +205,7 @@ Active * https://luakit.github.io/luakit/[luakit] (C/Lua, GTK+ with WebKit2) * https://nyxt.atlas.engineer/[Nyxt browser] (formerly "Next browser", Lisp, Emacs-like but also offers Vim bindings, QtWebKit or GTK+/WebKit2 - note there was a https://jgkamat.gitlab.io/blog/next-rce.html[critical remote code execution] which was handled quite badly) * https://vieb.dev/[Vieb] (JavaScript, Electron) +* https://surf.suckless.org/[surf] (C, GTK+ with WebKit1/WebKit2) * Chrome/Chromium addons: https://vimium.github.io/[Vimium], https://github.com/dcchambers/vb4c[vb4c] (fork of cVim) @@ -236,7 +237,6 @@ original site is gone but the Arch Linux wiki has some data) * https://www.uzbl.org/[uzbl] (C, GTK+ with WebKit1/WebKit2) * https://github.com/conformal/xombrero[xombrero] (C, GTK+ with WebKit1) * https://github.com/linkdd/cream-browser[Cream Browser] (C, GTK+ with WebKit1) -* https://surf.suckless.org/[surf] (C, GTK+ with WebKit1/WebKit2) * Firefox addons (not based on WebExtensions or no recent activity): http://www.vimperator.org/[Vimperator], http://bug.5digits.org/pentadactyl/index[Pentadactyl], diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 83d8a9601..46c6c283a 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -19,10 +19,18 @@ breaking changes (such as renamed commands) can happen in minor releases. v2.3.0 (unreleased) ------------------- +Added +~~~~~ + +- New `content.prefers_reduced_motion` setting to request websites to reduce + non-essential motion/animations. + Changed ~~~~~~~ - The `fonts.web.*` settings now support URL patterns. +- The `:greasemonkey-reload` command now shows a list of loaded scripts and has + a new `--quiet` switch to suppress that message. [[v2.2.3]] v2.2.3 (2021-06-01) diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index d8a6e761c..f570a3ffd 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -577,7 +577,7 @@ Toggle fullscreen mode. [[greasemonkey-reload]] === greasemonkey-reload -Syntax: +:greasemonkey-reload [*--force*]+ +Syntax: +:greasemonkey-reload [*--force*] [*--quiet*]+ Re-read Greasemonkey scripts from disk. @@ -586,6 +586,7 @@ The scripts are read from a 'greasemonkey' subdirectory in qutebrowser's data or ==== optional arguments * +*-f*+, +*--force*+: For any scripts that have required dependencies, re-download them. +* +*-q*+, +*--quiet*+: Suppress message after loading scripts. [[help]] === help diff --git a/doc/help/configuring.asciidoc b/doc/help/configuring.asciidoc index ad287b030..e1a57cdfb 100644 --- a/doc/help/configuring.asciidoc +++ b/doc/help/configuring.asciidoc @@ -437,3 +437,9 @@ Various emacs/conkeror-like keybinding configs exist: It's also mostly possible to get rid of modal keybindings by setting `input.insert_mode.auto_enter` to `false`, and `input.forward_unbound_keys` to `all`. + +Other resources +^^^^^^^^^^^^^^^ + +- https://www.ii.com/qutebrowser-tips-fragments/[Infinite Ink: qutebrowser Tips and Fragments] +- https://www.ii.com/qutebrowser-configpy/[Infinite Ink: qutebrowser’s Template config.py] diff --git a/doc/help/index.asciidoc b/doc/help/index.asciidoc index c734e1700..c7fb88c8d 100644 --- a/doc/help/index.asciidoc +++ b/doc/help/index.asciidoc @@ -52,6 +52,16 @@ ways: https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser[mailinglist] at mailto:qutebrowser@lists.qutebrowser.org[]. +Other resources +--------------- + +- https://blog.qutebrowser.org/[Development blog] +- https://twitter.com/qutebrowser[Twitter account], + https://fosstodon.org/@qutebrowser[Mastodon account] +- Infinite Ink: https://www.ii.com/qutebrowser-getting-started/[Getting Started + with qutebrowser] and https://www.ii.com/portal/qutebrowser/[other + qutebrowser articles] + License ------- diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index fb208e48c..90197fddb 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -187,6 +187,7 @@ |<<content.pdfjs,content.pdfjs>>|Allow pdf.js to view PDF files in the browser. |<<content.persistent_storage,content.persistent_storage>>|Allow websites to request persistent storage quota via `navigator.webkitPersistentStorage.requestQuota`. |<<content.plugins,content.plugins>>|Enable plugins in Web pages. +|<<content.prefers_reduced_motion,content.prefers_reduced_motion>>|Request websites to minimize non-essentials animations and motion. |<<content.print_element_backgrounds,content.print_element_backgrounds>>|Draw the background color and images also when the page is printed. |<<content.private_browsing,content.private_browsing>>|Open new windows in private browsing mode which does not record visited pages. |<<content.proxy,content.proxy>>|Proxy to use. @@ -2607,6 +2608,22 @@ Type: <<types,Bool>> Default: +pass:[false]+ +[[content.prefers_reduced_motion]] +=== content.prefers_reduced_motion +Request websites to minimize non-essentials animations and motion. +This results in the `prefers-reduced-motion` CSS media query to evaluate to `reduce` (rather than `no-preference`). +On Windows, if this setting is set to False, the system-wide animation setting is considered. + +This setting requires a restart. + +On QtWebEngine, this setting requires Qt 5.14 or newer. + +On QtWebKit, this setting is unavailable. + +Type: <<types,Bool>> + +Default: +pass:[false]+ + [[content.print_element_backgrounds]] === content.print_element_backgrounds Draw the background color and images also when the page is printed. diff --git a/doc/install.asciidoc b/doc/install.asciidoc index 20e2028d1..580a511c5 100644 --- a/doc/install.asciidoc +++ b/doc/install.asciidoc @@ -264,6 +264,10 @@ and QtWebEngine backend is also not available. On Windows ---------- +NOTE: As an additional resource, see +https://www.ii.com/installing-qutebrowser-on-windows/[Infinite Ink: Installing +qutebrowser on Windows]. + There are different ways to install qutebrowser on Windows: Prebuilt binaries diff --git a/doc/userscripts.asciidoc b/doc/userscripts.asciidoc index 747340454..b2af783fb 100644 --- a/doc/userscripts.asciidoc +++ b/doc/userscripts.asciidoc @@ -22,7 +22,10 @@ To call a userscript, it needs to be stored in your config or data directory und `userscripts` (for example: `~/.local/share/qutebrowser/userscripts/myscript`), or just use an absolute path. -NOTE: On Windows, only userscripts with `com`, `bat`, or `exe` extensions will be launched. +NOTE: On Windows, only userscripts with `com`, `bat`, or `exe` extensions will +be launched. As an additional resource, see +https://www.ii.com/qutebrowser-userscripts-on-windows/[Infinite Ink: +qutebrowser Userscripts on Windows]. Getting information ------------------- diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt index 7e1159089..1ecb63561 100644 --- a/misc/requirements/requirements-dev.txt +++ b/misc/requirements/requirements-dev.txt @@ -5,10 +5,11 @@ certifi==2021.5.30 cffi==1.14.5 chardet==4.0.0 cryptography==3.4.7 +Deprecated==1.2.12 github3.py==2.0.0 hunter==3.3.3 idna==2.10 -jwcrypto==0.8 +jwcrypto==0.9 manhole==1.8.0 packaging==20.9 pycparser==2.20 @@ -22,3 +23,4 @@ six==1.16.0 toml==0.10.2 uritemplate==3.0.1 # urllib3==1.26.5 +wrapt==1.12.1 diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt index 22261972c..7dfb82e0f 100644 --- a/misc/requirements/requirements-mypy.txt +++ b/misc/requirements/requirements-mypy.txt @@ -2,7 +2,7 @@ chardet==4.0.0 diff-cover==5.1.2 -importlib-metadata==4.3.1 +importlib-metadata==4.5.0 importlib-resources==5.1.4 inflect==5.3.0 Jinja2==3.0.1 diff --git a/misc/requirements/requirements-pylint.txt b/misc/requirements/requirements-pylint.txt index 13b1ef98b..5d6ef8f30 100644 --- a/misc/requirements/requirements-pylint.txt +++ b/misc/requirements/requirements-pylint.txt @@ -5,11 +5,12 @@ certifi==2021.5.30 cffi==1.14.5 chardet==4.0.0 cryptography==3.4.7 +Deprecated==1.2.12 future==0.18.2 github3.py==2.0.0 idna==2.10 isort==4.3.21 -jwcrypto==0.8 +jwcrypto==0.9 lazy-object-proxy==1.4.3 mccabe==0.6.1 pefile==2021.5.24 diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt index 0cdd02555..15c2503c7 100644 --- a/misc/requirements/requirements-tests.txt +++ b/misc/requirements/requirements-tests.txt @@ -14,7 +14,7 @@ filelock==3.0.12 Flask==2.0.1 glob2==0.7 hunter==3.3.3 -hypothesis==6.13.10 +hypothesis==6.13.14 icdiff==1.9.1 idna==2.10 iniconfig==1.1.1 @@ -37,12 +37,12 @@ pyparsing==2.4.7 pytest==6.2.4 pytest-bdd==4.0.2 pytest-benchmark==3.4.1 -pytest-cov==2.12.0 +pytest-cov==2.12.1 pytest-forked==1.3.0 pytest-icdiff==0.5 pytest-instafail==0.4.2 pytest-mock==3.6.1 -pytest-qt==3.3.0 +pytest-qt==4.0.0 pytest-repeat==0.9.1 pytest-rerunfailures==10.0 pytest-xdist==2.2.1 diff --git a/misc/userscripts/README.md b/misc/userscripts/README.md index 395797805..7dbb0c840 100644 --- a/misc/userscripts/README.md +++ b/misc/userscripts/README.md @@ -76,7 +76,9 @@ The following userscripts can be found on their own repositories. Opens DOIs on Sci-Hub. - [1password](https://github.com/tomoakley/dotfiles/blob/master/qutebrowser/userscripts/1password): Integration with 1password on macOS. - +- [localhost](https://github.com/SidharthArya/.qutebrowser/blob/master/userscripts/localhost): + Quickly navigate to localhost:port. For reference: [A quicker way to reach localhost with qutebrowser](https://sidhartharya.me/a-quicker-way-to-reach-localhost-with-qutebrowser/) + [Zotero]: https://www.zotero.org/ [Pocket]: https://getpocket.com/ [Instapaper]: https://www.instapaper.com/ diff --git a/misc/userscripts/readability-js b/misc/userscripts/readability-js index bb681810c..485957ddb 100755 --- a/misc/userscripts/readability-js +++ b/misc/userscripts/readability-js @@ -8,6 +8,7 @@ // # Prerequisites // // - Mozilla's readability library (npm install -g @mozilla/readability) +// - Also available in the AUR as nodejs-readability-git // - jsdom (npm install -g jsdom) // - qutejs (npm install -g qutejs) // diff --git a/qutebrowser/browser/greasemonkey.py b/qutebrowser/browser/greasemonkey.py index c1574aed1..03db3be0c 100644 --- a/qutebrowser/browser/greasemonkey.py +++ b/qutebrowser/browser/greasemonkey.py @@ -32,7 +32,7 @@ from typing import cast, List, Sequence from PyQt5.QtCore import pyqtSignal, QObject, QUrl from qutebrowser.utils import (log, standarddir, jinja, objreg, utils, - javascript, urlmatch, version, usertypes) + javascript, urlmatch, version, usertypes, message) from qutebrowser.api import cmdutils from qutebrowser.browser import downloads from qutebrowser.misc import objects @@ -101,6 +101,9 @@ class GreasemonkeyScript: HEADER_REGEX = r'// ==UserScript==|\n+// ==/UserScript==\n' PROPS_REGEX = r'// @(?P<prop>[^\s]+)\s*(?P<val>.*)' + def __str__(self): + return self.name + @classmethod def parse(cls, source, filename=None): """GreasemonkeyScript factory. @@ -266,7 +269,7 @@ class GreasemonkeyManager(QObject): self.load_scripts() - def load_scripts(self, *, force=False): + def load_scripts(self, *, force: bool = False) -> List[GreasemonkeyScript]: """Re-read Greasemonkey scripts from disk. The scripts are read from a 'greasemonkey' subdirectory in @@ -275,14 +278,19 @@ class GreasemonkeyManager(QObject): Args: force: For any scripts that have required dependencies, re-download them. + + Return: + A list of loaded scripts. """ self._run_start = [] self._run_end = [] self._run_idle = [] + scripts = [] for scripts_dir in _scripts_dirs(): scripts_dir = os.path.abspath(scripts_dir) log.greasemonkey.debug("Reading scripts from: {}".format(scripts_dir)) + for script_filename in glob.glob(os.path.join(scripts_dir, '*.js')): if not os.path.isfile(script_filename): continue @@ -290,10 +298,12 @@ class GreasemonkeyManager(QObject): with open(script_path, encoding='utf-8-sig') as script_file: script = GreasemonkeyScript.parse(script_file.read(), script_filename) - if not script.name: - script.name = script_filename + assert script.name, script self.add_script(script, force) + scripts.append(script) + self.scripts_reloaded.emit() + return sorted(scripts, key=str) def add_script(self, script, force=False): """Add a GreasemonkeyScript to this manager. @@ -304,8 +314,7 @@ class GreasemonkeyManager(QObject): """ if script.requires: log.greasemonkey.debug( - "Deferring script until requirements are " - "fulfilled: {}".format(script.name)) + f"Deferring script until requirements are fulfilled: {script}") self._get_required_scripts(script, force) else: self._add_script(script) @@ -319,14 +328,13 @@ class GreasemonkeyManager(QObject): self._run_idle.append(script) else: if script.run_at: - log.greasemonkey.warning("Script {} has invalid run-at " - "defined, defaulting to " - "document-end" - .format(script.name)) + log.greasemonkey.warning( + f"Script {script} has invalid run-at defined, defaulting to " + "document-end") # Default as per # https://wiki.greasespot.net/Metadata_Block#.40run-at self._run_end.append(script) - log.greasemonkey.debug("Loaded script: {}".format(script.name)) + log.greasemonkey.debug(f"Loaded script: {script}") def _required_url_to_file_path(self, url): requires_dir = os.path.join(_scripts_dirs()[0], 'requires') @@ -338,9 +346,8 @@ class GreasemonkeyManager(QObject): self._in_progress_dls.remove(download) if not self._add_script_with_requires(script): log.greasemonkey.debug( - "Finished download {} for script {} " - "but some requirements are still pending" - .format(download.basename, script.name)) + "Finished download {download.basename} for script {script} " + "but some requirements are still pending") def _add_script_with_requires(self, script, quiet=False): """Add a script with pending downloads to this GreasemonkeyManager. @@ -364,8 +371,7 @@ class GreasemonkeyManager(QObject): for url in reversed(script.requires): target_path = self._required_url_to_file_path(url) log.greasemonkey.debug( - "Adding required script for {} to IIFE: {}" - .format(script.name, url)) + f"Adding required script for {script} to IIFE: {url}") with open(target_path, encoding='utf8') as f: script.add_required_script(f.read()) @@ -426,7 +432,7 @@ class GreasemonkeyManager(QObject): @cmdutils.register() -def greasemonkey_reload(force=False): +def greasemonkey_reload(force: bool = False, quiet: bool = False) -> None: """Re-read Greasemonkey scripts from disk. The scripts are read from a 'greasemonkey' subdirectory in @@ -435,8 +441,12 @@ def greasemonkey_reload(force=False): Args: force: For any scripts that have required dependencies, re-download them. + quiet: Suppress message after loading scripts. """ - gm_manager.load_scripts(force=force) + scripts = gm_manager.load_scripts(force=force) + names = '\n'.join(str(script) for script in scripts) + if not quiet: + message.info(f"Loaded scripts:\n\n{names}") def init(): diff --git a/qutebrowser/browser/webkit/webpage.py b/qutebrowser/browser/webkit/webpage.py index 6fd11b7c8..ddbd78de2 100644 --- a/qutebrowser/browser/webkit/webpage.py +++ b/qutebrowser/browser/webkit/webpage.py @@ -343,7 +343,7 @@ class BrowserPage(QWebPage): for script in toload: if frame is self.mainFrame() or script.runs_on_sub_frames: - log.webview.debug('Running GM script: {}'.format(script.name)) + log.webview.debug(f'Running GM script: {script}') frame.evaluateJavaScript(script.code()) @pyqtSlot('QWebFrame*', 'QWebPage::Feature') diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index b85e84be2..d12741ec4 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -528,6 +528,22 @@ content.frame_flattening: This will flatten all the frames to become one scrollable page. +content.prefers_reduced_motion: + default: false + type: Bool + backend: + QtWebEngine: Qt 5.14 + QtWebKit: false + restart: true + desc: >- + Request websites to minimize non-essentials animations and motion. + + This results in the `prefers-reduced-motion` CSS media query to evaluate to + `reduce` (rather than `no-preference`). + + On Windows, if this setting is set to False, the system-wide animation + setting is considered. + content.site_specific_quirks: renamed: content.site_specific_quirks.enabled diff --git a/qutebrowser/config/qtargs.py b/qutebrowser/config/qtargs.py index cb17a0ced..c38ef5b01 100644 --- a/qutebrowser/config/qtargs.py +++ b/qutebrowser/config/qtargs.py @@ -334,7 +334,11 @@ def _qtwebengine_settings_args(versions: version.WebEngineVersions) -> Iterator[ }, 'content.headers.referer': { 'always': None, - } + }, + 'content.prefers_reduced_motion': { + True: '--force-prefers-reduced-motion', + False: None, + }, } qt_514_ver = utils.VersionNumber(5, 14) diff --git a/requirements.txt b/requirements.txt index 4163885b9..d2bd28949 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ adblock==0.4.4 colorama==0.4.4 dataclasses==0.6 ; python_version<"3.7" -importlib-metadata==4.3.1 ; python_version<"3.8" +importlib-metadata==4.5.0 ; python_version<"3.8" importlib-resources==5.1.4 ; python_version<"3.9" Jinja2==3.0.1 MarkupSafe==2.0.1 diff --git a/scripts/dev/recompile_requirements.py b/scripts/dev/recompile_requirements.py index 8dd9e4c09..e8a188f6c 100644 --- a/scripts/dev/recompile_requirements.py +++ b/scripts/dev/recompile_requirements.py @@ -185,6 +185,7 @@ CHANGELOG_URLS = { 'setuptools': 'https://setuptools.readthedocs.io/en/latest/history.html', 'future': 'https://python-future.org/whatsnew.html', 'pefile': 'https://github.com/erocarrera/pefile/commits/master', + 'Deprecated': 'https://github.com/tantale/deprecated/blob/master/CHANGELOG.rst', } diff --git a/scripts/mkvenv.py b/scripts/mkvenv.py index 58131bc05..ba31638d8 100755 --- a/scripts/mkvenv.py +++ b/scripts/mkvenv.py @@ -335,7 +335,7 @@ def _find_libs() -> Dict[Tuple[str, str], List[str]]: for line in ldconfig_proc.stdout.splitlines(): match = pattern.fullmatch(line.strip()) if match is None: - if 'libs found in cache' not in line: + if 'libs found in cache' not in line and 'Cache generated by:' not in line: utils.print_col(f'Failed to match ldconfig output: {line}', 'yellow') continue diff --git a/tests/end2end/data/prefers_reduced_motion.html b/tests/end2end/data/prefers_reduced_motion.html new file mode 100644 index 000000000..a37d43864 --- /dev/null +++ b/tests/end2end/data/prefers_reduced_motion.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Prefers reduced motion test</title> + <style> +#reduce-text { + display: none; +} +#no-preference-text { + display: none; +} + +@media (prefers-reduced-motion: no-preference) { + #no-preference-text { + display: inline; + } + #missing-support-text { + display: none; + } +} + +@media (prefers-reduced-motion: reduce) { + #reduce-text { + display: inline; + } + #missing-support-text { + display: none; + } +} + </style> + </head> + <body> + <p id="reduce-text">Reduced motion preference detected.</p> + <p id="no-preference-text">No preference detected.</p> + <p id="missing-support-text">Preference support missing.</p> + </body> +</html> diff --git a/tests/end2end/fixtures/quteprocess.py b/tests/end2end/fixtures/quteprocess.py index 0c0cfc50f..264c81283 100644 --- a/tests/end2end/fixtures/quteprocess.py +++ b/tests/end2end/fixtures/quteprocess.py @@ -229,6 +229,10 @@ def is_ignored_chromium_message(line): # gpu_process_transport_factory.cc(1019)] Lost UI shared context. 'Lost UI shared context.', + # [20870:20908:0607/081717.652282:ERROR:block_files.cc(465)] Failed to + # open /tmp/qutebrowser-basedir-cg284f_m/data/webengine/GPUCache/data_2 + 'Failed to open *GPUCache*', + # Qt 5.12 # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-70702 # [32123:32123:0923/224739.457307:ERROR:in_progress_cache_impl.cc(192)] diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py index 97c04eb0d..b860feed0 100644 --- a/tests/end2end/test_invocations.py +++ b/tests/end2end/test_invocations.py @@ -752,6 +752,30 @@ def test_dark_mode_mathml(quteproc_new, request, qtbot): ) +@testutils.qt514 +@pytest.mark.parametrize('value, preference', [ + ('true', 'Reduced motion'), + ('false', 'No'), +]) +@pytest.mark.skipif( + utils.is_windows, + reason="Outcome on Windows depends on system settings", +) +def test_prefers_reduced_motion(quteproc_new, request, value, preference): + if not request.config.webengine: + pytest.skip("Skipped with QtWebKit") + + args = _base_args(request.config) + [ + '--temp-basedir', + '-s', 'content.prefers_reduced_motion', value, + ] + quteproc_new.start(args) + + quteproc_new.open_path('data/prefers_reduced_motion.html') + content = quteproc_new.get_content() + assert content == f"{preference} preference detected." + + def test_unavailable_backend(request, quteproc_new): """Test starting with a backend which isn't available. @@ -802,4 +826,3 @@ def test_json_logging_without_debug(request, quteproc_new, runtime_tmpdir): quteproc_new.exit_expected = True quteproc_new.start(args, env={'XDG_RUNTIME_DIR': str(runtime_tmpdir)}) assert not quteproc_new.is_running() - assert not quteproc_new.captured_log |