Skip to content

Commit

Permalink
Implement "reduce language fingerprinting" (#12234)
Browse files Browse the repository at this point in the history
* Implement navigator.languages farbling

* add support for HTTP headers

* add support for farbling HTTP header

* add reduce language preference toggle in settings

* Implement font whitelist

* add sublabel to reduce-lang preference toggle

* rebase patches

* use anonymous namespace

* also add our AllowFontFamily method to TestFontSelector to avoid compile errors

* farble all non-whitelisted fonts without enumeration

* rename to MakePseudoRandomGeneratorForURL

* move session token management to singleton service

* move font whitelist to .cc file

* move prefs constants and code around

* pref names browsertest fix

* reduce patches (really)

* add web worker and service worker tests

* get URL differently, move DCHECK

* propogate reduce-language pref to renderers

* consolidate feature detection, add some comments

* lint

* gn_check

* gn_check

* refactor default locale lookup

* lint

* default session key to 12345 if command line switch is missing
brave/brave-browser#22021

* change 12345 -> 23456 so it doesn’t match the test default

Co-authored-by: bridiver <[email protected]>
  • Loading branch information
pilgrim-brave and bridiver authored Mar 31, 2022
1 parent 712a215 commit f6dddf2
Show file tree
Hide file tree
Showing 48 changed files with 1,789 additions and 22 deletions.
10 changes: 8 additions & 2 deletions app/brave_generated_resources.grd
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@
</message>
</if>
<message name="IDS_WIDEVINE_INSTALL_MESSAGE" desc="Bubble info text when Widevine is not installed. 'Widevine' is the name of a plugin and should not be translated.">
Widevine is sometimes needed to play media on a webpage. It's a Google extension loaded from Google servers, which Brave cannot inspect. By installing, you'll agree to Google's terms of use.
Widevine is sometimes needed to play media on a webpage. It's a Google extension loaded from Google servers, which Brave cannot inspect. By installing, you'll agree to Google's terms of use.
</message>
<message name="IDS_WIDEVINE_PERMISSIONS_BUBBLE_FOOTNOTE_TEXT" desc="Message shown on the bottom of the widevine permissions bubble.">
<ph name="LEARN_MORE_ABOUT_WIDEVINE">$1<ex>Learn more about Widevine</ex></ph>.
Expand Down Expand Up @@ -337,7 +337,7 @@ Or change later at <ph name="SETTINGS_EXTENIONS_LINK">$2<ex>brave://settings/ext
Auto-redirect AMP pages
</message>
<message name="IDS_SETTINGS_DE_AMP_SUB_LABEL" desc="The sub-label describing De-AMP feature">
Always visit original (non-AMP) page URLs, instead of Google's Accelerated Mobile Page versions
Always visit original (non-AMP) page URLs, instead of Google's Accelerated Mobile Page versions
</message>
<message name="IDS_SETTINGS_APPEARANCE_SETTINGS_SHOW_AUTOCOMPLETE_IN_ADDRESS_BAR" desc="The label for settings switch controlling the showing of autocomplete in address bar">
Show autocomplete in address bar
Expand Down Expand Up @@ -653,6 +653,12 @@ Or change later at <ph name="SETTINGS_EXTENIONS_LINK">$2<ex>brave://settings/ext
<message name="IDS_SETTINGS_BRAVE_SHIELDS_FINGERPRINTING_CONTROL_LABEL" desc="Default Brave fingerprinting control setting label">
Block fingerprinting
</message>
<message name="IDS_SETTINGS_BRAVE_SHIELDS_REDUCE_LANGUAGE_CONTROL_LABEL" desc="Default Brave reduce language control setting label">
Prevent sites from fingerprinting me based on my language preferences
</message>
<message name="IDS_SETTINGS_BRAVE_SHIELDS_REDUCE_LANGUAGE_SUBITEM" desc="Description that shows under main toggle setting for reduce language control setting label">
Enabling this setting reduces how much web sites can learn about your language preferences.
</message>
<message name="IDS_SETTINGS_BRAVE_SHIELDS_HTTPS_EVERYWHERE_CONTROL_LABEL" desc="Default Brave upgrade connections to HTTPS control setting label">
Upgrade connections to HTTPS
</message>
Expand Down
9 changes: 9 additions & 0 deletions browser/about_flags.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ using brave_shields::features::kBraveDarkModeBlock;
using brave_shields::features::kBraveDomainBlock;
using brave_shields::features::kBraveDomainBlock1PES;
using brave_shields::features::kBraveExtensionNetworkBlocking;
using brave_shields::features::kBraveReduceLanguage;
using brave_shields::features::kCosmeticFilteringSyncLoad;

using de_amp::features::kBraveDeAMP;
Expand Down Expand Up @@ -146,6 +147,10 @@ constexpr char kBraveExtensionNetworkBlockingName[] =
constexpr char kBraveExtensionNetworkBlockingDescription[] =
"Enable blocking for network requests initiated by extensions";

constexpr char kBraveReduceLanguageName[] = "Reduce language identifiability";
constexpr char kBraveReduceLanguageDescription[] =
"Reduce the identifiability of my language preferences";

constexpr char kCosmeticFilteringSyncLoadName[] =
"Enable sync loading of cosmetic filter rules";
constexpr char kCosmeticFilteringSyncLoadDescription[] =
Expand Down Expand Up @@ -499,6 +504,10 @@ const flags_ui::FeatureEntry::Choice kBraveSkusEnvChoices[] = {
flag_descriptions::kBraveExtensionNetworkBlockingName, \
flag_descriptions::kBraveExtensionNetworkBlockingDescription, kOsAll, \
FEATURE_VALUE_TYPE(kBraveExtensionNetworkBlocking)}, \
{"brave-reduce-language", \
flag_descriptions::kBraveReduceLanguageName, \
flag_descriptions::kBraveReduceLanguageDescription, kOsAll, \
FEATURE_VALUE_TYPE(kBraveReduceLanguage)}, \
{"brave-cosmetic-filtering-sync-load", \
flag_descriptions::kCosmeticFilteringSyncLoadName, \
flag_descriptions::kCosmeticFilteringSyncLoadDescription, kOsAll, \
Expand Down
2 changes: 2 additions & 0 deletions browser/brave_browser_process.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
namespace brave {
class BraveReferralsService;
class BraveP3AService;
class BraveFarblingService;
} // namespace brave

namespace brave_component_updater {
Expand Down Expand Up @@ -104,6 +105,7 @@ class BraveBrowserProcess {
speedreader_rewriter_service() = 0;
#endif
virtual brave_ads::ResourceComponent* resource_component() = 0;
virtual brave::BraveFarblingService* brave_farbling_service() = 0;
};

extern BraveBrowserProcess* g_brave_browser_process;
Expand Down
9 changes: 9 additions & 0 deletions browser/brave_browser_process_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "brave/browser/brave_browser_process_impl.h"

#include <string>
#include <utility>

#include "base/bind.h"
Expand All @@ -27,6 +28,7 @@
#include "brave/components/brave_shields/browser/ad_block_regional_service_manager.h"
#include "brave/components/brave_shields/browser/ad_block_service.h"
#include "brave/components/brave_shields/browser/ad_block_subscription_service_manager.h"
#include "brave/components/brave_shields/browser/brave_farbling_service.h"
#include "brave/components/brave_shields/browser/https_everywhere_service.h"
#include "brave/components/brave_sync/network_time_helper.h"
#include "brave/components/debounce/browser/debounce_component_installer.h"
Expand All @@ -47,6 +49,7 @@
#include "content/public/browser/child_process_security_policy.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/gurl.h"

#if BUILDFLAG(ENABLE_BRAVE_REFERRALS)
#include "brave/components/brave_referrals/browser/brave_referrals_service.h"
Expand Down Expand Up @@ -381,3 +384,9 @@ ipfs::BraveIpfsClientUpdater* BraveBrowserProcessImpl::ipfs_client_updater() {
return ipfs_client_updater_.get();
}
#endif // BUILDFLAG(ENABLE_IPFS)

brave::BraveFarblingService* BraveBrowserProcessImpl::brave_farbling_service() {
if (!brave_farbling_service_)
brave_farbling_service_ = std::make_unique<brave::BraveFarblingService>();
return brave_farbling_service_.get();
}
4 changes: 4 additions & 0 deletions browser/brave_browser_process_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace brave {
class BraveReferralsService;
class BraveP3AService;
class HistogramsBraveizer;
class BraveFarblingService;
} // namespace brave

namespace brave_component_updater {
Expand Down Expand Up @@ -115,6 +116,7 @@ class BraveBrowserProcessImpl : public BraveBrowserProcess,
speedreader::SpeedreaderRewriterService* speedreader_rewriter_service()
override;
#endif
brave::BraveFarblingService* brave_farbling_service() override;

private:
// BrowserProcessImpl overrides:
Expand Down Expand Up @@ -173,6 +175,8 @@ class BraveBrowserProcessImpl : public BraveBrowserProcess,
speedreader_rewriter_service_;
#endif

std::unique_ptr<brave::BraveFarblingService> brave_farbling_service_;

SEQUENCE_CHECKER(sequence_checker_);
};

Expand Down
22 changes: 13 additions & 9 deletions browser/brave_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

#include "base/bind.h"
#include "base/json/json_reader.h"
#include "base/rand_util.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
#include "brave/browser/brave_browser_main_extra_parts.h"
#include "brave/browser/brave_browser_process.h"
#include "brave/browser/brave_shields/brave_shields_web_contents_observer.h"
#include "brave/browser/brave_shields/reduce_language_navigation_throttle.h"
#include "brave/browser/brave_wallet/brave_wallet_context_utils.h"
#include "brave/browser/brave_wallet/brave_wallet_provider_delegate_impl.h"
#include "brave/browser/brave_wallet/brave_wallet_service_factory.h"
Expand Down Expand Up @@ -45,6 +45,7 @@
#include "brave/components/brave_search/common/brave_search_fallback.mojom.h"
#include "brave/components/brave_search/common/brave_search_utils.h"
#include "brave/components/brave_shields/browser/ad_block_service.h"
#include "brave/components/brave_shields/browser/brave_farbling_service.h"
#include "brave/components/brave_shields/browser/brave_shields_util.h"
#include "brave/components/brave_shields/browser/domain_block_navigation_throttle.h"
#include "brave/components/brave_shields/common/brave_shield_constants.h"
Expand Down Expand Up @@ -352,9 +353,7 @@ void MaybeBindSkusSdkImpl(

} // namespace

BraveContentBrowserClient::BraveContentBrowserClient()
: session_token_(base::RandUint64()),
incognito_session_token_(base::RandUint64()) {}
BraveContentBrowserClient::BraveContentBrowserClient() {}

BraveContentBrowserClient::~BraveContentBrowserClient() {}

Expand Down Expand Up @@ -616,11 +615,9 @@ void BraveContentBrowserClient::AppendExtraCommandLineSwitches(
Profile* profile =
process ? Profile::FromBrowserContext(process->GetBrowserContext())
: nullptr;
if (profile && !profile->IsOffTheRecord()) {
session_token = session_token_;
} else {
session_token = incognito_session_token_;
}
session_token =
g_brave_browser_process->brave_farbling_service()->session_token(
profile && !profile->IsOffTheRecord());
}
command_line->AppendSwitchASCII("brave_session_token",
base::NumberToString(session_token));
Expand Down Expand Up @@ -912,6 +909,13 @@ BraveContentBrowserClient::CreateThrottlesForNavigation(
g_browser_process->GetApplicationLocale()))
throttles.push_back(std::move(domain_block_navigation_throttle));

if (std::unique_ptr<content::NavigationThrottle>
reduce_language_navigation_throttle = brave_shields::
ReduceLanguageNavigationThrottle::MaybeCreateThrottleFor(
handle, HostContentSettingsMapFactory::GetForProfile(
Profile::FromBrowserContext(context))))
throttles.push_back(std::move(reduce_language_navigation_throttle));

return throttles;
}

Expand Down
3 changes: 0 additions & 3 deletions browser/brave_content_browser_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,6 @@ class BraveContentBrowserClient : public ChromeContentBrowserClient {
blink::web_pref::WebPreferences* prefs) override;

private:
uint64_t session_token_;
uint64_t incognito_session_token_;

void OnAllowGoogleAuthChanged();

std::unique_ptr<PrefChangeRegistrar, content::BrowserThread::DeleteOnUIThread>
Expand Down
2 changes: 2 additions & 0 deletions browser/brave_prefs_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ IN_PROC_BROWSER_TEST_F(BraveProfilePrefsBrowserTest, MiscBravePrefs) {
brave_shields::prefs::kTwitterEmbedControlType));
EXPECT_FALSE(chrome_test_utils::GetProfile(this)->GetPrefs()->GetBoolean(
brave_shields::prefs::kLinkedInEmbedControlType));
EXPECT_TRUE(chrome_test_utils::GetProfile(this)->GetPrefs()->GetBoolean(
brave_shields::prefs::kReduceLanguageEnabled));
#if BUILDFLAG(ENABLE_BRAVE_WAYBACK_MACHINE)
EXPECT_TRUE(chrome_test_utils::GetProfile(this)->GetPrefs()->GetBoolean(
kWebTorrentEnabled));
Expand Down
3 changes: 3 additions & 0 deletions browser/brave_profile_prefs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "brave/components/brave_rewards/common/pref_names.h"
#include "brave/components/brave_search/browser/brave_search_default_host.h"
#include "brave/components/brave_search/common/brave_search_utils.h"
#include "brave/components/brave_shields/browser/brave_farbling_service.h"
#include "brave/components/brave_shields/common/pref_names.h"
#include "brave/components/brave_sync/brave_sync_prefs.h"
#include "brave/components/brave_today/browser/brave_news_controller.h"
Expand Down Expand Up @@ -437,6 +438,8 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
registry->SetDefaultPrefValue(policy::policy_prefs::kEnableDirectSockets,
base::Value(false));

BraveFarblingService::RegisterProfilePrefs(registry);

RegisterProfilePrefsForMigration(registry);
}

Expand Down
18 changes: 18 additions & 0 deletions browser/brave_shields/brave_shields_web_contents_observer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
#include "brave/components/brave_shields/browser/brave_shields_util.h"
#include "brave/components/brave_shields/common/brave_shield_constants.h"
#include "brave/components/brave_shields/common/features.h"
#include "brave/components/brave_shields/common/pref_names.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/renderer_configuration.mojom.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_utils.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
Expand Down Expand Up @@ -105,6 +107,14 @@ void BraveShieldsWebContentsObserver::RenderFrameCreated(RenderFrameHost* rfh) {
GetBraveShieldsRemote(rfh)->SetAllowScriptsFromOriginsOnce(
allowed_script_origins_);
}
if (rfh) {
if (content::BrowserContext* context = rfh->GetBrowserContext()) {
if (PrefService* pref_service = user_prefs::UserPrefs::Get(context)) {
GetBraveShieldsRemote(rfh)->SetReduceLanguageEnabled(
brave_shields::IsReduceLanguageEnabledForProfile(pref_service));
}
}
}

WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
if (web_contents) {
Expand Down Expand Up @@ -279,6 +289,14 @@ void BraveShieldsWebContentsObserver::ReadyToCommitNavigation(
observer->GetBraveShieldsRemote(rfh)
->SetAllowScriptsFromOriginsOnce(
observer->allowed_script_origins_);
if (content::BrowserContext* context = rfh->GetBrowserContext()) {
if (PrefService* pref_service =
user_prefs::UserPrefs::Get(context)) {
observer->GetBraveShieldsRemote(rfh)->SetReduceLanguageEnabled(
brave_shields::IsReduceLanguageEnabledForProfile(
pref_service));
}
}
},
base::Unretained(this)));
}
Expand Down
115 changes: 115 additions & 0 deletions browser/brave_shields/reduce_language_navigation_throttle.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "brave/browser/brave_shields/reduce_language_navigation_throttle.h"

#include <memory>
#include <utility>

#include "base/feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "brave/browser/brave_browser_process.h"
#include "brave/components/brave_shields/browser/brave_farbling_service.h"
#include "brave/components/brave_shields/browser/brave_shields_util.h"
#include "brave/components/brave_shields/common/features.h"
#include "chrome/browser/profiles/profile.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/language/core/browser/language_prefs.h"
#include "components/language/core/browser/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "net/http/http_util.h"

namespace brave_shields {

// static
std::unique_ptr<ReduceLanguageNavigationThrottle>
ReduceLanguageNavigationThrottle::MaybeCreateThrottleFor(
content::NavigationHandle* navigation_handle,
HostContentSettingsMap* content_settings) {
content::BrowserContext* context =
navigation_handle->GetWebContents()->GetBrowserContext();
PrefService* pref_service = user_prefs::UserPrefs::Get(context);
if (!IsReduceLanguageEnabledForProfile(pref_service))
return nullptr;
return std::make_unique<ReduceLanguageNavigationThrottle>(navigation_handle,
content_settings);
}

ReduceLanguageNavigationThrottle::ReduceLanguageNavigationThrottle(
content::NavigationHandle* navigation_handle,
HostContentSettingsMap* content_settings)
: content::NavigationThrottle(navigation_handle),
content_settings_(content_settings) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}

ReduceLanguageNavigationThrottle::~ReduceLanguageNavigationThrottle() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}

content::NavigationThrottle::ThrottleCheckResult
ReduceLanguageNavigationThrottle::WillStartRequest() {
UpdateHeaders();
return content::NavigationThrottle::PROCEED;
}

content::NavigationThrottle::ThrottleCheckResult
ReduceLanguageNavigationThrottle::WillRedirectRequest() {
UpdateHeaders();
return content::NavigationThrottle::PROCEED;
}

void ReduceLanguageNavigationThrottle::UpdateHeaders() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::NavigationHandle* handle = navigation_handle();
GURL url = handle->GetURL();
content::BrowserContext* context =
handle->GetWebContents()->GetBrowserContext();
PrefService* pref_service = user_prefs::UserPrefs::Get(context);

if (!brave_shields::ShouldDoReduceLanguage(content_settings_, url,
pref_service))
return;

ControlType fingerprinting_control_type =
brave_shields::GetFingerprintingControlType(content_settings_, url);

// If fingerprint blocking is maximum, set Accept-Language header to
// static value regardless of other preferences.
if (fingerprinting_control_type == ControlType::BLOCK) {
handle->SetRequestHeader(net::HttpRequestHeaders::kAcceptLanguage,
"en-US,en");
return;
}

// If fingerprint blocking is default, compute Accept-Language header
// based on user preferences.
std::string languages =
pref_service->Get(language::prefs::kAcceptLanguages)->GetString();
std::string first_language = language::GetFirstLanguage(languages);
// Potentially add a fake q value after the language code.
std::vector<std::string> q_values = {";q=0.5", ";q=0.6", ";q=0.7",
";q=0.8", ";q=0.9", ""};
std::mt19937_64 prng;
auto* profile = Profile::FromBrowserContext(context);
if (g_brave_browser_process->brave_farbling_service()
->MakePseudoRandomGeneratorForURL(
url, profile && !profile->IsOffTheRecord(), &prng)) {
first_language += q_values[prng() % q_values.size()];
}
handle->SetRequestHeader(net::HttpRequestHeaders::kAcceptLanguage,
first_language);
}

const char* ReduceLanguageNavigationThrottle::GetNameForLogging() {
return "ReduceLanguageNavigationThrottle";
}

} // namespace brave_shields
Loading

0 comments on commit f6dddf2

Please sign in to comment.