diff options
author | Ander Punnar <ander@kvlt.ee> | 2021-06-01 20:36:56 +0300 |
---|---|---|
committer | Ander Punnar <ander@kvlt.ee> | 2021-06-01 20:36:56 +0300 |
commit | 00a394506f149b600c9869a63dd37e847fe17cfe (patch) | |
tree | 58c1ba094a79fa537abada91426cf2f01610c9c2 | |
parent | 4e47af21586aad3846c2458dc0c8243e9d6eb792 (diff) | |
parent | b34988055071522e72c73b0f3a0bd3a6b59c6b9a (diff) | |
download | qutebrowser-00a394506f149b600c9869a63dd37e847fe17cfe.tar.gz qutebrowser-00a394506f149b600c9869a63dd37e847fe17cfe.zip |
Merge remote-tracking branch 'origin/master' into 4nd3r/hostblock_subdomains
45 files changed, 340 insertions, 164 deletions
diff --git a/.bumpversion.cfg b/.bumpversion.cfg index c0e16391b..94f9e42d8 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2.2.2 +current_version = 2.2.3 commit = True message = Release v{new_version} tag = True diff --git a/.github/workflows/bleeding.yml b/.github/workflows/bleeding.yml index 746810cb8..766f535d7 100644 --- a/.github/workflows/bleeding.yml +++ b/.github/workflows/bleeding.yml @@ -101,16 +101,16 @@ jobs: uses: Gottox/irc-message-action@v1 if: "needs.tests.result == 'success' && needs.pyinstaller.result == 'success'" with: - server: chat.freenode.net - channel: '#qutebrowser-dev' + server: irc.libera.chat + channel: '#qutebrowser-bots' nickname: qutebrowser-bot message: "[${{ github.workflow }}] \u00033Success:\u0003 ${{ github.ref }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (@${{ github.actor }})" - name: Send non-success IRC notification uses: Gottox/irc-message-action@v1 if: "needs.tests.result != 'success' || needs.pyinstaller.result != 'success'" with: - server: chat.freenode.net - channel: '#qutebrowser-dev' + server: irc.libera.chat + channel: '#qutebrowser-bots' nickname: qutebrowser-bot message: "[${{ github.workflow }}] \u00034FAIL:\u0003 ${{ github.ref }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (@${{ github.actor }})\n tests: ${{ needs.tests.result }}, pyinstaller: ${{ needs.pyinstaller.result }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 71c91e13b..e50ba2c60 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -215,16 +215,16 @@ jobs: uses: Gottox/irc-message-action@v1 if: "needs.linters.result == 'success' && needs.tests.result == 'success' && needs.tests-docker.result == 'success' && needs.codeql.result == 'success'" with: - server: chat.freenode.net - channel: '#qutebrowser-dev' + server: irc.libera.chat + channel: '#qutebrowser-bots' nickname: qutebrowser-bot message: "[${{ github.workflow }}] \u00033Success:\u0003 ${{ github.ref }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (@${{ github.actor }})" - name: Send failure IRC notification uses: Gottox/irc-message-action@v1 if: "needs.linters.result == 'failure' || needs.tests.result == 'failure' || needs.tests-docker.result == 'failure' || needs.codeql.result == 'failure'" with: - server: chat.freenode.net - channel: '#qutebrowser-dev' + server: irc.libera.chat + channel: '#qutebrowser-bots' nickname: qutebrowser-bot message: "[${{ github.workflow }}] \u00034FAIL:\u0003 ${{ github.ref }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (@${{ github.actor }})\n linters: ${{ needs.linters.result }}, tests: ${{ needs.tests.result }}, tests-docker: ${{ needs.tests-docker.result }}, codeql: ${{ needs.codeql.result }}" @@ -232,16 +232,16 @@ jobs: uses: Gottox/irc-message-action@v1 if: "needs.linters.result == 'skipped' || needs.tests.result == 'skipped' || needs.tests-docker.result == 'skipped' || needs.codeql.result == 'skipped'" with: - server: chat.freenode.net - channel: '#qutebrowser-dev' + server: irc.libera.chat + channel: '#qutebrowser-bots' nickname: qutebrowser-bot message: "[${{ github.workflow }}] \u00038Skipped:\u0003 ${{ github.ref }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (@${{ github.actor }})" - name: Send cancelled IRC notification uses: Gottox/irc-message-action@v1 if: "needs.linters.result == 'cancelled' || needs.tests.result == 'cancelled' || needs.tests-docker.result == 'cancelled' || needs.codeql.result == 'cancelled'" with: - server: chat.freenode.net - channel: '#qutebrowser-dev' + server: irc.libera.chat + channel: '#qutebrowser-bots' nickname: qutebrowser-bot message: "[${{ github.workflow }}] \u000314Cancelled:\u0003 ${{ github.ref }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (@${{ github.actor }})\n linters: ${{ needs.linters.result }}, tests: ${{ needs.tests.result }}, tests-docker: ${{ needs.tests-docker.result }}, codeql: ${{ needs.codeql.result }}" diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d4023d57c..2ac1bd58f 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -47,15 +47,15 @@ jobs: uses: Gottox/irc-message-action@v1 if: "needs.docker.result == 'success'" with: - server: chat.freenode.net - channel: '#qutebrowser-dev' + server: irc.libera.chat + channel: '#qutebrowser-bots' nickname: qutebrowser-bot message: "[${{ github.workflow }}] \u00033Success:\u0003 ${{ github.ref }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (@${{ github.actor }})" - name: Send non-success IRC notification uses: Gottox/irc-message-action@v1 if: "needs.docker.result != 'success'" with: - server: chat.freenode.net - channel: '#qutebrowser-dev' + server: irc.libera.chat + channel: '#qutebrowser-bots' nickname: qutebrowser-bot message: "[${{ github.workflow }}] \u00034FAIL:\u0003 ${{ github.ref }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (@${{ github.actor }})" diff --git a/.github/workflows/recompile-requirements.yml b/.github/workflows/recompile-requirements.yml index 68a0d588f..00d088da8 100644 --- a/.github/workflows/recompile-requirements.yml +++ b/.github/workflows/recompile-requirements.yml @@ -77,16 +77,16 @@ jobs: uses: Gottox/irc-message-action@v1 if: "needs.update.result == 'success'" with: - server: chat.freenode.net - channel: '#qutebrowser-dev' + server: irc.libera.chat + channel: '#qutebrowser-bots' nickname: qutebrowser-bot message: "[${{ github.workflow }}] \u00033Success:\u0003 ${{ github.ref }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (@${{ github.actor }})" - name: Send non-success IRC notification uses: Gottox/irc-message-action@v1 if: "needs.update.result != 'success'" with: - server: chat.freenode.net - channel: '#qutebrowser-dev' + server: irc.libera.chat + channel: '#qutebrowser-bots' nickname: qutebrowser-bot message: "[${{ github.workflow }}] \u00034FAIL:\u0003 ${{ github.ref }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (@${{ github.actor }})\n linters: ${{ needs.linters.result }}, tests: ${{ needs.tests.result }}, tests-docker: ${{ needs.tests-docker.result }}, codeql: ${{ needs.codeql.result }}" diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 428cf22f8..83d8a9601 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -22,8 +22,42 @@ v2.3.0 (unreleased) Changed ~~~~~~~ -The `fonts.web.*` settings now support URL patterns. +- The `fonts.web.*` settings now support URL patterns. +[[v2.2.3]] +v2.2.3 (2021-06-01) +------------------- + +Fixed +~~~~~ + +- Logging into Google accounts or sharing the camera on macOS 10.14+ crashed, + which is now fixed. +- The Windows installer now correctly aborts the installation on Windows 7 + (rather than attempting an install which won't work, since Windows 7 is + unsupported since the v2.0.0 release). +- Using `--json-logging` without `--debug` caused qutebrowser to crash since the + v1.13.0 release. It now works correctly again. +- Mixing Qt 5.14+ with QtWebEngine 5.12 caused a crash related to qutebrowser's + notification support, which is now fixed. +- The documentation now points to the new IRC channels on irc.libera.chat + instead of the defunct Freenode channels (due to a hostile takeover by + Freenode staff). +- Setting `content.headers.user_agent` or `.accept_language` to a value + containing non-ascii characters was permitted by qutebrowser, but resulted in + a crash when loading a page. Such values are now rejected properly. +- When quitting qutebrowser on the `qute://settings` page, a crash could happen, which is now fixed. +- When `:edit-text` is used, but the existing text in the input isn't + representable in the configured encoding (`editor.encoding`), qutebrowser would + crash. It now shows a proper error instead. +- The testsuite should now work properly on aarch64. +- When QtWebEngine is in a "stuck" state while `:selection-follow` was used, + this could cause a crash in qutebrowser. This is now fixed (speculatively, due + to lack of a reproducer). +- When the brave adblock data (`adblock-cache.dat`) got corrupted, qutebrowser + would crash when trying to load it. It now displays an error instead. +- Combining `/S` (silent) and `/allusers` when uninstalling via the Windows + installer now works properly. [[v2.2.2]] v2.2.2 (2021-05-20) diff --git a/doc/contributing.asciidoc b/doc/contributing.asciidoc index dc7b331b1..1f87e9163 100644 --- a/doc/contributing.asciidoc +++ b/doc/contributing.asciidoc @@ -26,9 +26,9 @@ several ways: (optionally https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser[subscribe] first). -* Join the IRC channel irc://irc.freenode.org/#qutebrowser[`#qutebrowser`] on -https://freenode.net/[Freenode] -(https://webchat.freenode.net/?channels=#qutebrowser[webchat]). +* Join the IRC channel link:ircs://irc.libera.chat:6697/#qutebrowser[`#qutebrowser`] on +https://libera.chat/[Libera Chat] (https://web.libera.chat/#qutebrowser[webchat], +https://matrix.to/#qutebrowser:libera.chat[via Matrix]). Finding something to work on ---------------------------- @@ -567,25 +567,33 @@ Chrome URLs With the QtWebEngine backend, qutebrowser supports several chrome:// urls which can be useful for debugging: +- chrome://accessibility/ - chrome://appcache-internals/ - chrome://blob-internals/ +- chrome://conversion-internals/ (QtWebEngine 5.15.3+) +- chrome://crash/ (crashes the current renderer process!) - chrome://gpu/ +- chrome://gpuclean/ (crashes the current renderer process!) +- chrome://gpucrash/ (crashes qutebrowser!) +- chrome://gpuhang/ (hangs qutebrowser!) - chrome://histograms/ - chrome://indexeddb-internals/ +- chrome://kill/ (kills the current renderer process!) - chrome://media-internals/ +- chrome://net-internals/ (QtWebEngine 5.15.4+) - chrome://network-errors/ -- chrome://serviceworker-internals/ -- chrome://webrtc-internals/ -- chrome://crash/ (crashes the current renderer process!) -- chrome://kill/ (kills the current renderer process!) -- chrome://gpucrash/ (crashes qutebrowser!) -- chrome://gpuhang/ (hangs qutebrowser!) -- chrome://gpuclean/ (crashes the current renderer process!) - chrome://ppapiflashcrash/ - chrome://ppapiflashhang/ +- chrome://process-internals/ - chrome://quota-internals/ -- chrome://taskscheduler-internals/ - chrome://sandbox/ (Linux only) +- chrome://serviceworker-internals/ +- chrome://taskscheduler-internals/ (removed in QtWebEngine 5.14) +- chrome://tracing/ (QtWebEngine 5.15.3+) +- chrome://ukm/ (QtWebEngine 5.15.3+) +- chrome://user-actions/ (QtWebEngine 5.15.3+) +- chrome://webrtc-internals/ +- chrome://webrtc-logs/ (QtWebEngine 5.15.3+) QtWebEngine internals ~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/help/index.asciidoc b/doc/help/index.asciidoc index 3a84cfca1..c734e1700 100644 --- a/doc/help/index.asciidoc +++ b/doc/help/index.asciidoc @@ -22,10 +22,10 @@ Getting help ------------ You can get help in the IRC channel -irc://irc.freenode.org/#qutebrowser[`#qutebrowser`] on -http://freenode.net/[Freenode] -(https://webchat.freenode.net/?channels=#qutebrowser[webchat]), or by writing a -message to the +link:ircs://irc.libera.chat:6697/#qutebrowser[`#qutebrowser`] on +https://libera.chat/[Libera Chat] +(https://web.libera.chat/#qutebrowser[webchat], https://matrix.to/#qutebrowser:libera.chat[via Matrix]), +or by writing a message to the https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser[mailinglist] at mailto:qutebrowser@lists.qutebrowser.org[]. diff --git a/doc/quickstart.asciidoc b/doc/quickstart.asciidoc index afe5ae231..2e61e442d 100644 --- a/doc/quickstart.asciidoc +++ b/doc/quickstart.asciidoc @@ -46,9 +46,9 @@ If you get stuck, you can get help in multiple ways: * The `:help` command inside qutebrowser shows the built-in documentation. Additionally, each command can be started with a `--help` flag to show its help. -* Chat via the IRC channel: irc://irc.freenode.org/#qutebrowser[`#qutebrowser`] on -https://freenode.net/[Freenode] -(https://webchat.freenode.net/?channels=#qutebrowser[webchat]) +* Chat via the IRC channel: link:ircs://irc.libera.chat:6697/#qutebrowser[`#qutebrowser`] on +https://libera.chat/[Libera Chat] (https://web.libera.chat/#qutebrowser[webchat], +or https://matrix.to/#qutebrowser:libera.chat[via Matrix]) * On Reddit: https://www.reddit.com/r/qutebrowser/[/r/qutebrowser] * Via https://github.com/qutebrowser/qutebrowser/discussions[GitHub Discussions] * Using the mailinglist: mailto:qutebrowser@lists.qutebrowser.org[] diff --git a/doc/qutebrowser.1.asciidoc b/doc/qutebrowser.1.asciidoc index 8564c8a51..8db231add 100644 --- a/doc/qutebrowser.1.asciidoc +++ b/doc/qutebrowser.1.asciidoc @@ -120,7 +120,7 @@ environment, the directories configured there are used instead of the above defaults. == BUGS -Bugs are tracked in the Github issue tracker at +Bugs are tracked in the Github issue tracker at https://github.com/qutebrowser/qutebrowser/issues. If you found a bug, use the built-in ':report' command to create a bug report @@ -152,8 +152,9 @@ this program. If not, see <https://www.gnu.org/licenses/>. https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser * Announce-only mailinglist: mailto:qutebrowser-announce@lists.qutebrowser.org[] / https://lists.schokokeks.org/mailman/listinfo.cgi/qutebrowser-announce -* IRC: irc://irc.freenode.org/#qutebrowser[`#qutebrowser`] on -https://freenode.net/[Freenode] +* IRC: link:ircs://irc.libera.chat:6697/#qutebrowser[`#qutebrowser`] on +https://libera.chat/[Libera Chat] (https://web.libera.chat/#qutebrowser[webchat], +https://matrix.to/#qutebrowser:libera.chat[via Matrix]) * Github: https://github.com/qutebrowser/qutebrowser == AUTHOR diff --git a/misc/cheatsheet.svg b/misc/cheatsheet.svg index e908f9496..7dcb6d4e1 100644 --- a/misc/cheatsheet.svg +++ b/misc/cheatsheet.svg @@ -2570,7 +2570,7 @@ id="flowPara5604" style="font-size:13.8667px;line-height:1.25;font-family:sans-serif;stroke-width:1.06667">Website: https://www.qutebrowser.org/ </flowPara><flowPara id="flowPara5595" - style="font-size:13.8667px;line-height:1.25;font-family:sans-serif;stroke-width:1.06667">IRC: #qutebrowser on Freenode</flowPara><flowPara + style="font-size:13.8667px;line-height:1.25;font-family:sans-serif;stroke-width:1.06667">IRC: #qutebrowser on Libera Chat (irc.libera.chat)</flowPara><flowPara id="flowPara5597" style="font-size:13.8667px;line-height:1.25;font-family:sans-serif;stroke-width:1.06667">Mailinglist: qutebrowser@lists.qutebrowser.org</flowPara></flowRoot> <text diff --git a/misc/nsis/install_pages.nsh b/misc/nsis/install_pages.nsh index a8e1f9253..c3cf973df 100755 --- a/misc/nsis/install_pages.nsh +++ b/misc/nsis/install_pages.nsh @@ -22,7 +22,7 @@ ; NsisMultiUser optional defines !define MULTIUSER_INSTALLMODE_ALLOW_BOTH_INSTALLATIONS 0 !define MULTIUSER_INSTALLMODE_ALLOW_ELEVATION 1 -!define MULTIUSER_INSTALLMODE_ALLOW_ELEVATION_IF_SILENT 0 +!define MULTIUSER_INSTALLMODE_ALLOW_ELEVATION_IF_SILENT 1 !define MULTIUSER_INSTALLMODE_DEFAULT_ALLUSERS 1 !if ${PLATFORM} == "win64" !define MULTIUSER_INSTALLMODE_64_BIT 1 diff --git a/misc/nsis/qutebrowser.nsi b/misc/nsis/qutebrowser.nsi index 3a96cb013..51f3b623d 100755 --- a/misc/nsis/qutebrowser.nsi +++ b/misc/nsis/qutebrowser.nsi @@ -59,7 +59,7 @@ ShowUninstDetails hide !define CONTACT "mail@qutebrowser.org"
!define COMMENTS "A keyboard-driven, vim-like browser based on PyQt5."
!define LANGID "1033" ; U.S. English
-!define MIN_WIN_VER "XP"
+!define MIN_WIN_VER "8"
!define SETUP_MUTEX "${PRODUCT_NAME} Setup Mutex" ; do not change this between program versions!
!define APP_MUTEX "${PRODUCT_NAME} App Mutex" ; do not change this between program versions!
!define REG_UN "Software\Microsoft\Windows\CurrentVersion\Uninstall"
diff --git a/misc/org.qutebrowser.qutebrowser.appdata.xml b/misc/org.qutebrowser.qutebrowser.appdata.xml index 95602b476..b7742ee84 100644 --- a/misc/org.qutebrowser.qutebrowser.appdata.xml +++ b/misc/org.qutebrowser.qutebrowser.appdata.xml @@ -44,6 +44,7 @@ </content_rating> <releases> <!-- Add new releases here --> +<release version="2.2.3" date="2021-06-01"/> <release version="2.2.2" date="2021-05-20"/> <release version="2.2.1" date="2021-04-29"/> <release version="2.2.0" date="2021-04-13"/> diff --git a/misc/requirements/requirements-check-manifest.txt b/misc/requirements/requirements-check-manifest.txt index f32dddc28..6d96812e5 100644 --- a/misc/requirements/requirements-check-manifest.txt +++ b/misc/requirements/requirements-check-manifest.txt @@ -1,6 +1,6 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -build==0.3.1.post1 +build==0.4.0 check-manifest==0.46 packaging==20.9 pep517==0.10.0 diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt index 2621579f6..7e1159089 100644 --- a/misc/requirements/requirements-dev.txt +++ b/misc/requirements/requirements-dev.txt @@ -1,7 +1,7 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py bump2version==1.0.1 -certifi==2020.12.5 +certifi==2021.5.30 cffi==1.14.5 chardet==4.0.0 cryptography==3.4.7 @@ -21,4 +21,4 @@ sip==6.1.0 six==1.16.0 toml==0.10.2 uritemplate==3.0.1 -# urllib3==1.26.4 +# urllib3==1.26.5 diff --git a/misc/requirements/requirements-flake8.txt b/misc/requirements/requirements-flake8.txt index 429d04dfe..bec5abf95 100644 --- a/misc/requirements/requirements-flake8.txt +++ b/misc/requirements/requirements-flake8.txt @@ -18,7 +18,7 @@ flake8-tuple==0.4.1 mccabe==0.6.1 pep8-naming==0.11.1 pycodestyle==2.7.0 -pydocstyle==6.0.0 +pydocstyle==6.1.1 pyflakes==2.3.1 six==1.16.0 snowballstemmer==2.1.0 diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt index 7d3d29e63..22261972c 100644 --- a/misc/requirements/requirements-mypy.txt +++ b/misc/requirements/requirements-mypy.txt @@ -1,14 +1,14 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py chardet==4.0.0 -diff-cover==5.1.1 -importlib-metadata==4.0.1 -importlib-resources==5.1.3 +diff-cover==5.1.2 +importlib-metadata==4.3.1 +importlib-resources==5.1.4 inflect==5.3.0 -Jinja2==3.0.0 +Jinja2==3.0.1 jinja2-pluralize==0.3.0 lxml==4.6.3 -MarkupSafe==2.0.0 +MarkupSafe==2.0.1 mypy==0.812 mypy-extensions==0.4.3 pluggy==0.13.1 diff --git a/misc/requirements/requirements-pylint.txt b/misc/requirements/requirements-pylint.txt index 13358f6d5..13b1ef98b 100644 --- a/misc/requirements/requirements-pylint.txt +++ b/misc/requirements/requirements-pylint.txt @@ -1,7 +1,7 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py astroid==2.3.3 # rq.filter: < 2.4 -certifi==2020.12.5 +certifi==2021.5.30 cffi==1.14.5 chardet==4.0.0 cryptography==3.4.7 @@ -12,7 +12,7 @@ isort==4.3.21 jwcrypto==0.8 lazy-object-proxy==1.4.3 mccabe==0.6.1 -pefile==2021.5.13 +pefile==2021.5.24 pycparser==2.20 pylint==2.4.4 # rq.filter: < 2.5 python-dateutil==2.8.1 @@ -21,5 +21,5 @@ requests==2.25.1 six==1.16.0 typed-ast==1.4.3 ; python_version<"3.8" uritemplate==3.0.1 -# urllib3==1.26.4 +# urllib3==1.26.5 wrapt==1.11.2 diff --git a/misc/requirements/requirements-sphinx.txt b/misc/requirements/requirements-sphinx.txt index 2aa55e0a3..ab8ceb6e5 100644 --- a/misc/requirements/requirements-sphinx.txt +++ b/misc/requirements/requirements-sphinx.txt @@ -2,24 +2,24 @@ alabaster==0.7.12 Babel==2.9.1 -certifi==2020.12.5 +certifi==2021.5.30 chardet==4.0.0 docutils==0.17.1 idna==2.10 imagesize==1.2.0 -Jinja2==2.11.3 -MarkupSafe==1.1.1 +Jinja2==3.0.1 +MarkupSafe==2.0.1 packaging==20.9 Pygments==2.9.0 pyparsing==2.4.7 pytz==2021.1 requests==2.25.1 snowballstemmer==2.1.0 -Sphinx==4.0.1 +Sphinx==4.0.2 sphinxcontrib-applehelp==1.0.2 sphinxcontrib-devhelp==1.0.2 -sphinxcontrib-htmlhelp==1.0.3 +sphinxcontrib-htmlhelp==2.0.0 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 -sphinxcontrib-serializinghtml==1.1.4 -urllib3==1.26.4 +sphinxcontrib-serializinghtml==1.1.5 +urllib3==1.26.5 diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt index 6c83c4fb7..0cdd02555 100644 --- a/misc/requirements/requirements-tests.txt +++ b/misc/requirements/requirements-tests.txt @@ -3,28 +3,28 @@ apipkg==1.5 attrs==21.2.0 beautifulsoup4==4.9.3 -certifi==2020.12.5 +certifi==2021.5.30 chardet==4.0.0 cheroot==8.5.2 -click==8.0.0 +click==8.0.1 coverage==5.5 EasyProcess==0.3 -execnet==1.8.0 +execnet==1.8.1 filelock==3.0.12 -Flask==2.0.0 +Flask==2.0.1 glob2==0.7 hunter==3.3.3 -hypothesis==6.12.0 +hypothesis==6.13.10 icdiff==1.9.1 idna==2.10 iniconfig==1.1.1 -itsdangerous==2.0.0 +itsdangerous==2.0.1 jaraco.functools==3.3.0 -# Jinja2==3.0.0 +# Jinja2==3.0.1 Mako==1.1.4 manhole==1.8.0 -# MarkupSafe==2.0.0 -more-itertools==8.7.0 +# MarkupSafe==2.0.1 +more-itertools==8.8.0 packaging==20.9 parse==1.19.0 parse-type==0.5.2 @@ -44,10 +44,10 @@ pytest-instafail==0.4.2 pytest-mock==3.6.1 pytest-qt==3.3.0 pytest-repeat==0.9.1 -pytest-rerunfailures==9.1.1 +pytest-rerunfailures==10.0 pytest-xdist==2.2.1 pytest-xvfb==2.0.0 -PyVirtualDisplay==2.1 +PyVirtualDisplay==2.2 requests==2.25.1 requests-file==1.5.1 six==1.16.0 @@ -55,6 +55,6 @@ sortedcontainers==2.4.0 soupsieve==2.2.1 tldextract==3.1.0 toml==0.10.2 -urllib3==1.26.4 +urllib3==1.26.5 vulture==2.3 -Werkzeug==2.0.0 +Werkzeug==2.0.1 diff --git a/misc/requirements/requirements-tox.txt b/misc/requirements/requirements-tox.txt index e8fd3f633..8bb7820ce 100644 --- a/misc/requirements/requirements-tox.txt +++ b/misc/requirements/requirements-tox.txt @@ -1,16 +1,16 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py appdirs==1.4.4 -distlib==0.3.1 +distlib==0.3.2 filelock==3.0.12 packaging==20.9 -pip==21.1.1 +pip==21.1.2 pluggy==0.13.1 py==1.10.0 pyparsing==2.4.7 -setuptools==56.2.0 +setuptools==57.0.0 six==1.16.0 toml==0.10.2 tox==3.23.1 -virtualenv==20.4.6 +virtualenv==20.4.7 wheel==0.36.2 diff --git a/misc/userscripts/open_download b/misc/userscripts/open_download index e6de005c8..62730f37c 100755 --- a/misc/userscripts/open_download +++ b/misc/userscripts/open_download @@ -15,7 +15,7 @@ # - It comes in handy if you enable downloads.remove_finished. If you want to # see the recent downloads, just press "sd". # -# Thorsten Wißmann, 2015 (thorsten` on freenode) +# Thorsten Wißmann, 2015 (thorsten` on Libera Chat) # Any feedback is welcome! set -e diff --git a/misc/userscripts/password_fill b/misc/userscripts/password_fill index 4ebeebdc5..c46253d41 100755 --- a/misc/userscripts/password_fill +++ b/misc/userscripts/password_fill @@ -5,7 +5,7 @@ cat <<EOF This script can only be used as a userscript for qutebrowser 2015, Thorsten Wißmann <edu _at_ thorsten-wissmann _dot_ de> In case of questions or suggestions, do not hesitate to send me an E-Mail or to -directly ask me via IRC (nickname thorsten\`) in #qutebrowser on freenode. +directly ask me via IRC (nickname thorsten\`) in #qutebrowser on Libera Chat. $blink!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$reset WARNING: the passwords are stored in qutebrowser's diff --git a/misc/userscripts/view_in_mpv b/misc/userscripts/view_in_mpv index 4ab37d617..472920433 100755 --- a/misc/userscripts/view_in_mpv +++ b/misc/userscripts/view_in_mpv @@ -21,7 +21,7 @@ # (comments and video suggestions), i.e. only the videos should disappear # when mpv is started. And that's precisely what the present script does. # -# Thorsten Wißmann, 2015 (thorsten` on freenode) +# Thorsten Wißmann, 2015 (thorsten` on Libera Chat) # Any feedback is welcome! set -e diff --git a/qutebrowser/__init__.py b/qutebrowser/__init__.py index 96062d9bd..812df63c8 100644 --- a/qutebrowser/__init__.py +++ b/qutebrowser/__init__.py @@ -26,7 +26,7 @@ __copyright__ = "Copyright 2014-2021 Florian Bruhin (The Compiler)" __license__ = "GPL" __maintainer__ = __author__ __email__ = "mail@qutebrowser.org" -__version__ = "2.2.2" +__version__ = "2.2.3" __version_info__ = tuple(int(part) for part in __version__.split('.')) __description__ = "A keyboard-driven, vim-like browser based on PyQt5." diff --git a/qutebrowser/browser/qutescheme.py b/qutebrowser/browser/qutescheme.py index 031b6fe06..68e36d249 100644 --- a/qutebrowser/browser/qutescheme.py +++ b/qutebrowser/browser/qutescheme.py @@ -41,7 +41,7 @@ from qutebrowser.browser import pdfjs, downloads, history from qutebrowser.config import config, configdata, configexc from qutebrowser.utils import (version, utils, jinja, log, message, docutils, resources, objreg, standarddir) -from qutebrowser.misc import guiprocess +from qutebrowser.misc import guiprocess, quitter from qutebrowser.qt import sip @@ -452,6 +452,9 @@ def qute_settings(url: QUrl) -> _HandlerRet: if url.password() != csrf_token: message.error("Invalid CSRF token for qute://settings!") raise RequestDeniedError("Invalid CSRF token!") + if quitter.instance.is_shutting_down: + log.config.debug("Ignoring /set request during shutdown") + return 'text/html', b'error: ignored' return _qute_settings_set(url) # Requests to qute://settings/set should only be allowed from diff --git a/qutebrowser/browser/webengine/notification.py b/qutebrowser/browser/webengine/notification.py index d8387e6d4..6b26157e6 100644 --- a/qutebrowser/browser/webengine/notification.py +++ b/qutebrowser/browser/webengine/notification.py @@ -65,12 +65,18 @@ if TYPE_CHECKING: from qutebrowser.config import config from qutebrowser.misc import objects -from qutebrowser.utils import qtutils, log, utils, debug, message +from qutebrowser.utils import qtutils, log, utils, debug, message, version bridge: Optional['NotificationBridgePresenter'] = None +def _notifications_supported() -> bool: + """Check whether the current QtWebEngine version has notification support.""" + versions = version.qtwebengine_versions(avoid_init=True) + return versions.webengine >= utils.VersionNumber(5, 14) + + def init() -> None: """Initialize the DBus notification presenter, if applicable. @@ -84,7 +90,8 @@ def init() -> None: # at a later point in time. However, doing so is probably too complex compared # to its usefulness. return - if not qtutils.version_check('5.14'): + + if not _notifications_supported(): return global bridge @@ -163,7 +170,7 @@ class NotificationBridgePresenter(QObject): def __init__(self, parent: QObject = None) -> None: super().__init__(parent) - assert qtutils.version_check('5.14') + assert _notifications_supported() self._active_notifications: Dict[int, 'QWebEngineNotification'] = {} self._adapter: Optional[AbstractNotificationAdapter] = None @@ -709,8 +716,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): def __init__(self, parent: QObject = None) -> None: super().__init__(bridge) - if not qtutils.version_check('5.14'): - raise Error("Notifications are not supported on Qt < 5.14") + assert _notifications_supported() if utils.is_windows: # The QDBusConnection destructor seems to cause error messages (and @@ -778,7 +784,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): self, name: str, vendor: str, - version: str, + ver: str, ) -> Optional[_ServerQuirks]: """Find quirks to use based on the server information.""" if (name, vendor) == ("notify-osd", "Canonical Ltd"): @@ -791,15 +797,15 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): # Still in active development but doesn't implement spec 1.2: # https://github.com/mate-desktop/mate-notification-daemon/issues/132 quirks = _ServerQuirks(spec_version="1.1") - if utils.VersionNumber.parse(version) <= utils.VersionNumber(1, 24): + if utils.VersionNumber.parse(ver) <= utils.VersionNumber(1, 24): # https://github.com/mate-desktop/mate-notification-daemon/issues/118 quirks.avoid_body_hyperlinks = True return quirks - elif (name, vendor) == ("naughty", "awesome") and version != "devel": + elif (name, vendor) == ("naughty", "awesome") and ver != "devel": # Still in active development but spec 1.0/1.2 support isn't # released yet: # https://github.com/awesomeWM/awesome/commit/e076bc664e0764a3d3a0164dabd9b58d334355f4 - parsed_version = utils.VersionNumber.parse(version.lstrip('v')) + parsed_version = utils.VersionNumber.parse(ver.lstrip('v')) if parsed_version <= utils.VersionNumber(4, 3): return _ServerQuirks(spec_version="1.0") elif (name, vendor) == ("twmnd", "twmnd"): @@ -810,7 +816,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): return _ServerQuirks(skip_capabilities=True) elif (name, vendor) == ("lxqt-notificationd", "lxqt.org"): quirks = _ServerQuirks() - parsed_version = utils.VersionNumber.parse(version) + parsed_version = utils.VersionNumber.parse(ver) if parsed_version <= utils.VersionNumber(0, 16): # https://github.com/lxqt/lxqt-notificationd/issues/253 quirks.escape_title = True @@ -843,13 +849,13 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): """Query notification server information and set quirks.""" reply = self.interface.call(QDBus.BlockWithGui, "GetServerInformation") self._verify_message(reply, "ssss", QDBusMessage.ReplyMessage) - name, vendor, version, spec_version = reply.arguments() + name, vendor, ver, spec_version = reply.arguments() log.misc.debug( - f"Connected to notification server: {name} {version} by {vendor}, " + f"Connected to notification server: {name} {ver} by {vendor}, " f"implementing spec {spec_version}") - quirks = self._find_quirks(name, vendor, version) + quirks = self._find_quirks(name, vendor, ver) if quirks is not None: log.misc.debug(f"Enabling quirks {quirks}") self._quirks = quirks @@ -857,7 +863,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter): expected_spec_version = self._quirks.spec_version or self.SPEC_VERSION if spec_version != expected_spec_version: log.misc.warning( - f"Notification server ({name} {version} by {vendor}) implements " + f"Notification server ({name} {ver} by {vendor}) implements " f"spec {spec_version}, but {expected_spec_version} was expected. " f"If {name} is up to date, please report a qutebrowser bug.") diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index c793a1929..f9b636bde 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -401,6 +401,16 @@ class WebEngineCaret(browsertab.AbstractCaret): self._js_call('reverseSelection') def _follow_selected_cb_wrapped(self, js_elem, tab): + if sip.isdeleted(self): + # Sometimes, QtWebEngine JS callbacks seem to be stuck, and will + # later get executed when the tab is closed. However, at this point, + # the WebEngineCaret is already gone. + log.webview.warning( + "Got follow_selected callback for deleted WebEngineCaret. " + "This is most likely due to a QtWebEngine bug, please report a " + "qutebrowser issue if you know a way to reproduce this.") + return + try: self._follow_selected_cb(js_elem, tab) finally: @@ -1593,7 +1603,9 @@ class WebEngineTab(browsertab.AbstractTab): up doing it twice. """ super()._on_url_changed(url) - if url.isValid() and qtutils.version_check('5.13'): + if (url.isValid() and + qtutils.version_check('5.13') and + not qtutils.version_check('5.14')): self.settings.update_for_url(url) @pyqtSlot(usertypes.NavigationRequest) diff --git a/qutebrowser/components/braveadblock.py b/qutebrowser/components/braveadblock.py index 0a39d5491..bd30f5d29 100644 --- a/qutebrowser/components/braveadblock.py +++ b/qutebrowser/components/braveadblock.py @@ -211,7 +211,15 @@ class BraveAdBlocker: if cache_exists: logger.debug("Loading cached adblock data: %s", self._cache_path) - self._engine.deserialize_from_file(str(self._cache_path)) + try: + self._engine.deserialize_from_file(str(self._cache_path)) + except ValueError as e: + if str(e) != "DeserializationError": + # All Rust exceptions get turned into a ValueError by + # python-adblock + raise + message.error("Reading adblock filter data failed (corrupted data?). " + "Please run :adblock-update.") else: if ( config.val.content.blocking.adblock.lists diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 80732d43d..b85e84be2 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -582,6 +582,7 @@ content.headers.accept_language: type: name: String none_ok: true + encoding: ascii supports_pattern: true default: en-US,en;q=0.9 desc: >- @@ -643,6 +644,7 @@ content.headers.user_agent: Safari/{webkit_version}' type: name: FormatString + encoding: ascii fields: - os_info - webkit_version diff --git a/qutebrowser/config/configtypes.py b/qutebrowser/config/configtypes.py index c157fba41..d3d5e3fb8 100644 --- a/qutebrowser/config/configtypes.py +++ b/qutebrowser/config/configtypes.py @@ -86,6 +86,21 @@ _UnsetNone = Union[None, usertypes.Unset] _StrUnsetNone = Union[str, _UnsetNone] +def _validate_encoding(encoding: Optional[str], value: str) -> None: + """Check if the given value fits into the given encoding. + + Raises ValidationError if not. + """ + if encoding is None: + return + + try: + value.encode(encoding) + except UnicodeEncodeError as e: + msg = f"{value!r} contains non-{encoding} characters: {e}" + raise configexc.ValidationError(value, msg) + + class ValidValues: """Container for valid values for a given type. @@ -377,6 +392,7 @@ class String(BaseType): maxlen: Maximum length (inclusive). forbidden: Forbidden chars in the string. regex: A regex used to validate the string. + encoding: The encoding the value needs to fit in. completions: completions to be used, or None """ @@ -407,24 +423,6 @@ class String(BaseType): self.encoding = encoding self.regex = regex - def _validate_encoding(self, value: str) -> None: - """Check if the given value fits into the configured encoding. - - Raises ValidationError if not. - - Args: - value: The value to check. - """ - if self.encoding is None: - return - - try: - value.encode(self.encoding) - except UnicodeEncodeError as e: - msg = "{!r} contains non-{} characters: {}".format( - value, self.encoding, e) - raise configexc.ValidationError(value, msg) - def to_py(self, value: _StrUnset) -> _StrUnsetNone: self._basic_py_validation(value, str) if isinstance(value, usertypes.Unset): @@ -432,7 +430,7 @@ class String(BaseType): elif not value: return None - self._validate_encoding(value) + _validate_encoding(self.encoding, value) self._validate_valid_values(value) if self.forbidden is not None and any(c in value @@ -1544,6 +1542,7 @@ class FormatString(BaseType): Attributes: fields: Which replacements are allowed in the format string. + encoding: Which encoding the string should fit into. completions: completions to be used, or None """ @@ -1551,11 +1550,13 @@ class FormatString(BaseType): self, *, fields: Iterable[str], none_ok: bool = False, + encoding: str = None, completions: _Completions = None, ) -> None: super().__init__( none_ok=none_ok, completions=completions) self.fields = fields + self.encoding = encoding self._completions = completions def to_py(self, value: _StrUnset) -> _StrUnsetNone: @@ -1565,6 +1566,8 @@ class FormatString(BaseType): elif not value: return None + _validate_encoding(self.encoding, value) + try: value.format(**{k: '' for k in self.fields}) except (KeyError, IndexError, AttributeError) as e: diff --git a/qutebrowser/misc/editor.py b/qutebrowser/misc/editor.py index 5741c6b47..d561a7b96 100644 --- a/qutebrowser/misc/editor.py +++ b/qutebrowser/misc/editor.py @@ -131,7 +131,7 @@ class ExternalEditor(QObject): raise ValueError("Already editing a file!") try: self._filename = self._create_tempfile(text, 'qutebrowser-editor-') - except OSError as e: + except (OSError, UnicodeEncodeError) as e: message.error("Failed to create initial file: {}".format(e)) return diff --git a/qutebrowser/misc/quitter.py b/qutebrowser/misc/quitter.py index 7d84c57f2..a51891685 100644 --- a/qutebrowser/misc/quitter.py +++ b/qutebrowser/misc/quitter.py @@ -54,7 +54,7 @@ class Quitter(QObject): Attributes: quit_status: The current quitting status. - _is_shutting_down: Whether we're currently shutting down. + is_shutting_down: Whether we're currently shutting down. _args: The argparse namespace. """ @@ -69,7 +69,7 @@ class Quitter(QObject): 'tabs': False, 'main': False, } - self._is_shutting_down = False + self.is_shutting_down = False self._args = args def on_last_window_closed(self) -> None: @@ -214,9 +214,9 @@ class Quitter(QObject): closing. is_restart: If we're planning to restart. """ - if self._is_shutting_down: + if self.is_shutting_down: return - self._is_shutting_down = True + self.is_shutting_down = True log.destroy.debug("Shutting down with status {}, session {}...".format( status, session)) diff --git a/qutebrowser/utils/log.py b/qutebrowser/utils/log.py index b6f1f3e9b..9cd07e2e3 100644 --- a/qutebrowser/utils/log.py +++ b/qutebrowser/utils/log.py @@ -33,7 +33,7 @@ import json import inspect import argparse from typing import (TYPE_CHECKING, Any, Iterator, Mapping, MutableSequence, - Optional, Set, Tuple, Union, cast) + Optional, Set, Tuple, Union) from PyQt5 import QtCore # Optional imports @@ -363,12 +363,16 @@ def change_console_formatter(level: int) -> None: level: The numeric logging level """ assert console_handler is not None + old_formatter = console_handler.formatter - old_formatter = cast(ColoredFormatter, console_handler.formatter) - console_fmt = get_console_format(level) - console_formatter = ColoredFormatter(console_fmt, DATEFMT, '{', - use_colors=old_formatter.use_colors) - console_handler.setFormatter(console_formatter) + if isinstance(old_formatter, ColoredFormatter): + console_fmt = get_console_format(level) + console_formatter = ColoredFormatter( + console_fmt, DATEFMT, '{', use_colors=old_formatter.use_colors) + console_handler.setFormatter(console_formatter) + else: + # Same format for all levels + assert isinstance(old_formatter, JSONFormatter), old_formatter def qt_message_handler(msg_type: QtCore.QtMsgType, diff --git a/requirements.txt b/requirements.txt index 88033d3e7..4163885b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,10 +3,10 @@ adblock==0.4.4 colorama==0.4.4 dataclasses==0.6 ; python_version<"3.7" -importlib-metadata==4.0.1 ; python_version<"3.8" -importlib-resources==5.1.3 ; python_version<"3.9" -Jinja2==3.0.0 -MarkupSafe==2.0.0 +importlib-metadata==4.3.1 ; python_version<"3.8" +importlib-resources==5.1.4 ; python_version<"3.9" +Jinja2==3.0.1 +MarkupSafe==2.0.1 Pygments==2.9.0 PyYAML==5.4.1 typing-extensions==3.10.0.0 diff --git a/scripts/cycle-inputs.js b/scripts/cycle-inputs.js index bb667bda7..fc2397c23 100644 --- a/scripts/cycle-inputs.js +++ b/scripts/cycle-inputs.js @@ -6,7 +6,7 @@ * CYCLE_INPUTS = "jseval -q -f ~/.config/qutebrowser/cycle-inputs.js" * config.bind('gi', CYCLE_INPUTS) * - * By dive on freenode <dave@dawoodfall.net> + * By dive <dave@dawoodfall.net> */ (function() { diff --git a/scripts/dev/build_release.py b/scripts/dev/build_release.py index be6492358..2ca97de11 100755 --- a/scripts/dev/build_release.py +++ b/scripts/dev/build_release.py @@ -269,7 +269,22 @@ INFO_PLIST_UPDATES = { "CFBundleTypeMIMETypes": ["text/xhtml"], "CFBundleTypeName": "XHTML document", "CFBundleTypeRole": "Viewer", - }] + }], + + # https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos + # + # Keys based on Google Chrome's .app, except Bluetooth keys which seem to + # be iOS-only. + # + # If we don't do this, we get a SIGABRT from macOS when those permissions + # are used, and even in some other situations (like logging into Google + # accounts)... + 'NSCameraUsageDescription': + 'A website in qutebrowser wants to use the camera.', + 'NSLocationUsageDescription': + 'A website in qutebrowser wants to use your location information.', + 'NSMicrophoneUsageDescription': + 'A website in qutebrowser wants to use your microphone.', } diff --git a/tests/end2end/data/downloads/mhtml/complex/complex.html b/tests/end2end/data/downloads/mhtml/complex/complex.html index b298aa37c..d44e9be0f 100644 --- a/tests/end2end/data/downloads/mhtml/complex/complex.html +++ b/tests/end2end/data/downloads/mhtml/complex/complex.html @@ -91,7 +91,7 @@ <div class="dyk"> ...the IRC channel for qutebrowser is <code>#qutebrowser</code> on - irc.freenode.net + irc.libera.chat </div> <div class="dyk"> diff --git a/tests/end2end/data/downloads/mhtml/complex/complex.mht b/tests/end2end/data/downloads/mhtml/complex/complex.mht index 0467da22f..a458f4dcb 100644 --- a/tests/end2end/data/downloads/mhtml/complex/complex.mht +++ b/tests/end2end/data/downloads/mhtml/complex/complex.mht @@ -108,7 +108,7 @@ aster/doc/contributing.asciidoc"> =20
<div class=3D"dyk">
...the IRC channel for qutebrowser is <code>#qutebrowser</code> on
- irc.freenode.net
+ irc.libera.chat
</div>
=20
<div class=3D"dyk">
diff --git a/tests/end2end/fixtures/testprocess.py b/tests/end2end/fixtures/testprocess.py index 33b154e9a..96e700390 100644 --- a/tests/end2end/fixtures/testprocess.py +++ b/tests/end2end/fixtures/testprocess.py @@ -25,7 +25,7 @@ import warnings import dataclasses import pytest -import pytestqt.plugin +import pytestqt.wait_signal from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QProcess, QObject, QElapsedTimer, QProcessEnvironment) from PyQt5.QtTest import QSignalSpy @@ -198,8 +198,7 @@ class Process(QObject): Should be used in a contextmanager. """ - blocker = pytestqt.plugin.SignalBlocker(timeout=timeout, - raising=raising) + blocker = pytestqt.wait_signal.SignalBlocker(timeout=timeout, raising=raising) blocker.connect(signal) return blocker diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py index 1ce22b7ea..97c04eb0d 100644 --- a/tests/end2end/test_invocations.py +++ b/tests/end2end/test_invocations.py @@ -26,6 +26,7 @@ import logging import importlib import re import json +import platform import pytest from PyQt5.QtCore import QProcess, QPoint @@ -39,6 +40,14 @@ ascii_locale = pytest.mark.skipif(sys.hexversion >= 0x03070000, "locale with LC_ALL=C") +# For some reason (some floating point rounding differences?), color values are +# slightly different (and wrong!) on ARM machines. We adjust our expected values +# accordingly, since we don't really care about the exact value, we just want to +# know that the underlying Chromium is respecting our preferences. +# FIXME what to do about 32-bit ARM? +IS_ARM = platform.machine() == 'aarch64' + + def _base_args(config): """Get the arguments to pass with every invocation.""" args = ['--debug', '--json-logging', '--no-err-windows'] @@ -55,7 +64,16 @@ def _base_args(config): @pytest.fixture -def temp_basedir_env(tmp_path, short_tmpdir): +def runtime_tmpdir(short_tmpdir): + """A directory suitable for XDG_RUNTIME_DIR.""" + runtime_dir = short_tmpdir / 'rt' + runtime_dir.ensure(dir=True) + runtime_dir.chmod(0o700) + return runtime_dir + + +@pytest.fixture +def temp_basedir_env(tmp_path, runtime_tmpdir): """Return a dict of environment variables that fakes --temp-basedir. We can't run --basedir or --temp-basedir for some tests, so we mess with @@ -63,12 +81,8 @@ def temp_basedir_env(tmp_path, short_tmpdir): """ data_dir = tmp_path / 'data' config_dir = tmp_path / 'config' - runtime_dir = short_tmpdir / 'rt' cache_dir = tmp_path / 'cache' - runtime_dir.ensure(dir=True) - runtime_dir.chmod(0o700) - lines = [ '[general]', 'quickstart-done = 1', @@ -83,7 +97,7 @@ def temp_basedir_env(tmp_path, short_tmpdir): env = { 'XDG_DATA_HOME': str(data_dir), 'XDG_CONFIG_HOME': str(config_dir), - 'XDG_RUNTIME_DIR': str(runtime_dir), + 'XDG_RUNTIME_DIR': str(runtime_tmpdir), 'XDG_CACHE_HOME': str(cache_dir), } return env @@ -512,7 +526,8 @@ def test_preferred_colorscheme_with_dark_mode( # No workaround known. expected_text = 'Light preference detected.' # light website color, inverted by darkmode - expected_color = testutils.Color(127, 127, 127) + expected_color = (testutils.Color(123, 125, 123) if IS_ARM + else testutils.Color(127, 127, 127)) xfail = "Chromium bug 1177973" elif qtwe_version == utils.VersionNumber(5, 15, 2): # Our workaround breaks when dark mode is enabled... @@ -524,7 +539,8 @@ def test_preferred_colorscheme_with_dark_mode( # Qt 5.14 and 5.15.0/.1 work correctly. # Hopefully, so does Qt 6.x in the future? expected_text = 'Dark preference detected.' - expected_color = testutils.Color(34, 34, 34) # dark website color + expected_color = (testutils.Color(33, 32, 33) if IS_ARM + else testutils.Color(34, 34, 34)) # dark website color xfail = False pos = QPoint(0, 0) @@ -625,30 +641,51 @@ def test_cookies_store(quteproc_new, request, short_tmpdir, store): quteproc_new.wait_for_quit() +# The 'colors' dictionaries in the parametrize decorator below have (QtWebEngine +# version, CPU architecture) as keys. Either of those (or both) can be None to +# say "on all other Qt versions" or "on all other CPU architectures". @pytest.mark.parametrize('filename, algorithm, colors', [ ( 'blank', 'lightness-cielab', { - '5.15': testutils.Color(18, 18, 18), - '5.14': testutils.Color(27, 27, 27), - None: testutils.Color(0, 0, 0), + ('5.15', None): testutils.Color(18, 18, 18), + ('5.15', 'aarch64'): testutils.Color(16, 16, 16), + ('5.14', None): testutils.Color(27, 27, 27), + ('5.14', 'aarch64'): testutils.Color(24, 24, 24), + (None, None): testutils.Color(0, 0, 0), } ), - ('blank', 'lightness-hsl', {None: testutils.Color(0, 0, 0)}), - ('blank', 'brightness-rgb', {None: testutils.Color(0, 0, 0)}), + ('blank', 'lightness-hsl', {(None, None): testutils.Color(0, 0, 0)}), + ('blank', 'brightness-rgb', {(None, None): testutils.Color(0, 0, 0)}), ( 'yellow', 'lightness-cielab', { - '5.15': testutils.Color(35, 34, 0), - '5.14': testutils.Color(35, 34, 0), - None: testutils.Color(204, 204, 0), + ('5.15', None): testutils.Color(35, 34, 0), + ('5.15', 'aarch64'): testutils.Color(33, 32, 0), + ('5.14', None): testutils.Color(35, 34, 0), + ('5.14', 'aarch64'): testutils.Color(33, 32, 0), + (None, None): testutils.Color(204, 204, 0), + } + ), + ( + 'yellow', + 'lightness-hsl', + { + (None, None): testutils.Color(204, 204, 0), + (None, 'aarch64'): testutils.Color(206, 207, 0), + }, + ), + ( + 'yellow', + 'brightness-rgb', + { + (None, None): testutils.Color(0, 0, 204), + (None, 'aarch64'): testutils.Color(0, 0, 206), } ), - ('yellow', 'lightness-hsl', {None: testutils.Color(204, 204, 0)}), - ('yellow', 'brightness-rgb', {None: testutils.Color(0, 0, 204)}), ]) def test_dark_mode(webengine_versions, quteproc_new, request, filename, algorithm, colors): @@ -664,7 +701,17 @@ def test_dark_mode(webengine_versions, quteproc_new, request, ver = webengine_versions.webengine minor_version = str(ver.strip_patch()) - expected = colors.get(minor_version, colors[None]) + + arch = platform.machine() + for key in [ + (minor_version, arch), + (minor_version, None), + (None, arch), + (None, None), + ]: + if key in colors: + expected = colors[key] + break quteproc_new.open_path(f'data/darkmode/{filename}.html') @@ -691,9 +738,11 @@ def test_dark_mode_mathml(quteproc_new, request, qtbot): quteproc_new.wait_for_js('Image loaded') # First make sure loading finished by looking outside of the image + expected = testutils.Color(0, 0, 206) if IS_ARM else testutils.Color(0, 0, 204) + quteproc_new.get_screenshot( probe_pos=QPoint(105, 0), - probe_color=testutils.Color(0, 0, 204), + probe_color=expected, ) # Then get the actual formula color, probing again in case it's not displayed yet... @@ -743,3 +792,14 @@ def test_unavailable_backend(request, quteproc_new): message=('*qutebrowser tried to start with the Qt* backend but failed ' 'because * could not be imported.*')) line.expected = True + + +def test_json_logging_without_debug(request, quteproc_new, runtime_tmpdir): + args = _base_args(request.config) + ['--temp-basedir', ':quit'] + args.remove('--debug') + args.remove('about:blank') # interfers with :quit at the end + + 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 diff --git a/tests/unit/config/test_configtypes.py b/tests/unit/config/test_configtypes.py index 3e1d15099..66b152937 100644 --- a/tests/unit/config/test_configtypes.py +++ b/tests/unit/config/test_configtypes.py @@ -1839,6 +1839,11 @@ class TestFormatString: with pytest.raises(configexc.ValidationError): typ.to_py(val) + def test_invalid_encoding(self, klass): + typ = klass(fields=[], encoding='ascii') + with pytest.raises(configexc.ValidationError): + typ.to_py('fooäbar') + @pytest.mark.parametrize('value', [ None, ['one', 'two'], diff --git a/tests/unit/config/test_configutils.py b/tests/unit/config/test_configutils.py index 725a38c28..e7ce15aff 100644 --- a/tests/unit/config/test_configutils.py +++ b/tests/unit/config/test_configutils.py @@ -382,5 +382,9 @@ class TestFontFamilies: if info.family() == fallback_family: return + if info.family() == 'Noto Sans Mono': + # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-94090 + return + # If we didn't fall back, we should've gotten a fixed-pitch font. assert info.fixedPitch(), info.family() diff --git a/tests/unit/misc/test_editor.py b/tests/unit/misc/test_editor.py index cd21308f8..8e5597a0e 100644 --- a/tests/unit/misc/test_editor.py +++ b/tests/unit/misc/test_editor.py @@ -148,6 +148,17 @@ class TestFileHandling: assert msg.text.startswith("Failed to create initial file: ") assert editor._proc is None + def test_encode_error(self, message_mock, editor, caplog, config_stub): + """Test file handling when the initial text can't be encoded.""" + config_stub.val.editor.encoding = 'ascii' + + with caplog.at_level(logging.ERROR): + editor.edit("fooäbar") + + msg = message_mock.getmsg(usertypes.MessageLevel.error) + assert msg.text.startswith("Failed to create initial file: ") + assert editor._proc is None + def test_double_edit(self, editor): editor.edit("") with pytest.raises(ValueError): |