0

Share user agent code between Chrome and WebLayer so that they remain in sync.

Remove WebLayer's copy of these methods which wasn't exactly the same and use the same logic as Chrome.

Bug: 1170830
Change-Id: I413c60c4c33082aa08b542211226030302bdb678
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2652033
Reviewed-by: Scott Violet <sky@chromium.org>
Commit-Queue: John Abd-El-Malek <jam@chromium.org>
Cr-Commit-Position: refs/heads/master@{#848208}
This commit is contained in:
John Abd-El-Malek
2021-01-28 19:14:41 +00:00
committed by Chromium LUCI CQ
parent 9b605d2490
commit ec1fc69e5b
50 changed files with 673 additions and 686 deletions

@ -2075,6 +2075,7 @@ static_library("browser") {
"//components/download/database",
"//components/download/public/background_service:public",
"//components/embedder_support",
"//components/embedder_support:browser_util",
"//components/encrypted_messages",
"//components/enterprise",
"//components/enterprise/common/proto:connectors_proto",

@ -4,13 +4,14 @@
#include "base/android/jni_string.h"
#include "chrome/android/chrome_jni_headers/ContentUtils_jni.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "components/embedder_support/android/util/user_agent_utils.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/web_contents.h"
static base::android::ScopedJavaLocalRef<jstring>
JNI_ContentUtils_GetBrowserUserAgent(JNIEnv* env) {
return base::android::ConvertUTF8ToJavaString(env, GetUserAgent());
return base::android::ConvertUTF8ToJavaString(
env, embedder_support::GetUserAgent());
}
static void JNI_ContentUtils_SetUserAgentOverride(
@ -18,6 +19,6 @@ static void JNI_ContentUtils_SetUserAgentOverride(
const base::android::JavaParamRef<jobject>& jweb_contents) {
content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(jweb_contents);
embedder_support::SetDesktopUserAgentOverride(web_contents,
::GetUserAgentMetadata());
embedder_support::SetDesktopUserAgentOverride(
web_contents, embedder_support::GetUserAgentMetadata());
}

@ -13,11 +13,11 @@
#include "build/build_config.h"
#include "chrome/browser/apps/platform_apps/app_window_registry_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/autofill/content/browser/risk/fingerprint.h"
#include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/language/core/browser/pref_names.h"
#include "components/metrics/metrics_service.h"
#include "components/prefs/pref_service.h"
@ -89,11 +89,12 @@ void LoadRiskData(uint64_t obfuscated_gaia_id,
g_browser_process->metrics_service()->GetInstallDate());
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
risk::GetFingerprint(
obfuscated_gaia_id, window_bounds, web_contents,
version_info::GetVersionNumber(), charset, accept_languages, install_time,
g_browser_process->GetApplicationLocale(), GetUserAgent(),
base::BindOnce(PassRiskData, std::move(callback)));
risk::GetFingerprint(obfuscated_gaia_id, window_bounds, web_contents,
version_info::GetVersionNumber(), charset,
accept_languages, install_time,
g_browser_process->GetApplicationLocale(),
embedder_support::GetUserAgent(),
base::BindOnce(PassRiskData, std::move(callback)));
}
} // namespace risk_util

@ -220,6 +220,7 @@
#include "components/dom_distiller/core/dom_distiller_switches.h"
#include "components/dom_distiller/core/url_constants.h"
#include "components/embedder_support/switches.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/error_page/common/error.h"
#include "components/error_page/common/error_page_switches.h"
#include "components/error_page/common/localized_error.h"
@ -351,7 +352,6 @@
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
#include "net/base/load_flags.h"
#include "net/base/mime_util.h"
#include "net/http/http_util.h"
#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "pdf/buildflags.h"
@ -1096,10 +1096,6 @@ void LaunchURL(const GURL& url,
}
}
std::string GetProduct() {
return version_info::GetProductNameAndVersionForUserAgent();
}
void MaybeAppendSecureOriginsAllowlistSwitch(base::CommandLine* cmdline) {
// |allowlist| combines pref/policy + cmdline switch in the browser process.
// For renderer and utility (e.g. NetworkService) processes the switch is the
@ -1217,125 +1213,6 @@ bool IsTopChromeWebUIURL(const GURL& url) {
} // namespace
// 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 escaped characters to ensure proper
// header parsing, along with an arbitrarily low version to ensure proper
// version checking.
blink::UserAgentBrandList GenerateBrandVersionList(
int seed,
base::Optional<std::string> brand,
std::string major_version,
base::Optional<std::string> maybe_greasey_brand) {
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());
// Previous values for indexes 0 and 1 were '\' and '"', temporarily removed
// because of compat issues
const std::vector<std::string> escaped_chars = {" ", " ", ";"};
std::string greasey_brand =
base::StrCat({escaped_chars[order[0]], "Not", escaped_chars[order[1]],
"A", escaped_chars[order[2]], "Brand"});
blink::UserAgentBrandVersion greasey_bv = {
maybe_greasey_brand.value_or(greasey_brand), "99"};
blink::UserAgentBrandVersion chromium_bv = {"Chromium", major_version};
blink::UserAgentBrandList greased_brand_version_list(3);
if (brand) {
blink::UserAgentBrandVersion brand_bv = {brand.value(), major_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;
}
const blink::UserAgentBrandList& GetBrandVersionList() {
static const base::NoDestructor<blink::UserAgentBrandList>
greased_brand_version_list([] {
int major_version_number;
std::string major_version = version_info::GetMajorVersionNumber();
base::StringToInt(major_version, &major_version_number);
base::Optional<std::string> brand;
#if !BUILDFLAG(CHROMIUM_BRANDING)
brand = version_info::GetProductName();
#endif
base::Optional<std::string> maybe_param_override =
base::GetFieldTrialParamValueByFeature(features::kGreaseUACH,
"brand_override");
if (maybe_param_override->empty())
maybe_param_override = base::nullopt;
return GenerateBrandVersionList(major_version_number, brand,
major_version, maybe_param_override);
}());
return *greased_brand_version_list;
}
std::string GetUserAgent() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kUserAgent)) {
std::string ua = command_line->GetSwitchValueASCII(switches::kUserAgent);
if (net::HttpUtil::IsValidHeaderValue(ua))
return ua;
LOG(WARNING) << "Ignored invalid value for flag --" << switches::kUserAgent;
}
if (base::FeatureList::IsEnabled(blink::features::kFreezeUserAgent)) {
return content::GetFrozenUserAgent(
command_line->HasSwitch(switches::kUseMobileUserAgent),
version_info::GetMajorVersionNumber());
}
std::string product = GetProduct();
#if defined(OS_ANDROID)
if (command_line->HasSwitch(switches::kUseMobileUserAgent))
product += " Mobile";
#endif
return content::BuildUserAgentFromProduct(product);
}
blink::UserAgentMetadata GetUserAgentMetadata() {
blink::UserAgentMetadata metadata;
metadata.brand_version_list = GetBrandVersionList();
metadata.full_version = version_info::GetVersionNumber();
metadata.platform = version_info::GetOSType();
metadata.platform_version =
content::GetOSVersion(content::IncludeAndroidBuildNumber::Exclude,
content::IncludeAndroidModel::Exclude);
metadata.architecture = content::GetLowEntropyCpuArchitecture();
metadata.model = content::BuildModelInfo();
metadata.mobile = false;
#if defined(OS_ANDROID)
metadata.mobile = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMobileUserAgent);
#endif
return metadata;
}
#if !defined(OS_ANDROID)
base::TimeDelta GetKeepaliveTimerTimeout() {
constexpr base::TimeDelta kDefaultValue = base::TimeDelta::FromSeconds(1);
@ -2290,7 +2167,7 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
*base::CommandLine::ForCurrentProcess();
static const char* const kCommonSwitchNames[] = {
switches::kUserAgent,
embedder_support::kUserAgent,
switches::kUserDataDir, // Make logs go to the right file.
};
command_line->CopySwitchesFrom(browser_command_line, kCommonSwitchNames,
@ -5772,15 +5649,15 @@ void ChromeContentBrowserClient::LogWebFeatureForCurrentPage(
}
std::string ChromeContentBrowserClient::GetProduct() {
return ::GetProduct();
return embedder_support::GetProduct();
}
std::string ChromeContentBrowserClient::GetUserAgent() {
return ::GetUserAgent();
return embedder_support::GetUserAgent();
}
blink::UserAgentMetadata ChromeContentBrowserClient::GetUserAgentMetadata() {
return ::GetUserAgentMetadata();
return embedder_support::GetUserAgentMetadata();
}
base::Optional<gfx::ImageSkia> ChromeContentBrowserClient::GetProductLogo() {

@ -108,17 +108,6 @@ class ChromeXrIntegrationClient;
}
#endif
// Returns the user agent of Chrome.
std::string GetUserAgent();
blink::UserAgentMetadata GetUserAgentMetadata();
blink::UserAgentBrandList GenerateBrandVersionList(
int seed,
base::Optional<std::string> brand,
std::string major_version,
base::Optional<std::string> maybe_greasey_brand);
class ChromeContentBrowserClient : public content::ContentBrowserClient {
public:
ChromeContentBrowserClient();

@ -14,11 +14,8 @@
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.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 "build/build_config.h"
#include "build/chromeos_buildflags.h"
@ -42,21 +39,14 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/user_agent.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/mock_render_process_host.h"
#include "media/media_buildflags.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/switches.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "url/gurl.h"
#if defined(USE_X11) || defined(USE_OZONE)
#include <sys/utsname.h>
#endif
#if !defined(OS_ANDROID)
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
@ -90,168 +80,6 @@ using content::BrowsingDataFilterBuilder;
using testing::_;
using ChromeContentBrowserClientTest = testing::Test;
namespace {
void CheckUserAgentStringOrdering(bool mobile_device) {
std::vector<std::string> pieces;
// Check if the pieces of the user agent string come in the correct order.
ChromeContentBrowserClient content_browser_client;
std::string buffer = content_browser_client.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 defined(OS_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 defined(OS_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);
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 defined(USE_X11) || defined(USE_OZONE)
// X11; Linux x86_64
// X11; CrOS armv7l 4537.56.0
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)";
}
ASSERT_EQ(2u, pieces.size());
ASSERT_EQ("X11", pieces[0]);
pieces = base::SplitStringUsingSubstr(pieces[1], " ", base::KEEP_WHITESPACE,
base::SPLIT_WANT_ALL);
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
// X11; CrOS armv7l 4537.56.0
// ^^
ASSERT_EQ(3u, pieces.size());
ASSERT_EQ("CrOS", pieces[0]);
ASSERT_EQ(machine, 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));
}
#else
// X11; Linux x86_64
// ^^
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(machine, pieces[1]);
#endif
#elif defined(OS_ANDROID)
// Linux; Android 7.1.1; Samsung Chromebook 3
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 defined(OS_FUCHSIA)
// X11; Fuchsia
ASSERT_EQ(2u, pieces.size());
ASSERT_EQ("X11", pieces[0]);
ASSERT_EQ("Fuchsia", pieces[1]);
#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));
}
}
} // namespace
TEST_F(ChromeContentBrowserClientTest, ShouldAssignSiteForURL) {
ChromeContentBrowserClient client;
EXPECT_FALSE(client.ShouldAssignSiteForURL(GURL("chrome-native://test")));
@ -627,157 +455,6 @@ TEST(ChromeContentBrowserClientTest, HandleWebUIReverse) {
nullptr));
}
TEST(ChromeContentBrowserClientTest, UserAgentStringFrozen) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(blink::features::kFreezeUserAgent);
#if defined(OS_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);
// Verify the mobile user agent string is not returned when not using a mobile
// user agent.
ASSERT_FALSE(command_line->HasSwitch(switches::kUseMobileUserAgent));
{
ChromeContentBrowserClient content_browser_client;
std::string buffer = content_browser_client.GetUserAgent();
EXPECT_EQ(buffer, base::StringPrintf(
content::frozen_user_agent_strings::kAndroid,
version_info::GetMajorVersionNumber().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));
{
ChromeContentBrowserClient content_browser_client;
std::string buffer = content_browser_client.GetUserAgent();
EXPECT_EQ(buffer, base::StringPrintf(
content::frozen_user_agent_strings::kAndroidMobile,
version_info::GetMajorVersionNumber().c_str()));
}
#else
{
ChromeContentBrowserClient content_browser_client;
std::string buffer = content_browser_client.GetUserAgent();
EXPECT_EQ(buffer, base::StringPrintf(
content::frozen_user_agent_strings::kDesktop,
version_info::GetMajorVersionNumber().c_str()));
}
#endif
}
TEST(ChromeContentBrowserClientTest, UserAgentStringOrdering) {
#if defined(OS_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(ChromeContentBrowserClientTest, UserAgentMetadata) {
ChromeContentBrowserClient content_browser_client;
auto metadata = content_browser_client.GetUserAgentMetadata();
std::string major_version = version_info::GetMajorVersionNumber();
// 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 product_brand_version = {
version_info::GetProductName(), version_info::GetMajorVersionNumber()};
bool contains_chromium_brand_version = false;
bool contains_product_brand_version = false;
for (const auto& brand_version : metadata.brand_version_list) {
if (brand_version == chromium_brand_version) {
contains_chromium_brand_version = true;
}
if (brand_version == product_brand_version) {
contains_product_brand_version = true;
}
}
EXPECT_TRUE(contains_chromium_brand_version);
EXPECT_TRUE(contains_product_brand_version);
EXPECT_EQ(metadata.full_version, version_info::GetVersionNumber());
EXPECT_EQ(metadata.platform_version,
content::GetOSVersion(content::IncludeAndroidBuildNumber::Exclude,
content::IncludeAndroidModel::Exclude));
// This makes sure no extra information is added to the platform version.
EXPECT_EQ(metadata.platform_version.find(";"), std::string::npos);
EXPECT_EQ(metadata.platform, version_info::GetOSType());
EXPECT_EQ(metadata.architecture, content::GetLowEntropyCpuArchitecture());
EXPECT_EQ(metadata.model, content::BuildModelInfo());
}
TEST(ChromeContentBrowserClientTest, GenerateBrandVersionList) {
blink::UserAgentMetadata metadata;
metadata.brand_version_list =
GenerateBrandVersionList(84, base::nullopt, "84", base::nullopt);
std::string brand_list = metadata.SerializeBrandVersionList();
EXPECT_EQ(R"(" Not A;Brand";v="99", "Chromium";v="84")", brand_list);
metadata.brand_version_list =
GenerateBrandVersionList(85, base::nullopt, "85", base::nullopt);
std::string brand_list_diff = metadata.SerializeBrandVersionList();
// Make sure the lists are different for different seeds
EXPECT_EQ(R"("Chromium";v="85", " Not;A Brand";v="99")", brand_list_diff);
EXPECT_NE(brand_list, brand_list_diff);
metadata.brand_version_list =
GenerateBrandVersionList(84, "Totally A Brand", "84", base::nullopt);
std::string brand_list_w_brand = metadata.SerializeBrandVersionList();
EXPECT_EQ(
R"(" Not A;Brand";v="99", "Chromium";v="84", "Totally A Brand";v="84")",
brand_list_w_brand);
metadata.brand_version_list =
GenerateBrandVersionList(84, base::nullopt, "84", "Clean GREASE");
std::string brand_list_grease_override = metadata.SerializeBrandVersionList();
EXPECT_EQ(R"("Clean GREASE";v="99", "Chromium";v="84")",
brand_list_grease_override);
EXPECT_NE(brand_list, brand_list_grease_override);
// Should DCHECK on negative numbers
EXPECT_DCHECK_DEATH(
GenerateBrandVersionList(-1, base::nullopt, "99", base::nullopt));
}
TEST(ChromeContentBrowserClientTest, LowEntropyCpuArchitecture) {
std::string arch = content::GetLowEntropyCpuArchitecture();
#if defined(OS_WIN) || defined(OS_MAC) || \
(defined(OS_POSIX) && !defined(OS_ANDROID))
EXPECT_TRUE("arm" == arch || "x86" == arch);
#else
EXPECT_EQ("", arch);
#endif
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
class ChromeContentSettingsRedirectTest
: public ChromeContentBrowserClientTest {

@ -259,6 +259,7 @@ source_set("chromeos") {
"//components/download/content/public",
"//components/drive",
"//components/drive:drive_chromeos",
"//components/embedder_support:browser_util",
"//components/enterprise",
"//components/exo",
"//components/favicon/core",

@ -23,7 +23,6 @@
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/chromeos/arc/arc_web_contents_data.h"
#include "chrome/browser/chromeos/arc/policy/arc_policy_util.h"
#include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
@ -49,6 +48,7 @@
#include "components/arc/arc_features.h"
#include "components/arc/arc_prefs.h"
#include "components/arc/arc_util.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/known_user.h"
#include "components/user_manager/user.h"
@ -659,7 +659,7 @@ std::unique_ptr<content::WebContents> CreateArcCustomTabWebContents(
ua_override.ua_string_override = content::BuildUserAgentFromOSAndProduct(
kOsOverrideForTabletSite, product);
ua_override.ua_metadata_override = ::GetUserAgentMetadata();
ua_override.ua_metadata_override = embedder_support::GetUserAgentMetadata();
ua_override.ua_metadata_override->platform = "Android";
ua_override.ua_metadata_override->platform_version = "9";
ua_override.ua_metadata_override->model = "Chrome tablet";

@ -14,7 +14,6 @@
#include "base/synchronization/lock.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/policy/policy_test_utils.h"
@ -27,6 +26,7 @@
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/metrics/content/subprocess_metrics_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_pref_names.h"
@ -1073,7 +1073,7 @@ IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UserAgentVersion) {
const GURL gurl = accept_ch_with_lifetime_url();
blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
blink::UserAgentMetadata ua = embedder_support::GetUserAgentMetadata();
// Navigate to a page that opts-into the header: the value should end with
// the major version, and not contain the full version.
@ -1095,7 +1095,7 @@ IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UserAgentVersion) {
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UAHintsTabletMode) {
const GURL gurl = accept_ch_with_lifetime_url();
blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
blink::UserAgentMetadata ua = embedder_support::GetUserAgentMetadata();
// First request: only minimal hints, no tablet override.
SetClientHintExpectationsOnMainFrame(false);
@ -1202,7 +1202,7 @@ void ClientHintsBrowserTest::TestProfilesIndependent(Browser* browser_a,
Browser* browser_b) {
const GURL gurl = accept_ch_with_lifetime_url();
blink::UserAgentMetadata ua = ::GetUserAgentMetadata();
blink::UserAgentMetadata ua = embedder_support::GetUserAgentMetadata();
// Navigate |browser_a| to a page that opts-into the header: the value should
// end with the major version, and not contain the full version.

@ -5,10 +5,10 @@
#include "chrome/browser/client_hints/client_hints_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "components/client_hints/browser/client_hints.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/prefs/pref_service.h"
@ -46,7 +46,7 @@ KeyedService* ClientHintsFactory::BuildServiceInstanceFor(
return new client_hints::ClientHints(
context, g_browser_process->network_quality_tracker(),
HostContentSettingsMapFactory::GetForProfile(context),
GetUserAgentMetadata(), local_state);
embedder_support::GetUserAgentMetadata(), local_state);
}
content::BrowserContext* ClientHintsFactory::GetBrowserContextToUse(

@ -19,7 +19,6 @@
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/data_use_measurement/chrome_data_use_measurement.h"
#include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
#include "chrome/browser/previews/previews_service.h"
@ -40,6 +39,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/previews/content/previews_ui_service.h"
@ -233,7 +233,8 @@ void DataReductionProxyChromeSettings::InitDataReductionProxySettings(
content::GetNetworkConnectionTracker(),
data_use_measurement::ChromeDataUseMeasurement::GetInstance(),
db_task_runner, commit_delay, GetClient(),
version_info::GetChannelString(chrome::GetChannel()), GetUserAgent());
version_info::GetChannelString(chrome::GetChannel()),
embedder_support::GetUserAgent());
data_reduction_proxy::DataReductionProxySettings::
InitDataReductionProxySettings(profile_prefs, std::move(service));

@ -6,8 +6,8 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/download/android/download_controller_base.h"
#include "components/embedder_support/user_agent_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_process_host.h"
@ -89,9 +89,9 @@ void InterceptOMADownloadNavigationThrottle::InterceptDownload() {
DownloadControllerBase::Get()->CreateAndroidDownload(
base::BindRepeating(&GetWebContents, process_id, routing_id),
DownloadInfo(navigation_handle()->GetURL(), original_url,
content_disposition, mime_type, GetUserAgent(),
// TODO(qinmin): Get the cookie from cookie store.
std::string(),
navigation_handle()->GetReferrer().url.spec()));
DownloadInfo(
navigation_handle()->GetURL(), original_url, content_disposition,
mime_type, embedder_support::GetUserAgent(),
// TODO(qinmin): Get the cookie from cookie store.
std::string(), navigation_handle()->GetReferrer().url.spec()));
}

@ -812,6 +812,7 @@ static_library("extensions") {
"//components/download/public/common:public",
"//components/drive",
"//components/embedder_support",
"//components/embedder_support:browser_util",
"//components/enterprise",
"//components/favicon/content",
"//components/feedback",

@ -15,7 +15,6 @@
#include "build/chromeos_buildflags.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/extensions/activity_log/activity_log.h"
#include "chrome/browser/extensions/api/chrome_extensions_api_client.h"
@ -51,6 +50,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/sessions/content/session_tab_helper.h"
#include "components/update_client/update_client.h"
#include "components/version_info/version_info.h"
@ -533,7 +533,7 @@ UserScriptListener* ChromeExtensionsBrowserClient::GetUserScriptListener() {
}
std::string ChromeExtensionsBrowserClient::GetUserAgent() const {
return ::GetUserAgent();
return embedder_support::GetUserAgent();
}
bool ChromeExtensionsBrowserClient::ShouldSchemeBypassNavigationChecks(

@ -8,10 +8,10 @@
#include "base/bind.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/media/router/data_decoder_util.h"
#include "components/cast_channel/cast_message_handler.h"
#include "components/cast_channel/cast_socket_service.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@ -35,8 +35,8 @@ cast_channel::CastMessageHandler* GetCastMessageHandler() {
static cast_channel::CastMessageHandler* instance =
new cast_channel::CastMessageHandler(
cast_channel::CastSocketService::GetInstance(),
base::BindRepeating(&ParseJsonFromIoThread), GetUserAgent(),
version_info::GetVersionNumber(),
base::BindRepeating(&ParseJsonFromIoThread),
embedder_support::GetUserAgent(), version_info::GetVersionNumber(),
g_browser_process->GetApplicationLocale());
return instance;
}

@ -26,7 +26,6 @@
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/profile_network_context_service_factory.h"
@ -41,6 +40,7 @@
#include "chrome/test/base/in_process_browser_test.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/language/core/browser/pref_names.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/policy/core/browser/browser_policy_connector.h"
@ -1391,7 +1391,7 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
ASSERT_TRUE(FetchHeaderEcho("accept-language", &accept_language));
EXPECT_EQ(system ? kNoAcceptLanguage : "en-US,en;q=0.9", accept_language);
ASSERT_TRUE(FetchHeaderEcho("user-agent", &user_agent));
EXPECT_EQ(::GetUserAgent(), user_agent);
EXPECT_EQ(embedder_support::GetUserAgent(), user_agent);
// Change AcceptLanguages preferences, and check that headers are updated.
// First, A single language.
@ -1402,7 +1402,7 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
ASSERT_TRUE(FetchHeaderEcho("accept-language", &accept_language2));
EXPECT_EQ(system ? kNoAcceptLanguage : "zu", accept_language2);
ASSERT_TRUE(FetchHeaderEcho("user-agent", &user_agent2));
EXPECT_EQ(::GetUserAgent(), user_agent2);
EXPECT_EQ(embedder_support::GetUserAgent(), user_agent2);
// Second, a single language with locale.
browser()->profile()->GetPrefs()->SetString(language::prefs::kAcceptLanguages,
@ -1412,7 +1412,7 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
ASSERT_TRUE(FetchHeaderEcho("accept-language", &accept_language3));
EXPECT_EQ(system ? kNoAcceptLanguage : "zu-ZA,zu;q=0.9", accept_language3);
ASSERT_TRUE(FetchHeaderEcho("user-agent", &user_agent3));
EXPECT_EQ(::GetUserAgent(), user_agent3);
EXPECT_EQ(embedder_support::GetUserAgent(), user_agent3);
// Third, a list with multiple languages. Incognito mode should return only
// the first.
@ -1430,7 +1430,7 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
accept_language4);
}
ASSERT_TRUE(FetchHeaderEcho("user-agent", &user_agent4));
EXPECT_EQ(::GetUserAgent(), user_agent4);
EXPECT_EQ(embedder_support::GetUserAgent(), user_agent4);
}
// First part of testing enable referrers. Check that referrers are enabled by

@ -21,7 +21,6 @@
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/component_updater/crl_set_component_installer.h"
#include "chrome/browser/component_updater/first_party_sets_component_installer.h"
#include "chrome/browser/component_updater/tls_deprecation_config_component_installer.h"
@ -35,6 +34,7 @@
#include "chrome/common/google_url_loader_throttle.h"
#include "chrome/common/pref_names.h"
#include "components/certificate_transparency/ct_known_logs.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/net_log/net_export_file_writer.h"
#include "components/net_log/net_log_proxy_source.h"
#include "components/network_session_configurator/common/network_features.h"
@ -584,7 +584,7 @@ void SystemNetworkContextManager::ConfigureDefaultNetworkContextParams(
network_context_params->enable_brotli = true;
network_context_params->user_agent = GetUserAgent();
network_context_params->user_agent = embedder_support::GetUserAgent();
// Disable referrers by default. Any consumer that enables referrers should
// respect prefs::kEnableReferrers from the appropriate pref store.

@ -14,7 +14,6 @@
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/download/download_service_factory.h"
#include "chrome/browser/image_fetcher/image_fetcher_service_factory.h"
#include "chrome/browser/net/system_network_context_manager.h"
@ -27,6 +26,7 @@
#include "chrome/browser/transition_manager/full_browser_transition_manager.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_constants.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/feed/feed_feature_list.h"
#include "components/image_fetcher/core/cached_image_fetcher.h"
#include "components/image_fetcher/core/image_fetcher_impl.h"
@ -135,8 +135,8 @@ std::unique_ptr<KeyedService> PrefetchServiceFactory::BuildServiceInstanceFor(
auto prefetch_network_request_factory =
std::make_unique<PrefetchNetworkRequestFactoryImpl>(
url_loader_factory, chrome::GetChannel(), GetUserAgent(),
profile_key->GetPrefs());
url_loader_factory, chrome::GetChannel(),
embedder_support::GetUserAgent(), profile_key->GetPrefs());
scoped_refptr<base::SequencedTaskRunner> background_task_runner =
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});

@ -7,10 +7,10 @@
#include <vector>
#include "build/build_config.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/common/pref_names.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/prefs/pref_service.h"
#include "components/search_engines/template_url_service.h"
#include "components/variations/net/variations_http_headers.h"
@ -169,7 +169,7 @@ bool BaseSearchPrefetchRequest::StartPrefetchRequest(Profile* profile) {
// https://w3c.github.io/webappsec/specs/upgrade/#feature-detect
resource_request->headers.SetHeader("Upgrade-Insecure-Requests", "1");
resource_request->headers.SetHeader(net::HttpRequestHeaders::kUserAgent,
GetUserAgent());
embedder_support::GetUserAgent());
resource_request->headers.SetHeader(content::kCorsExemptPurposeHeaderName,
"prefetch");
resource_request->headers.SetHeader(

@ -4,7 +4,7 @@
#include "chrome/browser/printing/printing_init.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/printing/browser/print_manager_utils.h"
#include "content/public/browser/web_contents.h"
#include "printing/buildflags/buildflags.h"
@ -25,7 +25,7 @@ void InitializePrinting(content::WebContents* web_contents) {
#else
printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
CreateCompositeClientIfNeeded(web_contents, GetUserAgent());
CreateCompositeClientIfNeeded(web_contents, embedder_support::GetUserAgent());
}
} // namespace printing

@ -19,7 +19,6 @@
#include "base/task_runner_util.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/profile_resetter/profile_reset_report.pb.h"
#include "chrome/browser/profile_resetter/reset_report_uploader.h"
#include "chrome/browser/profile_resetter/reset_report_uploader_factory.h"
@ -29,6 +28,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/prefs/pref_service.h"
#include "components/search_engines/template_url_service.h"
#include "components/strings/grit/components_strings.h"
@ -237,9 +237,8 @@ std::unique_ptr<base::ListValue> GetReadableFeedbackForSnapshot(
AddPair(list.get(),
l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_LOCALE),
g_browser_process->GetApplicationLocale());
AddPair(list.get(),
l10n_util::GetStringUTF16(IDS_VERSION_UI_USER_AGENT),
GetUserAgent());
AddPair(list.get(), l10n_util::GetStringUTF16(IDS_VERSION_UI_USER_AGENT),
embedder_support::GetUserAgent());
std::string version = version_info::GetVersionNumber();
version += chrome::GetChannelName();
AddPair(list.get(),

@ -11,12 +11,12 @@
#include "base/values.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "components/account_id/account_id.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
#include "components/policy/proto/device_management_backend.pb.h"
@ -112,7 +112,7 @@ namespace reporting {
base::Value GetContext(Profile* profile) {
base::Value context(base::Value::Type::DICTIONARY);
context.SetStringPath("browser.userAgent", GetUserAgent());
context.SetStringPath("browser.userAgent", embedder_support::GetUserAgent());
if (!profile)
return context;

@ -424,6 +424,7 @@ static_library("ui") {
"//components/download/content/factory",
"//components/download/content/public",
"//components/embedder_support",
"//components/embedder_support:browser_util",
"//components/encrypted_messages:encrypted_message_proto",
"//components/enterprise",
"//components/error_page/content/browser",

@ -22,7 +22,6 @@
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/dom_distiller/tab_utils.h"
#include "chrome/browser/favicon/favicon_utils.h"
@ -80,6 +79,7 @@
#include "components/bookmarks/common/bookmark_pref_names.h"
#include "components/browsing_data/content/browsing_data_helper.h"
#include "components/dom_distiller/core/url_utils.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/favicon/content/content_favicon_driver.h"
#include "components/find_in_page/find_tab_helper.h"
#include "components/find_in_page/find_types.h"
@ -1489,7 +1489,7 @@ void SetAndroidOsForTabletSite(content::WebContents* current_tab) {
blink::UserAgentOverride ua_override;
ua_override.ua_string_override = content::BuildUserAgentFromOSAndProduct(
kOsOverrideForTabletSite, product);
ua_override.ua_metadata_override = GetUserAgentMetadata();
ua_override.ua_metadata_override = embedder_support::GetUserAgentMetadata();
ua_override.ua_metadata_override->mobile = true;
ua_override.ua_metadata_override->platform =
kChPlatformOverrideForTabletSite;

@ -8,10 +8,10 @@
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/channel_info.h"
#include "components/autofill/core/browser/logging/log_router.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/grit/dev_ui_components_resources.h"
#include "components/version_info/version_info.h"
#include "components/version_ui/version_handler_helper.h"
@ -41,7 +41,7 @@ content::WebUIDataSource* CreateInternalsHTMLSource(
: "Developer build");
source->AddString(version_ui::kVersionModifier, chrome::GetChannelName());
source->AddString(version_ui::kCL, version_info::GetLastChange());
source->AddString(version_ui::kUserAgent, GetUserAgent());
source->AddString(version_ui::kUserAgent, embedder_support::GetUserAgent());
source->AddString("app_locale", g_browser_process->GetApplicationLocale());
return source;
}

@ -11,7 +11,6 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/version/version_handler.h"
#include "chrome/browser/ui/webui/version/version_util_win.h"
@ -20,6 +19,7 @@
#include "chrome/common/url_constants.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/grit/components_resources.h"
#include "components/strings/grit/components_chromium_strings.h"
#include "components/strings/grit/components_strings.h"
@ -171,7 +171,8 @@ void VersionUI::AddVersionDetailStrings(content::WebUIDataSource* html_source) {
l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_COPYRIGHT),
base::Time::Now()));
html_source->AddString(version_ui::kCL, version_info::GetLastChange());
html_source->AddString(version_ui::kUserAgent, GetUserAgent());
html_source->AddString(version_ui::kUserAgent,
embedder_support::GetUserAgent());
// Note that the executable path and profile path are retrieved asynchronously
// and returned in VersionHandler::OnGotFilePaths. The area is initially
// blank.

@ -565,9 +565,6 @@ const char kTryChromeAgain[] = "try-chrome-again";
// apps/origins. This should be used only for testing purpose.
const char kUnlimitedStorage[] = "unlimited-storage";
// A string used to override the default user agent with a custom one.
const char kUserAgent[] = "user-agent";
// Specifies the user data directory, which is where the browser will look for
// all of its state.
const char kUserDataDir[] = "user-data-dir";

@ -175,7 +175,6 @@ extern const char kTestName[];
extern const char kTrustedDownloadSources[];
extern const char kTryChromeAgain[];
extern const char kUnlimitedStorage[];
extern const char kUserAgent[];
extern const char kUserDataDir[];
extern const char kValidateCrx[];
extern const char kVersion[];

@ -11,20 +11,42 @@ static_library("embedder_support") {
]
}
source_set("unit_tests") {
testonly = true
sources = [ "origin_trials/origin_trial_policy_impl_unittest.cc" ]
# Target for general utilities that are only used in the browser process.
static_library("browser_util") {
sources = [
"user_agent_utils.cc",
"user_agent_utils.h",
]
deps = [
":embedder_support",
"//build:branding_buildflags",
"//components/version_info",
"//content/public/browser",
]
}
source_set("unit_tests") {
testonly = true
sources = [
"origin_trials/origin_trial_policy_impl_unittest.cc",
"user_agent_utils_unittest.cc",
]
deps = [
":browser_util",
"//base",
"//base/test:test_support",
"//components/embedder_support",
"//components/embedder_support/origin_trials",
"//components/version_info:version_info",
"//content/public/common",
"//mojo/core/embedder:embedder",
"//net:net",
"//net/traffic_annotation:test_support",
"//services/network:test_support",
"//testing/gtest",
"//third_party/blink/public/common:headers",
"//third_party/blink/public/mojom:mojom_platform_headers",
]

@ -0,0 +1,7 @@
include_rules = [
"+components/version_info",
"+content/public/browser",
"+content/public/common",
"+net",
"+third_party/blink/public/common",
]

@ -70,8 +70,6 @@ static_library("util") {
"util/response_delegate_impl.cc",
"util/response_delegate_impl.h",
"util/url_utilities.cc",
"util/user_agent_utils.cc",
"util/user_agent_utils.h",
"util/web_resource_response.cc",
"util/web_resource_response.h",
]

@ -1,11 +1,9 @@
include_rules = [
"+components/google/core/common",
"+components/version_info",
"+mojo/public/cpp/bindings",
"+mojo/public/cpp/system",
"+net",
"+services/network/public",
"+third_party/blink/public/common/user_agent",
"+third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h",
]

@ -1,33 +0,0 @@
// Copyright 2020 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/android/util/user_agent_utils.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/user_agent.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
namespace embedder_support {
void SetDesktopUserAgentOverride(content::WebContents* web_contents,
const blink::UserAgentMetadata& metadata) {
const char kLinuxInfoStr[] = "X11; Linux x86_64";
std::string product = version_info::GetProductNameAndVersionForUserAgent();
blink::UserAgentOverride spoofed_ua;
spoofed_ua.ua_string_override =
content::BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
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->architecture = "x86";
spoofed_ua.ua_metadata_override->model = std::string();
spoofed_ua.ua_metadata_override->mobile = false;
web_contents->SetUserAgentOverride(spoofed_ua, false);
}
} // namespace embedder_support

@ -1,23 +0,0 @@
// Copyright 2020 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.
#ifndef COMPONENTS_EMBEDDER_SUPPORT_ANDROID_UTIL_USER_AGENT_UTILS_H_
#define COMPONENTS_EMBEDDER_SUPPORT_ANDROID_UTIL_USER_AGENT_UTILS_H_
namespace blink {
struct UserAgentMetadata;
}
namespace content {
class WebContents;
}
namespace embedder_support {
void SetDesktopUserAgentOverride(content::WebContents* web_contents,
const blink::UserAgentMetadata& metadata);
} // namespace embedder_support
#endif // COMPONENTS_EMBEDDER_SUPPORT_ANDROID_UTIL_USER_AGENT_UTILS_H_

@ -21,4 +21,7 @@ const char kOriginTrialDisabledTokens[] = "origin-trial-disabled-tokens";
// checking origin trial tokens.
const char kOriginTrialPublicKey[] = "origin-trial-public-key";
// A string used to override the default user agent with a custom one.
const char kUserAgent[] = "user-agent";
} // namespace embedder_support

@ -15,6 +15,7 @@ extern const char kDisablePopupBlocking[];
extern const char kOriginTrialDisabledFeatures[];
extern const char kOriginTrialDisabledTokens[];
extern const char kOriginTrialPublicKey[];
extern const char kUserAgent[];
} // namespace embedder_support

@ -0,0 +1,166 @@
// 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 "build/branding_buildflags.h"
#include "components/embedder_support/switches.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"
namespace embedder_support {
std::string GetProduct() {
return version_info::GetProductNameAndVersionForUserAgent();
}
std::string GetUserAgent() {
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::kFreezeUserAgent)) {
return content::GetFrozenUserAgent(
command_line->HasSwitch(switches::kUseMobileUserAgent),
version_info::GetMajorVersionNumber());
}
std::string product = GetProduct();
#if defined(OS_ANDROID)
if (command_line->HasSwitch(switches::kUseMobileUserAgent))
product += " Mobile";
#endif
return content::BuildUserAgentFromProduct(product);
}
// 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 escaped characters to ensure proper
// header parsing, along with an arbitrarily low version to ensure proper
// version checking.
blink::UserAgentBrandList GenerateBrandVersionList(
int seed,
base::Optional<std::string> brand,
std::string major_version,
base::Optional<std::string> maybe_greasey_brand) {
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());
// Previous values for indexes 0 and 1 were '\' and '"', temporarily removed
// because of compat issues
const std::vector<std::string> escaped_chars = {" ", " ", ";"};
std::string greasey_brand =
base::StrCat({escaped_chars[order[0]], "Not", escaped_chars[order[1]],
"A", escaped_chars[order[2]], "Brand"});
blink::UserAgentBrandVersion greasey_bv = {
maybe_greasey_brand.value_or(greasey_brand), "99"};
blink::UserAgentBrandVersion chromium_bv = {"Chromium", major_version};
blink::UserAgentBrandList greased_brand_version_list(3);
if (brand) {
blink::UserAgentBrandVersion brand_bv = {brand.value(), major_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;
}
const blink::UserAgentBrandList& GetBrandVersionList() {
static const base::NoDestructor<blink::UserAgentBrandList>
greased_brand_version_list([] {
int major_version_number;
std::string major_version = version_info::GetMajorVersionNumber();
base::StringToInt(major_version, &major_version_number);
base::Optional<std::string> brand;
#if !BUILDFLAG(CHROMIUM_BRANDING)
brand = version_info::GetProductName();
#endif
base::Optional<std::string> maybe_param_override =
base::GetFieldTrialParamValueByFeature(features::kGreaseUACH,
"brand_override");
if (maybe_param_override->empty())
maybe_param_override = base::nullopt;
return GenerateBrandVersionList(major_version_number, brand,
major_version, maybe_param_override);
}());
return *greased_brand_version_list;
}
blink::UserAgentMetadata GetUserAgentMetadata() {
blink::UserAgentMetadata metadata;
metadata.brand_version_list = GetBrandVersionList();
metadata.full_version = version_info::GetVersionNumber();
metadata.platform = version_info::GetOSType();
metadata.platform_version =
content::GetOSVersion(content::IncludeAndroidBuildNumber::Exclude,
content::IncludeAndroidModel::Exclude);
metadata.architecture = content::GetLowEntropyCpuArchitecture();
metadata.model = content::BuildModelInfo();
metadata.mobile = false;
#if defined(OS_ANDROID)
metadata.mobile = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMobileUserAgent);
#endif
return metadata;
}
#if defined(OS_ANDROID)
void SetDesktopUserAgentOverride(content::WebContents* web_contents,
const blink::UserAgentMetadata& metadata) {
const char kLinuxInfoStr[] = "X11; Linux x86_64";
std::string product = version_info::GetProductNameAndVersionForUserAgent();
blink::UserAgentOverride spoofed_ua;
spoofed_ua.ua_string_override =
content::BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
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->architecture = "x86";
spoofed_ua.ua_metadata_override->model = std::string();
spoofed_ua.ua_metadata_override->mobile = false;
web_contents->SetUserAgentOverride(spoofed_ua, false);
}
#endif // OS_ANDROID
} // namespace embedder_support

@ -0,0 +1,45 @@
// 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.
#ifndef COMPONENTS_EMBEDDER_SUPPORT_USER_AGENT_UTILS_H_
#define COMPONENTS_EMBEDDER_SUPPORT_USER_AGENT_UTILS_H_
#include <string>
#include "build/build_config.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
namespace blink {
struct UserAgentMetadata;
}
namespace content {
class WebContents;
}
namespace embedder_support {
// Returns the product used in building the user-agent.
std::string GetProduct();
// Returns the user agent string for Chrome.
std::string GetUserAgent();
blink::UserAgentMetadata GetUserAgentMetadata();
blink::UserAgentBrandList GenerateBrandVersionList(
int seed,
base::Optional<std::string> brand,
std::string major_version,
base::Optional<std::string> maybe_greasey_brand);
#if defined(OS_ANDROID)
// This sets a user agent string to simulate a desktop user agent on mobile.
void SetDesktopUserAgentOverride(content::WebContents* web_contents,
const blink::UserAgentMetadata& metadata);
#endif
} // namespace embedder_support
#endif // COMPONENTS_EMBEDDER_SUPPORT_USER_AGENT_UTILS_H_

@ -0,0 +1,326 @@
// 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/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 "build/build_config.h"
#include "components/version_info/version_info.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"
#if defined(USE_X11) || defined(USE_OZONE)
#include <sys/utsname.h>
#endif
namespace embedder_support {
namespace {
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 defined(OS_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 defined(OS_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);
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 defined(USE_X11) || defined(USE_OZONE)
// X11; Linux x86_64
// X11; CrOS armv7l 4537.56.0
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)";
}
ASSERT_EQ(2u, pieces.size());
ASSERT_EQ("X11", pieces[0]);
pieces = base::SplitStringUsingSubstr(pieces[1], " ", base::KEEP_WHITESPACE,
base::SPLIT_WANT_ALL);
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
// X11; CrOS armv7l 4537.56.0
// ^^
ASSERT_EQ(3u, pieces.size());
ASSERT_EQ("CrOS", pieces[0]);
ASSERT_EQ(machine, 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));
}
#else
// X11; Linux x86_64
// ^^
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(machine, pieces[1]);
#endif
#elif defined(OS_ANDROID)
// Linux; Android 7.1.1; Samsung Chromebook 3
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 defined(OS_FUCHSIA)
// X11; Fuchsia
ASSERT_EQ(2u, pieces.size());
ASSERT_EQ("X11", pieces[0]);
ASSERT_EQ("Fuchsia", pieces[1]);
#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));
}
}
} // namespace
TEST(UserAgentUtilsTest, UserAgentStringOrdering) {
#if defined(OS_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(UserAgentUtilsTest, UserAgentStringFrozen) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(blink::features::kFreezeUserAgent);
#if defined(OS_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);
// 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();
EXPECT_EQ(buffer, base::StringPrintf(
content::frozen_user_agent_strings::kAndroid,
version_info::GetMajorVersionNumber().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();
EXPECT_EQ(buffer, base::StringPrintf(
content::frozen_user_agent_strings::kAndroidMobile,
version_info::GetMajorVersionNumber().c_str()));
}
#else
{
std::string buffer = GetUserAgent();
EXPECT_EQ(buffer, base::StringPrintf(
content::frozen_user_agent_strings::kDesktop,
version_info::GetMajorVersionNumber().c_str()));
}
#endif
}
TEST(UserAgentUtilsTest, UserAgentMetadata) {
auto metadata = GetUserAgentMetadata();
std::string major_version = version_info::GetMajorVersionNumber();
// 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 product_brand_version = {
version_info::GetProductName(), version_info::GetMajorVersionNumber()};
bool contains_chromium_brand_version = false;
bool contains_product_brand_version = false;
for (const auto& brand_version : metadata.brand_version_list) {
if (brand_version == chromium_brand_version) {
contains_chromium_brand_version = true;
}
if (brand_version == product_brand_version) {
contains_product_brand_version = true;
}
}
EXPECT_TRUE(contains_chromium_brand_version);
EXPECT_TRUE(contains_product_brand_version);
EXPECT_EQ(metadata.full_version, version_info::GetVersionNumber());
EXPECT_EQ(metadata.platform_version,
content::GetOSVersion(content::IncludeAndroidBuildNumber::Exclude,
content::IncludeAndroidModel::Exclude));
// This makes sure no extra information is added to the platform version.
EXPECT_EQ(metadata.platform_version.find(";"), std::string::npos);
EXPECT_EQ(metadata.platform, version_info::GetOSType());
EXPECT_EQ(metadata.architecture, content::GetLowEntropyCpuArchitecture());
EXPECT_EQ(metadata.model, content::BuildModelInfo());
}
TEST(UserAgentUtilsTest, GenerateBrandVersionList) {
blink::UserAgentMetadata metadata;
metadata.brand_version_list =
GenerateBrandVersionList(84, base::nullopt, "84", base::nullopt);
std::string brand_list = metadata.SerializeBrandVersionList();
EXPECT_EQ(R"(" Not A;Brand";v="99", "Chromium";v="84")", brand_list);
metadata.brand_version_list =
GenerateBrandVersionList(85, base::nullopt, "85", base::nullopt);
std::string brand_list_diff = metadata.SerializeBrandVersionList();
// Make sure the lists are different for different seeds
EXPECT_EQ(R"("Chromium";v="85", " Not;A Brand";v="99")", brand_list_diff);
EXPECT_NE(brand_list, brand_list_diff);
metadata.brand_version_list =
GenerateBrandVersionList(84, "Totally A Brand", "84", base::nullopt);
std::string brand_list_w_brand = metadata.SerializeBrandVersionList();
EXPECT_EQ(
R"(" Not A;Brand";v="99", "Chromium";v="84", "Totally A Brand";v="84")",
brand_list_w_brand);
metadata.brand_version_list =
GenerateBrandVersionList(84, base::nullopt, "84", "Clean GREASE");
std::string brand_list_grease_override = metadata.SerializeBrandVersionList();
EXPECT_EQ(R"("Clean GREASE";v="99", "Chromium";v="84")",
brand_list_grease_override);
EXPECT_NE(brand_list, brand_list_grease_override);
// Should DCHECK on negative numbers
EXPECT_DCHECK_DEATH(
GenerateBrandVersionList(-1, base::nullopt, "99", base::nullopt));
}
} // namespace embedder_support

@ -126,4 +126,15 @@ TEST(UserAgentStringTest, BuildOSCpuInfoFromOSVersionAndCpuType) {
}
}
TEST(UserAgentStringTest, LowEntropyCpuArchitecture) {
std::string arch = GetLowEntropyCpuArchitecture();
#if defined(OS_WIN) || defined(OS_MAC) || \
(defined(OS_POSIX) && !defined(OS_ANDROID))
EXPECT_TRUE("arm" == arch || "x86" == arch);
#else
EXPECT_EQ("", arch);
#endif
}
} // namespace content

@ -279,8 +279,6 @@ source_set("weblayer_lib_base") {
"browser/url_bar/page_info_delegate_impl.h",
"browser/url_bar/url_bar_controller_impl.cc",
"browser/url_bar/url_bar_controller_impl.h",
"browser/user_agent.cc",
"browser/user_agent.h",
"browser/web_contents_view_delegate_impl.cc",
"browser/web_contents_view_delegate_impl.h",
"browser/weblayer_browser_interface_binders.cc",
@ -388,6 +386,7 @@ source_set("weblayer_lib_base") {
"//components/download/content/factory",
"//components/download/content/public",
"//components/embedder_support",
"//components/embedder_support:browser_util",
"//components/embedder_support/origin_trials",
"//components/error_page/common",
"//components/error_page/content/browser",

@ -9,6 +9,7 @@
#include "base/path_service.h"
#include "base/time/default_clock.h"
#include "base/time/default_tick_clock.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/network_time/network_time_tracker.h"
#include "components/prefs/pref_service.h"
#include "components/subresource_filter/content/browser/ruleset_service.h"
@ -16,7 +17,6 @@
#include "content/public/browser/network_service_instance.h"
#include "services/network/public/cpp/network_quality_tracker.h"
#include "weblayer/browser/system_network_context_manager.h"
#include "weblayer/browser/user_agent.h"
#include "weblayer/common/weblayer_paths.h"
#if defined(OS_ANDROID)
@ -126,7 +126,7 @@ SafeBrowsingService* BrowserProcess::GetSafeBrowsingService() {
// Create and initialize safe_browsing_service on first get.
// Note: Initialize() needs to happen on UI thread.
safe_browsing_service_ =
std::make_unique<SafeBrowsingService>(GetUserAgent());
std::make_unique<SafeBrowsingService>(embedder_support::GetUserAgent());
safe_browsing_service_->Initialize();
}
return safe_browsing_service_.get();

@ -5,10 +5,10 @@
#include "weblayer/browser/client_hints_factory.h"
#include "components/client_hints/browser/client_hints.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/prefs/pref_service.h"
#include "weblayer/browser/browser_process.h"
#include "weblayer/browser/content_browser_client_impl.h"
#include "weblayer/browser/host_content_settings_map_factory.h"
class PrefService;
@ -43,7 +43,7 @@ KeyedService* ClientHintsFactory::BuildServiceInstanceFor(
return new client_hints::ClientHints(
context, BrowserProcess::GetInstance()->GetNetworkQualityTracker(),
HostContentSettingsMapFactory::GetForBrowserContext(context),
GetUserAgentMetadata(), local_state);
embedder_support::GetUserAgentMetadata(), local_state);
}
content::BrowserContext* ClientHintsFactory::GetBrowserContextToUse(

@ -21,6 +21,7 @@
#include "components/blocked_content/popup_blocker.h"
#include "components/captive_portal/core/buildflags.h"
#include "components/embedder_support/switches.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/error_page/content/browser/net_error_auto_reloader.h"
#include "components/network_time/network_time_tracker.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
@ -92,7 +93,6 @@
#include "weblayer/browser/signin_url_loader_throttle.h"
#include "weblayer/browser/system_network_context_manager.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/browser/user_agent.h"
#include "weblayer/browser/web_contents_view_delegate_impl.h"
#include "weblayer/browser/weblayer_browser_interface_binders.h"
#include "weblayer/browser/weblayer_security_blocking_page_factory.h"
@ -273,8 +273,6 @@ mojo::PendingRemote<prerender::mojom::PrerenderCanceler> GetPrerenderCanceler(
ContentBrowserClientImpl::ContentBrowserClientImpl(MainParams* params)
: params_(params) {
if (!SystemNetworkContextManager::HasInstance())
SystemNetworkContextManager::CreateInstance(GetUserAgent());
}
ContentBrowserClientImpl::~ContentBrowserClientImpl() = default;
@ -329,15 +327,15 @@ void ContentBrowserClientImpl::LogWebFeatureForCurrentPage(
}
std::string ContentBrowserClientImpl::GetProduct() {
return weblayer::GetProduct();
return embedder_support::GetProduct();
}
std::string ContentBrowserClientImpl::GetUserAgent() {
return weblayer::GetUserAgent();
return embedder_support::GetUserAgent();
}
blink::UserAgentMetadata ContentBrowserClientImpl::GetUserAgentMetadata() {
return weblayer::GetUserAgentMetadata();
return embedder_support::GetUserAgentMetadata();
}
void ContentBrowserClientImpl::OverrideWebkitPrefs(
@ -388,6 +386,9 @@ void ContentBrowserClientImpl::ConfigureNetworkContextParams(
void ContentBrowserClientImpl::OnNetworkServiceCreated(
network::mojom::NetworkService* network_service) {
if (!SystemNetworkContextManager::HasInstance())
SystemNetworkContextManager::CreateInstance(
embedder_support::GetUserAgent());
// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is
// complete.
#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
@ -839,6 +840,8 @@ void ContentBrowserClientImpl::CreateFeatureListAndFieldTrials() {
local_state_ = CreateLocalState();
feature_list_creator_ =
std::make_unique<FeatureListCreator>(local_state_.get());
if (!SystemNetworkContextManager::HasInstance())
SystemNetworkContextManager::CreateInstance(GetUserAgent());
feature_list_creator_->SetSystemNetworkContextManager(
SystemNetworkContextManager::GetInstance());
feature_list_creator_->CreateFeatureListAndFieldTrials();

@ -24,8 +24,6 @@ class FeatureListCreator;
class SafeBrowsingService;
struct MainParams;
blink::UserAgentMetadata GetUserAgentMetadata();
class ContentBrowserClientImpl : public content::ContentBrowserClient {
public:
explicit ContentBrowserClientImpl(MainParams* params);

@ -55,7 +55,6 @@
#include "weblayer/browser/browser_process.h"
#include "weblayer/browser/java/jni/ProfileImpl_jni.h"
#include "weblayer/browser/safe_browsing/safe_browsing_service.h"
#include "weblayer/browser/user_agent.h"
#endif
#if defined(OS_POSIX)

@ -24,7 +24,7 @@
#include "components/blocked_content/popup_tracker.h"
#include "components/captive_portal/core/buildflags.h"
#include "components/content_settings/browser/page_specific_content_settings.h"
#include "components/embedder_support/android/util/user_agent_utils.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/find_in_page/find_tab_helper.h"
#include "components/find_in_page/find_types.h"
#include "components/js_injection/browser/js_communication_host.h"
@ -79,7 +79,6 @@
#include "weblayer/browser/profile_impl.h"
#include "weblayer/browser/subresource_filter_client_impl.h"
#include "weblayer/browser/translate_client_impl.h"
#include "weblayer/browser/user_agent.h"
#include "weblayer/browser/weblayer_features.h"
#include "weblayer/common/isolated_world_ids.h"
#include "weblayer/public/fullscreen_delegate.h"
@ -835,8 +834,8 @@ void TabImpl::SetDesktopUserAgentEnabled(JNIEnv* env, jboolean enable) {
// Reset state that an earlier call to Navigation::SetUserAgentString()
// could have modified.
embedder_support::SetDesktopUserAgentOverride(web_contents_.get(),
GetUserAgentMetadata());
embedder_support::SetDesktopUserAgentOverride(
web_contents_.get(), embedder_support::GetUserAgentMetadata());
web_contents_->SetRendererInitiatedUserAgentOverrideOption(
content::NavigationController::UA_OVERRIDE_INHERIT);

@ -1,53 +0,0 @@
// Copyright 2020 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 "weblayer/browser/user_agent.h"
#include "base/command_line.h"
#include "components/version_info/version_info.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/user_agent.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
namespace weblayer {
std::string GetProduct() {
return version_info::GetProductNameAndVersionForUserAgent();
}
std::string GetUserAgent() {
std::string product = GetProduct();
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
// On android, content adds this switch automatically if the right conditions
// are met.
if (command_line.HasSwitch(switches::kUseMobileUserAgent))
product += " Mobile";
return content::BuildUserAgentFromProduct(product);
}
blink::UserAgentMetadata GetUserAgentMetadata() {
blink::UserAgentMetadata metadata;
std::string major_version = version_info::GetMajorVersionNumber();
metadata.brand_version_list.push_back({"Chromium", major_version});
// The CHROMIUM_BRANDING build flag is not available in //weblayer so we're
// going to assume it's a derivative.
metadata.brand_version_list.push_back(
{version_info::GetProductName(), major_version});
metadata.full_version = version_info::GetVersionNumber();
metadata.platform = version_info::GetOSType();
metadata.architecture = content::BuildCpuInfo();
metadata.model = content::BuildModelInfo();
metadata.mobile = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseMobileUserAgent);
return metadata;
}
} // namespace weblayer

@ -1,25 +0,0 @@
// Copyright 2020 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.
#ifndef WEBLAYER_BROWSER_USER_AGENT_H_
#define WEBLAYER_BROWSER_USER_AGENT_H_
#include <string>
namespace blink {
struct UserAgentMetadata;
}
namespace weblayer {
// Returns the product used in building the user-agent.
std::string GetProduct();
std::string GetUserAgent();
blink::UserAgentMetadata GetUserAgentMetadata();
} // namespace weblayer
#endif // WEBLAYER_BROWSER_USER_AGENT_H_

@ -8,13 +8,13 @@
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "components/crash/core/common/crash_key.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/page_info/android/page_info_client.h"
#include "weblayer/browser/android/metrics/weblayer_metrics_service_client.h"
#include "weblayer/browser/default_search_engine.h"
#include "weblayer/browser/devtools_server_android.h"
#include "weblayer/browser/java/jni/WebLayerImpl_jni.h"
#include "weblayer/browser/url_bar/page_info_client_impl.h"
#include "weblayer/browser/user_agent.h"
#include "weblayer/common/crash_reporter/crash_keys.h"
using base::android::JavaParamRef;
@ -40,7 +40,7 @@ static void JNI_WebLayerImpl_SetIsWebViewCompatMode(JNIEnv* env,
static base::android::ScopedJavaLocalRef<jstring>
JNI_WebLayerImpl_GetUserAgentString(JNIEnv* env) {
return base::android::ConvertUTF8ToJavaString(
base::android::AttachCurrentThread(), GetUserAgent());
base::android::AttachCurrentThread(), embedder_support::GetUserAgent());
}
static void JNI_WebLayerImpl_RegisterExternalExperimentIDs(