
The methodology used to generate this CL is documented in https://crbug.com/1098010#c34. No-Try: true No-Presubmit: true Bug: 1098010 Change-Id: I8c0f009d16350271f07d8e5e561085822cc9dd27 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3895935 Owners-Override: Avi Drissman <avi@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Mark Mentovai <mark@chromium.org> Auto-Submit: Avi Drissman <avi@chromium.org> Cr-Commit-Position: refs/heads/main@{#1047456}
210 lines
7.4 KiB
C++
210 lines
7.4 KiB
C++
// Copyright 2019 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include <string>
|
|
|
|
#include "base/test/scoped_feature_list.h"
|
|
#include "build/build_config.h"
|
|
#include "content/public/browser/navigation_controller.h"
|
|
#include "content/public/browser/navigation_entry.h"
|
|
#include "content/public/browser/web_contents.h"
|
|
#include "content/public/test/browser_test.h"
|
|
#include "content/public/test/browser_test_utils.h"
|
|
#include "content/public/test/content_browser_test.h"
|
|
#include "content/public/test/content_browser_test_utils.h"
|
|
#include "content/public/test/test_navigation_observer.h"
|
|
#include "content/shell/browser/shell.h"
|
|
#include "net/dns/mock_host_resolver.h"
|
|
#include "net/test/embedded_test_server/embedded_test_server.h"
|
|
#include "services/network/public/cpp/features.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
#include "ui/base/page_transition_types.h"
|
|
#include "url/gurl.h"
|
|
|
|
namespace content {
|
|
|
|
// Test suite covering the interaction between browser bookmarks and
|
|
// `Sec-Fetch-*` headers that can't be covered by Web Platform Tests (yet).
|
|
// See https://mikewest.github.io/sec-metadata/#directly-user-initiated and
|
|
// https://github.com/web-platform-tests/wpt/issues/16019.
|
|
class SecFetchBrowserTest : public ContentBrowserTest {
|
|
public:
|
|
SecFetchBrowserTest()
|
|
: https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
|
|
|
|
SecFetchBrowserTest(const SecFetchBrowserTest&) = delete;
|
|
SecFetchBrowserTest& operator=(const SecFetchBrowserTest&) = delete;
|
|
|
|
void SetUpOnMainThread() override {
|
|
host_resolver()->AddRule("*", "127.0.0.1");
|
|
https_test_server_.AddDefaultHandlers(GetTestDataFilePath());
|
|
https_test_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
|
|
ASSERT_TRUE(https_test_server_.Start());
|
|
}
|
|
|
|
WebContents* web_contents() { return shell()->web_contents(); }
|
|
|
|
void NavigateForHeader(const std::string& header) {
|
|
std::string url = "/echoheader?";
|
|
ASSERT_TRUE(
|
|
NavigateToURL(shell(), https_test_server_.GetURL(url + header)));
|
|
|
|
NavigationEntry* entry =
|
|
web_contents()->GetController().GetLastCommittedEntry();
|
|
ASSERT_TRUE(PageTransitionCoreTypeIs(entry->GetTransitionType(),
|
|
ui::PAGE_TRANSITION_TYPED));
|
|
}
|
|
|
|
GURL GetUrl(const std::string& path_and_query) {
|
|
return https_test_server_.GetURL(path_and_query);
|
|
}
|
|
|
|
GURL GetSecFetchUrl() { return GetUrl("/echoheader?sec-fetch-site"); }
|
|
|
|
std::string GetContent() {
|
|
return EvalJs(shell(), "document.body.innerText").ExtractString();
|
|
}
|
|
|
|
private:
|
|
net::EmbeddedTestServer https_test_server_;
|
|
base::test::ScopedFeatureList feature_list_;
|
|
};
|
|
|
|
IN_PROC_BROWSER_TEST_F(SecFetchBrowserTest, TypedNavigation) {
|
|
{
|
|
// Sec-Fetch-Dest: document
|
|
NavigateForHeader("Sec-Fetch-Dest");
|
|
EXPECT_EQ("document", GetContent());
|
|
}
|
|
|
|
{
|
|
// Sec-Fetch-Mode: navigate
|
|
NavigateForHeader("Sec-Fetch-Mode");
|
|
EXPECT_EQ("navigate", GetContent());
|
|
}
|
|
|
|
{
|
|
// Sec-Fetch-Site: none
|
|
NavigateForHeader("Sec-Fetch-Site");
|
|
EXPECT_EQ("none", GetContent());
|
|
}
|
|
|
|
{
|
|
// Sec-Fetch-User: ?1
|
|
NavigateForHeader("Sec-Fetch-User");
|
|
EXPECT_EQ("?1", GetContent());
|
|
}
|
|
}
|
|
|
|
// Verify that cross-port navigations are treated as same-site by
|
|
// Sec-Fetch-Site.
|
|
IN_PROC_BROWSER_TEST_F(SecFetchBrowserTest, CrossPortNavigation) {
|
|
net::EmbeddedTestServer server2(net::EmbeddedTestServer::TYPE_HTTPS);
|
|
server2.AddDefaultHandlers(GetTestDataFilePath());
|
|
server2.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
|
|
ASSERT_TRUE(server2.Start());
|
|
|
|
GURL initial_url = server2.GetURL("/title1.html");
|
|
GURL final_url = GetSecFetchUrl();
|
|
EXPECT_EQ(initial_url.scheme(), final_url.scheme());
|
|
EXPECT_EQ(initial_url.host(), final_url.host());
|
|
EXPECT_NE(initial_url.port(), final_url.port());
|
|
|
|
// Navigate to (paraphrasing): https://foo.com:port1/...
|
|
ASSERT_TRUE(NavigateToURL(shell(), initial_url));
|
|
|
|
// Navigate to (paraphrasing): https://foo.com:port2/... when the navigation
|
|
// is initiated from (paraphrasing): https://foo.com:port1/...
|
|
{
|
|
TestNavigationObserver nav_observer(shell()->web_contents());
|
|
ASSERT_TRUE(ExecJs(shell(), JsReplace("location = $1", final_url)));
|
|
nav_observer.Wait();
|
|
}
|
|
|
|
// Verify that https://foo.com:port1 is treated as same-site wrt
|
|
// https://foo.com:port2.
|
|
EXPECT_EQ("same-site", GetContent());
|
|
}
|
|
|
|
// This test verifies presence of a correct ("replayed") Sec-Fetch-Site HTTP
|
|
// request header in a history/back navigation.
|
|
//
|
|
// This is a regression test for https://crbug.com/946503.
|
|
//
|
|
// This test is slightly redundant with
|
|
// wpt/fetch/metadata/history.tentative.https.sub.html
|
|
// but it tests history navigations that are browser-initiated
|
|
// (e.g. as-if they were initiated by Chrome UI, not by javascript).
|
|
IN_PROC_BROWSER_TEST_F(SecFetchBrowserTest, BackNavigation) {
|
|
// Start the test at |initial_url|.
|
|
ASSERT_TRUE(embedded_test_server()->Start());
|
|
GURL initial_url(GetUrl("/title1.html"));
|
|
ASSERT_TRUE(NavigateToURL(shell(), initial_url));
|
|
|
|
// Renderer-initiated navigation to same-origin |main_url|.
|
|
GURL main_url(GetSecFetchUrl());
|
|
EXPECT_EQ(url::Origin::Create(initial_url), url::Origin::Create(main_url));
|
|
{
|
|
TestNavigationObserver nav_observer(shell()->web_contents(), 1);
|
|
ASSERT_TRUE(ExecJs(shell(), JsReplace("window.location = $1", main_url)));
|
|
nav_observer.Wait();
|
|
EXPECT_EQ("same-origin", GetContent());
|
|
}
|
|
|
|
// Renderer-initiated navigation to |cross_origin_url|.
|
|
{
|
|
GURL cross_origin_url(embedded_test_server()->GetURL("/title1.html"));
|
|
EXPECT_NE(url::Origin::Create(main_url),
|
|
url::Origin::Create(cross_origin_url));
|
|
TestNavigationObserver nav_observer(shell()->web_contents(), 1);
|
|
ASSERT_TRUE(
|
|
ExecJs(shell(), JsReplace("window.location = $1", cross_origin_url)));
|
|
nav_observer.Wait();
|
|
}
|
|
|
|
// Go back and verify that `Sec-Fetch-Site: same-origin` is again sent to the
|
|
// server.
|
|
{
|
|
TestNavigationObserver nav_observer(shell()->web_contents(), 1);
|
|
shell()->web_contents()->GetController().GoBack();
|
|
nav_observer.Wait();
|
|
EXPECT_EQ(main_url, shell()->web_contents()->GetLastCommittedURL());
|
|
EXPECT_EQ("same-origin", GetContent());
|
|
}
|
|
}
|
|
|
|
// This test verifies presence of a correct ("replayed") Sec-Fetch-Site HTTP
|
|
// request header in a history/reload navigation.
|
|
//
|
|
// This is a regression test for https://crbug.com/946503.
|
|
IN_PROC_BROWSER_TEST_F(SecFetchBrowserTest, ReloadNavigation) {
|
|
// Start the test at |initial_url|.
|
|
ASSERT_TRUE(embedded_test_server()->Start());
|
|
GURL initial_url(GetUrl("/title1.html"));
|
|
ASSERT_TRUE(NavigateToURL(shell(), initial_url));
|
|
|
|
// Renderer-initiated navigation to same-origin |main_url|.
|
|
GURL main_url(GetSecFetchUrl());
|
|
EXPECT_EQ(url::Origin::Create(initial_url), url::Origin::Create(main_url));
|
|
{
|
|
TestNavigationObserver nav_observer(shell()->web_contents(), 1);
|
|
ASSERT_TRUE(ExecJs(shell(), JsReplace("window.location = $1", main_url)));
|
|
nav_observer.Wait();
|
|
EXPECT_EQ("same-origin", GetContent());
|
|
}
|
|
|
|
// Reload and verify that `Sec-Fetch-Site: same-origin` is again sent to the
|
|
// server.
|
|
{
|
|
TestNavigationObserver nav_observer(shell()->web_contents(), 1);
|
|
shell()->web_contents()->GetController().Reload(ReloadType::BYPASSING_CACHE,
|
|
true);
|
|
nav_observer.Wait();
|
|
EXPECT_EQ(main_url, shell()->web_contents()->GetLastCommittedURL());
|
|
EXPECT_EQ("same-origin", GetContent());
|
|
}
|
|
}
|
|
|
|
} // namespace content
|