blob: 9d9a0aac10a353d8c446e1fd2323ccd947301fe8 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// 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 <vector>
#include "base/command_line.h"
#include "base/debug/stack_trace.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/version.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/embedder_support/pref_names.h"
#include "components/embedder_support/switches.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/user_agent.h"
#include "net/http/http_util.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include "base/win/registry.h"
#include "base/win/windows_version.h"
#endif // BUILDFLAG(IS_WIN)
namespace embedder_support {
namespace {
constexpr char kVersion99[] = "99";
#if BUILDFLAG(IS_WIN)
// The registry key where the UniversalApiContract version value can be read
// from.
constexpr wchar_t kWindowsRuntimeWellKnownContractsRegKeyName[] =
L"SOFTWARE\\Microsoft\\WindowsRuntime\\WellKnownContracts";
// Name of the UniversalApiContract registry.
constexpr wchar_t kUniversalApiContractName[] =
L"Windows.Foundation.UniversalApiContract";
// There's a chance that access to the registry key that contains the
// UniversalApiContract Version will not be available in the future. After we
// confirm that our Windows version is RS5 or greater, it is best to have the
// default return value be the highest known version number at the time this
// code is submitted. If the UniversalApiContract registry key is no longer
// available, there will either be a new API introduced, or we will need
// to rely on querying the IsApiContractPresentByMajor function used by
// user_agent_utils_unittest.cc.
const int kHighestKnownUniversalApiContractVersion = 15;
int GetPreRS5UniversalApiContractVersion() {
// This calls Kernel32Version() to get the real non-spoofable version (as
// opposed to base::win::GetVersion() which as of writing this seems to return
// different results depending on compatibility mode, and is spoofable).
// See crbug.com/1404448.
const base::win::Version version = base::win::OSInfo::Kernel32Version();
if (version == base::win::Version::WIN10) {
return 1;
}
if (version == base::win::Version::WIN10_TH2) {
return 2;
}
if (version == base::win::Version::WIN10_RS1) {
return 3;
}
if (version == base::win::Version::WIN10_RS2) {
return 4;
}
if (version == base::win::Version::WIN10_RS3) {
return 5;
}
if (version == base::win::Version::WIN10_RS4) {
return 6;
}
// The list above should account for all Windows versions prior to
// RS5.
NOTREACHED();
return 0;
}
// Returns the UniversalApiContract version number, which is available for
// Windows versions greater than RS5. Otherwise, returns 0.
const std::string& GetUniversalApiContractVersion() {
// Do not use this for runtime environment detection logic. This method should
// only be used to help populate the Sec-CH-UA-Platform client hint. If
// authoring code that depends on a minimum API contract version being
// available, you should instead leverage the OS's IsApiContractPresentByMajor
// method.
static const base::NoDestructor<std::string> universal_api_contract_version(
[] {
int major_version = 0;
int minor_version = 0;
if (base::win::OSInfo::Kernel32Version() <=
base::win::Version::WIN10_RS4) {
major_version = GetPreRS5UniversalApiContractVersion();
} else {
base::win::RegKey version_key(
HKEY_LOCAL_MACHINE, kWindowsRuntimeWellKnownContractsRegKeyName,
KEY_QUERY_VALUE | KEY_WOW64_64KEY);
if (version_key.Valid()) {
DWORD universal_api_contract_version = 0;
LONG result = version_key.ReadValueDW(
kUniversalApiContractName, &universal_api_contract_version);
if (result == ERROR_SUCCESS) {
major_version = HIWORD(universal_api_contract_version);
minor_version = LOWORD(universal_api_contract_version);
} else {
major_version = kHighestKnownUniversalApiContractVersion;
}
} else {
major_version = kHighestKnownUniversalApiContractVersion;
}
}
// The major version of the contract is stored in the HIWORD, while the
// minor version is stored in the LOWORD.
return base::StrCat({base::NumberToString(major_version), ".",
base::NumberToString(minor_version), ".0"});
}());
return *universal_api_contract_version;
}
const std::string& GetWindowsPlatformVersion() {
return GetUniversalApiContractVersion();
}
#endif // BUILDFLAG(IS_WIN)
// Returns true if the user agent string should force the major version into
// the minor position.
// TODO(crbug.com/1290820): Remove this method along with policy.
bool ShouldForceMajorVersionToMinorPosition(
ForceMajorVersionToMinorPosition force_major_to_minor) {
return (
(force_major_to_minor !=
ForceMajorVersionToMinorPosition::kForceDisabled &&
base::FeatureList::IsEnabled(
blink::features::kForceMajorVersionInMinorPositionInUserAgent)) ||
force_major_to_minor == ForceMajorVersionToMinorPosition::kForceEnabled);
}
// Returns true if the user agent reduction should be forced (or prevented).
// TODO(crbug.com/1330890): Remove this method along with policy.
bool ShouldReduceUserAgentMinorVersion(
UserAgentReductionEnterprisePolicyState user_agent_reduction) {
return ((user_agent_reduction !=
UserAgentReductionEnterprisePolicyState::kForceDisabled &&
base::FeatureList::IsEnabled(
blink::features::kReduceUserAgentMinorVersion)) ||
user_agent_reduction ==
UserAgentReductionEnterprisePolicyState::kForceEnabled);
}
// For desktop:
// Returns true if both kReduceUserAgentMinorVersionName and
// kReduceUserAgentPlatformOsCpu are enabled. It makes
// kReduceUserAgentPlatformOsCpu depend on kReduceUserAgentMinorVersionName.
//
// For android:
// Returns true if both kReduceUserAgentMinorVersionName and
// kReduceUserAgentAndroidVersionDeviceModel are enabled. It makes
// kReduceUserAgentAndroidVersionDeviceModel depend on
// kReduceUserAgentMinorVersionName.
//
// It helps us avoid introducing individual enterprise policy controls for
// sending unified platform for the user agent string.
bool ShouldSendUserAgentUnifiedPlatform(
UserAgentReductionEnterprisePolicyState user_agent_reduction) {
#if BUILDFLAG(IS_ANDROID)
return ShouldReduceUserAgentMinorVersion(user_agent_reduction) &&
base::FeatureList::IsEnabled(
blink::features::kReduceUserAgentAndroidVersionDeviceModel);
#else
return ShouldReduceUserAgentMinorVersion(user_agent_reduction) &&
base::FeatureList::IsEnabled(
blink::features::kReduceUserAgentPlatformOsCpu) &&
blink::features::kAllExceptLegacyWindowsPlatform.Get();
#endif
}
const std::string& GetMajorInMinorVersionNumber() {
static const base::NoDestructor<std::string> version_number([] {
base::Version version(version_info::GetVersionNumber());
std::string version_str;
const std::vector<uint32_t>& components = version.components();
for (size_t i = 0; i < components.size(); ++i) {
if (i > 0) {
version_str.append(".");
}
if (i == 0) {
// Hardcode major version to 99
version_str.append(kVersion99);
} else if (i == 1) {
// Force major into minor version
version_str.append(base::NumberToString(components[0]));
} else {
// build and patch stay the same
version_str.append(base::NumberToString(components[i]));
}
}
return version_str;
}());
return *version_number;
}
const std::string& GetReducedMajorInMinorVersionNumber() {
static const base::NoDestructor<std::string> version_number([] {
std::string version_str(kVersion99);
version_str.append(".");
version_str.append(version_info::GetMajorVersionNumber());
version_str.append(".0.0");
return version_str;
}());
return *version_number;
}
std::string GetVersionNumber(const UserAgentOptions& options) {
// Force major version to 99.
if (ShouldForceMajorVersionToMinorPosition(options.force_major_to_minor))
return GetMajorInMinorVersionNumber();
const std::string& version_str = version_info::GetVersionNumber();
return version_str;
}
const blink::UserAgentBrandList GetUserAgentBrandList(
const std::string& major_version,
bool enable_updated_grease_by_policy,
const std::string& full_version,
blink::UserAgentBrandVersionType output_version_type) {
int major_version_number;
bool parse_result = base::StringToInt(major_version, &major_version_number);
DCHECK(parse_result);
absl::optional<std::string> brand;
#if !BUILDFLAG(CHROMIUM_BRANDING)
brand = version_info::GetProductName();
#endif
absl::optional<std::string> maybe_brand_override =
base::GetFieldTrialParamValueByFeature(features::kGreaseUACH,
"brand_override");
absl::optional<std::string> maybe_version_override =
base::GetFieldTrialParamValueByFeature(features::kGreaseUACH,
"version_override");
if (maybe_brand_override->empty())
maybe_brand_override = absl::nullopt;
if (maybe_version_override->empty())
maybe_version_override = absl::nullopt;
std::string brand_version =
output_version_type == blink::UserAgentBrandVersionType::kFullVersion
? full_version
: major_version;
return GenerateBrandVersionList(major_version_number, brand, brand_version,
maybe_brand_override, maybe_version_override,
enable_updated_grease_by_policy,
output_version_type);
}
const blink::UserAgentBrandList GetUserAgentBrandMajorVersionList(
bool enable_updated_grease_by_policy) {
return GetUserAgentBrandList(version_info::GetMajorVersionNumber(),
enable_updated_grease_by_policy,
version_info::GetVersionNumber(),
blink::UserAgentBrandVersionType::kMajorVersion);
}
// TODO(crbug.com/1290820): Remove this method along with policy.
blink::UserAgentBrandList GetMajorInMinorUserAgentBrandMajorVersionList(
bool enable_updated_grease_by_policy) {
return GetUserAgentBrandList(kVersion99, enable_updated_grease_by_policy,
GetMajorInMinorVersionNumber(),
blink::UserAgentBrandVersionType::kMajorVersion);
}
// TODO(crbug.com/1291612): Consolidate *FullVersionList() methods by using
// GetVersionNumber()
blink::UserAgentBrandList GetUserAgentBrandFullVersionList(
bool enable_updated_grease_by_policy) {
return GetUserAgentBrandList(version_info::GetMajorVersionNumber(),
enable_updated_grease_by_policy,
version_info::GetVersionNumber(),
blink::UserAgentBrandVersionType::kFullVersion);
}
// TODO(crbug.com/1290820): Remove this method along with policy.
blink::UserAgentBrandList GetMajorInMinorUserAgentBrandFullVersionList(
bool enable_updated_grease_by_policy) {
return GetUserAgentBrandList(kVersion99, enable_updated_grease_by_policy,
GetMajorInMinorVersionNumber(),
blink::UserAgentBrandVersionType::kFullVersion);
}
// Return UserAgentBrandList with the major version populated in the brand
// `version` value.
// TODO(crbug.com/1291612): Consolidate *MajorVersionList() methods by using
// GetVersionNumber()
blink::UserAgentBrandList GetBrandMajorVersionList(
bool enable_updated_grease_by_policy,
ForceMajorVersionToMinorPosition force_major_to_minor) {
// Force major version to 99.
if (ShouldForceMajorVersionToMinorPosition(force_major_to_minor))
return GetMajorInMinorUserAgentBrandMajorVersionList(
enable_updated_grease_by_policy);
return GetUserAgentBrandMajorVersionList(enable_updated_grease_by_policy);
}
// Return UserAgentBrandList with the full version populated in the brand
// `version` value.
// TODO(crbug.com/1291612): Consolidate *FullVersionList() methods by using
// GetVersionNumber()
blink::UserAgentBrandList GetBrandFullVersionList(
bool enable_updated_grease_by_policy,
ForceMajorVersionToMinorPosition force_major_to_minor) {
// Force major version to 99.
if (ShouldForceMajorVersionToMinorPosition(force_major_to_minor))
return GetMajorInMinorUserAgentBrandFullVersionList(
enable_updated_grease_by_policy);
return GetUserAgentBrandFullVersionList(enable_updated_grease_by_policy);
}
// Returns a string representing the major version number of the user agent
// string for Chrome, potentially overridden by policy.
std::string GetMajorVersionForUserAgentString(
ForceMajorVersionToMinorPosition force_major_to_minor) {
// Force major version to 99.
if (ShouldForceMajorVersionToMinorPosition(force_major_to_minor))
return kVersion99;
return version_info::GetMajorVersionNumber();
}
} // namespace
std::string GetProductAndVersion(
ForceMajorVersionToMinorPosition force_major_to_minor,
UserAgentReductionEnterprisePolicyState user_agent_reduction) {
if (ShouldForceMajorVersionToMinorPosition(force_major_to_minor)) {
// Force major version to 99 and major version to minor version position.
if (ShouldReduceUserAgentMinorVersion(user_agent_reduction)) {
return "Chrome/" + GetReducedMajorInMinorVersionNumber();
} else {
return "Chrome/" + GetMajorInMinorVersionNumber();
}
} else {
if (ShouldReduceUserAgentMinorVersion(user_agent_reduction)) {
return version_info::GetProductNameAndVersionForReducedUserAgent(
blink::features::kUserAgentFrozenBuildVersion.Get().data());
} else {
return version_info::GetProductNameAndVersionForUserAgent();
}
}
}
// Internal function to handle return the full or "reduced" user agent string,
// depending on the UserAgentReduction enterprise policy.
std::string GetUserAgentInternal(
ForceMajorVersionToMinorPosition force_major_to_minor,
UserAgentReductionEnterprisePolicyState user_agent_reduction) {
std::string product =
GetProductAndVersion(force_major_to_minor, user_agent_reduction);
#if BUILDFLAG(IS_ANDROID)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMobileUserAgent))
product += " Mobile";
#endif
// In User-Agent reduction phase 5, only apply the <unifiedPlatform> to
// desktop UA strings.
// In User-Agent reduction phase 6, only apply the <unifiedPlatform> to
// android UA strings.
return ShouldSendUserAgentUnifiedPlatform(user_agent_reduction)
? content::BuildUnifiedPlatformUserAgentFromProduct(product)
: content::BuildUserAgentFromProduct(product);
}
std::string GetUserAgent(
ForceMajorVersionToMinorPosition force_major_to_minor,
UserAgentReductionEnterprisePolicyState user_agent_reduction) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(kUserAgent)) {
std::string ua = command_line->GetSwitchValueASCII(kUserAgent);
if (net::HttpUtil::IsValidHeaderValue(ua))
return ua;
LOG(WARNING) << "Ignored invalid value for flag --" << kUserAgent;
}
if (base::FeatureList::IsEnabled(blink::features::kFullUserAgent))
return GetFullUserAgent(force_major_to_minor);
if (base::FeatureList::IsEnabled(blink::features::kReduceUserAgent))
return GetReducedUserAgent(force_major_to_minor);
return GetUserAgentInternal(force_major_to_minor, user_agent_reduction);
}
std::string GetReducedUserAgent(
ForceMajorVersionToMinorPosition force_major_to_minor) {
return content::GetReducedUserAgent(
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMobileUserAgent),
GetMajorVersionForUserAgentString(force_major_to_minor));
}
std::string GetFullUserAgent(
ForceMajorVersionToMinorPosition force_major_to_minor) {
return GetUserAgentInternal(
force_major_to_minor,
UserAgentReductionEnterprisePolicyState::kForceDisabled);
}
// Generate a pseudo-random permutation of the following brand/version pairs:
// 1. The base project (i.e. Chromium)
// 2. The browser brand, if available
// 3. A randomized string containing GREASE characters to ensure proper
// header parsing, along with an arbitrarily low version to ensure proper
// version checking.
blink::UserAgentBrandList GenerateBrandVersionList(
int seed,
absl::optional<std::string> brand,
const std::string& version,
absl::optional<std::string> maybe_greasey_brand,
absl::optional<std::string> maybe_greasey_version,
bool enable_updated_grease_by_policy,
blink::UserAgentBrandVersionType output_version_type) {
DCHECK_GE(seed, 0);
const int npermutations = 6; // 3!
int permutation = seed % npermutations;
// Pick a stable permutation seeded by major version number. any values here
// and in order should be under three.
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[permutation];
DCHECK_EQ(6u, orders.size());
DCHECK_EQ(3u, order.size());
blink::UserAgentBrandVersion greasey_bv = GetGreasedUserAgentBrandVersion(
order, seed, maybe_greasey_brand, maybe_greasey_version,
enable_updated_grease_by_policy, output_version_type);
blink::UserAgentBrandVersion chromium_bv = {"Chromium", version};
blink::UserAgentBrandList greased_brand_version_list(3);
if (brand) {
blink::UserAgentBrandVersion brand_bv = {brand.value(), version};
greased_brand_version_list[order[0]] = greasey_bv;
greased_brand_version_list[order[1]] = chromium_bv;
greased_brand_version_list[order[2]] = brand_bv;
} else {
greased_brand_version_list[seed % 2] = greasey_bv;
greased_brand_version_list[(seed + 1) % 2] = chromium_bv;
// If left, the last element would make a blank "" at the end of the header.
greased_brand_version_list.pop_back();
}
return greased_brand_version_list;
}
// Process greased overridden brand version which is either major version or
// full version, return the corresponding output version type.
blink::UserAgentBrandVersion GetProcessedGreasedBrandVersion(
const std::string& greasey_brand,
const std::string& greasey_version,
blink::UserAgentBrandVersionType output_version_type) {
std::string greasey_major_version;
std::string greasey_full_version;
base::Version version(greasey_version);
DCHECK(version.IsValid());
// If the greased overridden version is a significant version type:
// * Major version: set the major version as the overridden version
// * Full version number: extending the version number with ".0.0.0"
// If the overridden version is full version format:
// * Major version: set the major version to match significant version format
// * Full version: set the full version as the overridden version
// https://wicg.github.io/ua-client-hints/#user-agent-full-version
if (version.components().size() > 1) {
greasey_major_version = base::NumberToString(version.components()[0]);
greasey_full_version = greasey_version;
} else {
greasey_major_version = greasey_version;
greasey_full_version = base::StrCat({greasey_version, ".0.0.0"});
}
blink::UserAgentBrandVersion output_greasey_bv = {
greasey_brand,
output_version_type == blink::UserAgentBrandVersionType::kFullVersion
? greasey_full_version
: greasey_major_version};
return output_greasey_bv;
}
blink::UserAgentBrandVersion GetGreasedUserAgentBrandVersion(
std::vector<int> permuted_order,
int seed,
absl::optional<std::string> maybe_greasey_brand,
absl::optional<std::string> maybe_greasey_version,
bool enable_updated_grease_by_policy,
blink::UserAgentBrandVersionType output_version_type) {
std::string greasey_brand;
std::string greasey_version;
// The updated algorithm is enabled by default, but we maintain the ability
// to opt out of it either via Finch (setting updated_algorithm to false) or
// via an enterprise policy escape hatch.
if (enable_updated_grease_by_policy &&
base::GetFieldTrialParamByFeatureAsBool(features::kGreaseUACH,
"updated_algorithm", true)) {
const std::vector<std::string> greasey_chars = {
" ", "(", ":", "-", ".", "/", ")", ";", "=", "?", "_"};
const std::vector<std::string> greased_versions = {"8", "99", "24"};
// See the spec:
// https://wicg.github.io/ua-client-hints/#create-arbitrary-brands-section
greasey_brand = base::StrCat(
{"Not", greasey_chars[(seed) % greasey_chars.size()], "A",
greasey_chars[(seed + 1) % greasey_chars.size()], "Brand"});
greasey_version = greased_versions[seed % greased_versions.size()];
return GetProcessedGreasedBrandVersion(
maybe_greasey_brand.value_or(greasey_brand),
maybe_greasey_version.value_or(greasey_version), output_version_type);
} else {
const std::vector<std::string> greasey_chars = {" ", " ", ";"};
greasey_brand = base::StrCat({greasey_chars[permuted_order[0]], "Not",
greasey_chars[permuted_order[1]], "A",
greasey_chars[permuted_order[2]], "Brand"});
greasey_version = "99";
// The old algorithm is held constant; it does not respond to experiment
// overrides.
return GetProcessedGreasedBrandVersion(greasey_brand, greasey_version,
output_version_type);
}
}
std::string GetPlatformForUAMetadata() {
#if BUILDFLAG(IS_MAC)
// TODO(crbug.com/1103047): This can be removed/re-refactored once we use
// "macOS" by default
return "macOS";
#elif BUILDFLAG(IS_CHROMEOS)
// TODO(crbug.com/1334198): The branding change to remove the space caused a
// regression that's solved here. Ideally, we would just use the new OS name
// without the space here too, but that needs a launch plan.
# if BUILDFLAG(GOOGLE_CHROME_BRANDING)
return "Chrome OS";
# else
return "Chromium OS";
# endif
#else
return version_info::GetOSType();
#endif
}
blink::UserAgentMetadata GetUserAgentMetadata() {
return GetUserAgentMetadata(nullptr);
}
blink::UserAgentMetadata GetUserAgentMetadata(const PrefService* pref_service) {
blink::UserAgentMetadata metadata;
bool enable_updated_grease_by_policy = true;
UserAgentOptions ua_options;
if (pref_service) {
if (pref_service->HasPrefPath(
policy::policy_prefs::kUserAgentClientHintsGREASEUpdateEnabled))
enable_updated_grease_by_policy = pref_service->GetBoolean(
policy::policy_prefs::kUserAgentClientHintsGREASEUpdateEnabled);
ua_options.force_major_to_minor = GetMajorToMinorFromPrefs(pref_service);
}
metadata.brand_version_list = GetBrandMajorVersionList(
enable_updated_grease_by_policy, ua_options.force_major_to_minor);
metadata.brand_full_version_list = GetBrandFullVersionList(
enable_updated_grease_by_policy, ua_options.force_major_to_minor);
metadata.full_version = GetVersionNumber(ua_options);
metadata.platform = GetPlatformForUAMetadata();
metadata.architecture = content::GetCpuArchitecture();
metadata.model = content::BuildModelInfo();
metadata.mobile = false;
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
metadata.mobile = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMobileUserAgent);
#endif
#if BUILDFLAG(IS_WIN)
metadata.platform_version = GetWindowsPlatformVersion();
#else
int32_t major, minor, bugfix = 0;
base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
metadata.platform_version =
base::StringPrintf("%d.%d.%d", major, minor, bugfix);
#endif
metadata.architecture = content::GetCpuArchitecture();
metadata.bitness = content::GetCpuBitness();
metadata.wow64 = content::IsWoW64();
return metadata;
}
#if BUILDFLAG(IS_ANDROID)
void SetDesktopUserAgentOverride(content::WebContents* web_contents,
const blink::UserAgentMetadata& metadata,
bool override_in_new_tabs) {
const char kLinuxInfoStr[] = "X11; Linux x86_64";
blink::UserAgentOverride spoofed_ua;
spoofed_ua.ua_string_override = content::BuildUserAgentFromOSAndProduct(
kLinuxInfoStr, GetProductAndVersion());
spoofed_ua.ua_metadata_override = metadata;
spoofed_ua.ua_metadata_override->platform = "Linux";
spoofed_ua.ua_metadata_override->platform_version =
std::string(); // match content::GetOSVersion(false) on Linux
spoofed_ua.ua_metadata_override->model = std::string();
spoofed_ua.ua_metadata_override->mobile = false;
// Match the above "CpuInfo" string, which is also the most common Linux
// CPU architecture and bitness.`
spoofed_ua.ua_metadata_override->architecture = "x86";
spoofed_ua.ua_metadata_override->bitness = "64";
spoofed_ua.ua_metadata_override->wow64 = false;
web_contents->SetUserAgentOverride(spoofed_ua, override_in_new_tabs);
}
#endif // BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_WIN)
int GetHighestKnownUniversalApiContractVersionForTesting() {
return kHighestKnownUniversalApiContractVersion;
}
#endif // BUILDFLAG(IS_WIN)
// TODO(crbug.com/1290820): Remove this function with policy.
embedder_support::ForceMajorVersionToMinorPosition GetMajorToMinorFromPrefs(
const PrefService* pref_service) {
if (!pref_service->HasPrefPath(kForceMajorVersionToMinorPosition))
return ForceMajorVersionToMinorPosition::kDefault;
switch (pref_service->GetInteger(kForceMajorVersionToMinorPosition)) {
case 1:
return ForceMajorVersionToMinorPosition::kForceDisabled;
case 2:
return ForceMajorVersionToMinorPosition::kForceEnabled;
case 0:
default:
return ForceMajorVersionToMinorPosition::kDefault;
}
}
embedder_support::UserAgentReductionEnterprisePolicyState
GetUserAgentReductionFromPrefs(const PrefService* pref_service) {
if (!pref_service->HasPrefPath(kReduceUserAgentMinorVersion))
return UserAgentReductionEnterprisePolicyState::kDefault;
switch (pref_service->GetInteger(kReduceUserAgentMinorVersion)) {
case 1:
return UserAgentReductionEnterprisePolicyState::kForceDisabled;
case 2:
return UserAgentReductionEnterprisePolicyState::kForceEnabled;
case 0:
default:
return UserAgentReductionEnterprisePolicyState::kDefault;
}
}
} // namespace embedder_support