blob: 421b7273803a6efde49cbee710074fc42828eaa2 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2019 The Chromium Authors
Mike West195a48a12019-03-27 12:37:052// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <string>
6
Mike West195a48a12019-03-27 12:37:057#include "base/test/scoped_feature_list.h"
8#include "build/build_config.h"
Lukasz Anforowicz435bcb582019-07-12 20:50:069#include "content/public/browser/navigation_controller.h"
Mike West195a48a12019-03-27 12:37:0510#include "content/public/browser/navigation_entry.h"
11#include "content/public/browser/web_contents.h"
Peter Kasting919ce652020-05-07 10:22:3612#include "content/public/test/browser_test.h"
Mike West195a48a12019-03-27 12:37:0513#include "content/public/test/browser_test_utils.h"
14#include "content/public/test/content_browser_test.h"
15#include "content/public/test/content_browser_test_utils.h"
Lukasz Anforowicz2d2a3ba2019-07-11 23:29:2016#include "content/public/test/test_navigation_observer.h"
Mike West195a48a12019-03-27 12:37:0517#include "content/shell/browser/shell.h"
18#include "net/dns/mock_host_resolver.h"
19#include "net/test/embedded_test_server/embedded_test_server.h"
Lukasz Anforowiczc5b4c91c2019-04-01 22:42:4020#include "services/network/public/cpp/features.h"
Mike West195a48a12019-03-27 12:37:0521#include "testing/gtest/include/gtest/gtest.h"
22#include "ui/base/page_transition_types.h"
23#include "url/gurl.h"
24
25namespace content {
26
27// Test suite covering the interaction between browser bookmarks and
28// `Sec-Fetch-*` headers that can't be covered by Web Platform Tests (yet).
29// See https://mikewest.github.io/sec-metadata/#directly-user-initiated and
30// https://github.com/web-platform-tests/wpt/issues/16019.
31class SecFetchBrowserTest : public ContentBrowserTest {
32 public:
33 SecFetchBrowserTest()
Yifan Luof579d812020-03-03 16:04:3334 : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
Mike West195a48a12019-03-27 12:37:0535
Peter Boström9b036532021-10-28 23:37:2836 SecFetchBrowserTest(const SecFetchBrowserTest&) = delete;
37 SecFetchBrowserTest& operator=(const SecFetchBrowserTest&) = delete;
38
Mike West195a48a12019-03-27 12:37:0539 void SetUpOnMainThread() override {
40 host_resolver()->AddRule("*", "127.0.0.1");
Alan Cutterfb5689192019-03-28 08:39:1941 https_test_server_.AddDefaultHandlers(GetTestDataFilePath());
Mike West195a48a12019-03-27 12:37:0542 https_test_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
43 ASSERT_TRUE(https_test_server_.Start());
Mike West195a48a12019-03-27 12:37:0544 }
45
46 WebContents* web_contents() { return shell()->web_contents(); }
47
48 void NavigateForHeader(const std::string& header) {
49 std::string url = "/echoheader?";
50 ASSERT_TRUE(
51 NavigateToURL(shell(), https_test_server_.GetURL(url + header)));
52
53 NavigationEntry* entry =
54 web_contents()->GetController().GetLastCommittedEntry();
55 ASSERT_TRUE(PageTransitionCoreTypeIs(entry->GetTransitionType(),
56 ui::PAGE_TRANSITION_TYPED));
57 }
58
Lukasz Anforowicz435bcb582019-07-12 20:50:0659 GURL GetUrl(const std::string& path_and_query) {
60 return https_test_server_.GetURL(path_and_query);
Mike West195a48a12019-03-27 12:37:0561 }
62
Lukasz Anforowicz435bcb582019-07-12 20:50:0663 GURL GetSecFetchUrl() { return GetUrl("/echoheader?sec-fetch-site"); }
64
Mike West195a48a12019-03-27 12:37:0565 std::string GetContent() {
66 return EvalJs(shell(), "document.body.innerText").ExtractString();
67 }
68
69 private:
70 net::EmbeddedTestServer https_test_server_;
71 base::test::ScopedFeatureList feature_list_;
Mike West195a48a12019-03-27 12:37:0572};
73
74IN_PROC_BROWSER_TEST_F(SecFetchBrowserTest, TypedNavigation) {
75 {
76 // Sec-Fetch-Dest: document
77 NavigateForHeader("Sec-Fetch-Dest");
78 EXPECT_EQ("document", GetContent());
79 }
80
81 {
82 // Sec-Fetch-Mode: navigate
83 NavigateForHeader("Sec-Fetch-Mode");
84 EXPECT_EQ("navigate", GetContent());
85 }
86
87 {
88 // Sec-Fetch-Site: none
89 NavigateForHeader("Sec-Fetch-Site");
90 EXPECT_EQ("none", GetContent());
91 }
92
93 {
Mike Westf1aff042019-04-06 08:33:3694 // Sec-Fetch-User: ?1
Mike West195a48a12019-03-27 12:37:0595 NavigateForHeader("Sec-Fetch-User");
Mike Westf1aff042019-04-06 08:33:3696 EXPECT_EQ("?1", GetContent());
Mike West195a48a12019-03-27 12:37:0597 }
98}
99
Lukasz Anforowicz2d2a3ba2019-07-11 23:29:20100// Verify that cross-port navigations are treated as same-site by
101// Sec-Fetch-Site.
102IN_PROC_BROWSER_TEST_F(SecFetchBrowserTest, CrossPortNavigation) {
103 net::EmbeddedTestServer server2(net::EmbeddedTestServer::TYPE_HTTPS);
104 server2.AddDefaultHandlers(GetTestDataFilePath());
105 server2.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
106 ASSERT_TRUE(server2.Start());
107
108 GURL initial_url = server2.GetURL("/title1.html");
109 GURL final_url = GetSecFetchUrl();
110 EXPECT_EQ(initial_url.scheme(), final_url.scheme());
111 EXPECT_EQ(initial_url.host(), final_url.host());
112 EXPECT_NE(initial_url.port(), final_url.port());
113
114 // Navigate to (paraphrasing): https://foo.com:port1/...
115 ASSERT_TRUE(NavigateToURL(shell(), initial_url));
116
117 // Navigate to (paraphrasing): https://foo.com:port2/... when the navigation
118 // is initiated from (paraphrasing): https://foo.com:port1/...
119 {
120 TestNavigationObserver nav_observer(shell()->web_contents());
121 ASSERT_TRUE(ExecJs(shell(), JsReplace("location = $1", final_url)));
122 nav_observer.Wait();
123 }
124
125 // Verify that https://foo.com:port1 is treated as same-site wrt
126 // https://foo.com:port2.
127 EXPECT_EQ("same-site", GetContent());
128}
129
Lukasz Anforowicz435bcb582019-07-12 20:50:06130// This test verifies presence of a correct ("replayed") Sec-Fetch-Site HTTP
131// request header in a history/back navigation.
132//
133// This is a regression test for https://crbug.com/946503.
134//
135// This test is slightly redundant with
Yifan Luoe84f7fa2019-11-18 12:54:51136// wpt/fetch/metadata/history.tentative.https.sub.html
Lukasz Anforowicz435bcb582019-07-12 20:50:06137// but it tests history navigations that are browser-initiated
138// (e.g. as-if they were initiated by Chrome UI, not by javascript).
139IN_PROC_BROWSER_TEST_F(SecFetchBrowserTest, BackNavigation) {
140 // Start the test at |initial_url|.
141 ASSERT_TRUE(embedded_test_server()->Start());
142 GURL initial_url(GetUrl("/title1.html"));
143 ASSERT_TRUE(NavigateToURL(shell(), initial_url));
144
145 // Renderer-initiated navigation to same-origin |main_url|.
146 GURL main_url(GetSecFetchUrl());
147 EXPECT_EQ(url::Origin::Create(initial_url), url::Origin::Create(main_url));
148 {
149 TestNavigationObserver nav_observer(shell()->web_contents(), 1);
150 ASSERT_TRUE(ExecJs(shell(), JsReplace("window.location = $1", main_url)));
151 nav_observer.Wait();
152 EXPECT_EQ("same-origin", GetContent());
153 }
154
155 // Renderer-initiated navigation to |cross_origin_url|.
156 {
157 GURL cross_origin_url(embedded_test_server()->GetURL("/title1.html"));
158 EXPECT_NE(url::Origin::Create(main_url),
159 url::Origin::Create(cross_origin_url));
160 TestNavigationObserver nav_observer(shell()->web_contents(), 1);
161 ASSERT_TRUE(
162 ExecJs(shell(), JsReplace("window.location = $1", cross_origin_url)));
163 nav_observer.Wait();
164 }
165
166 // Go back and verify that `Sec-Fetch-Site: same-origin` is again sent to the
167 // server.
168 {
169 TestNavigationObserver nav_observer(shell()->web_contents(), 1);
170 shell()->web_contents()->GetController().GoBack();
171 nav_observer.Wait();
172 EXPECT_EQ(main_url, shell()->web_contents()->GetLastCommittedURL());
173 EXPECT_EQ("same-origin", GetContent());
174 }
175}
176
177// This test verifies presence of a correct ("replayed") Sec-Fetch-Site HTTP
178// request header in a history/reload navigation.
179//
180// This is a regression test for https://crbug.com/946503.
181IN_PROC_BROWSER_TEST_F(SecFetchBrowserTest, ReloadNavigation) {
182 // Start the test at |initial_url|.
183 ASSERT_TRUE(embedded_test_server()->Start());
184 GURL initial_url(GetUrl("/title1.html"));
185 ASSERT_TRUE(NavigateToURL(shell(), initial_url));
186
187 // Renderer-initiated navigation to same-origin |main_url|.
188 GURL main_url(GetSecFetchUrl());
189 EXPECT_EQ(url::Origin::Create(initial_url), url::Origin::Create(main_url));
190 {
191 TestNavigationObserver nav_observer(shell()->web_contents(), 1);
192 ASSERT_TRUE(ExecJs(shell(), JsReplace("window.location = $1", main_url)));
193 nav_observer.Wait();
194 EXPECT_EQ("same-origin", GetContent());
195 }
196
197 // Reload and verify that `Sec-Fetch-Site: same-origin` is again sent to the
198 // server.
199 {
200 TestNavigationObserver nav_observer(shell()->web_contents(), 1);
201 shell()->web_contents()->GetController().Reload(ReloadType::BYPASSING_CACHE,
202 true);
203 nav_observer.Wait();
204 EXPECT_EQ(main_url, shell()->web_contents()->GetLastCommittedURL());
205 EXPECT_EQ("same-origin", GetContent());
206 }
207}
208
Mike West195a48a12019-03-27 12:37:05209} // namespace content