diff options
-rw-r--r-- | src/core/api/qwebengineclienthints.cpp | 10 | ||||
-rw-r--r-- | src/core/profile_adapter.cpp | 41 | ||||
-rw-r--r-- | src/core/profile_adapter.h | 1 | ||||
-rw-r--r-- | src/core/profile_qt.cpp | 36 | ||||
-rw-r--r-- | src/core/profile_qt.h | 1 | ||||
-rw-r--r-- | tests/auto/widgets/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 a895787d6..2f930c181 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 916a12234..4e911b297 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<content::WebContentsImpl *> 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 e222cb5f1..cbc811822 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -200,7 +200,6 @@ public: 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 04c58ac34..57bc91942 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::ExtensionSystemQt*>(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<std::vector<int>> orders{ { 0, 1, 2 }, { 0, 2, 1 }, { 1, 0, 2 }, + { 1, 2, 0 }, { 2, 0, 1 }, { 2, 1, 0 } }; + const std::vector<int> 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 8161b70ca..1d8b746aa 100644 --- a/src/core/profile_qt.h +++ b/src/core/profile_qt.h @@ -75,6 +75,7 @@ public: 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 1a063d7d1..c9354a9be 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")); |