From 52106c383b41ea7629399f75059bbcba9abb1ba6 Mon Sep 17 00:00:00 2001 From: toofar Date: Sat, 23 Mar 2024 11:14:53 +1300 Subject: Show chromium security patch version in :version Webengine added a getter for their chromium patch level back in Qt 6.3, since they backport security fixes from chromium in the periods between doing major chromium feature upgrades. It's pulled from a hardcoded string in the webengine source `src/core/web_engine_context.cpp` that's manually updated when they backport something. The "(plus any distribution patches)" bit in there is because it was pointed out that some distributions backport their own security patches or even use webengine from a branch when the hardcoded string only gets updated at release time, despite patches being backported in the meantime. Closes: https://github.com/qutebrowser/qutebrowser/issues/7187 --- doc/changelog.asciidoc | 4 ++++ qutebrowser/utils/version.py | 20 +++++++++++++++++++- tests/unit/utils/test_version.py | 25 +++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 89e33679e..fce509dd7 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -24,6 +24,10 @@ Added - When qutebrowser receives a SIGHUP it will now reload any config.py file in use (same as the `:config-source` command does). (#8108) +- The Chromium security patch version is now shown in the backend string in + --version and :version. This reflects the latest Chromium version that + security fixes have been backported to the base QtWebEngine version from. + (#7187) Changed ~~~~~~~ diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py index 59da5b5f0..30aeedd20 100644 --- a/qutebrowser/utils/version.py +++ b/qutebrowser/utils/version.py @@ -535,6 +535,7 @@ class WebEngineVersions: webengine: utils.VersionNumber chromium: Optional[str] source: str + chromium_security: Optional[str] = None chromium_major: Optional[int] = dataclasses.field(init=False) _CHROMIUM_VERSIONS: ClassVar[Dict[utils.VersionNumber, str]] = { @@ -629,6 +630,8 @@ class WebEngineVersions: s = f'QtWebEngine {self.webengine}' if self.chromium is not None: s += f', based on Chromium {self.chromium}' + if self.chromium_security is not None: + s += f', with security patches up to {self.chromium_security} (plus any distribution patches)' if self.source != 'UA': s += f' (from {self.source})' return s @@ -686,7 +689,12 @@ class WebEngineVersions: return cls._CHROMIUM_VERSIONS.get(minor_version) @classmethod - def from_api(cls, qtwe_version: str, chromium_version: Optional[str]) -> 'WebEngineVersions': + def from_api( + cls, + qtwe_version: str, + chromium_version: Optional[str], + chromium_security: Optional[str] = None, + ) -> 'WebEngineVersions': """Get the versions based on the exact versions. This is called if we have proper APIs to get the versions easily @@ -696,6 +704,7 @@ class WebEngineVersions: return cls( webengine=parsed, chromium=chromium_version, + chromium_security=chromium_security, source='api', ) @@ -796,11 +805,20 @@ def qtwebengine_versions(*, avoid_init: bool = False) -> WebEngineVersions: except ImportError: pass # Needs QtWebEngine 6.2+ with PyQtWebEngine 6.3.1+ else: + try: + from qutebrowser.qt.webenginecore import ( + qWebEngineChromiumSecurityPatchVersion, + ) + chromium_security = qWebEngineChromiumSecurityPatchVersion() + except ImportError: + chromium_security = None # Needs QtWebEngine 6.3+ + qtwe_version = qWebEngineVersion() assert qtwe_version is not None return WebEngineVersions.from_api( qtwe_version=qtwe_version, chromium_version=qWebEngineChromiumVersion(), + chromium_security=chromium_security, ) from qutebrowser.browser.webengine import webenginesettings diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index 38134b40e..f24bf2a7a 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -915,6 +915,17 @@ class TestWebEngineVersions: source='faked'), "QtWebEngine 5.15.2, based on Chromium 87.0.4280.144 (from faked)", ), + ( + version.WebEngineVersions( + webengine=utils.VersionNumber(5, 15, 2), + chromium='87.0.4280.144', + chromium_security='9000.1', + source='faked'), + ( + "QtWebEngine 5.15.2, based on Chromium 87.0.4280.144, with security " + "patches up to 9000.1 (plus any distribution patches) (from faked)" + ), + ), ]) def test_str(self, version, expected): assert str(version) == expected @@ -1024,6 +1035,20 @@ class TestWebEngineVersions: assert inferred == real + def test_real_chromium_security_version(self, qapp): + """Check the API for reading the chromium security patch version.""" + try: + from qutebrowser.qt.webenginecore import ( + qWebEngineChromiumVersion, + qWebEngineChromiumSecurityPatchVersion, + ) + except ImportError: + pytest.skip("Requires QtWebEngine 6.3+") + + base = utils.VersionNumber.parse(qWebEngineChromiumVersion()) + security = utils.VersionNumber.parse(qWebEngineChromiumSecurityPatchVersion()) + assert security >= base + class FakeQSslSocket: -- cgit v1.2.3-54-g00ecf