From bf18029ff6478b27d65fd658c21e0dd7428a6077 Mon Sep 17 00:00:00 2001 From: Qt Submodule Update Bot Date: Wed, 21 May 2025 11:58:46 +0000 Subject: [PATCH 1/3] Update dependencies on 'dev' in qt/qtwebengine Change-Id: I4150bbcd6649b2ae144fa2afe0d3c64df1548135 Reviewed-by: Qt Submodule Update Bot --- dependencies.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index 5bac06d21a7..6b10fdcc8cd 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: 1869c3815f6057ee677ffc9df886654a6f0c090b + ref: e7134fe5773eca1f482ba8ec5a52c816789c4e33 required: true ../qtpositioning: - ref: c348e2faafc77db7b27541d56e9395ed02e225fd + ref: b67f6e52b26a11f4db57f1300b7d975d8e1c16bc required: false ../qttools: - ref: 8cc1e98caa435f3a2d244ee0b8cadcef6360850f + ref: b79f4f1e126ede4156d909e63d23daa7117767b5 required: false ../qtwebchannel: - ref: 71c581a6efacf74d975416ce4d2c562c7d144fe7 + ref: d61cab2270ab8b667637359f9d377de27dbce3db required: false From 0e1b14e58278a2f3a54cbc77707b96738a4c8b01 Mon Sep 17 00:00:00 2001 From: Kaloyan Chehlarski Date: Wed, 21 May 2025 15:24:58 +0200 Subject: [PATCH 2/3] Ignore QInputMethodEvent::MimeData MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduced with 2a9444920bcd2f5d1832971bd6275ebdc5515546 We need the version checks to support building on top of older Qt versions. Change-Id: Ifddf8a194a23233eeab61111380dc62ce407f6e7 Reviewed-by: Tor Arne Vestbø --- src/pdfquick/qquickpdfselection.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pdfquick/qquickpdfselection.cpp b/src/pdfquick/qquickpdfselection.cpp index b21044b1471..bc939a9bed5 100644 --- a/src/pdfquick/qquickpdfselection.cpp +++ b/src/pdfquick/qquickpdfselection.cpp @@ -232,6 +232,9 @@ void QQuickPdfSelection::inputMethodEvent(QInputMethodEvent *event) case QInputMethodEvent::Language: case QInputMethodEvent::Ruby: case QInputMethodEvent::TextFormat: +#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0) + case QInputMethodEvent::MimeData: +#endif break; } } From dabf55e53279ea07d98bb00f28f65185c8a9c5ba Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Thu, 6 Mar 2025 13:45:33 +0100 Subject: [PATCH 3/3] Client Hints: Improve version lists There are several issues affecting Sec-CH-UA and -Full-Version-List, because the general algorithm which extends and shuffles these lists was not used in WebEngine. At the current version of Chromium we can't use the corresponding user agent utils functions, because they only allow one extra brand/version pair besides the two generated (Chromium and Not-A-Brand) ones. This change implements a simplified method to extend and shuffle the version lists to follow the behavior of Chromium and support more than three elements. QTBUG-133799: The order of brands and versions are still not customizable by the API user, but it is permutated in each major version of Chromium to comply with the standards. To allow customization of the order seems to be impossible without changing our public API. QTBUG-133708: The missing values of Sec-CH-UA are generated from the full version list, not customizable individually. This way it keeps the same values and the same algorithmically generated order as the full version list. Task-number: QTBUG-133711 Task-number: QTBUG-133708 Task-number: QTBUG-133777 Task-number: QTBUG-133799 Change-Id: I96f214ce54190666a34779130a04b56f600abef7 Reviewed-by: Peter Varga Reviewed-by: Moss Heim --- src/core/api/qwebengineclienthints.cpp | 10 +++-- src/core/profile_adapter.cpp | 41 +++++++++++++++---- src/core/profile_adapter.h | 1 - src/core/profile_qt.cpp | 36 ++++++++++++++-- src/core/profile_qt.h | 1 + .../qwebenginepage/tst_qwebenginepage.cpp | 16 ++++++-- 6 files changed, 86 insertions(+), 19 deletions(-) diff --git a/src/core/api/qwebengineclienthints.cpp b/src/core/api/qwebengineclienthints.cpp index a895787d648..2f930c1811b 100644 --- a/src/core/api/qwebengineclienthints.cpp +++ b/src/core/api/qwebengineclienthints.cpp @@ -132,10 +132,14 @@ QString QWebEngineClientHints::bitness() const /*! \property QWebEngineClientHints::fullVersionList - The value of the \c{Sec-CH-UA-Full-Version-List} HTTP header and \c{fullVersionList} member of NavigatorUAData in JavaScript. + The value of the \c{Sec-CH-UA-Full-Version-List} HTTP header and \c{fullVersionList} member of + NavigatorUAData in JavaScript. - It holds brand name and version number pairs in a QVariantMap. The provided values will be automatically extended by the currently used version - of Chromium and a semi-random brand. + The value of Sec-CH-UA header will also be generated from this by truncating the version + numbers. + + It holds brand name and version number pairs in a QVariantMap. The provided values will be + automatically extended by the currently used version of Chromium and a semi-random brand. */ QVariantMap QWebEngineClientHints::fullVersionList() const { diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 916a1223410..4e911b2972f 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -6,6 +6,7 @@ #include "base/files/file_util.h" #include "base/task/cancelable_task_tracker.h" #include "base/threading/thread_restrictions.h" +#include "base/version_info/version_info.h" #include "components/embedder_support/user_agent_utils.h" #include "components/favicon/core/favicon_service.h" #include "components/history/content/browser/history_database_helper.h" @@ -53,6 +54,36 @@ inline QString buildLocationFromStandardPath(const QString &standardPath, const location += "/QtWebEngine/"_L1 % name; return location; } + +void PopulateBrandVersionLists(const QJsonObject &fullVersionList, + blink::UserAgentMetadata &userAgentMetadata) +{ + userAgentMetadata.brand_version_list.clear(); + userAgentMetadata.brand_full_version_list.clear(); + + for (const QString &key : fullVersionList.keys()) { + std::string version = fullVersionList.value(key).toString().toStdString(); + userAgentMetadata.brand_full_version_list.push_back({ key.toStdString(), version }); + version = version.substr(0, version.find('.')); + userAgentMetadata.brand_version_list.push_back({ key.toStdString(), version }); + } + + // Shuffle the lists + int permutations = 1; + for (int i = 2; i <= fullVersionList.size(); i++) + permutations *= i; + // We keep the brand lists identical throughout the lifetime of each major version of Chromium. + permutations = version_info::GetMajorVersionNumberAsInt() % permutations; + auto compare = [](blink::UserAgentBrandVersion &a, blink::UserAgentBrandVersion &b) { + return a.brand + a.version < b.brand + b.version; + }; + for (int i = 0; i < permutations; i++) { + std::next_permutation(userAgentMetadata.brand_version_list.begin(), + userAgentMetadata.brand_version_list.end(), compare); + std::next_permutation(userAgentMetadata.brand_full_version_list.begin(), + userAgentMetadata.brand_full_version_list.end(), compare); + } +} } namespace QtWebEngineCore { @@ -713,13 +744,7 @@ void ProfileAdapter::setClientHint(ClientHint clientHint, const QVariant &value) userAgentMetadata.bitness = value.toString().toStdString(); break; case ProfileAdapter::UAFullVersionList: { - userAgentMetadata.brand_full_version_list.clear(); - QJsonObject fullVersionList = value.toJsonObject(); - for (const QString &key : fullVersionList.keys()) - userAgentMetadata.brand_full_version_list.push_back({ - key.toStdString(), - fullVersionList.value(key).toString().toStdString() - }); + PopulateBrandVersionLists(value.toJsonObject(), userAgentMetadata); break; } case ProfileAdapter::UAWOW64: @@ -758,7 +783,7 @@ void ProfileAdapter::setClientHintsEnabled(bool enabled) void ProfileAdapter::resetClientHints() { - m_profile->m_userAgentMetadata = embedder_support::GetUserAgentMetadata(); + m_profile->initUserAgentMetadata(); std::vector list = content::WebContentsImpl::GetAllWebContents(); for (content::WebContentsImpl *web_contents : list) { if (web_contents->GetBrowserContext() == m_profile.data()) { diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index e222cb5f1a7..cbc8118224a 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -200,7 +200,6 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapter : public QObject void setClientHintsEnabled(bool enabled); void resetClientHints(); - void clearHttpCache(); #if QT_CONFIG(ssl) diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp index 04c58ac34e6..57bc9194201 100644 --- a/src/core/profile_qt.cpp +++ b/src/core/profile_qt.cpp @@ -20,6 +20,7 @@ #include "base/path_service.h" #include "base/files/file_util.h" #include "base/task/thread_pool.h" +#include "base/version_info/version_info.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/prefs/pref_service.h" #include "components/user_prefs/user_prefs.h" @@ -48,9 +49,7 @@ enum { }; ProfileQt::ProfileQt(ProfileAdapter *profileAdapter) - : m_profileIOData(new ProfileIODataQt(this)) - , m_profileAdapter(profileAdapter) - , m_userAgentMetadata(embedder_support::GetUserAgentMetadata()) + : m_profileIOData(new ProfileIODataQt(this)), m_profileAdapter(profileAdapter) { profile_metrics::SetBrowserProfileType(this, IsOffTheRecord() ? profile_metrics::BrowserProfileType::kIncognito @@ -68,6 +67,8 @@ ProfileQt::ProfileQt(ProfileAdapter *profileAdapter) #if BUILDFLAG(ENABLE_EXTENSIONS) static_cast(extensions::ExtensionSystem::Get(this))->InitForRegularProfile(true); #endif + + initUserAgentMetadata(); } ProfileQt::~ProfileQt() @@ -300,6 +301,35 @@ const PrefServiceAdapter &ProfileQt::prefServiceAdapter() const return m_prefServiceAdapter; } +void ProfileQt::initUserAgentMetadata() +{ + m_userAgentMetadata = embedder_support::GetUserAgentMetadata(); + m_userAgentMetadata.brand_version_list.clear(); + m_userAgentMetadata.brand_full_version_list.clear(); + + // Chromium version + m_userAgentMetadata.brand_version_list.emplace_back( + blink::UserAgentBrandVersion("Chromium", version_info::GetMajorVersionNumber())); + m_userAgentMetadata.brand_full_version_list.emplace_back(blink::UserAgentBrandVersion( + "Chromium", std::string(version_info::GetVersionNumber()))); + + // We keep the brand lists identical throughout the lifetime of each major version of Chromium. + int seed = version_info::GetMajorVersionNumberAsInt(); + // Generate a greasey version + const std::vector> orders{ { 0, 1, 2 }, { 0, 2, 1 }, { 1, 0, 2 }, + { 1, 2, 0 }, { 2, 0, 1 }, { 2, 1, 0 } }; + const std::vector order = orders[seed % 6]; + m_userAgentMetadata.brand_version_list.emplace_back( + embedder_support::GetGreasedUserAgentBrandVersion( + order, seed, std::nullopt, std::nullopt, true, + blink::UserAgentBrandVersionType::kMajorVersion)); + + m_userAgentMetadata.brand_full_version_list.emplace_back( + embedder_support::GetGreasedUserAgentBrandVersion( + order, seed, std::nullopt, std::nullopt, true, + blink::UserAgentBrandVersionType::kFullVersion)); +} + const blink::UserAgentMetadata &ProfileQt::userAgentMetadata() { return m_userAgentMetadata; diff --git a/src/core/profile_qt.h b/src/core/profile_qt.h index 8161b70ca12..1d8b746aa64 100644 --- a/src/core/profile_qt.h +++ b/src/core/profile_qt.h @@ -75,6 +75,7 @@ class ProfileQt : public Profile PrefServiceAdapter &prefServiceAdapter(); const PrefServiceAdapter &prefServiceAdapter() const; + void initUserAgentMetadata(); const blink::UserAgentMetadata &userAgentMetadata(); private: diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 1a063d7d137..c9354a9bef5 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -5482,12 +5482,16 @@ void tst_QWebEnginePage::clientHints() QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); QWebEngineClientHints *clientHints = page.profile()->clientHints(); + // fullVersionList is extended by Chromium and a greased brand by default + QCOMPARE(clientHints->fullVersionList().size(), 2); + QVERIFY(clientHints->fullVersionList().contains("Chromium")); clientHints->setAllClientHintsEnabled(clientHintsEnabled); HttpServer server; int requestCount = 0; - connect(&server, &HttpServer::newRequest, [&] (HttpReqRep *r) { - // Platform and Mobile hints are always sent and can't be disabled with this API + connect(&server, &HttpServer::newRequest, [&](HttpReqRep *r) { + // UA, Platform and Mobile hints are always sent and can't be disabled with this API + QVERIFY(r->hasRequestHeader("Sec-CH-UA")); QVERIFY(r->hasRequestHeader("Sec-CH-UA-Platform")); QVERIFY(r->hasRequestHeader("Sec-CH-UA-Mobile")); if (!clientHintsEnabled) { @@ -5512,9 +5516,10 @@ void tst_QWebEnginePage::clientHints() QCOMPARE(QString(r->requestHeader("Sec-CH-UA-Platform-Version")).remove("\""), platformVersion.toLower()); QCOMPARE(QString(r->requestHeader("Sec-CH-UA-Bitness")).remove("\""), bitness.toLower()); QCOMPARE(QString(r->requestHeader("Sec-CH-UA-Wow64")).remove("\""), isWOW64 ? "?1" : "?0"); - for (auto i = fullVersionList.cbegin(), end = fullVersionList.cend(); i != end; ++i) + for (auto i = fullVersionList.cbegin(), end = fullVersionList.cend(); i != end; ++i) { + QVERIFY(QString(r->requestHeader("Sec-CH-UA")).contains(i.key().toLower())); QVERIFY(QString(r->requestHeader("Sec-CH-UA-Full-Version-List")).contains(i.key().toLower())); - + } for (auto formFactor : formFactors) QVERIFY(QString(r->requestHeader("Sec-CH-UA-Form-Factors")).contains(formFactor.toLower())); } @@ -5549,8 +5554,10 @@ void tst_QWebEnginePage::clientHints() QCOMPARE(clientHints->bitness(), bitness); QCOMPARE(clientHints->isWow64(), isWOW64); QCOMPARE(clientHints->formFactors(), formFactors); + QCOMPARE(clientHints->fullVersionList().size(), fullVersionList.size()); for (auto i = fullVersionList.cbegin(), end = fullVersionList.cend(); i != end; ++i) QCOMPARE(clientHints->fullVersionList()[i.key()], i.value()); + QVERIFY(!clientHints->fullVersionList().contains("Chromium")); // A new user agent string should not override/disable client hints page.profile()->setHttpUserAgent(QStringLiteral("Custom user agent")); @@ -5571,6 +5578,7 @@ void tst_QWebEnginePage::clientHints() QCOMPARE_NE(clientHints->platformVersion(), platformVersion); QCOMPARE_NE(clientHints->bitness(), bitness); QCOMPARE_NE(clientHints->formFactors(), formFactors); + QCOMPARE(clientHints->fullVersionList().size(), 2); for (auto i = fullVersionList.cbegin(), end = fullVersionList.cend(); i != end; ++i) QVERIFY(!clientHints->fullVersionList().contains(i.key())); QVERIFY(clientHints->fullVersionList().contains("Chromium"));