blob: a38ca44cd4a3f82ed12cbefa68fab26938739e78 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include "base/containers/contains.h"
#include "base/metrics/histogram_base.h"
#include "base/strings/strcat.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/cookie_deprecation_label/cookie_deprecation_label_test_utils.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_features.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_content_browser_client.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
namespace {
using ::net::test_server::EmbeddedTestServer;
constexpr char kSecCookieDeprecationHeaderStatus[] =
"Privacy.3PCD.SecCookieDeprecationHeaderStatus";
class CookieDeprecationLabelBrowserTestBase : public ContentBrowserTest {
public:
CookieDeprecationLabelBrowserTestBase() {
scoped_feature_list_.InitAndEnableFeature(
features::kCookieDeprecationFacilitatedTestingLabels);
}
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
}
WebContents* web_contents() { return shell()->web_contents(); }
protected:
void AddImageToDocument(const GURL& src_url) {
ASSERT_EQ(true,
EvalJs(shell(),
base::StrCat({"((() => { const img = "
"document.createElement('img'); img.src = '",
src_url.spec(), "'; return true; })())"})));
}
void FetchWithSecCookieDeprecationHeader(const GURL& url,
const std::string& header_value) {
ASSERT_EQ(true,
EvalJs(shell(),
base::StrCat({"((() => {"
"const headers = new Headers();"
"headers.append('Sec-Cookie-Deprecation', '",
header_value,
"');"
"fetch('",
url.spec(),
"', { headers });"
"return true; })())"})));
}
std::unique_ptr<net::EmbeddedTestServer> CreateTestServer(
net::test_server::EmbeddedTestServer::Type type) {
auto server = std::make_unique<net::EmbeddedTestServer>(type);
server->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
server->ServeFilesFromSourceDirectory("content/test/data");
return server;
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
class CookieDeprecationLabelDisabledBrowserTestBase
: public CookieDeprecationLabelBrowserTestBase {
protected:
void RunTest() {
base::HistogramTester histograms;
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
auto response_a_a =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_a");
auto response_a_b =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_b");
ASSERT_TRUE(https_server->Start());
ASSERT_TRUE(NavigateToURL(web_contents(),
https_server->GetURL("d.test", "/hello.html")));
AddImageToDocument(/*src_url=*/https_server->GetURL("a.test", "/a_a"));
// [a.test/a] - Non opted-in request should not receive a label header.
response_a_a->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_a->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_a =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_a->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response_a_a->AddCustomHeader(
"Location", https_server->GetURL("a.test", "/a_b").spec());
// a.test opts in to receiving the label.
http_response_a_a->AddCustomHeader(
"Set-Cookie",
"receive-cookie-deprecation=any-value; Secure; HttpOnly; "
"Path=/; SameSite=None; Partitioned");
response_a_a->Send(http_response_a_a->ToResponseString());
response_a_a->Done();
// [a.test/b] - Even if opted-in, the request should not receive a label
// header when the feature is disabled.
response_a_b->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_b->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_b =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_b->set_code(net::HTTP_OK);
response_a_b->Send(http_response_a_b->ToResponseString());
response_a_b->Done();
content::FetchHistogramsFromChildProcesses();
histograms.ExpectTotalCount(kSecCookieDeprecationHeaderStatus, 0);
}
base::test::ScopedFeatureList scoped_feature_list_;
};
class CookieDeprecationLabelDisabledBrowserTest
: public CookieDeprecationLabelDisabledBrowserTestBase {
public:
CookieDeprecationLabelDisabledBrowserTest() {
scoped_feature_list_.InitAndDisableFeature(
features::kCookieDeprecationFacilitatedTesting);
}
};
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelDisabledBrowserTest,
FeatureDisabled_CookieDeprecationLabelHeaderNotAdded) {
RunTest();
}
class CookieDeprecationLabelOnlyDisabledBrowserTest
: public CookieDeprecationLabelDisabledBrowserTestBase {
public:
CookieDeprecationLabelOnlyDisabledBrowserTest() {
scoped_feature_list_.InitWithFeaturesAndParameters(
/*enabled=*/{{features::kCookieDeprecationFacilitatedTesting,
{{"label", "label_test"}}}},
/*disabled=*/{features::kCookieDeprecationFacilitatedTestingLabels});
}
};
IN_PROC_BROWSER_TEST_F(
CookieDeprecationLabelOnlyDisabledBrowserTest,
LabelsFeatureDisabled_CookieDeprecationLabelHeaderNotAdded) {
RunTest();
}
class CookieDeprecationLabelEnabledBrowserTest
: public CookieDeprecationLabelBrowserTestBase {
public:
CookieDeprecationLabelEnabledBrowserTest() {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
features::kCookieDeprecationFacilitatedTesting,
{{"label", "label_test"}});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelEnabledBrowserTest,
HeaderAddedOnceOptedIn) {
base::HistogramTester histograms;
constexpr base::HistogramBase::Sample32 kNoCookie = 2;
constexpr base::HistogramBase::Sample32 kHeaderSet = 0;
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
auto response_a_a =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_a");
auto response_a_b =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_b");
auto response_a_c =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_c");
auto response_a_d =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_d");
auto response_a_e =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_e");
auto response_b_a =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/b_a");
ASSERT_TRUE(https_server->Start());
GURL initial_page_url = https_server->GetURL("d.test", "/hello.html");
ASSERT_TRUE(NavigateToURL(web_contents(), initial_page_url));
base::HistogramBase::Count32 no_cookie_requests = 0;
content::FetchHistogramsFromChildProcesses();
histograms.ExpectBucketCount(kSecCookieDeprecationHeaderStatus, kNoCookie,
++no_cookie_requests);
AddImageToDocument(/*src_url=*/https_server->GetURL("a.test", "/a_a"));
// [a.test/a] - Non opted-in request should not receive a label header.
response_a_a->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_a->http_request()->headers,
"Sec-Cookie-Deprecation"));
content::FetchHistogramsFromChildProcesses();
histograms.ExpectBucketCount(kSecCookieDeprecationHeaderStatus, kNoCookie,
++no_cookie_requests);
auto http_response_a_a =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_a->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response_a_a->AddCustomHeader(
"Location", https_server->GetURL("a.test", "/a_b").spec());
// a.test opts in to receiving the label.
http_response_a_a->AddCustomHeader(
"Set-Cookie",
"receive-cookie-deprecation=any-value; Secure; HttpOnly; "
"Path=/; SameSite=None; Partitioned");
response_a_a->Send(http_response_a_a->ToResponseString());
response_a_a->Done();
// [a.test/b] - Opted-in requests should receive a label header.
response_a_b->WaitForRequest();
ASSERT_TRUE(base::Contains(response_a_b->http_request()->headers,
"Sec-Cookie-Deprecation"));
base::HistogramBase::Count32 header_set_requests = 0;
content::FetchHistogramsFromChildProcesses();
histograms.ExpectBucketCount(kSecCookieDeprecationHeaderStatus, kHeaderSet,
++header_set_requests);
EXPECT_EQ(response_a_b->http_request()->headers.at("Sec-Cookie-Deprecation"),
"label_test");
auto http_response_a_b =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_b->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response_a_b->AddCustomHeader(
"Location", https_server->GetURL("b.test", "/b_a").spec());
response_a_b->Send(http_response_a_b->ToResponseString());
response_a_b->Done();
// [b.test/a] - Redirection request to non opted-in sites should not receive a
// label header.
response_b_a->WaitForRequest();
ASSERT_FALSE(base::Contains(response_b_a->http_request()->headers,
"Sec-Cookie-Deprecation"));
content::FetchHistogramsFromChildProcesses();
histograms.ExpectBucketCount(kSecCookieDeprecationHeaderStatus, kNoCookie,
++no_cookie_requests);
auto http_response_b_a =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_b_a->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response_b_a->AddCustomHeader(
"Location", https_server->GetURL("a.test", "/a_c").spec());
response_b_a->Send(http_response_b_a->ToResponseString());
response_b_a->Done();
// [a.test/c] - Redirection to an opted-in site following a non opted-in site
// should include the label header.
response_a_c->WaitForRequest();
ASSERT_TRUE(base::Contains(response_a_c->http_request()->headers,
"Sec-Cookie-Deprecation"));
content::FetchHistogramsFromChildProcesses();
histograms.ExpectBucketCount(kSecCookieDeprecationHeaderStatus, kHeaderSet,
++header_set_requests);
EXPECT_EQ(response_a_c->http_request()->headers.at("Sec-Cookie-Deprecation"),
"label_test");
auto http_response_a_c =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_c->set_code(net::HTTP_OK);
response_a_c->Send(http_response_a_c->ToResponseString());
response_a_c->Done();
// Make a second request from the same top level site
ASSERT_TRUE(NavigateToURL(web_contents(), initial_page_url));
AddImageToDocument(/*src_url=*/https_server->GetURL("a.test", "/a_d"));
// [a.test/d] - a.test was previously opted-in, it should receive the header.
response_a_d->WaitForRequest();
ASSERT_TRUE(base::Contains(response_a_d->http_request()->headers,
"Sec-Cookie-Deprecation"));
content::FetchHistogramsFromChildProcesses();
histograms.ExpectBucketCount(kSecCookieDeprecationHeaderStatus, kHeaderSet,
++header_set_requests);
EXPECT_EQ(response_a_d->http_request()->headers.at("Sec-Cookie-Deprecation"),
"label_test");
auto http_response_a_d =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_d->set_code(net::HTTP_OK);
response_a_d->Send(http_response_a_d->ToResponseString());
response_a_d->Done();
// Make a third requests from a different top level site
ASSERT_TRUE(NavigateToURL(web_contents(),
https_server->GetURL("a.test", "/hello.html")));
AddImageToDocument(/*src_url=*/https_server->GetURL("a.test", "/a_e"));
// [a.test/e] - a.test was previously opted-in but from the d.test top level
// site. Given the current top level site is now a.test, it
// should not receive the header.
response_a_e->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_e->http_request()->headers,
"Sec-Cookie-Deprecation"));
content::FetchHistogramsFromChildProcesses();
histograms.ExpectBucketCount(kSecCookieDeprecationHeaderStatus, kHeaderSet,
header_set_requests);
histograms.ExpectBucketCount(
kSecCookieDeprecationHeaderStatus, kNoCookie,
no_cookie_requests + 3); // 2 navigations and 1 image
auto http_response_a_e =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_e->set_code(net::HTTP_OK);
response_a_e->Send(http_response_a_e->ToResponseString());
response_a_e->Done();
}
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelEnabledBrowserTest,
HeaderCanOnlyBeSetViaOptInCookie) {
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
auto response_a_a =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_a");
auto response_a_b =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_b");
ASSERT_TRUE(https_server->Start());
GURL initial_page_url = https_server->GetURL("a.test", "/hello.html");
ASSERT_TRUE(NavigateToURL(web_contents(), initial_page_url));
FetchWithSecCookieDeprecationHeader(
/*url=*/https_server->GetURL("a.test", "/a_a"),
/*header_value=*/"not_label_test");
response_a_a->WaitForRequest();
// The header cannot be added unless it set using the opt-in cookie.
ASSERT_FALSE(base::Contains(response_a_a->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_a =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_a->set_code(net::HTTP_OK);
// a.test opts in to receiving the label.
http_response_a_a->AddCustomHeader(
"Set-Cookie",
"receive-cookie-deprecation=any-value; Secure; HttpOnly; "
"Path=/; SameSite=None; Partitioned");
response_a_a->Send(http_response_a_a->ToResponseString());
response_a_a->Done();
FetchWithSecCookieDeprecationHeader(
/*url=*/https_server->GetURL("a.test", "/a_b"),
/*header_value=*/"not_label_test");
response_a_b->WaitForRequest();
ASSERT_TRUE(base::Contains(response_a_b->http_request()->headers,
"Sec-Cookie-Deprecation"));
// The header value is the one configured for the feature not the value
// manually set on the request.
EXPECT_EQ(response_a_b->http_request()->headers.at("Sec-Cookie-Deprecation"),
"label_test");
auto http_response_a_b =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_b->set_code(net::HTTP_OK);
response_a_b->Send(http_response_a_b->ToResponseString());
response_a_b->Done();
}
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelEnabledBrowserTest,
OptedInRedirectChain_HeaderAdded) {
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
auto response_a_a =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_a");
auto response_a_b =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_b");
auto response_a_c =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_c");
ASSERT_TRUE(https_server->Start());
GURL initial_page_url = https_server->GetURL("d.test", "/hello.html");
ASSERT_TRUE(NavigateToURL(web_contents(), initial_page_url));
AddImageToDocument(/*src_url=*/https_server->GetURL("a.test", "/a_a"));
response_a_a->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_a->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_a =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_a->set_code(net::HTTP_MOVED_PERMANENTLY);
// Redirect without opting-in to receiving the label.
http_response_a_a->AddCustomHeader(
"Location", https_server->GetURL("a.test", "/a_b").spec());
response_a_a->Send(http_response_a_a->ToResponseString());
response_a_a->Done();
response_a_b->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_b->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_b =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_b->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response_a_b->AddCustomHeader(
"Location", https_server->GetURL("a.test", "/a_c").spec());
// Opt-in without specifying the Path
http_response_a_b->AddCustomHeader(
"Set-Cookie",
"receive-cookie-deprecation=any-value; Secure; HttpOnly; "
"SameSite=None; Partitioned");
response_a_b->Send(http_response_a_b->ToResponseString());
response_a_b->Done();
response_a_c->WaitForRequest();
ASSERT_TRUE(base::Contains(response_a_c->http_request()->headers,
"Sec-Cookie-Deprecation"));
EXPECT_EQ(response_a_c->http_request()->headers.at("Sec-Cookie-Deprecation"),
"label_test");
auto http_response_a_c =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_c->set_code(net::HTTP_OK);
response_a_c->Send(http_response_a_c->ToResponseString());
response_a_c->Done();
}
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelEnabledBrowserTest,
InvalidOptInCookie_HeaderNotAdded) {
const struct {
const char* description;
const char* header_value;
} kTestCases[] = {
{"Not Secure",
"receive-cookie-deprecation=any-value; HttpOnly; Path=/; SameSite=None; "
"Partitioned"},
{"Not HttpOnly",
"receive-cookie-deprecation=any-value; Secure; Path=/; SameSite=None; "
"Partitioned"},
{"Not Partitioned",
"receive-cookie-deprecation=any-value; Secure; HttpOnly; Path=/; "
"SameSite=None;"},
{"Default SameSite",
"receive-cookie-deprecation=any-value; HttpOnly; Path=/; Secure; "
"Partitioned"},
{"Non matching Path",
"receive-cookie-deprecation=any-value; Secure; HttpOnly; Secure; "
"Path=/non-matching; SameSite=None; Partitioned"},
};
for (const auto& test_case : kTestCases) {
SCOPED_TRACE(test_case.description);
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
auto response_a_a =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_a");
auto response_a_b =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_b");
ASSERT_TRUE(https_server->Start());
GURL initial_page_url = https_server->GetURL("d.test", "/hello.html");
ASSERT_TRUE(NavigateToURL(web_contents(), initial_page_url));
AddImageToDocument(/*src_url=*/https_server->GetURL("a.test", "/a_a"));
// [a.test/a] - Non opted-in request should not receive a label header.
response_a_a->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_a->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_a =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_a->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response_a_a->AddCustomHeader(
"Location", https_server->GetURL("a.test", "/a_b").spec());
// a.test opts in to receiving the label.
http_response_a_a->AddCustomHeader("Set-Cookie", test_case.header_value);
response_a_a->Send(http_response_a_a->ToResponseString());
response_a_a->Done();
// [a.test/b] - The request should not receive the header as the opt-in
// cookie was not valid.
response_a_b->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_b->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_b =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_b->set_code(net::HTTP_OK);
response_a_b->Send(http_response_a_b->ToResponseString());
response_a_b->Done();
}
}
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelEnabledBrowserTest,
RequestNotSecure_HeaderNotAdded) {
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
auto http_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTP);
auto response_a_a =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_a");
auto response_a_b =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_b");
auto response_a_c =
std::make_unique<net::test_server::ControllableHttpResponse>(
http_server.get(), "/a_c");
ASSERT_TRUE(http_server->Start());
ASSERT_TRUE(https_server->Start());
// Setup the cookie for a.test and confirm that we receive it over https.
ASSERT_TRUE(
NavigateToURL(shell(), https_server->GetURL("a.test", "/hello.html")));
AddImageToDocument(/*src_url=*/https_server->GetURL("a.test", "/a_a"));
response_a_a->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_a->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_a =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_a->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response_a_a->AddCustomHeader(
"Set-Cookie",
"receive-cookie-deprecation=any-value; Secure; HttpOnly; "
"Path=/; SameSite=None; Partitioned");
http_response_a_a->AddCustomHeader(
"Location", https_server->GetURL("a.test", "/a_b").spec());
response_a_a->Send(http_response_a_a->ToResponseString());
response_a_a->Done();
response_a_b->WaitForRequest();
ASSERT_TRUE(base::Contains(response_a_b->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_b =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_b->set_code(net::HTTP_OK);
response_a_b->Send(http_response_a_b->ToResponseString());
response_a_b->Done();
// Confirms that the header is not sent for a.test over http.
ASSERT_TRUE(
NavigateToURL(shell(), http_server->GetURL("a.test", "/hello.html")));
AddImageToDocument(/*src_url=*/http_server->GetURL("a.test", "/a_c"));
response_a_c->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_c->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_c =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_c->set_code(net::HTTP_OK);
response_a_c->Send(http_response_a_c->ToResponseString());
response_a_c->Done();
}
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelEnabledBrowserTest,
NotAllowed_EmptyLabelReturned) {
MockCookieDeprecationLabelContentBrowserClientBase<
ContentBrowserTestContentBrowserClient>
browser_client;
EXPECT_CALL(browser_client, IsCookieDeprecationLabelAllowedForContext)
.WillOnce(testing::Return(false));
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
ASSERT_TRUE(https_server->Start());
EXPECT_TRUE(
NavigateToURL(shell(), https_server->GetURL("a.test", "/hello.html")));
EXPECT_EQ(EvalJs(shell(), R"((async () => {
return await navigator.cookieDeprecationLabel.getValue();
})())"),
"");
}
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelEnabledBrowserTest,
Allowed_LabelReturned) {
MockCookieDeprecationLabelContentBrowserClientBase<
ContentBrowserTestContentBrowserClient>
browser_client;
EXPECT_CALL(browser_client, IsCookieDeprecationLabelAllowedForContext)
.WillOnce(testing::Return(true));
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
ASSERT_TRUE(https_server->Start());
EXPECT_TRUE(
NavigateToURL(shell(), https_server->GetURL("a.test", "/hello.html")));
EXPECT_EQ(EvalJs(shell(), R"((async () => {
return await navigator.cookieDeprecationLabel.getValue();
})())"),
"label_test");
}
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelEnabledBrowserTest,
OffTheRecord_EmptyLabelReturned) {
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
ASSERT_TRUE(https_server->Start());
auto* incognito_shell = CreateOffTheRecordBrowser();
EXPECT_TRUE(NavigateToURL(incognito_shell,
https_server->GetURL("a.test", "/hello.html")));
EXPECT_EQ(EvalJs(incognito_shell, R"((async () => {
return await navigator.cookieDeprecationLabel.getValue();
})())"),
"");
}
class CookieDeprecationLabelEnabledEmptyLabelBrowserTest
: public CookieDeprecationLabelBrowserTestBase {
public:
CookieDeprecationLabelEnabledEmptyLabelBrowserTest() {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
features::kCookieDeprecationFacilitatedTesting, {{"label", ""}});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelEnabledEmptyLabelBrowserTest,
EmptyLabel_CookieDeprecationLabelHeaderNotAdded) {
base::HistogramTester histograms;
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
auto response_a_a =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_a");
auto response_a_b =
std::make_unique<net::test_server::ControllableHttpResponse>(
https_server.get(), "/a_b");
ASSERT_TRUE(https_server->Start());
ASSERT_TRUE(NavigateToURL(web_contents(),
https_server->GetURL("d.test", "/hello.html")));
AddImageToDocument(/*src_url=*/https_server->GetURL("a.test", "/a_a"));
// [a.test/a] - Non opted-in request should not receive a label header.
response_a_a->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_a->http_request()->headers,
"Sec-Cookie-Deprecation"));
auto http_response_a_a =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_a->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response_a_a->AddCustomHeader(
"Location", https_server->GetURL("a.test", "/a_b").spec());
// a.test opts in to receiving the label.
http_response_a_a->AddCustomHeader(
"Set-Cookie",
"receive-cookie-deprecation=any-value; Secure; HttpOnly; "
"Path=/; SameSite=None; Partitioned");
response_a_a->Send(http_response_a_a->ToResponseString());
response_a_a->Done();
// [a.test/b] - Even if opted-in, the request should not receive a label
// header when the label is empty.
response_a_b->WaitForRequest();
ASSERT_FALSE(base::Contains(response_a_b->http_request()->headers,
"Sec-Cookie-Deprecation"));
// kNoLabel = 1
content::FetchHistogramsFromChildProcesses();
// This is a side effect of using an empty label "" as a sentinel value to
// indicate that the client is not eligible. When it is but the label is
// empty, it also records `kNoLabel`. 3 requests: nav, img & redirect
histograms.ExpectBucketCount(kSecCookieDeprecationHeaderStatus, 1, 3);
auto http_response_a_b =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response_a_b->set_code(net::HTTP_OK);
response_a_b->Send(http_response_a_b->ToResponseString());
response_a_b->Done();
}
class CookieDeprecationLabelOffTheRecordEnabledBrowserTest
: public CookieDeprecationLabelBrowserTestBase {
public:
CookieDeprecationLabelOffTheRecordEnabledBrowserTest() {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
features::kCookieDeprecationFacilitatedTesting,
{{"label", "label_test"}, {"enable_otr_profiles", "true"}});
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
// Ensure that cookie deprecation labels are present in incognito mode if the
// "enable_otr_profiles" feature parameter is true. See also the
// CookieDeprecationLabelEnabledBrowserTest.OffTheRecord_EmptyLabelReturned
// test.
IN_PROC_BROWSER_TEST_F(CookieDeprecationLabelOffTheRecordEnabledBrowserTest,
OffTheRecord_LabelReturned) {
auto https_server = CreateTestServer(EmbeddedTestServer::TYPE_HTTPS);
ASSERT_TRUE(https_server->Start());
auto* incognito_shell = CreateOffTheRecordBrowser();
EXPECT_TRUE(NavigateToURL(incognito_shell,
https_server->GetURL("a.test", "/hello.html")));
EXPECT_EQ(EvalJs(incognito_shell, R"((async () => {
return await navigator.cookieDeprecationLabel.getValue();
})())"),
"label_test");
}
} // namespace
} // namespace content