blob: cae635d82a93e77af257e6e7aea255d333ee9713 [file] [log] [blame]
// 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 "base/strings/strcat.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#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/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/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "net/base/features.h"
#include "net/cookies/canonical_cookie_test_helpers.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/network/public/cpp/network_switches.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
using ::testing::IsEmpty;
using ::testing::Key;
using ::testing::UnorderedElementsAre;
// This file contains tests for cookie access via HTTP requests.
// See also (tests for cookie access via JavaScript):
// //content/browser/renderer_host/cookie_browsertest.cc
class HttpCookieBrowserTest : public ContentBrowserTest,
public ::testing::WithParamInterface<bool> {
public:
HttpCookieBrowserTest() : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
if (DoesSameSiteConsiderRedirectChain()) {
feature_list_.InitAndEnableFeature(
net::features::kCookieSameSiteConsidersRedirectChain);
}
}
~HttpCookieBrowserTest() override = default;
void SetUpOnMainThread() override {
ContentBrowserTest::SetUpOnMainThread();
host_resolver()->AddRule("*", "127.0.0.1");
https_server()->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
https_server()->AddDefaultHandlers(GetTestDataFilePath());
ASSERT_TRUE(https_server()->Start());
}
void SetUpCommandLine(base::CommandLine* command_line) override {
ContentBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(
network::switches::kUseFirstPartySet,
base::StringPrintf("https://%s,https://%s,https://%s", kHostA, kHostB,
kHostC));
}
bool DoesSameSiteConsiderRedirectChain() { return GetParam(); }
const char* kHostA = "a.test";
const char* kHostB = "b.test";
const char* kHostC = "c.test";
const char* kHostD = "d.test";
const char* kSameSiteStrictCookieName = "samesite_strict_cookie";
const char* kSameSiteLaxCookieName = "samesite_lax_cookie";
const char* kSameSiteNoneCookieName = "samesite_none_cookie";
const char* kSameSiteUnspecifiedCookieName = "samesite_unspecified_cookie";
const char* kSamePartyLaxCookieName = "sameparty_lax_cookie";
const char* kSamePartyNoneCookieName = "sameparty_none_cookie";
const char* kSamePartyUnspecifiedCookieName = "sameparty_unspecified_cookie";
const std::string kSetSameSiteCookiesURL = base::StrCat({
"/set-cookie?",
kSameSiteStrictCookieName,
"=1;SameSite=Strict&",
kSameSiteLaxCookieName,
"=1;SameSite=Lax&",
kSameSiteUnspecifiedCookieName,
"=1&",
kSameSiteNoneCookieName,
"=1;Secure;SameSite=None",
});
const std::string kSetSamePartyCookiesURL = base::StrCat({
"/set-cookie?",
kSamePartyLaxCookieName,
"=1;SameParty;Secure;SameSite=Lax&",
kSamePartyNoneCookieName,
"=1;SameParty;Secure;SameSite=None&",
kSamePartyUnspecifiedCookieName,
"=1;SameParty;Secure",
});
void SetSameSiteCookies(const std::string& host) {
BrowserContext* context = shell()->web_contents()->GetBrowserContext();
EXPECT_TRUE(SetCookie(
context, https_server()->GetURL(host, "/"),
base::StrCat({kSameSiteStrictCookieName, "=1; samesite=strict"})));
EXPECT_TRUE(
SetCookie(context, https_server()->GetURL(host, "/"),
base::StrCat({kSameSiteLaxCookieName, "=1; samesite=lax"})));
EXPECT_TRUE(SetCookie(
context, https_server()->GetURL(host, "/"),
base::StrCat({kSameSiteNoneCookieName, "=1; samesite=none; secure"})));
EXPECT_TRUE(
SetCookie(context, https_server()->GetURL(host, "/"),
base::StrCat({kSameSiteUnspecifiedCookieName, "=1"})));
}
void SetSamePartyCookies(const std::string& host) {
BrowserContext* context = shell()->web_contents()->GetBrowserContext();
EXPECT_TRUE(
SetCookie(context, https_server()->GetURL(host, "/"),
base::StrCat({kSamePartyLaxCookieName,
"=1; samesite=lax; secure; sameparty"})));
EXPECT_TRUE(
SetCookie(context, https_server()->GetURL(host, "/"),
base::StrCat({kSamePartyNoneCookieName,
"=1; samesite=none; secure; sameparty"})));
EXPECT_TRUE(SetCookie(context, https_server()->GetURL(host, "/"),
base::StrCat({kSamePartyUnspecifiedCookieName,
"=1; secure; sameparty"})));
}
GURL EchoCookiesUrl(net::EmbeddedTestServer* test_server,
const std::string& host) {
return test_server->GetURL(host, "/echoheader?Cookie");
}
GURL SetSameSiteCookiesUrl(net::EmbeddedTestServer* test_server,
const std::string& host) {
return test_server->GetURL(host, kSetSameSiteCookiesURL);
}
GURL SetSamePartyCookiesUrl(net::EmbeddedTestServer* test_server,
const std::string& host) {
return test_server->GetURL(host, kSetSamePartyCookiesURL);
}
GURL RedirectUrl(net::EmbeddedTestServer* test_server,
const std::string& host,
const GURL& target_url) {
return test_server->GetURL(host, "/server-redirect?" + target_url.spec());
}
RenderFrameHostImpl* SelectDescendentFrame(
const std::vector<int>& indices) const {
RenderFrameHostImpl* selected_frame = static_cast<RenderFrameHostImpl*>(
shell()->web_contents()->GetMainFrame());
for (int index : indices) {
selected_frame = selected_frame->child_at(index)->current_frame_host();
}
return selected_frame;
}
std::string ExtractFrameContent(RenderFrameHost* frame) const {
return EvalJs(frame, "document.body.textContent").ExtractString();
}
void NavigateFrameHostToURL(RenderFrameHost* iframe, const GURL& url) {
TestNavigationObserver nav_observer(shell()->web_contents());
ExecuteScriptAsync(iframe, JsReplace("location = $1", url));
nav_observer.Wait();
}
void ArrangeFrames(const std::string& frame_tree) {
EXPECT_TRUE(NavigateToURL(
shell()->web_contents(),
https_server()->GetURL(
frame_tree.substr(0, frame_tree.find("(")),
base::StrCat({"/cross_site_iframe_factory.html?", frame_tree}))));
}
// Returns the text contents of the Cookie header from the leaf frame.
// `frame_tree_pattern` contains a format template for the query string to be
// passed to cross_site_iframe_factory, where the URL of the desired leaf
// frame is `leaf_url`, e.g. some URL that ends up at `/echoheader?Cookie`.
std::string ArrangeFramesAndGetContentFromLeaf(
const std::string& frame_tree_pattern,
const std::vector<int>& leaf_path,
const GURL& leaf_url) {
std::string frame_tree =
base::StringPrintf(frame_tree_pattern.c_str(), leaf_url.spec().c_str());
ArrangeFrames(frame_tree);
RenderFrameHostImpl* leaf = SelectDescendentFrame(leaf_path);
return ExtractFrameContent(leaf);
}
// Returns the cookies for the leaf's origin.
// `frame_tree_pattern` contains a format template for the query string to be
// passed to cross_site_iframe_factory, where the URL of the desired leaf
// frame is `leaf_url`, e.g. some URL that ends up at `/set-cookie`.
std::vector<net::CanonicalCookie> ArrangeFramesAndGetCanonicalCookiesForLeaf(
const std::string& frame_tree_pattern,
const GURL& leaf_url) {
GURL leaf_origin_url = url::Origin::Create(leaf_url).GetURL();
return ArrangeFramesAndGetCanonicalCookiesForLeaf(
frame_tree_pattern, leaf_url, leaf_origin_url);
}
// Same as above but returns cookies for a separately specified `cookie_url`.
std::vector<net::CanonicalCookie> ArrangeFramesAndGetCanonicalCookiesForLeaf(
const std::string& frame_tree_pattern,
const GURL& leaf_url,
const GURL& cookie_url) {
std::string frame_tree =
base::StringPrintf(frame_tree_pattern.c_str(), leaf_url.spec().c_str());
ArrangeFrames(frame_tree);
return GetCanonicalCookies(shell()->web_contents()->GetBrowserContext(),
cookie_url);
}
uint32_t ClearCookies() {
return DeleteCookies(shell()->web_contents()->GetBrowserContext(),
network::mojom::CookieDeletionFilter());
}
net::EmbeddedTestServer* https_server() { return &https_server_; }
// is_user_initiated_navigation - true if user initiates navigation to 404,
// - false script initiates this navigation
// is_cross_site_navigation - true if testing in a cross-site context,
// - false if testing in a same-site context
// is_user_initiated_reload - true if user initates the reload,
// false if the reload via script
std::string Test404ReloadCookie(bool is_user_initiated_navigation,
bool is_cross_site_navigation,
bool is_user_initiated_reload) {
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
// Set target as A or B and cookies based on cross_site param
const char* target = is_cross_site_navigation ? kHostB : kHostA;
GURL target_URL =
https_server()->GetURL(target, "/echo-cookie-with-status?status=404");
SetSameSiteCookies(target);
// Start at a website A
EXPECT_TRUE(
NavigateToURL(web_contents, EchoCookiesUrl(https_server(), kHostA)));
// Navigate method based on whether user or script initiated
if (is_user_initiated_navigation) {
EXPECT_TRUE(NavigateToURL(web_contents, target_URL));
} else {
EXPECT_TRUE(NavigateToURLFromRenderer(web_contents, target_URL));
}
// Trigger either user or script reload
TestNavigationObserver nav_observer(web_contents);
if (is_user_initiated_reload) {
shell()->Reload();
} else {
ExecuteScriptAsync(
web_contents->GetMainFrame(),
content::JsReplace("window.location.reload($1);", true));
}
nav_observer.Wait();
// Return the cookies rendered on frame
return ExtractFrameContent(web_contents->GetMainFrame());
}
private:
net::test_server::EmbeddedTestServer https_server_;
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SendSameSiteCookies) {
SetSameSiteCookies(kHostA);
SetSameSiteCookies(kHostB);
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
// Main frame browser-initiated navigation sends all SameSite cookies.
ASSERT_TRUE(
NavigateToURL(web_contents, EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(
ExtractFrameContent(web_contents->GetMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
// Main frame same-site (A => A) navigation sends all SameSite cookies.
ASSERT_TRUE(NavigateToURLFromRenderer(
web_contents->GetMainFrame(), EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(
ExtractFrameContent(web_contents->GetMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
// Main frame cross-site (A => B) navigation sends all but Strict cookies.
ASSERT_TRUE(NavigateToURLFromRenderer(
web_contents->GetMainFrame(), EchoCookiesUrl(https_server(), kHostB)));
EXPECT_THAT(ExtractFrameContent(web_contents->GetMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteLaxCookieName), Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
// Same-site iframe (A embedded in A) sends all SameSite cookies.
EXPECT_THAT(
ArrangeFramesAndGetContentFromLeaf(
"a.test(%s)", {0}, EchoCookiesUrl(https_server(), kHostA)),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
// Cross-site iframe (B embedded in A) sends only None cookies.
EXPECT_THAT(
ArrangeFramesAndGetContentFromLeaf(
"a.test(%s)", {0}, EchoCookiesUrl(https_server(), kHostB)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SendSameSiteCookies_Redirect) {
SetSameSiteCookies(kHostA);
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
// Main frame same-site redirect (A->A) sends all SameSite cookies.
ASSERT_TRUE(NavigateToURL(
web_contents,
RedirectUrl(https_server(), kHostA,
EchoCookiesUrl(https_server(), kHostA)),
/*expected_commit_url=*/EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(
ExtractFrameContent(web_contents->GetMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
if (DoesSameSiteConsiderRedirectChain()) {
// Main frame cross-site redirect (B->A) sends Lax but not Strict SameSite
// cookies...
ASSERT_TRUE(NavigateToURL(
web_contents,
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA)),
/*expected_commit_url=*/EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(ExtractFrameContent(web_contents->GetMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteLaxCookieName), Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
// ... even if the first URL is same-site. (A->B->A)
ASSERT_TRUE(NavigateToURL(
web_contents,
RedirectUrl(https_server(), kHostA,
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA))),
/*expected_commit_url=*/EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(ExtractFrameContent(web_contents->GetMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteLaxCookieName), Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
} else {
// If redirect chains are not considered, then cross-site redirects do not
// make the request cross-site.
ASSERT_TRUE(NavigateToURL(
web_contents,
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA)),
/*expected_commit_url=*/EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(ExtractFrameContent(web_contents->GetMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
ASSERT_TRUE(NavigateToURL(
web_contents,
RedirectUrl(https_server(), kHostA,
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA))),
/*expected_commit_url=*/EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(ExtractFrameContent(web_contents->GetMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
}
// A same-site redirected iframe (A->A embedded in A) sends all SameSite
// cookies.
EXPECT_THAT(
ArrangeFramesAndGetContentFromLeaf(
"a.test(%s)", {0},
RedirectUrl(https_server(), kHostA,
EchoCookiesUrl(https_server(), kHostA))),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
if (DoesSameSiteConsiderRedirectChain()) {
// A cross-site redirected iframe in a same-site context (B->A embedded in
// A) does not send SameSite cookies...
EXPECT_THAT(ArrangeFramesAndGetContentFromLeaf(
"a.test(%s)", {0},
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA))),
net::CookieStringIs(
UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
// ... even if the first URL is same-site. (A->B->A embedded in A)
EXPECT_THAT(
ArrangeFramesAndGetContentFromLeaf(
"a.test(%s)", {0},
RedirectUrl(https_server(), kHostA,
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA)))),
net::CookieStringIs(
UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
} else {
// If redirect chains are not considered, then cross-site redirects do not
// make the request cross-site.
EXPECT_THAT(ArrangeFramesAndGetContentFromLeaf(
"a.test(%s)", {0},
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA))),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
EXPECT_THAT(
ArrangeFramesAndGetContentFromLeaf(
"a.test(%s)", {0},
RedirectUrl(https_server(), kHostA,
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA)))),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
}
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SetSameSiteCookies) {
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
// Main frame can set all SameSite cookies.
ASSERT_TRUE(NavigateToURL(
web_contents, https_server()->GetURL(kHostA, kSetSameSiteCookiesURL)));
EXPECT_THAT(GetCanonicalCookies(web_contents->GetBrowserContext(),
https_server()->GetURL(kHostA, "/")),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteStrictCookieName),
net::MatchesCookieWithName(kSameSiteLaxCookieName),
net::MatchesCookieWithName(kSameSiteNoneCookieName),
net::MatchesCookieWithName(kSameSiteUnspecifiedCookieName)));
ASSERT_EQ(4U, ClearCookies());
// Same-site iframe (A embedded in A) sets all SameSite cookies.
EXPECT_THAT(ArrangeFramesAndGetCanonicalCookiesForLeaf(
"a.test(%s)", SetSameSiteCookiesUrl(https_server(), kHostA)),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteStrictCookieName),
net::MatchesCookieWithName(kSameSiteLaxCookieName),
net::MatchesCookieWithName(kSameSiteNoneCookieName),
net::MatchesCookieWithName(kSameSiteUnspecifiedCookieName)));
ASSERT_EQ(4U, ClearCookies());
// Cross-site iframe (B embedded in A) sets only None cookies.
EXPECT_THAT(ArrangeFramesAndGetCanonicalCookiesForLeaf(
"a.test(%s)", SetSameSiteCookiesUrl(https_server(), kHostB)),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteNoneCookieName)));
ASSERT_EQ(1U, ClearCookies());
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SetSameSiteCookies_Redirect) {
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
// Same-site redirected main frame navigation can set all SameSite cookies.
ASSERT_TRUE(NavigateToURL(
web_contents,
RedirectUrl(https_server(), kHostA,
SetSameSiteCookiesUrl(https_server(), kHostA)),
/*expected_commit_url=*/SetSameSiteCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(GetCanonicalCookies(web_contents->GetBrowserContext(),
https_server()->GetURL(kHostA, "/")),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteStrictCookieName),
net::MatchesCookieWithName(kSameSiteLaxCookieName),
net::MatchesCookieWithName(kSameSiteNoneCookieName),
net::MatchesCookieWithName(kSameSiteUnspecifiedCookieName)));
ASSERT_EQ(4U, ClearCookies());
// Cross-site redirected main frame navigation can set all SameSite cookies.
ASSERT_TRUE(NavigateToURL(
web_contents,
RedirectUrl(https_server(), kHostB,
SetSameSiteCookiesUrl(https_server(), kHostA)),
/*expected_commit_url=*/SetSameSiteCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(GetCanonicalCookies(web_contents->GetBrowserContext(),
https_server()->GetURL(kHostA, "/")),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteStrictCookieName),
net::MatchesCookieWithName(kSameSiteLaxCookieName),
net::MatchesCookieWithName(kSameSiteNoneCookieName),
net::MatchesCookieWithName(kSameSiteUnspecifiedCookieName)));
ASSERT_EQ(4U, ClearCookies());
// A same-site redirected iframe sets all SameSite cookies.
EXPECT_THAT(ArrangeFramesAndGetCanonicalCookiesForLeaf(
"a.test(%s)",
RedirectUrl(https_server(), kHostA,
SetSameSiteCookiesUrl(https_server(), kHostA)),
https_server()->GetURL(kHostA, "/")),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteStrictCookieName),
net::MatchesCookieWithName(kSameSiteLaxCookieName),
net::MatchesCookieWithName(kSameSiteNoneCookieName),
net::MatchesCookieWithName(kSameSiteUnspecifiedCookieName)));
ASSERT_EQ(4U, ClearCookies());
if (DoesSameSiteConsiderRedirectChain()) {
// A cross-site redirected iframe only sets SameSite=None cookies.
EXPECT_THAT(ArrangeFramesAndGetCanonicalCookiesForLeaf(
"a.test(%s)",
RedirectUrl(https_server(), kHostB,
SetSameSiteCookiesUrl(https_server(), kHostA)),
https_server()->GetURL(kHostA, "/")),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteNoneCookieName)));
ASSERT_EQ(1U, ClearCookies());
} else {
EXPECT_THAT(
ArrangeFramesAndGetCanonicalCookiesForLeaf(
"a.test(%s)",
RedirectUrl(https_server(), kHostB,
SetSameSiteCookiesUrl(https_server(), kHostA)),
https_server()->GetURL(kHostA, "/")),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteStrictCookieName),
net::MatchesCookieWithName(kSameSiteLaxCookieName),
net::MatchesCookieWithName(kSameSiteNoneCookieName),
net::MatchesCookieWithName(kSameSiteUnspecifiedCookieName)));
ASSERT_EQ(4U, ClearCookies());
}
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SendSamePartyCookies) {
SetSamePartyCookies(kHostA);
SetSamePartyCookies(kHostD);
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
// No embedded frame. The top-level site has access to its cookies.
ASSERT_TRUE(NavigateToURL(
web_contents, https_server()->GetURL(kHostA, "/echoheader?Cookie")));
EXPECT_THAT(ExtractFrameContent(web_contents->GetMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSamePartyLaxCookieName), Key(kSamePartyNoneCookieName),
Key(kSamePartyUnspecifiedCookieName))));
// Same-site FPS-member iframe (A embedded in A) sends A's SameParty cookies.
EXPECT_THAT(ArrangeFramesAndGetContentFromLeaf(
"a.test(%s)", {0}, EchoCookiesUrl(https_server(), kHostA)),
net::CookieStringIs(UnorderedElementsAre(
Key(kSamePartyLaxCookieName), Key(kSamePartyNoneCookieName),
Key(kSamePartyUnspecifiedCookieName))));
// Cross-site, same-party iframe (B embedded in A) does not send A's SameParty
// cookies (since it's the wrong domain).
EXPECT_EQ(ArrangeFramesAndGetContentFromLeaf(
"a.test(%s)", {0}, EchoCookiesUrl(https_server(), kHostB)),
"None");
// Cross-site, same-party iframe (A embedded in B) sends A's SameParty
// cookies.
EXPECT_THAT(ArrangeFramesAndGetContentFromLeaf(
"b.test(%s)", {0}, EchoCookiesUrl(https_server(), kHostA)),
net::CookieStringIs(UnorderedElementsAre(
Key(kSamePartyLaxCookieName), Key(kSamePartyNoneCookieName),
Key(kSamePartyUnspecifiedCookieName))));
// Cross-site, same-party nested iframe (A embedded in B embedded in A) sends
// A's SameParty cookies.
EXPECT_THAT(
ArrangeFramesAndGetContentFromLeaf(
"a.test(b.test(%s))", {0, 0}, EchoCookiesUrl(https_server(), kHostA)),
net::CookieStringIs(UnorderedElementsAre(
Key(kSamePartyLaxCookieName), Key(kSamePartyNoneCookieName),
Key(kSamePartyUnspecifiedCookieName))));
// Cross-site, same-party nested iframe (A embedded in B embedded in C
// embedded in A) sends A's SameParty cookies.
EXPECT_THAT(ArrangeFramesAndGetContentFromLeaf(
"a.test(c.test(b.test(%s)))", {0, 0, 0},
EchoCookiesUrl(https_server(), kHostA)),
net::CookieStringIs(UnorderedElementsAre(
Key(kSamePartyLaxCookieName), Key(kSamePartyNoneCookieName),
Key(kSamePartyUnspecifiedCookieName))));
// Cross-site, cross-party iframe (D embedded in A) sends only D's
// SameSite=None cookie, since D is not in A's First-Party Set.
EXPECT_THAT(
ArrangeFramesAndGetContentFromLeaf(
"a.test(%s)", {0}, EchoCookiesUrl(https_server(), kHostD)),
net::CookieStringIs(UnorderedElementsAre(Key(kSamePartyNoneCookieName))));
// Cross-site, cross-party iframe (A embedded in D) doesn't send A's SameParty
// cookies.
EXPECT_EQ(ArrangeFramesAndGetContentFromLeaf(
"d.test(%s)", {0}, EchoCookiesUrl(https_server(), kHostA)),
"None");
// Cross-site, cross-party nested iframe (A embedded in B embedded in D)
// doesn't send A's SameParty cookies.
EXPECT_EQ(
ArrangeFramesAndGetContentFromLeaf(
"d.test(b.test(%s))", {0, 0}, EchoCookiesUrl(https_server(), kHostA)),
"None");
// No embedded frame. The top-level site has access to its cookies, regardless
// of whether the site is in an FPS, or whether the cookies are SameParty.
ASSERT_TRUE(NavigateToURL(
web_contents, https_server()->GetURL(kHostD, "/echoheader?Cookie")));
EXPECT_THAT(ExtractFrameContent(web_contents->GetMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSamePartyLaxCookieName), Key(kSamePartyNoneCookieName),
Key(kSamePartyUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SetSamePartyCookies) {
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
// No embedded frame, FPS member. The top-level FPS site can set its cookies.
ASSERT_TRUE(NavigateToURL(
web_contents, https_server()->GetURL(kHostA, kSetSamePartyCookiesURL)));
EXPECT_THAT(GetCanonicalCookies(web_contents->GetBrowserContext(),
https_server()->GetURL(kHostA, "/")),
UnorderedElementsAre(
net::MatchesCookieWithName(kSamePartyLaxCookieName),
net::MatchesCookieWithName(kSamePartyNoneCookieName),
net::MatchesCookieWithName(kSamePartyUnspecifiedCookieName)));
ASSERT_EQ(3U, ClearCookies());
// Same-site FPS-member iframe (A embedded in A) sets A's SameParty cookies.
EXPECT_THAT(ArrangeFramesAndGetCanonicalCookiesForLeaf(
"a.test(%s)", SetSamePartyCookiesUrl(https_server(), kHostA)),
UnorderedElementsAre(
net::MatchesCookieWithName(kSamePartyLaxCookieName),
net::MatchesCookieWithName(kSamePartyNoneCookieName),
net::MatchesCookieWithName(kSamePartyUnspecifiedCookieName)));
ASSERT_EQ(3U, ClearCookies());
// Cross-site, same-party iframe (A embedded in B) sets A's SameParty
// cookies.
EXPECT_THAT(ArrangeFramesAndGetCanonicalCookiesForLeaf(
"b.test(%s)", SetSamePartyCookiesUrl(https_server(), kHostA)),
UnorderedElementsAre(
net::MatchesCookieWithName(kSamePartyLaxCookieName),
net::MatchesCookieWithName(kSamePartyNoneCookieName),
net::MatchesCookieWithName(kSamePartyUnspecifiedCookieName)));
ASSERT_EQ(3U, ClearCookies());
// Cross-site, same-party nested iframe (A embedded in B embedded in A) sets
// A's SameParty cookies.
EXPECT_THAT(
ArrangeFramesAndGetCanonicalCookiesForLeaf(
"a.test(b.test(%s))", SetSamePartyCookiesUrl(https_server(), kHostA)),
UnorderedElementsAre(
net::MatchesCookieWithName(kSamePartyLaxCookieName),
net::MatchesCookieWithName(kSamePartyNoneCookieName),
net::MatchesCookieWithName(kSamePartyUnspecifiedCookieName)));
ASSERT_EQ(3U, ClearCookies());
// Cross-site, same-party nested iframe (A embedded in B embedded in C
// embedded in A) sets A's SameParty cookies.
EXPECT_THAT(ArrangeFramesAndGetCanonicalCookiesForLeaf(
"a.test(c.test(b.test(%s)))",
SetSamePartyCookiesUrl(https_server(), kHostA)),
UnorderedElementsAre(
net::MatchesCookieWithName(kSamePartyLaxCookieName),
net::MatchesCookieWithName(kSamePartyNoneCookieName),
net::MatchesCookieWithName(kSamePartyUnspecifiedCookieName)));
ASSERT_EQ(3U, ClearCookies());
// Cross-site, cross-party iframe (D embedded in A) sets D's SameSite=None
// cookie, since it's not an FPS member (and SameParty is ignored).
EXPECT_THAT(ArrangeFramesAndGetCanonicalCookiesForLeaf(
"a.test(%s)", SetSamePartyCookiesUrl(https_server(), kHostD)),
UnorderedElementsAre(
net::MatchesCookieWithName(kSamePartyNoneCookieName)));
ASSERT_EQ(1U, ClearCookies());
// Cross-site, cross-party iframe (A embedded in D) doesn't set A's SameParty
// cookies, since A is an FPS member and SameParty is not ignored..
EXPECT_THAT(ArrangeFramesAndGetCanonicalCookiesForLeaf(
"d.test(%s)", SetSamePartyCookiesUrl(https_server(), kHostA)),
IsEmpty());
ASSERT_EQ(0U, ClearCookies());
// Cross-site, cross-party nested iframe (A embedded in B embedded in D)
// doesn't set A's SameParty cookies.
EXPECT_THAT(
ArrangeFramesAndGetCanonicalCookiesForLeaf(
"d.test(b.test(%s))", SetSamePartyCookiesUrl(https_server(), kHostA)),
IsEmpty());
ASSERT_EQ(0U, ClearCookies());
// No embedded frame, non-FPS member. The top-level site can set its cookies.
ASSERT_TRUE(NavigateToURL(
web_contents, https_server()->GetURL(kHostD, kSetSamePartyCookiesURL)));
EXPECT_THAT(GetCanonicalCookies(web_contents->GetBrowserContext(),
https_server()->GetURL(kHostD, "/")),
UnorderedElementsAre(
net::MatchesCookieWithName(kSamePartyLaxCookieName),
net::MatchesCookieWithName(kSamePartyNoneCookieName),
net::MatchesCookieWithName(kSamePartyUnspecifiedCookieName)));
ASSERT_EQ(3U, ClearCookies());
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
ScriptNavigationSameSite404ScriptReload) {
EXPECT_THAT(
Test404ReloadCookie(/* is_user_initiated_navigation= */ false,
/* is_cross_site_navigation= */ false,
/* is_user_initiated_reload= */ false),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
ScriptNavigationSameSite404UserReload) {
EXPECT_THAT(
Test404ReloadCookie(/* is_user_initiated_navigation= */ false,
/* is_cross_site_navigation= */ false,
/* is_user_initiated_reload= */ true),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
ScriptNavigationCrossSite404ScriptReload) {
EXPECT_THAT(
Test404ReloadCookie(/* is_user_initiated_navigation= */ false,
/* is_cross_site_navigation= */ true,
/* is_user_initiated_reload= */ false),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
ScriptNavigationCrossSite404UserReload) {
EXPECT_THAT(Test404ReloadCookie(/* is_user_initiated_navigation= */ false,
/* is_cross_site_navigation= */ true,
/* is_user_initiated_reload= */ true),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteLaxCookieName), Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
UserNavigationSameSite404ScriptReload) {
EXPECT_THAT(
Test404ReloadCookie(/* is_user_initiated_navigation= */ true,
/* is_cross_site_navigation= */ false,
/* is_user_initiated_reload= */ false),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
UserNavigationSameSite404UserReload) {
EXPECT_THAT(
Test404ReloadCookie(/* is_user_initiated_navigation= */ true,
/* is_cross_site_navigation= */ false,
/* is_user_initiated_reload= */ true),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
UserNavigationCrossSite404ScriptReload) {
EXPECT_THAT(
Test404ReloadCookie(/* is_user_initiated_navigation= */ true,
/* is_cross_site_navigation= */ true,
/* is_user_initiated_reload= */ false),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
UserNavigationCrossSite404UserReload) {
EXPECT_THAT(
Test404ReloadCookie(/* is_user_initiated_navigation= */ true,
/* is_cross_site_navigation= */ true,
/* is_user_initiated_reload= */ true),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
INSTANTIATE_TEST_SUITE_P(/* no label */,
HttpCookieBrowserTest,
::testing::Bool());
} // namespace
} // namespace content