From 6bd2b06b47354fa97c4456430c61077b5dcac658 Mon Sep 17 00:00:00 2001 From: Mark Pilgrim Date: Mon, 22 Mar 2021 15:43:39 -0400 Subject: [PATCH] Fix farbled user agent on mobile --- browser/brave_content_browser_client.cc | 28 +++--- browser/brave_content_browser_client.h | 9 +- ...avigator_useragent_farbling_browsertest.cc | 91 +++++++++++-------- 3 files changed, 76 insertions(+), 52 deletions(-) diff --git a/browser/brave_content_browser_client.cc b/browser/brave_content_browser_client.cc index 1c62ea40dc5..07c9f0acb80 100644 --- a/browser/brave_content_browser_client.cc +++ b/browser/brave_content_browser_client.cc @@ -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; diff --git a/browser/brave_content_browser_client.h b/browser/brave_content_browser_client.h index f2100b064a6..4a290175364 100644 --- a/browser/brave_content_browser_client.h +++ b/browser/brave_content_browser_client.h @@ -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> - 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 pref_change_registrar_; diff --git a/browser/farbling/brave_navigator_useragent_farbling_browsertest.cc b/browser/farbling/brave_navigator_useragent_farbling_browsertest.cc index e1cbfb4803c..a6319f76ca2 100644 --- a/browser/farbling/brave_navigator_useragent_farbling_browsertest.cc +++ b/browser/farbling/brave_navigator_useragent_farbling_browsertest.cc @@ -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 - int ExecScriptGetInt(const std::string& script, T* frame) { - int value; - EXPECT_TRUE(ExecuteScriptAndExtractInt(frame, script, &value)); - return value; - } - - template - 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 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()); }