0

[FPF-CI] Add CanvasNoiseTokenManager and CanvasNoiseToken.

Noise tokens will be used as a randomized identifier for Canvas noising.
As Canvas noising is intended to be web-platform wide, we add the
following additions into both //content and //third_party/blink.

The CanvasNoiseTokenManager is a browser-sided token generator that
manages noise tokens generated once per BrowserContext instance,
meaning, each browser session/profile will generate its own noise token.
This noise token is then piped to the renderer using
RendererPreferences. On the Blink side, a frame-local global,
called CanvasNoiseToken, will store the noise token.

Bug: 392627601
Change-Id: I9292cdd8087741dc2d1cb743caeaea3050014f3d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6226586
Reviewed-by: Giovanni Ortuno Urquidi <ortuno@chromium.org>
Commit-Queue: John Kim <johnykim@google.com>
Reviewed-by: Antonio Sartori <antoniosartori@chromium.org>
Reviewed-by: Tom Van Goethem <tov@chromium.org>
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1435582}
This commit is contained in:
John Kim
2025-03-20 11:50:49 -07:00
committed by Chromium LUCI CQ
parent 3495c90294
commit c12563dd41
19 changed files with 217 additions and 1 deletions

@ -1113,6 +1113,8 @@ source_set("browser") {
"find_in_page_client.h",
"find_request_manager.cc",
"find_request_manager.h",
"fingerprinting_protection/canvas_noise_token_data.cc",
"fingerprinting_protection/canvas_noise_token_data.h",
"first_party_sets/database/first_party_sets_database.cc",
"first_party_sets/database/first_party_sets_database.h",
"first_party_sets/first_party_set_parser.cc",

@ -0,0 +1,2 @@
file://third_party/blink/public/common/fingerprinting_protection/OWNERS

@ -0,0 +1,45 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/fingerprinting_protection/canvas_noise_token_data.h"
#include <cstdint>
#include <memory>
#include "base/feature_list.h"
#include "base/numerics/byte_conversions.h"
#include "base/supports_user_data.h"
#include "content/public/browser/browser_context.h"
#include "third_party/blink/public/common/features.h"
namespace content {
namespace {
const void* const kBrowserContextCanvasNoiseTokenKey =
&kBrowserContextCanvasNoiseTokenKey;
} // namespace
// static
uint64_t CanvasNoiseTokenData::GetToken(BrowserContext* context) {
CHECK(base::FeatureList::IsEnabled(blink::features::kCanvasInterventions));
return CanvasNoiseTokenData::GetOrCreateForBrowserContext(context);
}
// static
uint64_t CanvasNoiseTokenData::GetOrCreateForBrowserContext(
BrowserContext* context) {
CanvasNoiseTokenData* data = static_cast<CanvasNoiseTokenData*>(
context->GetUserData(&kBrowserContextCanvasNoiseTokenKey));
if (data != nullptr) {
return data->session_token_;
}
auto new_data = std::make_unique<CanvasNoiseTokenData>();
uint64_t token = new_data->session_token_;
context->SetUserData(&kBrowserContextCanvasNoiseTokenKey,
std::move(new_data));
return token;
}
} // namespace content

@ -0,0 +1,37 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_FINGERPRINTING_PROTECTION_CANVAS_NOISE_TOKEN_DATA_H_
#define CONTENT_BROWSER_FINGERPRINTING_PROTECTION_CANVAS_NOISE_TOKEN_DATA_H_
#include <cstdint>
#include "base/rand_util.h"
#include "content/public/browser/browser_context.h"
#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
namespace content {
// A user data class that generates and stores BrowserContext-associated noise
// tokens used for canvas noising.
class CONTENT_EXPORT CanvasNoiseTokenData
: public base::SupportsUserData::Data {
public:
CanvasNoiseTokenData() = default;
// Gets the 64 bit BrowserContext-associated noise token.
static uint64_t GetToken(BrowserContext* context);
private:
// TODO(crbug.com/402088092): |force_create| will be responsible for
// regenerating possible existing tokens, add integration for regenerating
// tokens.
static uint64_t GetOrCreateForBrowserContext(BrowserContext* context);
uint64_t session_token_{base::RandUint64()};
};
} // namespace content
#endif // CONTENT_BROWSER_FINGERPRINTING_PROTECTION_CANVAS_NOISE_TOKEN_DATA_H_

@ -0,0 +1,48 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include "base/test/scoped_feature_list.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
namespace content {
class CanvasNoiseTokenDataBrowserTest : public content::ContentBrowserTest {
public:
CanvasNoiseTokenDataBrowserTest() = default;
void SetUpOnMainThread() override {}
void TearDown() override { scoped_feature_list_.Reset(); }
private:
base::test::ScopedFeatureList scoped_feature_list_{
blink::features::kCanvasInterventions};
};
IN_PROC_BROWSER_TEST_F(CanvasNoiseTokenDataBrowserTest,
DifferentBrowserContextDifferCanvasNoiseTokens) {
auto* normal_tab =
static_cast<WebContentsImpl*>(CreateBrowser()->web_contents());
uint64_t normal_token =
normal_tab->GetMutableRendererPrefs()->canvas_noise_token;
auto* incognito_tab = static_cast<WebContentsImpl*>(
CreateOffTheRecordBrowser()->web_contents());
uint64_t incognito_token =
incognito_tab->GetMutableRendererPrefs()->canvas_noise_token;
EXPECT_NE(normal_token, 0UL);
EXPECT_NE(incognito_token, 0UL);
EXPECT_NE(normal_token, incognito_token);
}
} // namespace content

@ -84,6 +84,7 @@
#include "content/browser/download/save_package.h"
#include "content/browser/fenced_frame/fenced_frame.h"
#include "content/browser/find_request_manager.h"
#include "content/browser/fingerprinting_protection/canvas_noise_token_data.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/guest_page_holder_impl.h"
#include "content/browser/host_zoom_map_impl.h"
@ -1354,6 +1355,11 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
if (input::IsTransferInputToVizSupported()) {
SetupRenderInputRouterDelegateConnection();
}
if (base::FeatureList::IsEnabled(blink::features::kCanvasInterventions)) {
renderer_preferences_.canvas_noise_token =
CanvasNoiseTokenData::GetToken(browser_context);
}
}
void WebContentsImpl::SetupRenderInputRouterDelegateConnection() {
@ -8851,6 +8857,10 @@ const blink::RendererPreferences& WebContentsImpl::GetRendererPrefs(
*render_view_host->frame_tree()->GetMainFrame())) {
return guest->GetRendererPrefs();
}
if (base::FeatureList::IsEnabled(blink::features::kCanvasInterventions)) {
renderer_preferences_.canvas_noise_token =
CanvasNoiseTokenData::GetToken(GetBrowserContext());
}
RenderViewHostImpl::GetPlatformSpecificPrefs(&renderer_preferences_);
return renderer_preferences_;
}

@ -143,7 +143,11 @@ void ResizeWebContentsView(Shell* shell,
class WebContentsImplBrowserTest : public ContentBrowserTest {
public:
WebContentsImplBrowserTest() = default;
WebContentsImplBrowserTest() {
scoped_feature_list_.InitAndEnableFeature(
blink::features::kCanvasInterventions);
}
void SetUp() override {
RenderWidgetHostImpl::DisableResizeAckCheckForTesting();
ContentBrowserTest::SetUp();

@ -1488,6 +1488,7 @@ test("content_browsertests") {
"../browser/file_system_access/file_system_access_observer_browsertest.cc",
"../browser/file_system_access/file_system_chooser_browsertest.cc",
"../browser/find_request_manager_browsertest.cc",
"../browser/fingerprinting_protection/canvas_noise_token_data_browsertest.cc",
"../browser/first_party_sets/first_party_sets_handler_impl_browsertest.cc",
"../browser/first_party_sets/test/first_party_sets_initialization_browsertest.cc",
"../browser/font_access/font_access_manager_browsertest.cc",

@ -145,6 +145,7 @@ source_set("common") {
"fenced_frame/redacted_fenced_frame_config.cc",
"fenced_frame/redacted_fenced_frame_config_mojom_traits.cc",
"fetch/fetch_api_request_body_mojom_traits.cc",
"fingerprinting_protection/canvas_noise_token.cc",
"frame/delegated_capability_request_token.cc",
"frame/frame_ad_evidence.cc",
"frame/frame_ad_evidence_mojom_traits.cc",

@ -0,0 +1 @@
file://third_party/blink/public/common/fingerprinting_protection/OWNERS

@ -0,0 +1,23 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/public/common/fingerprinting_protection/canvas_noise_token.h"
namespace blink {
namespace {
uint64_t noise_token_ = 0;
} // namespace
// static
void CanvasNoiseToken::Set(uint64_t token) {
noise_token_ = token;
}
// static
uint64_t CanvasNoiseToken::Get() {
return noise_token_;
}
} // namespace blink

@ -128,6 +128,8 @@ bool StructTraits<blink::mojom::RendererPreferencesDataView,
return false;
}
out->canvas_noise_token = data.canvas_noise_token();
return true;
}

@ -146,6 +146,7 @@ source_set("headers") {
"fenced_frame/redacted_fenced_frame_config_mojom_traits.h",
"fetch/fetch_api_request_headers_map.h",
"fetch/fetch_api_request_headers_mojom_traits.h",
"fingerprinting_protection/canvas_noise_token.h",
"forcedark/forcedark_switches.h",
"frame/delegated_capability_request_token.h",
"frame/fenced_frame_sandbox_flags.h",

@ -0,0 +1 @@
file://third_party/blink/renderer/core/canvas_interventions/OWNERS

@ -0,0 +1,25 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_FINGERPRINTING_PROTECTION_CANVAS_NOISE_TOKEN_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_FINGERPRINTING_PROTECTION_CANVAS_NOISE_TOKEN_H_
#include <cstdint>
#include "third_party/blink/public/common/common_export.h"
namespace blink {
// A static class that stores a per-renderer process noise token sent by the
// browser. Noise tokens are one of many attributes that handle canvas noising
// for fingerprinting protection. This class simply stores the 64 bit token and
// makes it available across Blink.
class BLINK_COMMON_EXPORT CanvasNoiseToken final {
public:
static void Set(uint64_t token);
static uint64_t Get();
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_FINGERPRINTING_PROTECTION_CANVAS_NOISE_TOKEN_H_

@ -91,6 +91,7 @@ struct BLINK_COMMON_EXPORT RendererPreferences {
bool caret_browsing_enabled{false};
bool uses_platform_autofill{false};
std::vector<uint16_t> explicitly_allowed_network_ports;
uint64_t canvas_noise_token{0};
RendererPreferences();
RendererPreferences(const RendererPreferences& other);

@ -275,6 +275,11 @@ struct BLINK_COMMON_EXPORT
return data.explicitly_allowed_network_ports;
}
static const uint64_t& canvas_noise_token(
const ::blink::RendererPreferences& data) {
return data.canvas_noise_token;
}
static bool Read(blink::mojom::RendererPreferencesDataView,
::blink::RendererPreferences* out);
};

@ -201,4 +201,8 @@ struct RendererPreferences {
bool uses_platform_autofill = false;
array<uint16> explicitly_allowed_network_ports;
// A randomized 64 bit token that is generated per browser session,
// used for canvas noising.
uint64 canvas_noise_token = 0;
};

@ -47,6 +47,7 @@
#include "media/base/media_switches.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/fingerprinting_protection/canvas_noise_token.h"
#include "third_party/blink/public/common/history/session_history_constants.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_menu_source_type.h"
@ -3562,6 +3563,8 @@ void WebViewImpl::UpdateRendererPreferences(
}
#endif
CanvasNoiseToken::Set(renderer_preferences_.canvas_noise_token);
MaybePreloadSystemFonts(GetPage());
}