-
Notifications
You must be signed in to change notification settings - Fork 6.6k
/
canvas_input_key_browsertest.cc
167 lines (145 loc) · 6.42 KB
/
canvas_input_key_browsertest.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "build/build_config.h"
#include "chrome/common/privacy_budget/scoped_privacy_budget_config.h"
#include "chrome/test/base/chrome_test_utils.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
#if defined(OS_ANDROID)
#include "chrome/test/base/android/android_browser_test.h"
#else
#include "chrome/test/base/in_process_browser_test.h"
#endif
namespace {
using base::StringToInt64;
using base::StringToUint64;
using blink::IdentifiableSurface;
constexpr char kFingerprintingScriptUrlSwitch[] = "fingerprinting-script-url";
constexpr char kFingerprintExpectationSwitch[] = "fingerprint-expectation";
constexpr char kInputKeyExpectationSwitch[] = "input-key-expectation";
constexpr char kValueExpectationSwitch[] = "value-expectation";
// NOTE: This test is *disabled* so that it doesn't run on waterfall -- to run
// the test, invoke the test binary as follows:
//
// testing/xvfb.py out/Default/browser_tests --gtest_also_run_disabled_tests
// --gtest_filter="*CanvasInputKeyBrowserTest*"
// --fingerprinting-script-url="file URL goes here"
// [--fingerprint-expectation="optional expected fingerprint goes here"]
// [--input-key-expectation="optional key expectation goes here"]
// [--value-expectation="optional value expectation goes here"]
//
// The --fingerprinting-script-url must resolve to an HTML page that runs a
// script that calls window.domAutomationController.send() with the computed
// fingerprint.
//
// This test runs on Android as well as desktop platforms.
class DISABLED_CanvasInputKeyBrowserTest : public PlatformBrowserTest {
public:
DISABLED_CanvasInputKeyBrowserTest() {
privacy_budget_config_.Apply(test::ScopedPrivacyBudgetConfig::Parameters());
}
content::WebContents* web_contents() {
return chrome_test_utils::GetActiveWebContents(this);
}
void SetUpCommandLine(base::CommandLine* command_line) override {
fingerprinting_script_url_ =
command_line->GetSwitchValueASCII(kFingerprintingScriptUrlSwitch);
fingerprint_expectation_ =
command_line->GetSwitchValueASCII(kFingerprintExpectationSwitch);
input_key_expectation_ =
command_line->GetSwitchValueASCII(kInputKeyExpectationSwitch);
value_expectation_ =
command_line->GetSwitchValueASCII(kValueExpectationSwitch);
}
void SetUpOnMainThread() override {
ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
}
ukm::TestUkmRecorder& recorder() { return *ukm_recorder_; }
protected:
std::string fingerprinting_script_url_;
std::string fingerprint_expectation_;
std::string input_key_expectation_;
std::string value_expectation_;
test::ScopedPrivacyBudgetConfig privacy_budget_config_;
std::unique_ptr<ukm::TestAutoSetUkmRecorder> ukm_recorder_;
};
struct MetricKeyValue {
uint64_t input_key;
int64_t value;
};
// Verify that there's only one entry of type |type|, and return the the
// |input_key|, |value| pair.
template <typename MapType>
base::Optional<MetricKeyValue> ExtractKeyOfType(IdentifiableSurface::Type type,
const MapType& metrics) {
MetricKeyValue last_result = {};
for (const auto& pair : metrics) {
auto surface = IdentifiableSurface::FromMetricHash(pair.first);
if (surface.GetType() == type) {
if (last_result.input_key != 0) {
ADD_FAILURE() << "Saw at least 2 surfaces of type "
<< static_cast<uint64_t>(type)
<< ". First input hash: " << last_result.input_key
<< " second input hash: " << surface.GetInputHash();
return base::nullopt;
}
last_result.input_key = surface.GetInputHash();
last_result.value = pair.second;
}
}
return last_result;
}
IN_PROC_BROWSER_TEST_F(DISABLED_CanvasInputKeyBrowserTest,
TestCanvasFingerprint) {
ASSERT_TRUE(embedded_test_server()->Start());
content::DOMMessageQueue messages;
base::RunLoop run_loop;
recorder().SetOnAddEntryCallback(ukm::builders::Identifiability::kEntryName,
run_loop.QuitClosure());
ASSERT_TRUE(
content::NavigateToURL(web_contents(), GURL(fingerprinting_script_url_)));
// The document computes the canvas fingerprint and sends a message back to
// the test. Receipt of the message indicates that the script successfully
// completed.
std::string fingerprint;
ASSERT_TRUE(messages.WaitForMessage(&fingerprint));
// Navigating away from the test page causes the document to be unloaded. That
// will cause any buffered metrics to be flushed.
content::NavigateToURLBlockUntilNavigationsComplete(web_contents(),
GURL("about:blank"), 1);
// Wait for the metrics to come down the pipe.
content::RunAllTasksUntilIdle();
run_loop.Run();
auto merged_entries = recorder().GetMergedEntriesByName(
ukm::builders::Identifiability::kEntryName);
// Shouldn't be more than one source here. If this changes, then we'd need to
// adjust this test to deal.
ASSERT_EQ(1u, merged_entries.size());
base::Optional<MetricKeyValue> canvas_key_value =
ExtractKeyOfType(IdentifiableSurface::Type::kCanvasReadback,
merged_entries.begin()->second->metrics);
ASSERT_TRUE(canvas_key_value);
LOG(INFO) << "Canvas fingerprint is: " << fingerprint;
LOG(INFO) << "Input key is: " << canvas_key_value->input_key;
LOG(INFO) << "Value is: " << canvas_key_value->value;
if (!fingerprint_expectation_.empty())
EXPECT_EQ(fingerprint_expectation_, fingerprint);
if (!input_key_expectation_.empty()) {
uint64_t parsed_input_key_expectation;
EXPECT_TRUE(
StringToUint64(input_key_expectation_, &parsed_input_key_expectation));
EXPECT_EQ(parsed_input_key_expectation, canvas_key_value->input_key);
}
if (!value_expectation_.empty()) {
int64_t parsed_value_expectation;
EXPECT_TRUE(StringToInt64(value_expectation_, &parsed_value_expectation));
EXPECT_EQ(parsed_value_expectation, canvas_key_value->value);
}
}
} // namespace