diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index f5e91a340..233a86865 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -49,6 +49,11 @@ Changed resource system (rather than compiling them into a Qt resource file). Packagers are advised to use `misc/Makefile` if possible, which has been updated with the new paths. +- The `content.javascript.can_access_clipboard` setting got renamed to + `content.javascript.clipboard` and now understands three different values + rather than being a boolean: `none` (formerly `false`), `access` (formerly + `true`) and `access-paste` (additionally allows pasting content, needed for + websites like Photopea or GitHub Codespaces). [[v2.5.1]] v2.5.1 (unreleased) @@ -59,6 +64,8 @@ Fixed - The `qute-pass` userscript is marked as executable again. - PDF.js now works properly again with the macOS and Windows releases. +- The MathML workaround for darkmode (e.g. black on black Wikipedia formula) + now also works for display (rather than inline) math. - Fixes for various notification-related crashes: * With the `tiramisu` notification server (due to invalid behavior of the server, now a non-fatal error) * With the `budgie` notification server when closing a notification (due to invalid behavior of the server, now worked around) diff --git a/doc/faq.asciidoc b/doc/faq.asciidoc index 503893b66..4b3596285 100644 --- a/doc/faq.asciidoc +++ b/doc/faq.asciidoc @@ -354,9 +354,9 @@ There is a total of four possible approaches to get dark websites: of the Dark Reader extension. This is mostly untested, though. How do I make copy to clipboard buttons work?:: -You can `:set content.javascript.can_access_clipboard true`, or -`:set -u some.domain content.javascript.can_access_clipboard true` if you want to limit -the setting to `some.domain`. +You can `:set content.javascript.clipboard access` to allow this globally (not +recommended!), or `:set -u some.domain content.javascript.clipboad access` if +you want to limit the setting to `some.domain`. == Troubleshooting diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index 2f60525f4..f43548629 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -167,9 +167,9 @@ |<>|Enable hyperlink auditing (``). |<>|Load images automatically in web pages. |<>|Show javascript alerts. -|<>|Allow JavaScript to read from or write to the clipboard. |<>|Allow JavaScript to close tabs. |<>|Allow JavaScript to open new tabs without user interaction. +|<>|Allow JavaScript to read from or write to the clipboard. |<>|Enable JavaScript. |<>|Log levels to use for JavaScript console logging messages. |<>|Use the standard JavaScript modal dialog for `alert()` and `confirm()`. @@ -2333,17 +2333,6 @@ Type: <> Default: +pass:[true]+ -[[content.javascript.can_access_clipboard]] -=== content.javascript.can_access_clipboard -Allow JavaScript to read from or write to the clipboard. -With QtWebEngine, writing the clipboard as response to a user interaction is always allowed. - -This setting supports link:configuring{outfilesuffix}#patterns[URL patterns]. - -Type: <> - -Default: +pass:[false]+ - [[content.javascript.can_close_tabs]] === content.javascript.can_close_tabs Allow JavaScript to close tabs. @@ -2366,6 +2355,23 @@ Type: <> Default: +pass:[false]+ +[[content.javascript.clipboard]] +=== content.javascript.clipboard +Allow JavaScript to read from or write to the clipboard. +With QtWebEngine, writing the clipboard as response to a user interaction is always allowed. + +This setting supports link:configuring{outfilesuffix}#patterns[URL patterns]. + +Type: <> + +Valid values: + + * +none+: Disable access to clipboard. + * +access+: Allow reading from and writing to the clipboard. + * +access-paste+: Allow accessing the clipboard and pasting clipboard content. + +Default: +pass:[none]+ + [[content.javascript.enabled]] === content.javascript.enabled Enable JavaScript. diff --git a/doc/stacktrace.asciidoc b/doc/stacktrace.asciidoc index 3d95aa25e..87410bd48 100644 --- a/doc/stacktrace.asciidoc +++ b/doc/stacktrace.asciidoc @@ -68,55 +68,13 @@ Then install the needed debuginfo packages: Archlinux ^^^^^^^^^ -For Archlinux, no debug information is provided. You can either compile Qt -yourself (which will take a few hours even on a modern machine) or use -debugging symbols compiled/packaged by me (x86_64 only). - -To install my pre-built packages -++++++++++++++++++++++++++++++++ - -First download and sign the key: +For Archlinux, debug information is provided via their https://wiki.archlinux.org/title/Debuginfod[Debuginfod instance]. To use it, set the following in your environment: ---- -# pacman-key -r 0xD6A1C70FE80A0C82 -$ pacman-key -f 0xD6A1C70FE80A0C82 - Key fingerprint = 14AF EC28 70C6 4863 C5C7 ACCB D6A1 C70F E80A 0C82 -# pacman-key --lsign-key 0xD6A1C70FE80A0C82 +DEBUGINFOD_URLS="https://debuginfod.archlinux.org/" ---- -Then edit your `/etc/pacman.conf` to add the repository to the bottom: - ----- -[qt-debug] -Server = https://qutebrowser.org/qt-debug/$arch ----- - -Then install the packages: - ----- -# pacman -Suy python-pyqt5-debug qt5-base-debug qt5-webkit-debug qt5-webengine-debug ----- - -The `-debug` packages conflict with the non-debug variants - it's safe to -remove them. - -To compile by yourself -++++++++++++++++++++++ - -Note that building Qt will likely take multiple hours, even on a recent system. -I'd also expect it to take around 6 GB of RAM and 30 GB of disk space for a -successful compile run. - ----- -$ git clone https://github.com/qutebrowser/qt-debug-pkgbuild.git -$ cd qt-debug-pkgbuild -$ export DEBUG_CFLAGS='-ggdb3 -fvar-tracking-assignments -Og' -$ export DEBUG_CXXFLAGS='-ggdb3 -fvar-tracking-assignments -Og' -$ cd qt5 -$ makepkg -si --pkg qt5-base-debug,qt5-webkit-debug,qt5-webengine-debug -$ cd ../pyqt5 -$ makepkg -si --pkg python-pyqt5-debug ----- +(Until early 2021, there was a custom [`qt-debug` repository](https://github.com/qutebrowser/qt-debug-pkgbuild). This is now archived.) Getting the stack trace ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt index 462ea6e9e..9a4bb1a39 100644 --- a/misc/requirements/requirements-dev.txt +++ b/misc/requirements/requirements-dev.txt @@ -7,7 +7,7 @@ certifi==2021.10.8 cffi==1.15.0 charset-normalizer==2.0.12 commonmark==0.9.1 -cryptography==37.0.1 +cryptography==37.0.2 docutils==0.18.1 github3.py==3.2.0 hunter==3.4.3 @@ -31,7 +31,7 @@ readme-renderer==35.0 requests==2.27.1 requests-toolbelt==0.9.1 rfc3986==2.0.0 -rich==12.3.0 +rich==12.4.1 SecretStorage==3.3.2 sip==6.6.1 six==1.16.0 diff --git a/misc/requirements/requirements-flake8.txt b/misc/requirements/requirements-flake8.txt index 8cfd81966..0efee2d73 100644 --- a/misc/requirements/requirements-flake8.txt +++ b/misc/requirements/requirements-flake8.txt @@ -15,7 +15,7 @@ flake8-plugin-utils==1.3.2 flake8-polyfill==1.0.2 flake8-pytest-style==1.6.0 flake8-string-format==0.3.0 -flake8-tidy-imports==4.6.0 +flake8-tidy-imports==4.7.0 flake8-tuple==0.4.1 mccabe==0.6.1 pep8-naming==0.12.1 diff --git a/misc/requirements/requirements-pylint.txt b/misc/requirements/requirements-pylint.txt index 5a21eb210..4bcc7ca53 100644 --- a/misc/requirements/requirements-pylint.txt +++ b/misc/requirements/requirements-pylint.txt @@ -1,10 +1,10 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -astroid==2.11.2 +astroid==2.11.4 certifi==2021.10.8 cffi==1.15.0 charset-normalizer==2.0.12 -cryptography==37.0.1 +cryptography==37.0.2 dill==0.3.4 future==0.18.2 github3.py==3.2.0 @@ -16,7 +16,7 @@ pefile==2021.9.3 platformdirs==2.5.2 pycparser==2.21 PyJWT==2.3.0 -pylint==2.13.5 +pylint==2.13.8 python-dateutil==2.8.2 ./scripts/dev/pylint_checkers requests==2.27.1 @@ -26,4 +26,4 @@ typed-ast==1.5.3 ; python_version<"3.8" typing_extensions==4.2.0 uritemplate==4.1.1 # urllib3==1.26.9 -wrapt==1.14.0 +wrapt==1.14.1 diff --git a/misc/requirements/requirements-pylint.txt-raw b/misc/requirements/requirements-pylint.txt-raw index 0d59fc96d..54e12a02a 100644 --- a/misc/requirements/requirements-pylint.txt-raw +++ b/misc/requirements/requirements-pylint.txt-raw @@ -1,6 +1,4 @@ pylint -# WORKAROUND for https://github.com/PyCQA/pylint/issues/6438#issuecomment-1108747642 -astroid != 2.11.3 ./scripts/dev/pylint_checkers requests github3.py diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt index e77cf12d5..e3b0dcd4b 100644 --- a/misc/requirements/requirements-tests.txt +++ b/misc/requirements/requirements-tests.txt @@ -12,10 +12,8 @@ filelock==3.6.0 Flask==2.1.2 glob2==0.7 hunter==3.4.3 -hypothesis==6.46.1 -icdiff==2.0.5 +hypothesis==6.46.2 idna==3.3 -importlib-metadata==4.11.3 iniconfig==1.1.1 itsdangerous==2.1.2 jaraco.functools==3.5.0 @@ -23,12 +21,11 @@ jaraco.functools==3.5.0 Mako==1.2.0 manhole==1.8.0 # MarkupSafe==2.1.1 -more-itertools==8.12.0 +more-itertools==8.13.0 packaging==21.3 parse==1.19.0 parse-type==0.6.0 pluggy==1.0.0 -pprintpp==0.4.0 py==1.11.0 py-cpuinfo==8.0.0 Pygments==2.12.0 @@ -38,7 +35,6 @@ pytest-bdd==4.1.0 pytest-benchmark==3.4.1 pytest-cov==3.0.0 pytest-forked==1.4.0 -pytest-icdiff==0.5 pytest-instafail==0.4.2 pytest-mock==3.7.0 pytest-qt==4.0.2 @@ -52,10 +48,9 @@ requests-file==1.5.1 six==1.16.0 sortedcontainers==2.4.0 soupsieve==2.3.2.post1 -tldextract==3.2.1 +tldextract==3.3.0 toml==0.10.2 tomli==2.0.1 urllib3==1.26.9 vulture==2.3 Werkzeug==2.1.2 -zipp==3.8.0 diff --git a/misc/requirements/requirements-tests.txt-raw b/misc/requirements/requirements-tests.txt-raw index 5586a86ef..f5edc9b6d 100644 --- a/misc/requirements/requirements-tests.txt-raw +++ b/misc/requirements/requirements-tests.txt-raw @@ -28,8 +28,6 @@ pytest-xvfb PyVirtualDisplay # To run on multiple cores with -n pytest-xdist -# For nicer output -pytest-icdiff # Needed to test misc/userscripts/qute-lastpass tldextract diff --git a/qutebrowser/browser/shared.py b/qutebrowser/browser/shared.py index f195bbf28..3ea323d96 100644 --- a/qutebrowser/browser/shared.py +++ b/qutebrowser/browser/shared.py @@ -341,7 +341,8 @@ def get_user_stylesheet(searching=False): 'misc-mathml-darkmode' not in config.val.content.site_specific_quirks.skip): # WORKAROUND for MathML-output on Wikipedia being black on black. # See https://bugs.chromium.org/p/chromium/issues/detail?id=1126606 - css += '\nimg.mwe-math-fallback-image-inline { filter: invert(100%); }' + css += ('\nimg.mwe-math-fallback-image-inline, ' + 'img.mwe-math-fallback-image-display { filter: invert(100%); }') return css diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index 0b25726c0..ad374ed9b 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -117,8 +117,6 @@ class WebEngineSettings(websettings.AbstractSettings): Attr(QWebEngineSettings.JavascriptEnabled), 'content.javascript.can_open_tabs_automatically': Attr(QWebEngineSettings.JavascriptCanOpenWindows), - 'content.javascript.can_access_clipboard': - Attr(QWebEngineSettings.JavascriptCanAccessClipboard), 'content.plugins': Attr(QWebEngineSettings.PluginsEnabled), 'content.hyperlink_auditing': @@ -199,26 +197,47 @@ class WebEngineSettings(websettings.AbstractSettings): QWebEngineSettings.FantasyFont: QFont.Fantasy, } - def set_unknown_url_scheme_policy( - self, policy: Union[str, usertypes.Unset]) -> bool: - """Set the UnknownUrlSchemePolicy to use. + _JS_CLIPBOARD_SETTINGS = { + 'none': { + QWebEngineSettings.WebAttribute.JavascriptCanAccessClipboard: False, + QWebEngineSettings.WebAttribute.JavascriptCanPaste: False, + }, + 'access': { + QWebEngineSettings.WebAttribute.JavascriptCanAccessClipboard: True, + QWebEngineSettings.WebAttribute.JavascriptCanPaste: False, + }, + 'access-paste': { + QWebEngineSettings.WebAttribute.JavascriptCanAccessClipboard: True, + QWebEngineSettings.WebAttribute.JavascriptCanPaste: True, + }, + } - Return: - True if there was a change, False otherwise. - """ - old_value = self._settings.unknownUrlSchemePolicy() + def set_unknown_url_scheme_policy( + self, policy: Union[str, usertypes.Unset]) -> None: + """Set the UnknownUrlSchemePolicy to use.""" if isinstance(policy, usertypes.Unset): self._settings.resetUnknownUrlSchemePolicy() - new_value = self._settings.unknownUrlSchemePolicy() else: new_value = self._UNKNOWN_URL_SCHEME_POLICY[policy] self._settings.setUnknownUrlSchemePolicy(new_value) - return old_value != new_value + + def _set_js_clipboard(self, value: Union[str, usertypes.Unset]) -> None: + attr_access = QWebEngineSettings.WebAttribute.JavascriptCanAccessClipboard + attr_paste = QWebEngineSettings.WebAttribute.JavascriptCanPaste + + if isinstance(value, usertypes.Unset): + self._settings.resetAttribute(attr_access) + self._settings.resetAttribute(attr_paste) + else: + for attr, attr_val in self._JS_CLIPBOARD_SETTINGS[value].items(): + self._settings.setAttribute(attr, attr_val) def _update_setting(self, setting, value): if setting == 'content.unknown_url_scheme_policy': - return self.set_unknown_url_scheme_policy(value) - return super()._update_setting(setting, value) + self.set_unknown_url_scheme_policy(value) + elif setting == 'content.javascript.clipboard': + self._set_js_clipboard(value) + super()._update_setting(setting, value) def init_settings(self): super().init_settings() diff --git a/qutebrowser/browser/webkit/webkitsettings.py b/qutebrowser/browser/webkit/webkitsettings.py index cac6236ce..1348c849b 100644 --- a/qutebrowser/browser/webkit/webkitsettings.py +++ b/qutebrowser/browser/webkit/webkitsettings.py @@ -57,8 +57,9 @@ class WebKitSettings(websettings.AbstractSettings): Attr(QWebSettings.JavascriptCanOpenWindows), 'content.javascript.can_close_tabs': Attr(QWebSettings.JavascriptCanCloseWindows), - 'content.javascript.can_access_clipboard': - Attr(QWebSettings.JavascriptCanAccessClipboard), + 'content.javascript.clipboard': + Attr(QWebSettings.JavascriptCanAccessClipboard, + converter=lambda val: val != "none"), 'content.plugins': Attr(QWebSettings.PluginsEnabled), 'content.webgl': diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 771cf0493..2ccb520b3 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -869,9 +869,14 @@ content.javascript.alert: type: Bool desc: Show javascript alerts. -content.javascript.can_access_clipboard: - default: false - type: Bool +content.javascript.clipboard: + default: none + type: + name: String + valid_values: + - none: Disable access to clipboard. + - access: Allow reading from and writing to the clipboard. + - access-paste: Allow accessing the clipboard and pasting clipboard content. supports_pattern: true desc: >- Allow JavaScript to read from or write to the clipboard. diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py index d97771fad..f2651d1cd 100644 --- a/qutebrowser/config/configfiles.py +++ b/qutebrowser/config/configfiles.py @@ -422,6 +422,12 @@ class YamlMigrations(QObject): false_value='load-insecurely', ask_value='ask', ) + self._migrate_renamed_bool( + old_name='content.javascript.can_access_clipboard', + new_name='content.javascript.clipboard', + true_value='access', + false_value='none', + ) for setting in ['colors.webpage.force_dark_color_scheme', 'colors.webpage.prefers_color_scheme_dark']: diff --git a/qutebrowser/config/websettings.py b/qutebrowser/config/websettings.py index 41aeec6a3..779ed0b6b 100644 --- a/qutebrowser/config/websettings.py +++ b/qutebrowser/config/websettings.py @@ -164,14 +164,10 @@ class AbstractSettings: assert encoding is not usertypes.UNSET # unclear how to reset self._settings.setDefaultTextEncoding(encoding) - def _update_setting(self, setting: str, value: Any) -> bool: + def _update_setting(self, setting: str, value: Any) -> None: """Update the given setting/value. - Unknown settings are ignored. - - Return: - True if there was a change, False otherwise. - """ + Unknown settings are ignored.""" if setting in self._ATTRIBUTES: self.set_attribute(setting, value) elif setting in self._FONT_SIZES: @@ -180,7 +176,6 @@ class AbstractSettings: self.set_font_family(setting, value) elif setting == 'content.default_encoding': self.set_default_text_encoding(value) - return False def update_setting(self, setting: str) -> None: """Update the given setting.""" diff --git a/qutebrowser/misc/throttle.py b/qutebrowser/misc/throttle.py index ac565b68d..16a14d4bd 100644 --- a/qutebrowser/misc/throttle.py +++ b/qutebrowser/misc/throttle.py @@ -85,6 +85,7 @@ class Throttle(QObject): (cur_time_ms - self._last_call_ms)) # Disconnect any existing calls, continue if no connections. try: + # pylint: disable=no-value-for-parameter self._timer.timeout.disconnect() except TypeError: pass diff --git a/scripts/dev/changelog_urls.json b/scripts/dev/changelog_urls.json index cc7a6f639..0b6b071c5 100644 --- a/scripts/dev/changelog_urls.json +++ b/scripts/dev/changelog_urls.json @@ -119,9 +119,6 @@ "tldextract": "https://github.com/john-kurkowski/tldextract/blob/master/CHANGELOG.md", "typing_extensions": "https://github.com/python/typing/blob/master/typing_extensions/CHANGELOG", "diff-cover": "https://github.com/Bachmann1234/diff_cover/blob/master/CHANGELOG", - "pytest-icdiff": "https://github.com/hjwp/pytest-icdiff/blob/master/HISTORY.rst", - "icdiff": "https://github.com/jeffkaufman/icdiff/blob/master/ChangeLog", - "pprintpp": "https://github.com/wolever/pprintpp/blob/master/CHANGELOG.txt", "beautifulsoup4": "https://bazaar.launchpad.net/~leonardr/beautifulsoup/bs4/view/head:/CHANGELOG", "check-manifest": "https://github.com/mgedmin/check-manifest/blob/master/CHANGES.rst", "yamllint": "https://github.com/adrienverge/yamllint/blob/master/CHANGELOG.rst", diff --git a/tests/end2end/data/darkmode/mathml-display.html b/tests/end2end/data/darkmode/mathml-display.html new file mode 100644 index 000000000..f0c280cca --- /dev/null +++ b/tests/end2end/data/darkmode/mathml-display.html @@ -0,0 +1,23 @@ + + + + + MathML-like SVG + + + + Pythagorean theorem + + + diff --git a/tests/end2end/data/darkmode/mathml.html b/tests/end2end/data/darkmode/mathml-inline.html similarity index 100% rename from tests/end2end/data/darkmode/mathml.html rename to tests/end2end/data/darkmode/mathml-inline.html diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py index 0d49ff109..5a34d0357 100644 --- a/tests/end2end/test_invocations.py +++ b/tests/end2end/test_invocations.py @@ -723,7 +723,8 @@ def test_dark_mode(webengine_versions, quteproc_new, request, ) -def test_dark_mode_mathml(quteproc_new, request, qtbot): +@pytest.mark.parametrize("suffix", ["inline", "display"]) +def test_dark_mode_mathml(quteproc_new, request, qtbot, suffix): if not request.config.webengine: pytest.skip("Skipped with QtWebKit") @@ -734,7 +735,7 @@ def test_dark_mode_mathml(quteproc_new, request, qtbot): ] quteproc_new.start(args) - quteproc_new.open_path('data/darkmode/mathml.html') + quteproc_new.open_path(f'data/darkmode/mathml-{suffix}.html') quteproc_new.wait_for_js('Image loaded') # First make sure loading finished by looking outside of the image diff --git a/tests/unit/config/test_configtypes.py b/tests/unit/config/test_configtypes.py index c34efce54..e4351d619 100644 --- a/tests/unit/config/test_configtypes.py +++ b/tests/unit/config/test_configtypes.py @@ -223,6 +223,7 @@ class TestAll: """Patch aliases so Command works.""" config_stub.val.aliases = {} + # pylint: disable-next=too-many-function-args @pytest.fixture(params=list(gen_classes())) def klass(self, request): return request.param