#include "base/strings/strcat.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/devtools/protocol/devtools_protocol_test_support.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.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/frame_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/url_loader_interceptor.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 "services/network/public/mojom/cookie_manager.mojom.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;
constexpr std::string_view kHostA = "a.test";
constexpr std::string_view kHostB = "b.test";
constexpr std::string_view kHostC = "c.test";
constexpr std::string_view kSameSiteNoneCookieName = "samesite_none_cookie";
constexpr std::string_view kSameSiteStrictCookieName = "samesite_strict_cookie";
constexpr std::string_view kSameSiteLaxCookieName = "samesite_lax_cookie";
constexpr std::string_view kSameSiteUnspecifiedCookieName =
"samesite_unspecified_cookie";
constexpr std::string_view kHostPrefixCookieName = "__Host-prefixed_cookie";
constexpr std::string_view kSecurePrefixCookieName = "__Secure-prefixed_cookie";
constexpr std::string_view kEchoCookiesWithCorsPath = "/echocookieswithcors";
std::string FrameTreeForHostAndUrl(std::string_view host, const GURL& url) {
return base::StrCat({host, "(", url.spec(), ")"});
}
std::string FrameTreeForUrl(const GURL& url) {
return FrameTreeForHostAndUrl(kHostA, url);
}
GURL RedirectUrl(net::EmbeddedTestServer* test_server,
std::string_view host,
const GURL& target_url) {
return test_server->GetURL(host, "/server-redirect?" + target_url.spec());
}
class HttpCookieBrowserTest : public ContentBrowserTest,
public ::testing::WithParamInterface<bool> {
public:
HttpCookieBrowserTest() : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
feature_list_.InitWithFeatureState(
net::features::kCookieSameSiteConsidersRedirectChain,
DoesSameSiteConsiderRedirectChain());
}
~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());
embedded_test_server()->AddDefaultHandlers(GetTestDataFilePath());
ASSERT_TRUE(https_server()->Start());
ASSERT_TRUE(embedded_test_server()->Start());
}
bool DoesSameSiteConsiderRedirectChain() { return GetParam(); }
const std::string kSetSameSiteCookiesPath = base::StrCat({
"/set-cookie?",
kSameSiteStrictCookieName,
"=1;SameSite=Strict&",
kSameSiteLaxCookieName,
"=1;SameSite=Lax&",
kSameSiteUnspecifiedCookieName,
"=1&",
kSameSiteNoneCookieName,
"=1;Secure;SameSite=None",
});
void SetSameSiteCookies(std::string_view 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"})));
}
std::string GetSetPrefixedCookiesPath(std::string_view host) {
return base::StrCat({
"/set-cookie?",
kSecurePrefixCookieName,
"=1;Secure&",
kHostPrefixCookieName,
"=1;Secure;Path=/&",
"__Secure-missing-attr=1&",
"__Host-wrong-path=1;Secure&",
"__Host-wrong-domain=1;Secure;Domain=",
host,
"&",
"__Host-wrong-secure=1;Path=/&",
});
}
void SetPrefixedCookies(std::string_view host,
net::EmbeddedTestServer* test_server = nullptr) {
if (!test_server) {
test_server = https_server();
}
BrowserContext* context = shell()->web_contents()->GetBrowserContext();
ASSERT_TRUE(
SetCookie(context, test_server->GetURL(host, "/"),
base::StrCat({kHostPrefixCookieName, "=1; Secure; Path=/"})));
ASSERT_TRUE(
SetCookie(context, test_server->GetURL(host, "/"),
base::StrCat({kSecurePrefixCookieName, "=1; Secure"})));
}
GURL EchoCookiesUrl(net::EmbeddedTestServer* test_server,
std::string_view host) {
return test_server->GetURL(host, "/echoheader?Cookie");
}
GURL SetSameSiteCookiesUrl(net::EmbeddedTestServer* test_server,
std::string_view host) {
return test_server->GetURL(host, kSetSameSiteCookiesPath);
}
std::string ExtractFrameContent(RenderFrameHost* frame) const {
return EvalJs(frame, "document.body.textContent").ExtractString();
}
uint32_t ClearCookies() {
return DeleteCookies(shell()->web_contents()->GetBrowserContext(),
network::mojom::CookieDeletionFilter());
}
net::EmbeddedTestServer* https_server() { return &https_server_; }
WebContents* web_contents() { return shell()->web_contents(); }
std::string Test404ReloadCookie(bool is_user_initiated_navigation,
bool is_cross_site_navigation,
bool is_user_initiated_reload) {
std::string_view target = is_cross_site_navigation ? kHostB : kHostA;
GURL target_URL =
https_server()->GetURL(target, "/echo-cookie-with-status?status=404");
SetSameSiteCookies(target);
EXPECT_TRUE(
NavigateToURL(web_contents(), EchoCookiesUrl(https_server(), kHostA)));
if (is_user_initiated_navigation) {
EXPECT_TRUE(NavigateToURL(web_contents(), target_URL));
} else {
EXPECT_TRUE(NavigateToURLFromRenderer(web_contents(), target_URL));
}
TestNavigationObserver nav_observer(web_contents());
if (is_user_initiated_reload) {
shell()->Reload();
} else {
ExecuteScriptAsync(
web_contents()->GetPrimaryMainFrame(),
content::JsReplace("window.location.reload($1);", true));
}
nav_observer.Wait();
return ExtractFrameContent(web_contents()->GetPrimaryMainFrame());
}
private:
net::test_server::EmbeddedTestServer https_server_;
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SendSameSiteCookies) {
SetSameSiteCookies(kHostA);
SetSameSiteCookies(kHostB);
ASSERT_TRUE(
NavigateToURL(web_contents(), EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
ASSERT_TRUE(
NavigateToURLFromRenderer(web_contents()->GetPrimaryMainFrame(),
EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
ASSERT_TRUE(
NavigateToURLFromRenderer(web_contents()->GetPrimaryMainFrame(),
EchoCookiesUrl(https_server(), kHostB)));
EXPECT_THAT(ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteLaxCookieName), Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
EXPECT_THAT(
content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(https_server(), kHostA)), {0}),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
EXPECT_THAT(
content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(https_server(), kHostB)), {0}),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SendSameSiteCookies_Redirect) {
SetSameSiteCookies(kHostA);
ASSERT_TRUE(NavigateToURL(
web_contents(),
RedirectUrl(https_server(), kHostA,
EchoCookiesUrl(https_server(), kHostA)),
EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
if (DoesSameSiteConsiderRedirectChain()) {
ASSERT_TRUE(NavigateToURL(
web_contents(),
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA)),
EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteLaxCookieName), Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
ASSERT_TRUE(NavigateToURL(
web_contents(),
RedirectUrl(https_server(), kHostA,
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA))),
EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteLaxCookieName), Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
} else {
ASSERT_TRUE(NavigateToURL(
web_contents(),
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA)),
EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
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))),
EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
}
EXPECT_THAT(
content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(RedirectUrl(https_server(), kHostA,
EchoCookiesUrl(https_server(), kHostA))),
{0}),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
if (DoesSameSiteConsiderRedirectChain()) {
EXPECT_THAT(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA))),
{0}),
net::CookieStringIs(
UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(RedirectUrl(
https_server(), kHostA,
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA)))),
{0}),
net::CookieStringIs(
UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
} else {
EXPECT_THAT(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA))),
{0}),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
EXPECT_THAT(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(
RedirectUrl(https_server(), kHostB,
EchoCookiesUrl(https_server(), kHostA))),
{0}),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
}
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SetSameSiteCookies) {
ASSERT_TRUE(NavigateToURL(
web_contents(), https_server()->GetURL(kHostA, kSetSameSiteCookiesPath)));
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());
const GURL url_a = SetSameSiteCookiesUrl(https_server(), kHostA);
EXPECT_THAT(content::ArrangeFramesAndGetCanonicalCookiesForLeaf(
web_contents(), https_server(), FrameTreeForUrl(url_a),
url::Origin::Create(url_a).GetURL()),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteStrictCookieName),
net::MatchesCookieWithName(kSameSiteLaxCookieName),
net::MatchesCookieWithName(kSameSiteNoneCookieName),
net::MatchesCookieWithName(kSameSiteUnspecifiedCookieName)));
ASSERT_EQ(4U, ClearCookies());
const GURL url_b = SetSameSiteCookiesUrl(https_server(), kHostB);
EXPECT_THAT(content::ArrangeFramesAndGetCanonicalCookiesForLeaf(
web_contents(), https_server(), FrameTreeForUrl(url_b),
url::Origin::Create(url_b).GetURL()),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteNoneCookieName)));
ASSERT_EQ(1U, ClearCookies());
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SetSameSiteCookies_Redirect) {
ASSERT_TRUE(NavigateToURL(
web_contents(),
RedirectUrl(https_server(), kHostA,
SetSameSiteCookiesUrl(https_server(), kHostA)),
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());
ASSERT_TRUE(NavigateToURL(
web_contents(),
RedirectUrl(https_server(), kHostB,
SetSameSiteCookiesUrl(https_server(), kHostA)),
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());
EXPECT_THAT(content::ArrangeFramesAndGetCanonicalCookiesForLeaf(
web_contents(), https_server(),
FrameTreeForUrl(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()) {
EXPECT_THAT(content::ArrangeFramesAndGetCanonicalCookiesForLeaf(
web_contents(), https_server(),
FrameTreeForUrl(RedirectUrl(
https_server(), kHostB,
SetSameSiteCookiesUrl(https_server(), kHostA))),
https_server()->GetURL(kHostA, "/")),
UnorderedElementsAre(
net::MatchesCookieWithName(kSameSiteNoneCookieName)));
ASSERT_EQ(1U, ClearCookies());
} else {
EXPECT_THAT(
content::ArrangeFramesAndGetCanonicalCookiesForLeaf(
web_contents(), https_server(),
FrameTreeForUrl(
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, SendPrefixedCookies) {
SetPrefixedCookies(kHostA);
ASSERT_TRUE(
NavigateToURL(web_contents(), EchoCookiesUrl(https_server(), kHostA)));
EXPECT_THAT(ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSecurePrefixCookieName), Key(kHostPrefixCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
SendPrefixedCookies_OmitsIfInsecure) {
SetPrefixedCookies(kHostA);
ASSERT_TRUE(NavigateToURL(web_contents(),
EchoCookiesUrl(embedded_test_server(), kHostA)));
EXPECT_THAT(ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(IsEmpty()));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SendPrefixedCookiesLocalhost) {
SetPrefixedCookies("localhost", embedded_test_server());
ASSERT_TRUE(NavigateToURL(
web_contents(), EchoCookiesUrl(embedded_test_server(), "localhost")));
EXPECT_THAT(ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(
Key(kSecurePrefixCookieName), Key(kHostPrefixCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest, SetPrefixedCookies) {
ASSERT_TRUE(NavigateToURL(
web_contents(),
https_server()->GetURL(kHostA, GetSetPrefixedCookiesPath(kHostA))));
EXPECT_THAT(GetCanonicalCookies(web_contents()->GetBrowserContext(),
https_server()->GetURL(kHostA, "/")),
UnorderedElementsAre(
net::MatchesCookieWithName(kHostPrefixCookieName),
net::MatchesCookieWithName(kSecurePrefixCookieName)));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
SetPrefixedCookies_DisallowedIfInsecure) {
ASSERT_TRUE(NavigateToURL(web_contents(),
embedded_test_server()->GetURL(
kHostA, GetSetPrefixedCookiesPath(kHostA))));
EXPECT_THAT(GetCanonicalCookies(web_contents()->GetBrowserContext(),
embedded_test_server()->GetURL(kHostA, "/")),
IsEmpty());
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
ScriptNavigationSameSite404ScriptReload) {
EXPECT_THAT(
Test404ReloadCookie( false,
false,
false),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
ScriptNavigationSameSite404UserReload) {
EXPECT_THAT(
Test404ReloadCookie( false,
false,
true),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
ScriptNavigationCrossSite404ScriptReload) {
EXPECT_THAT(
Test404ReloadCookie( false,
true,
false),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
ScriptNavigationCrossSite404UserReload) {
EXPECT_THAT(Test404ReloadCookie( false,
true,
true),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteLaxCookieName), Key(kSameSiteNoneCookieName),
Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
UserNavigationSameSite404ScriptReload) {
EXPECT_THAT(
Test404ReloadCookie( true,
false,
false),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
UserNavigationSameSite404UserReload) {
EXPECT_THAT(
Test404ReloadCookie( true,
false,
true),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
UserNavigationCrossSite404ScriptReload) {
EXPECT_THAT(
Test404ReloadCookie( true,
true,
false),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
IN_PROC_BROWSER_TEST_P(HttpCookieBrowserTest,
UserNavigationCrossSite404UserReload) {
EXPECT_THAT(
Test404ReloadCookie( true,
true,
true),
net::CookieStringIs(UnorderedElementsAre(
Key(kSameSiteStrictCookieName), Key(kSameSiteLaxCookieName),
Key(kSameSiteNoneCookieName), Key(kSameSiteUnspecifiedCookieName))));
}
std::unique_ptr<net::test_server::HttpResponse>
HandleEchoCookiesWithCorsRequest(const net::test_server::HttpRequest& request) {
if (request.relative_url != kEchoCookiesWithCorsPath) {
return nullptr;
}
auto http_response = std::make_unique<net::test_server::BasicHttpResponse>();
std::string content;
if (auto it = request.headers.find(net::HttpRequestHeaders::kCookie);
it != request.headers.end()) {
content = it->second;
}
http_response->set_code(net::HTTP_OK);
http_response->set_content_type("text/plain");
if (auto it = request.headers.find(net::HttpRequestHeaders::kOrigin);
it != request.headers.end()) {
http_response->AddCustomHeader("Access-Control-Allow-Headers",
"credentials");
http_response->AddCustomHeader("Access-Control-Allow-Origin", it->second);
http_response->AddCustomHeader("Origin", it->second);
http_response->AddCustomHeader("Vary", "Origin");
http_response->AddCustomHeader("Access-Control-Allow-Methods", "POST");
http_response->AddCustomHeader("Access-Control-Allow-Credentials", "true");
}
http_response->set_content(content);
return http_response;
}
class ThirdPartyCookiesHttpCookieBrowserTest : public ContentBrowserTest {
public:
ThirdPartyCookiesHttpCookieBrowserTest()
: https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
~ThirdPartyCookiesHttpCookieBrowserTest() 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());
https_server()->RegisterRequestHandler(
base::BindRepeating(&HandleEchoCookiesWithCorsRequest));
ASSERT_TRUE(https_server()->Start());
}
WebContents* web_contents() const { return shell()->web_contents(); }
net::EmbeddedTestServer* https_server() { return &https_server_; }
GURL EchoCookiesUrl(std::string_view host) {
return https_server()->GetURL(host, "/echoheader?Cookie");
}
std::string ExtractFrameContent(RenderFrameHost* frame) const {
return EvalJs(frame, "document.body.textContent").ExtractString();
}
std::string ExtractCookieFromDocument(RenderFrameHost* frame) const {
return EvalJs(frame, "document.cookie").ExtractString();
}
std::string PostWithCredentials(RenderFrameHost* frame, const GURL& url) {
constexpr char script[] = R"JS(
fetch($1, {method: 'POST', 'credentials' : 'include'}
).then((result) => result.text());
)JS";
return EvalJs(frame, JsReplace(script, url)).ExtractString();
}
EvalJsResult Fetch(RenderFrameHost* frame,
const GURL& url,
std::string_view mode,
std::string_view credentials) {
constexpr char script[] = R"JS(
fetch($1, {mode: $2, credentials: $3}).then(result => result.text());
)JS";
return EvalJs(frame, JsReplace(script, url, mode, credentials));
}
bool CookieStoreEmpty(RenderFrameHost* frame) {
constexpr char script[] = R"JS(
(async () => {
let cookies = await cookieStore.getAll();
return cookies.length == 0;
})();
)JS";
return EvalJs(frame, script).ExtractBool();
}
EvalJsResult NavigateToURLWithPOST(RenderFrameHost* frame,
std::string_view host) {
TestNavigationObserver observer(web_contents());
constexpr char script[] = R"JS(
let form = document.createElement('form');
form.setAttribute('method', 'POST');
form.setAttribute('action', $1);
document.body.appendChild(form);
form.submit();
)JS";
EvalJsResult result =
EvalJs(frame, JsReplace(script, EchoCookiesUrl(host)));
observer.WaitForNavigationFinished();
EXPECT_TRUE(WaitForLoadStop(web_contents()));
return result;
}
EvalJsResult ReadCookiesViaFetchWithRedirect(
RenderFrameHost* frame,
std::string_view intermediate_host,
std::string_view destination_host) {
constexpr char script[] = "fetch($1).then((result) => result.text());";
GURL redirect_url = RedirectUrl(https_server(), intermediate_host,
EchoCookiesUrl(destination_host));
return EvalJs(frame, JsReplace(script, redirect_url));
}
private:
net::test_server::EmbeddedTestServer https_server_;
};
class ThirdPartyCookiesBlockedHttpCookieBrowserTest
: public ThirdPartyCookiesHttpCookieBrowserTest {
public:
ThirdPartyCookiesBlockedHttpCookieBrowserTest() {
feature_list_.InitWithFeatures(
{
net::features::kForceThirdPartyCookieBlocking,
},
{});
}
~ThirdPartyCookiesBlockedHttpCookieBrowserTest() override = default;
private:
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
SameSiteNoneCookieNavigateCrossSiteEmbedToSameSiteUrl) {
ASSERT_TRUE(base::FeatureList::IsEnabled(
net::features::kForceThirdPartyCookieBlocking));
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat({kSameSiteNoneCookieName, "=1;Secure;SameSite=None;"})));
EXPECT_THAT(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(kHostB)), {0}),
net::CookieStringIs(UnorderedElementsAre()));
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
EchoCookiesUrl(kHostA)));
EXPECT_THAT(
ExtractFrameContent(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
SameSiteNoneCookieCrossSitePostRequest) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostB, "/"),
base::StrCat({kSameSiteNoneCookieName, "=1;Secure;SameSite=None;"})));
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostB)));
ASSERT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostA)));
EXPECT_THAT(PostWithCredentials(
web_contents()->GetPrimaryMainFrame(),
https_server()->GetURL(kHostB, kEchoCookiesWithCorsPath)),
"");
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
SameSiteNoneCookieCrossSiteSubresourceNavigationPost) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostB, "/"),
base::StrCat({kSameSiteNoneCookieName, "=1;Secure;SameSite=None;"})));
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostB)));
ASSERT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostA)));
ASSERT_TRUE(
NavigateToURLWithPOST(web_contents()->GetPrimaryMainFrame(), kHostB)
.is_ok());
EXPECT_THAT(web_contents()->GetLastCommittedURL().GetHost(), kHostB);
EXPECT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
RedirectCrossSiteSubresourceToSameSiteUrl) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat({kSameSiteNoneCookieName, "=1;Secure;SameSite=None;"})));
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostA)));
ASSERT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_EQ(ReadCookiesViaFetchWithRedirect(
web_contents()->GetPrimaryMainFrame(), kHostB, kHostA),
"None");
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
SameSiteNoneCookieBlockedOnABEmbeddedIframe) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat({kSameSiteNoneCookieName, "=1;Secure;SameSite=None;"})));
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostA)));
ASSERT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
ASSERT_THAT(
ExtractCookieFromDocument(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
ASSERT_TRUE(
GetCookies(web_contents()->GetBrowserContext(), EchoCookiesUrl(kHostA))
.starts_with(kSameSiteNoneCookieName));
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostB)));
EXPECT_THAT(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForHostAndUrl(kHostB, EchoCookiesUrl(kHostA)), {0}),
"None");
EXPECT_TRUE(ExtractCookieFromDocument(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0))
.empty());
EXPECT_TRUE(
CookieStoreEmpty(ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)));
}
IN_PROC_BROWSER_TEST_F(
ThirdPartyCookiesBlockedHttpCookieBrowserTest,
SameSiteNoneCookieBlockedInCrossSiteFetchRequestFromTopLevelFrame) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat({kSameSiteNoneCookieName, "=1;Secure;SameSite=None;"})));
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostA)));
ASSERT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostB)));
EXPECT_THAT(Fetch(web_contents()->GetPrimaryMainFrame(),
https_server()->GetURL(kHostA, kEchoCookiesWithCorsPath),
"cors", "include")
.ExtractString(),
net::CookieStringIs(IsEmpty()));
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
TestCrossSitePartitionKeyNotAvailable) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat(
{kSameSiteNoneCookieName, "=1;Secure;SameSite=None;Partitioned"}),
net::CookieOptions::SameSiteCookieContext::MakeInclusive(),
net::CookiePartitionKey::FromURLForTesting(
https_server()->GetURL(kHostA, "/"),
net::CookiePartitionKey::AncestorChainBit::kSameSite)));
ASSERT_EQ(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(kHostB)), {0}),
"None");
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
EchoCookiesUrl(kHostA)));
EXPECT_THAT(
ExtractFrameContent(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(
ExtractCookieFromDocument(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
TestSubresourceRedirects) {
ASSERT_EQ(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(kHostB)), {0}),
"None");
net::CookiePartitionKey partition_key =
net::CookiePartitionKey::FromURLForTesting(
https_server()->GetURL(kHostA, "/"),
net::CookiePartitionKey::AncestorChainBit::kCrossSite);
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostC, "/"),
base::StrCat(
{kSameSiteNoneCookieName, "=1;Secure;SameSite=None;partitioned"}),
net::CookieOptions::SameSiteCookieContext(
net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE),
partition_key));
std::vector<net::CanonicalCookie> cookies = GetCanonicalCookies(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostC, "/"),
net::CookiePartitionKeyCollection(partition_key));
ASSERT_EQ(cookies.size(), 1u);
ASSERT_TRUE(cookies[0].IsPartitioned());
ASSERT_TRUE(cookies[0].PartitionKey()->IsThirdParty());
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
EchoCookiesUrl(kHostC)));
EXPECT_THAT(
ExtractFrameContent(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(
ExtractCookieFromDocument(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
TestTopLevelRedirects) {
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostA)));
ASSERT_THAT(ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
"None");
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat(
{kSameSiteNoneCookieName, "=1;Secure;SameSite=None;partitioned"}),
net::CookieOptions::SameSiteCookieContext::MakeInclusive(),
net::CookiePartitionKey::FromURLForTesting(
https_server()->GetURL(kHostA, "/"),
net::CookiePartitionKey::AncestorChainBit::kSameSite)));
ASSERT_TRUE(
NavigateToURL(web_contents(),
RedirectUrl(https_server(), kHostB, EchoCookiesUrl(kHostA)),
EchoCookiesUrl(kHostA)));
EXPECT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(
ExtractCookieFromDocument(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_F(
ThirdPartyCookiesBlockedHttpCookieBrowserTest,
TestSameSiteEmbeddedResourceToCrossSiteEmbeddedResource) {
ASSERT_EQ(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(kHostA)), {0}),
"None");
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostB, "/"),
base::StrCat(
{kSameSiteNoneCookieName, "=1;Secure;SameSite=None;Partitioned"}),
net::CookieOptions::SameSiteCookieContext::MakeInclusive(),
net::CookiePartitionKey::FromURLForTesting(
https_server()->GetURL(kHostA, "/"),
net::CookiePartitionKey::AncestorChainBit::kCrossSite)));
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
EchoCookiesUrl(kHostB)));
EXPECT_THAT(
ExtractFrameContent(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(
ExtractCookieFromDocument(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
CrossSiteToSameSiteIframeRedirects) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat(
{kSameSiteNoneCookieName, "=1;Secure;SameSite=None;Partitioned"}),
net::CookieOptions::SameSiteCookieContext::MakeInclusive(),
net::CookiePartitionKey::FromURLForTesting(
https_server()->GetURL(kHostA, "/"),
net::CookiePartitionKey::AncestorChainBit::kSameSite)));
ASSERT_EQ(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(kHostA)), {0}),
"samesite_none_cookie=1");
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
RedirectUrl(https_server(), kHostB, EchoCookiesUrl(kHostA)),
EchoCookiesUrl(kHostA)));
EXPECT_THAT(
ExtractFrameContent(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(
ExtractCookieFromDocument(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
RedirectCrossSiteThroughSameSiteIframe) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat(
{kSameSiteNoneCookieName, "=1;Secure;SameSite=None;Partitioned"}),
net::CookieOptions::SameSiteCookieContext::MakeInclusive(),
net::CookiePartitionKey::FromURLForTesting(
https_server()->GetURL(kHostA, "/"),
net::CookiePartitionKey::AncestorChainBit::kSameSite)));
ASSERT_EQ(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(kHostA)), {0}),
"samesite_none_cookie=1");
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
RedirectUrl(https_server(), kHostB,
RedirectUrl(https_server(), kHostA, EchoCookiesUrl(kHostA))),
EchoCookiesUrl(kHostA)));
EXPECT_THAT(
ExtractFrameContent(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(
ExtractCookieFromDocument(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
RedirectTwoCrossSitesThroughSameSiteIframe) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat(
{kSameSiteNoneCookieName, "=1;Secure;SameSite=None;Partitioned"}),
net::CookieOptions::SameSiteCookieContext::MakeInclusive(),
net::CookiePartitionKey::FromURLForTesting(
https_server()->GetURL(kHostA, "/"),
net::CookiePartitionKey::AncestorChainBit::kSameSite)));
ASSERT_EQ(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(kHostA)), {0}),
"samesite_none_cookie=1");
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
RedirectUrl(https_server(), kHostB,
RedirectUrl(https_server(), kHostC,
RedirectUrl(https_server(), kHostA,
EchoCookiesUrl(kHostA)))),
EchoCookiesUrl(kHostA)));
EXPECT_THAT(
ExtractFrameContent(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(
ExtractCookieFromDocument(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_F(
ThirdPartyCookiesBlockedHttpCookieBrowserTest,
RedirectCrossSiteIframeToSameSiteThenNavigateToSameSite) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat(
{kSameSiteNoneCookieName, "=1;Secure;SameSite=None;Partitioned"}),
net::CookieOptions::SameSiteCookieContext::MakeInclusive(),
net::CookiePartitionKey::FromURLForTesting(
https_server()->GetURL(kHostA, "/"),
net::CookiePartitionKey::AncestorChainBit::kSameSite)));
ASSERT_EQ(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(kHostA)), {0}),
"samesite_none_cookie=1");
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
RedirectUrl(https_server(), kHostB, EchoCookiesUrl(kHostA)),
EchoCookiesUrl(kHostA)));
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
EchoCookiesUrl(kHostA)));
EXPECT_THAT(
ExtractFrameContent(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(
ExtractCookieFromDocument(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
IN_PROC_BROWSER_TEST_F(ThirdPartyCookiesBlockedHttpCookieBrowserTest,
CrossSiteToSameSiteIframeNavigation) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat(
{kSameSiteNoneCookieName, "=1;Secure;SameSite=None;Partitioned"}),
net::CookieOptions::SameSiteCookieContext::MakeInclusive(),
net::CookiePartitionKey::FromURLForTesting(
https_server()->GetURL(kHostA, "/"),
net::CookiePartitionKey::AncestorChainBit::kSameSite)));
ASSERT_EQ(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForUrl(EchoCookiesUrl(kHostA)), {0}),
"samesite_none_cookie=1");
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
EchoCookiesUrl(kHostB)));
ASSERT_TRUE(NavigateToURLFromRenderer(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0),
EchoCookiesUrl(kHostA)));
EXPECT_THAT(
ExtractFrameContent(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(
ExtractCookieFromDocument(
ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0)),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
class DevToolsOverridesThirdPartyCookiesBrowserTest
: public ThirdPartyCookiesHttpCookieBrowserTest {
public:
DevToolsOverridesThirdPartyCookiesBrowserTest() = default;
~DevToolsOverridesThirdPartyCookiesBrowserTest() override = default;
void SetUpOnMainThread() override {
ThirdPartyCookiesHttpCookieBrowserTest::SetUpOnMainThread();
web_contents_devtools_client.AttachToWebContents(shell()->web_contents());
web_contents_devtools_client.SendCommandAsync("Network.enable");
}
void TearDownOnMainThread() override {
web_contents_devtools_client.DetachProtocolClient();
frame_devtools_client.DetachProtocolClient();
}
protected:
void NavigateToPageWith3pIFrame(std::string_view host) {
frame_devtools_client.DetachProtocolClient();
GURL main_url(https_server()->GetURL(host, "/page_with_blank_iframe.html"));
ASSERT_TRUE(content::NavigateToURL(web_contents(), main_url));
EXPECT_TRUE(
NavigateIframeToURL(web_contents(), "test_iframe",
https_server()->GetURL(kHostB, "/empty.html")));
frame_devtools_client.AttachToFrameTreeHost(GetFrame());
frame_devtools_client.SendCommandSync("Network.enable");
}
content::RenderFrameHost* GetFrame() {
return ChildFrameAt(web_contents()->GetPrimaryMainFrame(), 0);
}
std::string SetCookieFromJS(content::RenderFrameHost* render_frame_host,
std::string cookie) {
content::EvalJsResult result = content::EvalJs(
render_frame_host,
"document.cookie = '" + cookie + "; SameSite=None; Secure'",
content::EXECUTE_SCRIPT_NO_USER_GESTURE);
return result.ExtractString();
}
std::string ReadCookiesFromJS(content::RenderFrameHost* render_frame_host) {
std::string res = content::EvalJs(render_frame_host, "document.cookie",
content::EXECUTE_SCRIPT_NO_USER_GESTURE)
.ExtractString();
return res;
}
void SendSetCookieControls(bool enable_third_party_cookie_restriction,
bool disable_third_party_cookie_metadata,
bool disable_third_party_cookie_heuristics) {
base::Value::Dict command_params;
web_contents_devtools_client.SendCommandSync("Network.enable");
command_params.Set("enableThirdPartyCookieRestriction",
enable_third_party_cookie_restriction);
command_params.Set("disableThirdPartyCookieMetadata",
disable_third_party_cookie_metadata);
command_params.Set("disableThirdPartyCookieHeuristics",
disable_third_party_cookie_heuristics);
web_contents_devtools_client.SendCommandSync("Network.setCookieControls",
std::move(command_params));
}
content::TestDevToolsProtocolClient web_contents_devtools_client;
content::TestDevToolsProtocolClient frame_devtools_client;
};
IN_PROC_BROWSER_TEST_F(DevToolsOverridesThirdPartyCookiesBrowserTest,
DevToolsForceDisableTPCFromJS) {
NavigateToPageWith3pIFrame(kHostA);
SetCookieFromJS(GetFrame(), "cookieAllowed=true");
EXPECT_EQ(ReadCookiesFromJS(GetFrame()), "cookieAllowed=true");
SendSetCookieControls(true,
false,
false);
NavigateToPageWith3pIFrame("a.test");
SetCookieFromJS(GetFrame(), "cookieAllowed=false");
EXPECT_EQ(ReadCookiesFromJS(GetFrame()), "");
frame_devtools_client.SendCommandSync("Network.disable");
web_contents_devtools_client.SendCommandSync("Network.disable");
EXPECT_EQ(ReadCookiesFromJS(GetFrame()), "cookieAllowed=true");
}
IN_PROC_BROWSER_TEST_F(DevToolsOverridesThirdPartyCookiesBrowserTest,
DevToolsForceDisableTPC) {
ASSERT_TRUE(SetCookie(
web_contents()->GetBrowserContext(), https_server()->GetURL(kHostA, "/"),
base::StrCat({kSameSiteNoneCookieName, "=1;Secure;SameSite=None;"})));
ASSERT_TRUE(NavigateToURL(web_contents(), EchoCookiesUrl(kHostA)));
ASSERT_THAT(
ExtractFrameContent(web_contents()->GetPrimaryMainFrame()),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
ASSERT_THAT(
content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForHostAndUrl(kHostB, EchoCookiesUrl(kHostA)), {0}),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
SendSetCookieControls(true,
false,
false);
EXPECT_THAT(content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForHostAndUrl(kHostB, EchoCookiesUrl(kHostA)), {0}),
"None");
EXPECT_THAT(Fetch(web_contents()->GetPrimaryMainFrame(),
https_server()->GetURL(kHostA, kEchoCookiesWithCorsPath),
"cors", "include")
.ExtractString(),
net::CookieStringIs(IsEmpty()));
web_contents_devtools_client.SendCommandAsync("Network.disable");
EXPECT_THAT(
content::ArrangeFramesAndGetContentFromLeaf(
web_contents(), https_server(),
FrameTreeForHostAndUrl(kHostB, EchoCookiesUrl(kHostA)), {0}),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
EXPECT_THAT(
Fetch(web_contents()->GetPrimaryMainFrame(),
https_server()->GetURL(kHostA, kEchoCookiesWithCorsPath), "cors",
"include")
.ExtractString(),
net::CookieStringIs(UnorderedElementsAre(Key(kSameSiteNoneCookieName))));
}
INSTANTIATE_TEST_SUITE_P(,
HttpCookieBrowserTest,
::testing::Bool());
}
}