blob: 7761755fc7b8ab2fcdfc590b487a385212907c5d [file] [log] [blame]
David Van Clevec0228a92020-05-06 02:06:331// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/test/metrics/histogram_tester.h"
6#include "base/test/scoped_feature_list.h"
7#include "chrome/browser/ui/browser.h"
8#include "chrome/test/base/in_process_browser_test.h"
9#include "chrome/test/base/ui_test_utils.h"
Peter Kasting919ce652020-05-07 10:22:3610#include "content/public/test/browser_test.h"
David Van Clevec0228a92020-05-06 02:06:3311#include "content/public/test/browser_test_utils.h"
12#include "content/public/test/test_navigation_observer.h"
13#include "net/test/embedded_test_server/embedded_test_server.h"
14#include "services/network/public/cpp/features.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace content {
18
19// The Trust Token API (https://github.com/wicg/trust-token-api) allows clients
20// to annotate outgoing requests with certain cryptographic state, by providing
21// parameters alongside Fetch, XHR, and iframe-tag loads. These tests confirm
22// that providing Trust Tokens parameters to each of these API entry points
23// increments the corresponding Blink UseCounter. Although Trust Tokens is part
24// of the web platform and the use counters are incremented in Blink, these
25// tests live in //chrome because the Page Load Metrics framework, Chrome's way
26// of listening for use counter updates, is not available in the content shell.
27
28class TrustTokenUseCountersBrowsertest : public InProcessBrowserTest {
29 public:
30 TrustTokenUseCountersBrowsertest() {
31 features_.InitAndEnableFeature(network::features::kTrustTokens);
32 }
33
34 void SetUpOnMainThread() override {
35 server_.AddDefaultHandlers(
36 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
37 ASSERT_TRUE(server_.Start());
38 }
39
40 protected:
41 base::test::ScopedFeatureList features_;
42
43 net::EmbeddedTestServer server_{net::EmbeddedTestServer::TYPE_HTTPS};
44};
45
46IN_PROC_BROWSER_TEST_F(TrustTokenUseCountersBrowsertest, CountsFetchUse) {
47 base::HistogramTester histograms;
48
49 GURL start_url(server_.GetURL("/title1.html"));
50 EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), start_url));
51
52 std::string cmd = R"(
53 (async () => {
54 await fetch("/page404.html", {trustToken: {type: 'token-request'}});
55 } )(); )";
56
57 // We use EvalJs here, not ExecJs, because EvalJs waits for promises to
58 // resolve. We expect a failure because the destination of the Trust
59 // Tokens operation-bearing request will 404; this is fine since we just need
60 // to test that the usage metric fired when the command was called.
61 EXPECT_FALSE(
62 content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), cmd)
63 .error.empty());
64
65 // Navigate away in order to flush use counters.
66 EXPECT_TRUE(
67 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
68
69 histograms.ExpectBucketCount("Blink.UseCounter.Features",
70 blink::mojom::WebFeature::kTrustTokenFetch, 1);
71}
72
73IN_PROC_BROWSER_TEST_F(TrustTokenUseCountersBrowsertest, CountsXhrUse) {
74 GURL start_url(server_.GetURL("/title1.html"));
75 EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), start_url));
76
77 base::HistogramTester histograms;
78
79 // Execute a Trust Tokens issuance against a nonexistent endpoint.
80 std::string cmd = R"(
81 (async () => {
82 let request = new XMLHttpRequest();
83 request.open('GET', '/page404.html');
84 request.setTrustToken({
85 type: 'token-request'
86 });
87 let promise = new Promise((res, rej) => {
88 request.onload = res; request.onerror = rej;
89 });
90 request.send();
91 await promise;
92 })(); )";
93
94 // We use EvalJs here, not ExecJs, because EvalJs waits for promises to
95 // resolve. We expect a failure because the destination of the Trust
96 // Tokens operation-bearing request will 404; this is fine since we just need
97 // to test that the usage metric fired when the command was called.
98 EXPECT_FALSE(
99 content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), cmd)
100 .error.empty());
101
102 // Navigate away in order to flush use counters.
103 EXPECT_TRUE(
104 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
105
106 histograms.ExpectBucketCount("Blink.UseCounter.Features",
107 blink::mojom::WebFeature::kTrustTokenXhr, 1);
108}
109
110IN_PROC_BROWSER_TEST_F(TrustTokenUseCountersBrowsertest, CountsIframeUse) {
111 base::HistogramTester histograms;
112
113 GURL start_url(server_.GetURL("/iframe.html"));
114 EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), start_url));
115
116 content::WebContents* web_contents =
117 browser()->tab_strip_model()->GetActiveWebContents();
118
119 // It's important to set the trust token arguments before updating src, as
120 // the latter triggers a load. It's also important to JsReplace the trustToken
121 // argument here, because iframe.trustToken expects a (properly escaped)
122 // JSON-encoded string as its value, not a JS object.
123 EXPECT_TRUE(ExecJs(web_contents,
124 JsReplace(
125 R"( const myFrame = document.getElementById("test");
126 myFrame.trustToken = $1;
127 myFrame.src = $2;)",
128 R"({"type": "token-request"})", "/page404.html")));
129 TestNavigationObserver load_observer(web_contents);
130 load_observer.Wait();
131
132 // Navigate away in order to flush use counters.
133 EXPECT_TRUE(
134 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
135
136 histograms.ExpectBucketCount("Blink.UseCounter.Features",
137 blink::mojom::WebFeature::kTrustTokenIframe, 1);
138}
139
140} // namespace content