Merge pull request #8320 from brave/mpilgrim_ua_mobile

Fix farbled user agent on mobile
This commit is contained in:
Mark Pilgrim
2021-03-31 10:09:28 -04:00
committed by GitHub
3 changed files with 76 additions and 52 deletions
+17 -11
View File
@@ -181,7 +181,11 @@ std::string GetUserAgentPlatform() {
}
std::string GetMinimalProduct() {
return version_info::GetProductNameAndVersionForUserAgent();
std::string product = version_info::GetProductNameAndVersionForUserAgent();
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kUseMobileUserAgent))
product += " Mobile";
return product;
}
std::string GetMinimalOSVersion() {
@@ -523,6 +527,16 @@ void BraveContentBrowserClient::MaybeHideReferrer(
}
}
std::string BraveContentBrowserClient::GetMinimalUserAgent() {
std::string minimal_os_info;
base::StringAppendF(&minimal_os_info, "%s%s", GetUserAgentPlatform().c_str(),
content::BuildOSCpuInfoFromOSVersionAndCpuType(
GetMinimalOSVersion(), content::BuildCpuInfo())
.c_str());
return content::BuildUserAgentFromOSAndProduct(minimal_os_info,
GetMinimalProduct());
}
std::string BraveContentBrowserClient::GetEffectiveUserAgent(
content::BrowserContext* browser_context,
const GURL& url) {
@@ -538,16 +552,8 @@ std::string BraveContentBrowserClient::GetEffectiveUserAgent(
// respect it.
if (GetBraveShieldsEnabled(map, url) &&
(GetFingerprintingControlType(map, url) != ControlType::ALLOW) &&
(ua == content::BuildUserAgentFromProduct(
version_info::GetProductNameAndVersionForUserAgent()))) {
std::string minimal_os_info;
base::StringAppendF(&minimal_os_info, "%s%s",
GetUserAgentPlatform().c_str(),
content::BuildOSCpuInfoFromOSVersionAndCpuType(
GetMinimalOSVersion(), content::BuildCpuInfo())
.c_str());
ua = content::BuildUserAgentFromOSAndProduct(minimal_os_info,
GetMinimalProduct());
(ua == content::BuildUserAgentFromProduct(GetMinimalProduct()))) {
ua = GetMinimalUserAgent();
}
}
return ua;
+7 -2
View File
@@ -18,6 +18,7 @@
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
class BraveNavigatorUserAgentFarblingBrowserTest;
class PrefChangeRegistrar;
namespace content {
@@ -100,19 +101,23 @@ class BraveContentBrowserClient : public ChromeContentBrowserClient {
GURL GetEffectiveURL(content::BrowserContext* browser_context,
const GURL& url) override;
static bool HandleURLOverrideRewrite(GURL* url,
static bool HandleURLOverrideRewrite(
GURL* url,
content::BrowserContext* browser_context);
std::vector<std::unique_ptr<content::NavigationThrottle>>
CreateThrottlesForNavigation(content::NavigationHandle* handle) override;
CreateThrottlesForNavigation(content::NavigationHandle* handle) override;
std::string GetEffectiveUserAgent(content::BrowserContext* browser_context,
const GURL& url) override;
private:
friend class ::BraveNavigatorUserAgentFarblingBrowserTest;
uint64_t session_token_;
uint64_t incognito_session_token_;
void OnAllowGoogleAuthChanged();
std::string GetMinimalUserAgent();
std::unique_ptr<PrefChangeRegistrar, content::BrowserThread::DeleteOnUIThread>
pref_change_registrar_;
@@ -35,8 +35,7 @@
using brave_shields::ControlType;
using content::TitleWatcher;
const char kUserAgentScript[] =
"domAutomationController.send(navigator.userAgent);";
const char kUserAgentScript[] = "navigator.userAgent";
class BraveNavigatorUserAgentFarblingBrowserTest : public InProcessBrowserTest {
public:
@@ -78,9 +77,8 @@ class BraveNavigatorUserAgentFarblingBrowserTest : public InProcessBrowserTest {
return user_agents_[user_agents_.size() - 1];
}
std::string effective_user_agent() {
return browser_content_client_->GetEffectiveUserAgent(
browser()->profile(), contents()->GetLastCommittedURL());
std::string minimal_user_agent() {
return browser_content_client_->GetMinimalUserAgent();
}
HostContentSettingsMap* content_settings() {
@@ -105,20 +103,6 @@ class BraveNavigatorUserAgentFarblingBrowserTest : public InProcessBrowserTest {
embedded_test_server()->GetURL(domain, "/"));
}
template <typename T>
int ExecScriptGetInt(const std::string& script, T* frame) {
int value;
EXPECT_TRUE(ExecuteScriptAndExtractInt(frame, script, &value));
return value;
}
template <typename T>
std::string ExecScriptGetStr(const std::string& script, T* frame) {
std::string value;
EXPECT_TRUE(ExecuteScriptAndExtractString(frame, script, &value));
return value;
}
content::WebContents* contents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
@@ -134,6 +118,15 @@ class BraveNavigatorUserAgentFarblingBrowserTest : public InProcessBrowserTest {
std::vector<std::string> user_agents_;
};
class BraveNavigatorUserAgentFarblingMobileBrowserTest
: public BraveNavigatorUserAgentFarblingBrowserTest {
void SetUpCommandLine(base::CommandLine* command_line) override {
#if defined(OS_ANDROID)
command_line->AppendSwitch(switches::kUseMobileUserAgent);
#endif
}
};
// Tests results of farbling user agent
IN_PROC_BROWSER_TEST_F(BraveNavigatorUserAgentFarblingBrowserTest,
FarbleNavigatorUserAgent) {
@@ -143,32 +136,36 @@ IN_PROC_BROWSER_TEST_F(BraveNavigatorUserAgentFarblingBrowserTest,
GURL url_b = embedded_test_server()->GetURL(domain_b, "/simple.html");
GURL url_z = embedded_test_server()->GetURL(domain_z, "/simple.html");
// get real navigator.userAgent
std::string real_ua = embedder_support::GetUserAgent();
std::string unfarbled_ua = embedder_support::GetUserAgent();
// Farbling level: off
AllowFingerprinting(domain_b);
NavigateToURLUntilLoadStop(url_b);
EXPECT_EQ(last_requested_http_user_agent(), real_ua);
std::string off_ua_b = ExecScriptGetStr(kUserAgentScript, contents());
// user agent should be the same as the real user agent
EXPECT_EQ(off_ua_b, real_ua);
// HTTP User-Agent header we just sent in that request should be the same as
// the unfarbled user agent
EXPECT_EQ(last_requested_http_user_agent(), unfarbled_ua);
auto off_ua_b = EvalJs(contents(), kUserAgentScript);
// user agent should be the same as the unfarbled user agent
EXPECT_EQ(unfarbled_ua, off_ua_b);
AllowFingerprinting(domain_z);
NavigateToURLUntilLoadStop(url_z);
// HTTP User-Agent header we just sent in that request should be the same as
// the real user agent
EXPECT_EQ(last_requested_http_user_agent(), real_ua);
std::string off_ua_z = ExecScriptGetStr(kUserAgentScript, contents());
// the unfarbled user agent
EXPECT_EQ(last_requested_http_user_agent(), unfarbled_ua);
auto off_ua_z = EvalJs(contents(), kUserAgentScript);
// user agent should be the same on every domain if farbling is off
EXPECT_EQ(off_ua_z, real_ua);
EXPECT_EQ(unfarbled_ua, off_ua_z);
// Farbling level: default
// navigator.userAgent may be farbled, but the farbling is not
// domain-specific
SetFingerprintingDefault(domain_b);
NavigateToURLUntilLoadStop(url_b);
std::string default_ua_b = ExecScriptGetStr(kUserAgentScript, contents());
std::string default_ua_b =
EvalJs(contents(), kUserAgentScript).ExtractString();
SetFingerprintingDefault(domain_z);
NavigateToURLUntilLoadStop(url_z);
std::string default_ua_z = ExecScriptGetStr(kUserAgentScript, contents());
std::string default_ua_z =
EvalJs(contents(), kUserAgentScript).ExtractString();
// user agent should be the same on every domain if farbling is default
EXPECT_EQ(default_ua_b, default_ua_z);
@@ -179,12 +176,12 @@ IN_PROC_BROWSER_TEST_F(BraveNavigatorUserAgentFarblingBrowserTest,
BlockFingerprinting(domain_b);
// test known values
NavigateToURLUntilLoadStop(url_b);
std::string max_ua_b = ExecScriptGetStr(kUserAgentScript, contents());
EXPECT_EQ(max_ua_b, default_ua_b + " ");
auto max_ua_b = EvalJs(contents(), kUserAgentScript);
EXPECT_EQ(default_ua_b + " ", max_ua_b);
BlockFingerprinting(domain_z);
NavigateToURLUntilLoadStop(url_z);
std::string max_ua_z = ExecScriptGetStr(kUserAgentScript, contents());
EXPECT_EQ(max_ua_z, default_ua_z + " ");
auto max_ua_z = EvalJs(contents(), kUserAgentScript);
EXPECT_EQ(default_ua_z + " ", max_ua_z);
// test that iframes also inherit the farbled user agent
// (farbling level is still maximum)
@@ -202,8 +199,8 @@ IN_PROC_BROWSER_TEST_F(BraveNavigatorUserAgentFarblingBrowserTest,
NavigateToURLUntilLoadStop(embedded_test_server()->GetURL(
domain_b, "/navigator/workers-useragent.html"));
// HTTP User-Agent header we just sent in that request should be the same as
// the real user agent
EXPECT_EQ(last_requested_http_user_agent(), effective_user_agent());
// the farbled user agent
EXPECT_EQ(last_requested_http_user_agent(), minimal_user_agent());
TitleWatcher watcher3(contents(), expected_title);
EXPECT_EQ(expected_title, watcher3.WaitAndGetTitle());
@@ -211,7 +208,23 @@ IN_PROC_BROWSER_TEST_F(BraveNavigatorUserAgentFarblingBrowserTest,
// verify that user agent is reset properly after having been farbled
AllowFingerprinting(domain_b);
NavigateToURLUntilLoadStop(url_b);
EXPECT_EQ(last_requested_http_user_agent(), real_ua);
std::string off_ua_b2 = ExecScriptGetStr(kUserAgentScript, contents());
EXPECT_EQ(off_ua_b, off_ua_b2);
EXPECT_EQ(last_requested_http_user_agent(), unfarbled_ua);
auto off_ua_b2 = EvalJs(contents(), kUserAgentScript);
EXPECT_EQ(off_ua_b.ExtractString(), off_ua_b2);
}
// Tests results of farbling with mobile user agent
IN_PROC_BROWSER_TEST_F(BraveNavigatorUserAgentFarblingMobileBrowserTest,
FarbleNavigatorUserAgentMobile) {
base::string16 expected_title = base::ASCIIToUTF16("pass");
std::string domain_b = "b.com";
GURL url_b = embedded_test_server()->GetURL(domain_b, "/simple.html");
SetFingerprintingDefault(domain_b);
NavigateToURLUntilLoadStop(url_b);
std::string default_ua_b =
EvalJs(contents(), kUserAgentScript).ExtractString();
BlockFingerprinting(domain_b);
NavigateToURLUntilLoadStop(url_b);
EXPECT_EQ(default_ua_b + " ", EvalJs(contents(), kUserAgentScript));
EXPECT_EQ(last_requested_http_user_agent(), minimal_user_agent());
}