| // Copyright 2021 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/embedder_support/user_agent_utils.h" |
| |
| #include "base/command_line.h" |
| #include "base/strings/strcat.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/system/sys_info.h" |
| #include "base/test/gtest_util.h" |
| #include "base/test/scoped_command_line.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/version.h" |
| #include "build/build_config.h" |
| #include "components/embedder_support/pref_names.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "components/version_info/version_info.h" |
| #include "content/public/common/content_features.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/common/user_agent.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/common/features.h" |
| #include "third_party/blink/public/common/user_agent/user_agent_brand_version_type.h" |
| #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" |
| #include "third_party/re2/src/re2/re2.h" |
| |
| #if BUILDFLAG(IS_POSIX) |
| #include <sys/utsname.h> |
| #endif |
| |
| #if BUILDFLAG(IS_WIN) |
| #include <windows.foundation.metadata.h> |
| #include <wrl.h> |
| |
| #include "base/win/core_winrt_util.h" |
| #include "base/win/hstring_reference.h" |
| #include "base/win/scoped_hstring.h" |
| #include "base/win/scoped_winrt_initializer.h" |
| #include "base/win/windows_version.h" |
| #endif // BUILDFLAG(IS_WIN) |
| |
| namespace embedder_support { |
| |
| namespace { |
| |
| // A regular expression that matches Chrome/{major_version}.{minor_version} in |
| // the User-Agent string, where the first capture is the {major_version} and the |
| // second capture is the {minor_version}. |
| static constexpr char kChromeProductVersionRegex[] = |
| "Chrome/([0-9]+).([0-9]+).([0-9]+).([0-9]+)"; |
| |
| #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) |
| std::string GetMachine() { |
| struct utsname unixinfo; |
| uname(&unixinfo); |
| std::string machine = unixinfo.machine; |
| if (strcmp(unixinfo.machine, "x86_64") == 0 && |
| sizeof(void*) == sizeof(int32_t)) { |
| machine = "i686 (x86_64)"; |
| } |
| return machine; |
| } |
| #endif |
| |
| void CheckUserAgentStringOrdering(bool mobile_device) { |
| std::vector<std::string> pieces; |
| |
| // Check if the pieces of the user agent string come in the correct order. |
| std::string buffer = GetUserAgent(); |
| |
| pieces = base::SplitStringUsingSubstr( |
| buffer, "Mozilla/5.0 (", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| ASSERT_EQ(2u, pieces.size()); |
| buffer = pieces[1]; |
| EXPECT_EQ("", pieces[0]); |
| |
| pieces = base::SplitStringUsingSubstr( |
| buffer, ") AppleWebKit/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| ASSERT_EQ(2u, pieces.size()); |
| buffer = pieces[1]; |
| std::string os_str = pieces[0]; |
| |
| pieces = |
| base::SplitStringUsingSubstr(buffer, " (KHTML, like Gecko) ", |
| base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| ASSERT_EQ(2u, pieces.size()); |
| buffer = pieces[1]; |
| std::string webkit_version_str = pieces[0]; |
| |
| pieces = base::SplitStringUsingSubstr( |
| buffer, " Safari/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| ASSERT_EQ(2u, pieces.size()); |
| std::string product_str = pieces[0]; |
| std::string safari_version_str = pieces[1]; |
| |
| EXPECT_FALSE(os_str.empty()); |
| |
| pieces = base::SplitStringUsingSubstr(os_str, "; ", base::KEEP_WHITESPACE, |
| base::SPLIT_WANT_ALL); |
| #if BUILDFLAG(IS_WIN) |
| // Windows NT 10.0; Win64; x64 |
| // Windows NT 10.0; WOW64 |
| // Windows NT 10.0 |
| std::string os_and_version = pieces[0]; |
| for (unsigned int i = 1; i < pieces.size(); ++i) { |
| bool equals = ((pieces[i] == "WOW64") || (pieces[i] == "Win64") || |
| pieces[i] == "x64"); |
| ASSERT_TRUE(equals); |
| } |
| pieces = base::SplitStringUsingSubstr(pieces[0], " ", base::KEEP_WHITESPACE, |
| base::SPLIT_WANT_ALL); |
| ASSERT_EQ(3u, pieces.size()); |
| ASSERT_EQ("Windows", pieces[0]); |
| ASSERT_EQ("NT", pieces[1]); |
| double version; |
| ASSERT_TRUE(base::StringToDouble(pieces[2], &version)); |
| ASSERT_LE(4.0, version); |
| ASSERT_GT(11.0, version); |
| #elif BUILDFLAG(IS_MAC) |
| // Macintosh; Intel Mac OS X 10_15_4 |
| ASSERT_EQ(2u, pieces.size()); |
| ASSERT_EQ("Macintosh", pieces[0]); |
| pieces = base::SplitStringUsingSubstr(pieces[1], " ", base::KEEP_WHITESPACE, |
| base::SPLIT_WANT_ALL); |
| ASSERT_EQ(5u, pieces.size()); |
| ASSERT_EQ("Intel", pieces[0]); |
| ASSERT_EQ("Mac", pieces[1]); |
| ASSERT_EQ("OS", pieces[2]); |
| ASSERT_EQ("X", pieces[3]); |
| pieces = base::SplitStringUsingSubstr(pieces[4], "_", base::KEEP_WHITESPACE, |
| base::SPLIT_WANT_ALL); |
| { |
| int major, minor, patch; |
| base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &patch); |
| // crbug.com/1175225 |
| if (major > 10) |
| major = 10; |
| ASSERT_EQ(base::StringPrintf("%d", major), pieces[0]); |
| } |
| int value; |
| ASSERT_TRUE(base::StringToInt(pieces[1], &value)); |
| ASSERT_LE(0, value); |
| ASSERT_TRUE(base::StringToInt(pieces[2], &value)); |
| ASSERT_LE(0, value); |
| #elif BUILDFLAG(IS_CHROMEOS) |
| // X11; CrOS armv7l 4537.56.0 |
| ASSERT_EQ(2u, pieces.size()); |
| ASSERT_EQ("X11", pieces[0]); |
| pieces = base::SplitStringUsingSubstr(pieces[1], " ", base::KEEP_WHITESPACE, |
| base::SPLIT_WANT_ALL); |
| ASSERT_EQ(3u, pieces.size()); |
| ASSERT_EQ("CrOS", pieces[0]); |
| ASSERT_EQ(GetMachine(), pieces[1]); |
| pieces = base::SplitStringUsingSubstr(pieces[2], ".", base::KEEP_WHITESPACE, |
| base::SPLIT_WANT_ALL); |
| for (unsigned int i = 1; i < pieces.size(); ++i) { |
| int value; |
| ASSERT_TRUE(base::StringToInt(pieces[i], &value)); |
| } |
| #elif BUILDFLAG(IS_LINUX) |
| // X11; Linux x86_64 |
| ASSERT_EQ(2u, pieces.size()); |
| ASSERT_EQ("X11", pieces[0]); |
| pieces = base::SplitStringUsingSubstr(pieces[1], " ", base::KEEP_WHITESPACE, |
| base::SPLIT_WANT_ALL); |
| ASSERT_EQ(2u, pieces.size()); |
| // This may not be Linux in all cases in the wild, but it is on the bots. |
| ASSERT_EQ("Linux", pieces[0]); |
| ASSERT_EQ(GetMachine(), pieces[1]); |
| #elif BUILDFLAG(IS_ANDROID) |
| // Linux; Android 7.1.1; Pixel 2 |
| ASSERT_GE(3u, pieces.size()); |
| ASSERT_EQ("Linux", pieces[0]); |
| std::string model; |
| if (pieces.size() > 2) |
| model = pieces[2]; |
| |
| pieces = base::SplitStringUsingSubstr(pieces[1], " ", base::KEEP_WHITESPACE, |
| base::SPLIT_WANT_ALL); |
| ASSERT_EQ(2u, pieces.size()); |
| ASSERT_EQ("Android", pieces[0]); |
| pieces = base::SplitStringUsingSubstr(pieces[1], ".", base::KEEP_WHITESPACE, |
| base::SPLIT_WANT_ALL); |
| for (unsigned int i = 1; i < pieces.size(); ++i) { |
| int value; |
| ASSERT_TRUE(base::StringToInt(pieces[i], &value)); |
| } |
| |
| if (!model.empty()) { |
| if (base::SysInfo::GetAndroidBuildCodename() == "REL") |
| ASSERT_EQ(base::SysInfo::HardwareModelName(), model); |
| else |
| ASSERT_EQ("", model); |
| } |
| #elif BUILDFLAG(IS_FUCHSIA) |
| // X11; Fuchsia |
| ASSERT_EQ(1u, pieces.size()); |
| ASSERT_EQ("Fuchsia", pieces[0]); |
| #else |
| #error Unsupported platform |
| #endif |
| |
| // Check that the version numbers match. |
| EXPECT_FALSE(webkit_version_str.empty()); |
| EXPECT_FALSE(safari_version_str.empty()); |
| EXPECT_EQ(webkit_version_str, safari_version_str); |
| |
| EXPECT_TRUE( |
| base::StartsWith(product_str, "Chrome/", base::CompareCase::SENSITIVE)); |
| if (mobile_device) { |
| // "Mobile" gets tacked on to the end for mobile devices, like phones. |
| EXPECT_TRUE( |
| base::EndsWith(product_str, " Mobile", base::CompareCase::SENSITIVE)); |
| } |
| } |
| |
| #if BUILDFLAG(IS_WIN) |
| bool ResolveCoreWinRT() { |
| return base::win::ResolveCoreWinRTDelayload() && |
| base::win::ScopedHString::ResolveCoreWinRTStringDelayload() && |
| base::win::HStringReference::ResolveCoreWinRTStringDelayload(); |
| } |
| |
| // On Windows, the client hint sec-ch-ua-platform-version should be |
| // the highest supported version of the UniversalApiContract. |
| void VerifyWinPlatformVersion(std::string version) { |
| ASSERT_TRUE(ResolveCoreWinRT()); |
| base::win::ScopedWinrtInitializer scoped_winrt_initializer; |
| ASSERT_TRUE(scoped_winrt_initializer.Succeeded()); |
| |
| base::win::HStringReference api_info_class_name( |
| RuntimeClass_Windows_Foundation_Metadata_ApiInformation); |
| |
| Microsoft::WRL::ComPtr< |
| ABI::Windows::Foundation::Metadata::IApiInformationStatics> |
| api; |
| HRESULT result = base::win::RoGetActivationFactory(api_info_class_name.Get(), |
| IID_PPV_ARGS(&api)); |
| ASSERT_EQ(result, S_OK); |
| |
| base::win::HStringReference universal_contract_name( |
| L"Windows.Foundation.UniversalApiContract"); |
| |
| std::vector<std::string> version_parts = base::SplitString( |
| version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| |
| EXPECT_EQ(version_parts[2], "0"); |
| |
| int major_version; |
| base::StringToInt(version_parts[0], &major_version); |
| |
| // If this check fails, our highest known UniversalApiContract version |
| // needs to be updated. |
| EXPECT_LE(major_version, |
| GetHighestKnownUniversalApiContractVersionForTesting()); |
| |
| int minor_version; |
| base::StringToInt(version_parts[1], &minor_version); |
| |
| boolean is_supported = false; |
| // Verify that the major and minor versions are supported. |
| result = api->IsApiContractPresentByMajor(universal_contract_name.Get(), |
| major_version, &is_supported); |
| EXPECT_EQ(result, S_OK); |
| EXPECT_TRUE(is_supported) |
| << " expected major version " << major_version << " to be supported."; |
| result = api->IsApiContractPresentByMajorAndMinor( |
| universal_contract_name.Get(), major_version, minor_version, |
| &is_supported); |
| EXPECT_EQ(result, S_OK); |
| EXPECT_TRUE(is_supported) |
| << " expected major version " << major_version << " and minor version " |
| << minor_version << " to be supported."; |
| |
| // Verify that the next highest value is not supported. |
| result = api->IsApiContractPresentByMajorAndMinor( |
| universal_contract_name.Get(), major_version, minor_version + 1, |
| &is_supported); |
| EXPECT_EQ(result, S_OK); |
| EXPECT_FALSE(is_supported) << " expected minor version " << minor_version + 1 |
| << " to not be supported with a major version of " |
| << major_version << "."; |
| result = api->IsApiContractPresentByMajor(universal_contract_name.Get(), |
| major_version + 1, &is_supported); |
| EXPECT_EQ(result, S_OK); |
| EXPECT_FALSE(is_supported) << " expected major version " << major_version + 1 |
| << " to not be supported."; |
| } |
| |
| void VerifyLegacyWinPlatformVersion(const std::string& version) { |
| switch (base::win::GetVersion()) { |
| case base::win::Version::WIN7: |
| EXPECT_EQ("0.1.0", version); |
| break; |
| case base::win::Version::WIN8: |
| EXPECT_EQ("0.2.0", version); |
| break; |
| case base::win::Version::WIN8_1: |
| EXPECT_EQ("0.3.0", version); |
| break; |
| default: |
| EXPECT_EQ("0.0.0", version); |
| break; |
| } |
| } |
| #endif // BUILDFLAG(IS_WIN) |
| |
| bool ContainsBrandVersion(const blink::UserAgentBrandList& brand_list, |
| const blink::UserAgentBrandVersion brand_version) { |
| for (const auto& brand_list_entry : brand_list) { |
| if (brand_list_entry == brand_version) |
| return true; |
| } |
| return false; |
| } |
| |
| } // namespace |
| |
| class UserAgentUtilsTest : public testing::Test, |
| public testing::WithParamInterface<bool> { |
| public: |
| std::string MajorToMinorVersionNumber() { |
| const base::Version version = version_info::GetVersion(); |
| std::string version_str; |
| const auto& components = version.components(); |
| for (size_t i = 0; i < version.components().size(); ++i) { |
| if (i > 0) |
| version_str.append("."); |
| if (i == 0) |
| version_str.append("99"); |
| else if (i == 1) |
| version_str.append(base::NumberToString(components[0])); |
| else |
| version_str.append(base::NumberToString(components[i])); |
| } |
| return version_str; |
| } |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| TEST_F(UserAgentUtilsTest, UserAgentStringOrdering) { |
| #if BUILDFLAG(IS_ANDROID) |
| const char* const kArguments[] = {"chrome"}; |
| base::test::ScopedCommandLine scoped_command_line; |
| base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine(); |
| command_line->InitFromArgv(1, kArguments); |
| |
| // Do it for regular devices. |
| ASSERT_FALSE(command_line->HasSwitch(switches::kUseMobileUserAgent)); |
| CheckUserAgentStringOrdering(false); |
| |
| // Do it for mobile devices. |
| command_line->AppendSwitch(switches::kUseMobileUserAgent); |
| ASSERT_TRUE(command_line->HasSwitch(switches::kUseMobileUserAgent)); |
| CheckUserAgentStringOrdering(true); |
| #else |
| CheckUserAgentStringOrdering(false); |
| #endif |
| } |
| |
| TEST_F(UserAgentUtilsTest, UserAgentStringReduced) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitAndEnableFeature(blink::features::kReduceUserAgent); |
| |
| #if BUILDFLAG(IS_ANDROID) |
| // Verify the correct user agent is returned when the UseMobileUserAgent |
| // command line flag is present. |
| const char* const kArguments[] = {"chrome"}; |
| base::test::ScopedCommandLine scoped_command_line; |
| base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine(); |
| command_line->InitFromArgv(1, kArguments); |
| const std::string major_version_number = |
| version_info::GetMajorVersionNumber(); |
| const char* const major_version = major_version_number.c_str(); |
| |
| // Verify the mobile user agent string is not returned when not using a mobile |
| // user agent. |
| ASSERT_FALSE(command_line->HasSwitch(switches::kUseMobileUserAgent)); |
| { |
| std::string buffer = GetUserAgent(); |
| std::string device_compat = ""; |
| EXPECT_EQ(buffer, |
| base::StringPrintf(content::frozen_user_agent_strings::kAndroid, |
| content::GetUnifiedPlatform().c_str(), |
| major_version, device_compat.c_str())); |
| } |
| |
| // Verify the mobile user agent string is returned when using a mobile user |
| // agent. |
| command_line->AppendSwitch(switches::kUseMobileUserAgent); |
| ASSERT_TRUE(command_line->HasSwitch(switches::kUseMobileUserAgent)); |
| { |
| std::string buffer = GetUserAgent(); |
| std::string device_compat = "Mobile "; |
| EXPECT_EQ(buffer, |
| base::StringPrintf(content::frozen_user_agent_strings::kAndroid, |
| content::GetUnifiedPlatform().c_str(), |
| major_version, device_compat.c_str())); |
| } |
| |
| // Verify that the reduced user agent string respects |
| // --force-major-version-to-minor |
| scoped_feature_list.Reset(); |
| scoped_feature_list.InitWithFeatures( |
| {blink::features::kReduceUserAgent, |
| blink::features::kForceMajorVersionInMinorPositionInUserAgent}, {}); |
| { |
| std::string buffer = GetReducedUserAgent(); |
| std::string device_compat = "Mobile "; |
| EXPECT_EQ(buffer, |
| base::StringPrintf(content::frozen_user_agent_strings::kAndroid, |
| content::GetUnifiedPlatform().c_str(), "99", |
| device_compat.c_str())); |
| } |
| |
| // Ensure that the ForceMajorVersionToMinorPosition policy is applied even |
| // when it contradicts Blink feature status values. |
| scoped_feature_list.Reset(); |
| scoped_feature_list.InitWithFeatures( |
| {blink::features::kReduceUserAgent, |
| blink::features::kForceMajorVersionInMinorPositionInUserAgent}, |
| {}); |
| { |
| std::string buffer = GetReducedUserAgent(kForceDisabled); |
| std::string device_compat = "Mobile "; |
| EXPECT_EQ(buffer, |
| base::StringPrintf(content::frozen_user_agent_strings::kAndroid, |
| content::GetUnifiedPlatform().c_str(), |
| major_version, device_compat.c_str())); |
| } |
| #else |
| { |
| std::string buffer = GetUserAgent(); |
| EXPECT_EQ(buffer, base::StringPrintf( |
| content::frozen_user_agent_strings::kDesktop, |
| content::GetUnifiedPlatform().c_str(), |
| version_info::GetMajorVersionNumber().c_str())); |
| } |
| |
| // Verify that the reduced user agent string respects |
| // --force-major-version-to-minor |
| scoped_feature_list.Reset(); |
| scoped_feature_list.InitWithFeatures( |
| {blink::features::kReduceUserAgent, |
| blink::features::kForceMajorVersionInMinorPositionInUserAgent}, {}); |
| { |
| std::string buffer = GetReducedUserAgent(); |
| EXPECT_EQ(buffer, |
| base::StringPrintf(content::frozen_user_agent_strings::kDesktop, |
| content::GetUnifiedPlatform().c_str(), "99")); |
| } |
| |
| // Ensure that the ForceMajorVersionToMinorPosition policy is applied even |
| // when it contradicts Blink feature status values. |
| scoped_feature_list.Reset(); |
| scoped_feature_list.InitWithFeatures( |
| {blink::features::kReduceUserAgent, |
| blink::features::kForceMajorVersionInMinorPositionInUserAgent}, |
| {}); |
| { |
| std::string buffer = GetReducedUserAgent(kForceDisabled); |
| EXPECT_EQ(buffer, base::StringPrintf( |
| content::frozen_user_agent_strings::kDesktop, |
| content::GetUnifiedPlatform().c_str(), |
| version_info::GetMajorVersionNumber().c_str())); |
| } |
| #endif |
| |
| EXPECT_EQ(GetUserAgent(), GetReducedUserAgent()); |
| } |
| |
| TEST_F(UserAgentUtilsTest, UserAgentStringFull) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| |
| // Verify that the full user agent string respects |
| // --force-major-version-to-minor |
| scoped_feature_list.Reset(); |
| scoped_feature_list.InitWithFeatures( |
| {blink::features::kFullUserAgent, |
| blink::features::kForceMajorVersionInMinorPositionInUserAgent}, |
| {}); |
| { EXPECT_EQ(GetUserAgent(), GetFullUserAgent()); } |
| |
| // Verify that the full user agent string when both reduced and full UA |
| // feature enabled respects |
| // --force-major-version-to-minor |
| scoped_feature_list.Reset(); |
| scoped_feature_list.InitWithFeatures( |
| {blink::features::kFullUserAgent, blink::features::kReduceUserAgent, |
| blink::features::kForceMajorVersionInMinorPositionInUserAgent}, |
| {}); |
| { EXPECT_EQ(GetUserAgent(), GetFullUserAgent()); } |
| } |
| |
| TEST_F(UserAgentUtilsTest, UserAgentMetadata) { |
| auto metadata = GetUserAgentMetadata(); |
| |
| const std::string major_version = version_info::GetMajorVersionNumber(); |
| const std::string full_version = version_info::GetVersionNumber(); |
| const std::string major_to_minor_full_version = MajorToMinorVersionNumber(); |
| |
| // According to spec, Sec-CH-UA should contain what project the browser is |
| // based on (i.e. Chromium in this case) as well as the actual product. |
| // In CHROMIUM_BRANDING builds this will check chromium twice. That should be |
| // ok though. |
| |
| const blink::UserAgentBrandVersion chromium_brand_version = {"Chromium", |
| major_version}; |
| const blink::UserAgentBrandVersion major_to_minor_chromium_brand_version = { |
| "Chromium", "99"}; |
| const blink::UserAgentBrandVersion product_brand_version = { |
| version_info::GetProductName(), major_version}; |
| const blink::UserAgentBrandVersion major_to_minor_product_brand_version = { |
| version_info::GetProductName(), "99"}; |
| |
| EXPECT_TRUE(ContainsBrandVersion(metadata.brand_version_list, |
| chromium_brand_version)); |
| EXPECT_TRUE( |
| ContainsBrandVersion(metadata.brand_version_list, product_brand_version)); |
| |
| // verify full version list |
| const blink::UserAgentBrandVersion chromium_brand_full_version = { |
| "Chromium", full_version}; |
| const blink::UserAgentBrandVersion |
| major_to_minor_chromium_brand_full_version = { |
| "Chromium", major_to_minor_full_version}; |
| const blink::UserAgentBrandVersion product_brand_full_version = { |
| version_info::GetProductName(), full_version}; |
| const blink::UserAgentBrandVersion major_to_minor_product_brand_full_version = |
| {version_info::GetProductName(), major_to_minor_full_version}; |
| |
| EXPECT_TRUE(ContainsBrandVersion(metadata.brand_full_version_list, |
| chromium_brand_full_version)); |
| EXPECT_TRUE(ContainsBrandVersion(metadata.brand_full_version_list, |
| product_brand_full_version)); |
| EXPECT_EQ(metadata.full_version, full_version); |
| |
| // Ensure ForceMajorVersionToMinorPosition is respected, |
| TestingPrefServiceSimple pref_service; |
| |
| // ForceMajorVersionToMinorPosition: kForceDisabled |
| pref_service.registry()->RegisterIntegerPref( |
| kForceMajorVersionToMinorPosition, kForceDisabled); |
| metadata = GetUserAgentMetadata(&pref_service); |
| EXPECT_EQ(metadata.full_version, full_version); |
| EXPECT_TRUE(ContainsBrandVersion(metadata.brand_version_list, |
| chromium_brand_version)); |
| EXPECT_TRUE( |
| ContainsBrandVersion(metadata.brand_version_list, product_brand_version)); |
| EXPECT_TRUE(ContainsBrandVersion(metadata.brand_full_version_list, |
| chromium_brand_full_version)); |
| EXPECT_TRUE(ContainsBrandVersion(metadata.brand_full_version_list, |
| product_brand_full_version)); |
| EXPECT_FALSE(ContainsBrandVersion(metadata.brand_version_list, |
| major_to_minor_chromium_brand_version)); |
| EXPECT_FALSE(ContainsBrandVersion(metadata.brand_version_list, |
| major_to_minor_product_brand_version)); |
| EXPECT_FALSE( |
| ContainsBrandVersion(metadata.brand_full_version_list, |
| major_to_minor_chromium_brand_full_version)); |
| EXPECT_FALSE(ContainsBrandVersion(metadata.brand_full_version_list, |
| major_to_minor_product_brand_full_version)); |
| |
| // ForceMajorVersionToMinorPosition: kForceEnabled |
| pref_service.SetInteger(kForceMajorVersionToMinorPosition, kForceEnabled); |
| metadata = GetUserAgentMetadata(&pref_service); |
| EXPECT_EQ(metadata.full_version, major_to_minor_full_version); |
| EXPECT_TRUE(ContainsBrandVersion(metadata.brand_version_list, |
| major_to_minor_chromium_brand_version)); |
| EXPECT_TRUE(ContainsBrandVersion(metadata.brand_version_list, |
| major_to_minor_product_brand_version)); |
| EXPECT_TRUE(ContainsBrandVersion(metadata.brand_full_version_list, |
| major_to_minor_chromium_brand_full_version)); |
| EXPECT_TRUE(ContainsBrandVersion(metadata.brand_full_version_list, |
| major_to_minor_product_brand_full_version)); |
| EXPECT_FALSE(ContainsBrandVersion(metadata.brand_version_list, |
| chromium_brand_version)); |
| EXPECT_FALSE( |
| ContainsBrandVersion(metadata.brand_version_list, product_brand_version)); |
| EXPECT_FALSE(ContainsBrandVersion(metadata.brand_full_version_list, |
| chromium_brand_full_version)); |
| EXPECT_FALSE(ContainsBrandVersion(metadata.brand_full_version_list, |
| product_brand_full_version)); |
| |
| #if BUILDFLAG(IS_WIN) |
| if (base::win::GetVersion() < base::win::Version::WIN10) { |
| VerifyLegacyWinPlatformVersion(metadata.platform_version); |
| } else { |
| VerifyWinPlatformVersion(metadata.platform_version); |
| } |
| #else |
| int32_t major, minor, bugfix = 0; |
| base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix); |
| EXPECT_EQ(metadata.platform_version, |
| base::StringPrintf("%d.%d.%d", major, minor, bugfix)); |
| #endif |
| // This makes sure no extra information is added to the platform version. |
| EXPECT_EQ(metadata.platform_version.find(";"), std::string::npos); |
| // TODO(crbug.com/1103047): This can be removed/re-refactored once we use |
| // "macOS" by default |
| #if BUILDFLAG(IS_MAC) |
| EXPECT_EQ(metadata.platform, "macOS"); |
| #else |
| EXPECT_EQ(metadata.platform, version_info::GetOSType()); |
| #endif |
| EXPECT_EQ(metadata.architecture, content::GetCpuArchitecture()); |
| EXPECT_EQ(metadata.model, content::BuildModelInfo()); |
| EXPECT_EQ(metadata.bitness, content::GetCpuBitness()); |
| EXPECT_EQ(metadata.wow64, content::IsWoW64()); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GenerateBrandVersionListUnbranded) { |
| blink::UserAgentMetadata metadata; |
| metadata.brand_version_list = GenerateBrandVersionList( |
| 84, absl::nullopt, "84", absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| metadata.brand_full_version_list = GenerateBrandVersionList( |
| 84, absl::nullopt, "84.0.0.0", absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| // 1. verify major version |
| std::string brand_list = metadata.SerializeBrandMajorVersionList(); |
| EXPECT_EQ(R"("/Not=A?Brand";v="8", "Chromium";v="84")", brand_list); |
| // 2. verify full version |
| std::string brand_list_w_fv = metadata.SerializeBrandFullVersionList(); |
| EXPECT_EQ(R"("/Not=A?Brand";v="8.0.0.0", "Chromium";v="84.0.0.0")", |
| brand_list_w_fv); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GenerateBrandVersionListUnbrandedVerifySeedChanges) { |
| blink::UserAgentMetadata metadata; |
| |
| metadata.brand_version_list = GenerateBrandVersionList( |
| 84, absl::nullopt, "84", absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| // Capture the serialized brand lists with version 84 as the seed. |
| std::string brand_list = metadata.SerializeBrandMajorVersionList(); |
| std::string brand_list_w_fv = metadata.SerializeBrandFullVersionList(); |
| |
| metadata.brand_version_list = GenerateBrandVersionList( |
| 85, absl::nullopt, "85", absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| metadata.brand_full_version_list = GenerateBrandVersionList( |
| 85, absl::nullopt, "85.0.0.0", absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| |
| // Make sure the lists are different for different seeds (84 vs 85). |
| // 1. verify major version |
| std::string brand_list_diff = metadata.SerializeBrandMajorVersionList(); |
| EXPECT_EQ(R"("Chromium";v="85", ")Not?A_Brand";v="99")", brand_list_diff); |
| EXPECT_NE(brand_list, brand_list_diff); |
| // 2.verify full version |
| std::string brand_list_diff_w_fv = metadata.SerializeBrandFullVersionList(); |
| EXPECT_EQ(R"("Chromium";v="85.0.0.0", ")Not?A_Brand";v="99.0.0.0")", |
| brand_list_diff_w_fv); |
| EXPECT_NE(brand_list_w_fv, brand_list_diff_w_fv); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GenerateBrandVersionListWithGreaseBrandOverride) { |
| blink::UserAgentMetadata metadata; |
| // The GREASE generation algorithm should respond to experiment overrides. |
| metadata.brand_version_list = GenerateBrandVersionList( |
| 84, absl::nullopt, "84", "Clean GREASE", absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| metadata.brand_full_version_list = GenerateBrandVersionList( |
| 84, absl::nullopt, "84.0.0.0", "Clean GREASE", absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| // 1. verify major version |
| std::string brand_list_grease_override = |
| metadata.SerializeBrandMajorVersionList(); |
| EXPECT_EQ(R"("Clean GREASE";v="8", "Chromium";v="84")", |
| brand_list_grease_override); |
| // 2. verify full version |
| std::string brand_list_grease_override_fv = |
| metadata.SerializeBrandFullVersionList(); |
| EXPECT_EQ(R"("Clean GREASE";v="8.0.0.0", "Chromium";v="84.0.0.0")", |
| brand_list_grease_override_fv); |
| } |
| |
| TEST_F(UserAgentUtilsTest, |
| GenerateBrandVersionListWithGreaseBrandAndVersionOverride) { |
| blink::UserAgentMetadata metadata; |
| |
| metadata.brand_version_list = GenerateBrandVersionList( |
| 84, absl::nullopt, "84", "Clean GREASE", "1024", true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| metadata.brand_full_version_list = GenerateBrandVersionList( |
| 84, absl::nullopt, "84.0.0.0", "Clean GREASE", "1024", true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| // 1. verify major version |
| std::string brand_list_and_version_grease_override = |
| metadata.SerializeBrandMajorVersionList(); |
| EXPECT_EQ(R"("Clean GREASE";v="1024", "Chromium";v="84")", |
| brand_list_and_version_grease_override); |
| // 2. verify full version |
| std::string brand_list_and_version_grease_override_fv = |
| metadata.SerializeBrandFullVersionList(); |
| EXPECT_EQ(R"("Clean GREASE";v="1024.0.0.0", "Chromium";v="84.0.0.0")", |
| brand_list_and_version_grease_override_fv); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GenerateBrandVersionListWithGreaseVersionOverride) { |
| blink::UserAgentMetadata metadata; |
| |
| metadata.brand_version_list = GenerateBrandVersionList( |
| 84, absl::nullopt, "84", absl::nullopt, "1024", true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| metadata.brand_full_version_list = GenerateBrandVersionList( |
| 84, absl::nullopt, "84.0.0.0", absl::nullopt, "1024", true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| // 1. verify major version |
| std::string brand_version_grease_override = |
| metadata.SerializeBrandMajorVersionList(); |
| EXPECT_EQ(R"("/Not=A?Brand";v="1024", "Chromium";v="84")", |
| brand_version_grease_override); |
| // 2. verify full version |
| std::string brand_version_grease_override_fv = |
| metadata.SerializeBrandFullVersionList(); |
| EXPECT_EQ(R"("/Not=A?Brand";v="1024.0.0.0", "Chromium";v="84.0.0.0")", |
| brand_version_grease_override_fv); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GenerateBrandVersionListWithBrand) { |
| blink::UserAgentMetadata metadata; |
| metadata.brand_version_list = GenerateBrandVersionList( |
| 84, "Totally A Brand", "84", absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| metadata.brand_full_version_list = GenerateBrandVersionList( |
| 84, "Totally A Brand", "84.0.0.0", absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| // 1. verify major version |
| std::string brand_list_w_brand = metadata.SerializeBrandMajorVersionList(); |
| EXPECT_EQ( |
| R"("/Not=A?Brand";v="8", "Chromium";v="84", "Totally A Brand";v="84")", |
| brand_list_w_brand); |
| // 2. verify full version |
| std::string brand_list_w_brand_fv = metadata.SerializeBrandFullVersionList(); |
| EXPECT_EQ(base::StrCat({"\"/Not=A?Brand\";v=\"8.0.0.0\", ", |
| "\"Chromium\";v=\"84.0.0.0\", ", |
| "\"Totally A Brand\";v=\"84.0.0.0\""}), |
| brand_list_w_brand_fv); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GenerateBrandVersionListInvalidSeed) { |
| // Should DCHECK on negative numbers |
| EXPECT_DCHECK_DEATH(GenerateBrandVersionList( |
| -1, absl::nullopt, "99", absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion)); |
| EXPECT_DCHECK_DEATH(GenerateBrandVersionList( |
| -1, absl::nullopt, "99.0.0.0", absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion)); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GetGreasedUserAgentBrandVersionOldAlgorithm) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| // Test to ensure the old algorithm is respected when opted into. |
| scoped_feature_list.InitAndEnableFeatureWithParameters( |
| features::kGreaseUACH, {{"updated_algorithm", "false"}}); |
| |
| std::vector<int> permuted_order{0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99.0.0.0"); |
| } |
| |
| TEST_F(UserAgentUtilsTest, |
| GetGreasedUserAgentBrandVersionOldAlgorithmIgnoresBrandOverrides) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| // Test to ensure the old algorithm is respected when the flag is not set. |
| scoped_feature_list.InitAndEnableFeatureWithParameters( |
| features::kGreaseUACH, {{"updated_algorithm", "false"}}); |
| // With the new algorithm disabled, we want to avoid experiment params |
| // ("WhatIsGrease", 1024) from taking an effect. |
| std::vector<int> permuted_order{0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, "WhatIsGrease", absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, "WhatIsGrease", absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99.0.0.0"); |
| } |
| |
| TEST_F(UserAgentUtilsTest, |
| GetGreasedUserAgentBrandVersionOldAlgorithmIgnoresVersionOverrides) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| // Test to ensure the old algorithm is respected when the flag is not set. |
| scoped_feature_list.InitAndEnableFeatureWithParameters( |
| features::kGreaseUACH, {{"updated_algorithm", "false"}}); |
| // With the new algorithm disabled, we want to avoid experiment params |
| // ("WhatIsGrease", 1024) from taking an effect. |
| std::vector<int> permuted_order{0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, "1024", true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, "1024", true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99.0.0.0"); |
| } |
| |
| TEST_F( |
| UserAgentUtilsTest, |
| GetGreasedUserAgentBrandVersionOldAlgorithmIgnoresBrandAndVersionOverrides) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| // Test to ensure the old algorithm is respected when the flag is not set. |
| scoped_feature_list.InitAndEnableFeatureWithParameters( |
| features::kGreaseUACH, {{"updated_algorithm", "false"}}); |
| // With the new algorithm disabled, we want to avoid experiment params |
| // ("WhatIsGrease", 1024) from taking an effect. |
| std::vector<int> permuted_order{0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, "WhatIsGrease", "1024", true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, "WhatIsGrease", "1024", true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99.0.0.0"); |
| } |
| |
| // Tests to ensure the new algorithm works and is still overridable. |
| TEST_F(UserAgentUtilsTest, GetGreasedUserAgentBrandVersionNewAlgorithm) { |
| std::vector<int> permuted_order{0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, "/Not=A?Brand"); |
| EXPECT_EQ(greased_bv.version, "8"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, "/Not=A?Brand"); |
| EXPECT_EQ(greased_bv.version, "8.0.0.0"); |
| } |
| |
| TEST_F(UserAgentUtilsTest, |
| GetGreasedUserAgentBrandVersionNewAlgorithmBrandOverride) { |
| std::vector<int> permuted_order{0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, "WhatIsGrease", absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, "WhatIsGrease"); |
| EXPECT_EQ(greased_bv.version, "8"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, "WhatIsGrease", absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, "WhatIsGrease"); |
| EXPECT_EQ(greased_bv.version, "8.0.0.0"); |
| } |
| |
| TEST_F(UserAgentUtilsTest, |
| GetGreasedUserAgentBrandVersionNewAlgorithmVersionOverride) { |
| std::vector<int> permuted_order{0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, "1024", true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, "/Not=A?Brand"); |
| EXPECT_EQ(greased_bv.version, "1024"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, "1024", true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, "/Not=A?Brand"); |
| EXPECT_EQ(greased_bv.version, "1024.0.0.0"); |
| } |
| |
| TEST_F(UserAgentUtilsTest, |
| GetGreasedUserAgentBrandVersionNewAlgorithmBrandAndVersionOverride) { |
| std::vector<int> permuted_order{0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, "WhatIsGrease", "1024", true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, "WhatIsGrease"); |
| EXPECT_EQ(greased_bv.version, "1024"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, "WhatIsGrease", "1024", true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, "WhatIsGrease"); |
| EXPECT_EQ(greased_bv.version, "1024.0.0.0"); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GetGreasedUserAgentBrandVersionFullVersions) { |
| std::vector<int> permuted_order = {2, 1, 0}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 86, absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, ";Not_A Brand"); |
| EXPECT_EQ(greased_bv.version, "24"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 86, absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, ";Not_A Brand"); |
| EXPECT_EQ(greased_bv.version, "24.0.0.0"); |
| |
| // Test the greasy input with full version |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, "1024.0.0.0", true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, "/Not=A?Brand"); |
| EXPECT_EQ(greased_bv.version, "1024"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, "1024.0.0.0", true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, "/Not=A?Brand"); |
| EXPECT_EQ(greased_bv.version, "1024.0.0.0"); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GetGreasedUserAgentBrandVersionEnterpriseOverride) { |
| // Ensure the enterprise override bool can force the old GREASE algorithm to |
| // be used. |
| std::vector<int> permuted_order = {0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, absl::nullopt, false, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, absl::nullopt, absl::nullopt, false, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99.0.0.0"); |
| } |
| |
| TEST_F( |
| UserAgentUtilsTest, |
| GetGreasedUserAgentBrandVersionEnterpriseOverrideSupersedesOtherOverrides) { |
| // Ensure the enterprise override bool can force the old GREASE algorithm to |
| // be used and supersedes passed-in brand/version overrides. |
| std::vector<int> permuted_order = {0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, "helloWorld", "100000", false, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99"); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, 84, "helloWorld", "100000", false, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_EQ(greased_bv.brand, " Not A;Brand"); |
| EXPECT_EQ(greased_bv.version, "99.0.0.0"); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GetGreasedUserAgentBrandVersionNoLeadingWhitespace) { |
| std::vector<int> permuted_order = {0, 1, 2}; |
| blink::UserAgentBrandVersion greased_bv; |
| // Go up to 110 based on the 11 total chars * 10 possible first chars. |
| for (int i = 0; i < 110; i++) { |
| // Regardless of the major version seed, the spec calls for no leading |
| // whitespace in the brand. |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, i, absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kMajorVersion); |
| EXPECT_NE(greased_bv.brand[0], ' '); |
| |
| greased_bv = GetGreasedUserAgentBrandVersion( |
| permuted_order, i, absl::nullopt, absl::nullopt, true, |
| blink::UserAgentBrandVersionType::kFullVersion); |
| EXPECT_NE(greased_bv.brand[0], ' '); |
| } |
| } |
| |
| TEST_F(UserAgentUtilsTest, GetProductAndVersion) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitWithFeatures( |
| /*enabled_features=*/{}, /*disabled_features=*/{ |
| blink::features::kForceMajorVersionInMinorPositionInUserAgent, |
| blink::features::kReduceUserAgentMinorVersion}); |
| |
| std::string product = GetProductAndVersion(); |
| std::string major_version; |
| std::string minor_version; |
| EXPECT_TRUE(re2::RE2::FullMatch(product, kChromeProductVersionRegex, |
| &major_version, &minor_version)); |
| EXPECT_EQ(major_version, version_info::GetMajorVersionNumber()); |
| EXPECT_EQ(minor_version, "0"); |
| |
| // Ensure policy is respected if ForceMajorToMinor is force enabled |
| product = GetProductAndVersion(/*force_major_to_minor=*/kForceEnabled); |
| EXPECT_TRUE(re2::RE2::FullMatch(product, kChromeProductVersionRegex, |
| &major_version, &minor_version)); |
| EXPECT_EQ(major_version, "99"); |
| EXPECT_EQ(minor_version, version_info::GetMajorVersionNumber()); |
| |
| // Ensure the build version FeatureParam is used when set. |
| scoped_feature_list.Reset(); |
| scoped_feature_list.InitWithFeaturesAndParameters( |
| /*enabled_features=*/{{blink::features::kReduceUserAgentMinorVersion, |
| {{{"build_version", "5555"}}}}}, |
| /*disabled_features=*/{ |
| blink::features::kForceMajorVersionInMinorPositionInUserAgent}); |
| product = GetProductAndVersion(); |
| std::string build_version; |
| std::string patch_version; |
| EXPECT_TRUE(re2::RE2::FullMatch(product, kChromeProductVersionRegex, |
| &major_version, &minor_version, |
| &build_version, &patch_version)); |
| EXPECT_EQ(major_version, version_info::GetMajorVersionNumber()); |
| EXPECT_EQ(minor_version, "0"); |
| EXPECT_EQ(build_version, "5555"); |
| EXPECT_EQ(patch_version, "0"); |
| |
| // Ensure policy is respected if ForcemajorToMinor is force disabled, even if |
| // the respective Blink feature is enabled. |
| scoped_feature_list.Reset(); |
| scoped_feature_list.InitWithFeatures( |
| /*enabled_features=*/{blink::features:: |
| kForceMajorVersionInMinorPositionInUserAgent}, |
| /*disabled_features=*/{blink::features::kReduceUserAgentMinorVersion}); |
| product = GetProductAndVersion(/*force_major_to_minor=*/kForceDisabled); |
| EXPECT_TRUE(re2::RE2::FullMatch(product, kChromeProductVersionRegex, |
| &major_version, &minor_version, |
| &build_version)); |
| EXPECT_EQ(major_version, version_info::GetMajorVersionNumber()); |
| EXPECT_EQ(minor_version, "0"); |
| EXPECT_NE(build_version, "9999"); |
| |
| product = GetProductAndVersion(); |
| EXPECT_TRUE(re2::RE2::FullMatch(product, kChromeProductVersionRegex, |
| &major_version, &minor_version, |
| &build_version)); |
| EXPECT_EQ(major_version, "99"); |
| EXPECT_EQ(minor_version, version_info::GetMajorVersionNumber()); |
| EXPECT_NE(build_version, "0"); |
| |
| scoped_feature_list.Reset(); |
| scoped_feature_list.InitWithFeatures( |
| /*enabled_features=*/{blink::features::kReduceUserAgentMinorVersion}, |
| /*disabled_features=*/{ |
| blink::features::kForceMajorVersionInMinorPositionInUserAgent}); |
| product = GetProductAndVersion(); |
| EXPECT_TRUE(re2::RE2::FullMatch(product, kChromeProductVersionRegex, |
| &major_version, &minor_version, |
| &build_version, &patch_version)); |
| EXPECT_EQ(major_version, version_info::GetMajorVersionNumber()); |
| EXPECT_EQ(minor_version, "0"); |
| EXPECT_EQ(build_version, "0"); |
| EXPECT_EQ(patch_version, "0"); |
| |
| scoped_feature_list.Reset(); |
| scoped_feature_list.InitWithFeatures( |
| /*enabled_features=*/{blink::features::kReduceUserAgentMinorVersion, |
| blink::features:: |
| kForceMajorVersionInMinorPositionInUserAgent}, |
| /*disabled_features=*/{}); |
| product = GetProductAndVersion(); |
| EXPECT_TRUE(re2::RE2::FullMatch(product, kChromeProductVersionRegex, |
| &major_version, &minor_version, |
| &build_version, &patch_version)); |
| EXPECT_EQ(major_version, "99"); |
| EXPECT_EQ(minor_version, version_info::GetMajorVersionNumber()); |
| EXPECT_EQ(build_version, "0"); |
| EXPECT_EQ(patch_version, "0"); |
| } |
| |
| TEST_F(UserAgentUtilsTest, GetUserAgent) { |
| const std::string ua = GetUserAgent(); |
| std::string major_version; |
| std::string minor_version; |
| EXPECT_TRUE(re2::RE2::PartialMatch(ua, kChromeProductVersionRegex, |
| &major_version, &minor_version)); |
| EXPECT_EQ(major_version, version_info::GetMajorVersionNumber()); |
| // Minor version should contain the actual minor version number. |
| EXPECT_EQ(minor_version, "0"); |
| } |
| |
| class UserAgentUtilsMinorVersionTest |
| : public testing::Test, |
| public testing::WithParamInterface<bool> { |
| public: |
| void SetUp() override { |
| if (ForceMajorInMinorVersion()) |
| scoped_feature_list_.InitAndEnableFeature( |
| blink::features::kForceMajorVersionInMinorPositionInUserAgent); |
| } |
| |
| bool ForceMajorInMinorVersion() { return GetParam(); } |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| } // namespace embedder_support |