From 83a232fbdfb35368a2035a97f91d4a56081e51d9 Mon Sep 17 00:00:00 2001 From: Mark Pilgrim Date: Tue, 27 Oct 2020 14:39:23 -0400 Subject: [PATCH] Implement navigator.deviceMemory farbling tests BUILD.gn changes feedback BUILD.gn hacks --- browser/farbling/BUILD.gn | 35 ++++ ...gator_devicememory_farbling_browsertest.cc | 152 ++++++++++++++++++ .../core/frame/navigator_device_memory.cc | 68 ++++++++ .../core/frame/navigator_device_memory.h | 20 +++ ...re-frame-navigator_device_memory.idl.patch | 12 ++ test/BUILD.gn | 8 +- 6 files changed, 288 insertions(+), 7 deletions(-) create mode 100644 browser/farbling/brave_navigator_devicememory_farbling_browsertest.cc create mode 100644 chromium_src/third_party/blink/renderer/core/frame/navigator_device_memory.cc create mode 100644 chromium_src/third_party/blink/renderer/core/frame/navigator_device_memory.h create mode 100644 patches/third_party-blink-renderer-core-frame-navigator_device_memory.idl.patch diff --git a/browser/farbling/BUILD.gn b/browser/farbling/BUILD.gn index dc65c8fa0cb2..0dd5178f0075 100644 --- a/browser/farbling/BUILD.gn +++ b/browser/farbling/BUILD.gn @@ -1,3 +1,8 @@ +# Copyright (c) 2020 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/. */ + source_set("farbling") { check_includes = false sources = [ @@ -16,3 +21,33 @@ source_set("farbling") { "//third_party/blink/public/common", ] } + +source_set("browser_tests") { + testonly = true + check_includes = false + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] + + sources = [ + "brave_enumeratedevices_farbling_browsertest.cc", + "brave_navigator_devicememory_farbling_browsertest.cc", + "brave_navigator_hardwareconcurrency_farbling_browsertest.cc", + "brave_navigator_plugins_farbling_browsertest.cc", + "brave_navigator_useragent_farbling_browsertest.cc", + "brave_offscreencanvas_farbling_browsertest.cc", + "brave_webaudio_farbling_browsertest.cc", + "brave_webgl_farbling_browsertest.cc", + ] + + deps = [ + "//brave/browser:browser_process", + "//brave/common:pref_names", + "//brave/components/brave_component_updater/browser:browser", + "//brave/components/brave_shields/browser:browser", + "//chrome/browser", + "//chrome/browser/ui", + "//chrome/test:test_support", + "//chrome/test:test_support_ui", + "//components/permissions:permissions", + "//content/test:test_support", + ] +} diff --git a/browser/farbling/brave_navigator_devicememory_farbling_browsertest.cc b/browser/farbling/brave_navigator_devicememory_farbling_browsertest.cc new file mode 100644 index 000000000000..7f61fe6dd008 --- /dev/null +++ b/browser/farbling/brave_navigator_devicememory_farbling_browsertest.cc @@ -0,0 +1,152 @@ +/* Copyright (c) 2020 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 "base/path_service.h" +#include "base/strings/stringprintf.h" +#include "base/task/post_task.h" +#include "base/test/thread_test_helper.h" +#include "brave/browser/brave_browser_process_impl.h" +#include "brave/browser/brave_content_browser_client.h" +#include "brave/browser/extensions/brave_base_local_data_files_browsertest.h" +#include "brave/common/brave_paths.h" +#include "brave/common/pref_names.h" +#include "brave/components/brave_component_updater/browser/local_data_files_service.h" +#include "brave/components/brave_shields/browser/brave_shields_util.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/chrome_content_client.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/network_session_configurator/common/network_switches.h" +#include "components/permissions/permission_request.h" +#include "components/prefs/pref_service.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "net/dns/mock_host_resolver.h" +#include "third_party/blink/public/common/device_memory/approximated_device_memory.h" + +using brave_shields::ControlType; + +const char kDeviceMemoryScript[] = "navigator.deviceMemory * 1024"; + +class BraveDeviceMemoryFarblingBrowserTest : public InProcessBrowserTest { + public: + BraveDeviceMemoryFarblingBrowserTest() + : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { + brave::RegisterPathProvider(); + base::FilePath test_data_dir; + base::PathService::Get(brave::DIR_TEST_DATA, &test_data_dir); + https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK); + https_server_.ServeFilesFromDirectory(test_data_dir); + EXPECT_TRUE(https_server_.Start()); + } + + BraveDeviceMemoryFarblingBrowserTest( + const BraveDeviceMemoryFarblingBrowserTest&) = delete; + BraveDeviceMemoryFarblingBrowserTest& operator=( + const BraveDeviceMemoryFarblingBrowserTest&) = delete; + + ~BraveDeviceMemoryFarblingBrowserTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + // HTTPS server only serves a valid cert for localhost, so this is needed + // to load pages from other hosts without an error + command_line->AppendSwitch(switches::kIgnoreCertificateErrors); + } + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + + content_client_.reset(new ChromeContentClient); + content::SetContentClient(content_client_.get()); + browser_content_client_.reset(new BraveContentBrowserClient()); + content::SetBrowserClientForTesting(browser_content_client_.get()); + + host_resolver()->AddRule("*", "127.0.0.1"); + } + + void TearDown() override { + browser_content_client_.reset(); + content_client_.reset(); + } + + protected: + base::test::ScopedFeatureList feature_list_; + net::EmbeddedTestServer https_server_; + + HostContentSettingsMap* content_settings() { + return HostContentSettingsMapFactory::GetForProfile(browser()->profile()); + } + + void AllowFingerprinting(std::string domain) { + brave_shields::SetFingerprintingControlType( + content_settings(), ControlType::ALLOW, + https_server_.GetURL(domain, "/")); + } + + void BlockFingerprinting(std::string domain) { + brave_shields::SetFingerprintingControlType( + content_settings(), ControlType::BLOCK, + https_server_.GetURL(domain, "/")); + } + + void SetFingerprintingDefault(std::string domain) { + brave_shields::SetFingerprintingControlType( + content_settings(), ControlType::DEFAULT, + https_server_.GetURL(domain, "/")); + } + + content::WebContents* contents() { + return browser()->tab_strip_model()->GetActiveWebContents(); + } + + bool NavigateToURLUntilLoadStop(const GURL& url) { + ui_test_utils::NavigateToURL(browser(), url); + return WaitForLoadStop(contents()); + } + + private: + std::unique_ptr content_client_; + std::unique_ptr browser_content_client_; +}; + +// Tests results of farbling known values +IN_PROC_BROWSER_TEST_F(BraveDeviceMemoryFarblingBrowserTest, + FarbleDeviceMemory) { + std::string domain1 = "b.com"; + std::string domain2 = "z.com"; + GURL url1 = https_server_.GetURL(domain1, "/simple.html"); + GURL url2 = https_server_.GetURL(domain2, "/simple.html"); + // set memory to 10GB + blink::ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(1024 * 10); + int true_value = + blink::ApproximatedDeviceMemory::GetApproximatedDeviceMemory() * 1024; + EXPECT_EQ(true_value, 8192); + // Farbling level: off + AllowFingerprinting(domain1); + NavigateToURLUntilLoadStop(url1); + EXPECT_EQ(true_value, EvalJs(contents(), kDeviceMemoryScript)); + AllowFingerprinting(domain2); + NavigateToURLUntilLoadStop(url2); + EXPECT_EQ(true_value, EvalJs(contents(), kDeviceMemoryScript)); + + // Farbling level: default + SetFingerprintingDefault(domain1); + NavigateToURLUntilLoadStop(url1); + EXPECT_EQ(4096, EvalJs(contents(), kDeviceMemoryScript)); + SetFingerprintingDefault(domain2); + NavigateToURLUntilLoadStop(url2); + EXPECT_EQ(2048, EvalJs(contents(), kDeviceMemoryScript)); + + // Farbling level: maximum + BlockFingerprinting(domain1); + NavigateToURLUntilLoadStop(url1); + EXPECT_EQ(1024, EvalJs(contents(), kDeviceMemoryScript)); + AllowFingerprinting(domain2); + NavigateToURLUntilLoadStop(url2); + EXPECT_EQ(8192, EvalJs(contents(), kDeviceMemoryScript)); +} diff --git a/chromium_src/third_party/blink/renderer/core/frame/navigator_device_memory.cc b/chromium_src/third_party/blink/renderer/core/frame/navigator_device_memory.cc new file mode 100644 index 000000000000..a2149346cef8 --- /dev/null +++ b/chromium_src/third_party/blink/renderer/core/frame/navigator_device_memory.cc @@ -0,0 +1,68 @@ +/* Copyright (c) 2020 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 + +#include "brave/third_party/blink/renderer/brave_farbling_constants.h" +#include "third_party/blink/public/common/device_memory/approximated_device_memory.h" +#include "third_party/blink/public/platform/web_content_settings_client.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/frame/navigator_device_memory.h" + +namespace brave { + +float FarbleDeviceMemory(blink::ExecutionContext* context) { + float true_value = + blink::ApproximatedDeviceMemory::GetApproximatedDeviceMemory(); + blink::WebContentSettingsClient* settings = + GetContentSettingsClientFor(context); + // If Brave Shields are down or anti-fingerprinting is off for this site, + // return the true value. + if (!settings || settings->GetBraveFarblingLevel() == BraveFarblingLevel::OFF) + return true_value; + + std::vector valid_values = {0.25, 0.5, 1.0, 2.0, 4.0, 8.0}; + int min_farbled_index; + int max_farbled_index; + if (settings->GetBraveFarblingLevel() == BraveFarblingLevel::MAXIMUM) { + // If anti-fingerprinting is at maximum, select a pseudo-random valid value + // based on domain + sesson key. + min_farbled_index = 0; + max_farbled_index = valid_values.size() - 1; + } else { + // If anti-fingerprinting is at default level, select a pseudo-random valid + // value between 0.5 and the true value (unless the true value is 0.25 in + // which case just return that). + auto true_it = + std::find(valid_values.begin(), valid_values.end(), true_value); + int true_index; + // Get index into |valid_values| of the true value. If it's not found, + // assume the last index. (This should not happen, but it allows us to + // fail closed instead of failing open.) + if (true_it != valid_values.end()) + true_index = std::distance(valid_values.begin(), true_it); + else + true_index = valid_values.size() - 1; + min_farbled_index = 1; + max_farbled_index = true_index; + if (max_farbled_index <= min_farbled_index) + return valid_values[min_farbled_index]; + } + std::mt19937_64 prng = + BraveSessionCache::From(*context).MakePseudoRandomGenerator(); + return valid_values[min_farbled_index + + (prng() % (max_farbled_index + 1 - min_farbled_index))]; +} + +} // namespace brave + +namespace blink { + +float NavigatorDeviceMemory::deviceMemory(ScriptState* script_state) const { + ExecutionContext* context = ExecutionContext::From(script_state); + return brave::FarbleDeviceMemory(context); +} + +} // namespace blink diff --git a/chromium_src/third_party/blink/renderer/core/frame/navigator_device_memory.h b/chromium_src/third_party/blink/renderer/core/frame/navigator_device_memory.h new file mode 100644 index 000000000000..c873b469a3b7 --- /dev/null +++ b/chromium_src/third_party/blink/renderer/core/frame/navigator_device_memory.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2020 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/. */ + +#ifndef BRAVE_CHROMIUM_SRC_THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_NAVIGATOR_DEVICE_MEMORY_H_ +#define BRAVE_CHROMIUM_SRC_THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_NAVIGATOR_DEVICE_MEMORY_H_ + +#include "third_party/blink/renderer/core/core_export.h" + +namespace blink { + +class CORE_EXPORT NavigatorDeviceMemory { + public: + float deviceMemory(ScriptState*) const; +}; + +} // namespace blink + +#endif // BRAVE_CHROMIUM_SRC_THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_NAVIGATOR_DEVICE_MEMORY_H_ diff --git a/patches/third_party-blink-renderer-core-frame-navigator_device_memory.idl.patch b/patches/third_party-blink-renderer-core-frame-navigator_device_memory.idl.patch new file mode 100644 index 000000000000..bc320fb6297c --- /dev/null +++ b/patches/third_party-blink-renderer-core-frame-navigator_device_memory.idl.patch @@ -0,0 +1,12 @@ +diff --git a/third_party/blink/renderer/core/frame/navigator_device_memory.idl b/third_party/blink/renderer/core/frame/navigator_device_memory.idl +index f016ac69fa7cb93dc078f0d49aa92ff8bfef1c0b..8204a381031d17eb2fdac11591859f7c221fffd2 100644 +--- a/third_party/blink/renderer/core/frame/navigator_device_memory.idl ++++ b/third_party/blink/renderer/core/frame/navigator_device_memory.idl +@@ -5,6 +5,6 @@ + // https://github.com/w3c/device-memory#the-web-exposed-api + + interface mixin NavigatorDeviceMemory { +- [HighEntropy=Direct,MeasureAs=NavigatorDeviceMemory,SecureContext] ++ [CallWith=ScriptState,HighEntropy=Direct,MeasureAs=NavigatorDeviceMemory,SecureContext] + readonly attribute float deviceMemory; + }; diff --git a/test/BUILD.gn b/test/BUILD.gn index c778f7a5209b..f94ddf4867a5 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -600,13 +600,6 @@ if (!is_android) { "//brave/browser/extensions/brave_extension_functional_test.h", "//brave/browser/extensions/brave_extension_provider_browsertest.cc", "//brave/browser/extensions/brave_theme_event_router_browsertest.cc", - "//brave/browser/farbling/brave_enumeratedevices_farbling_browsertest.cc", - "//brave/browser/farbling/brave_navigator_hardwareconcurrency_farbling_browsertest.cc", - "//brave/browser/farbling/brave_navigator_plugins_farbling_browsertest.cc", - "//brave/browser/farbling/brave_navigator_useragent_farbling_browsertest.cc", - "//brave/browser/farbling/brave_offscreencanvas_farbling_browsertest.cc", - "//brave/browser/farbling/brave_webaudio_farbling_browsertest.cc", - "//brave/browser/farbling/brave_webgl_farbling_browsertest.cc", "//brave/browser/net/brave_network_delegate_browsertest.cc", "//brave/browser/net/brave_network_delegate_hsts_fingerprinting_browsertest.cc", "//brave/browser/net/brave_site_hacks_network_delegate_helper_browsertest.cc", @@ -686,6 +679,7 @@ if (!is_android) { "//brave/browser/tor:browser_tests", "//brave/chromium_src/third_party/blink/renderer/modules:browser_tests", "//brave/components/ipfs/test:brave_ipfs_browser_tests", + "//brave/browser/farbling:browser_tests", "//brave/browser/ui/tabs/test:browser_tests", "//media:test_support", ]