#include <vector>
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_switches.h"
#include "base/barrier_callback.h"
#include "base/barrier_closure.h"
#include "base/check_deref.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/enum_set.h"
#include "base/notreached.h"
#include "base/test/bind.h"
#include "base/test/run_until.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "chrome/browser/ash/floating_sso/cookie_sync_conversions.h"
#include "chrome/browser/ash/floating_sso/cookie_sync_test_util.h"
#include "chrome/browser/ash/floating_sso/floating_sso_service.h"
#include "chrome/browser/ash/floating_sso/floating_sso_service_factory.h"
#include "chrome/browser/ash/floating_sso/floating_sso_sync_bridge.h"
#include "chrome/browser/ash/floating_workspace/floating_workspace_util.h"
#include "chrome/browser/policy/policy_test_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/keyed_service/core/dependency_graph.h"
#include "components/keyed_service/core/keyed_service_base_factory.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "components/sync/base/pref_names.h"
#include "components/sync/model/entity_change.h"
#include "components/sync/protocol/cookie_specifics.pb.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/browser_test.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_util.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
namespace ash::floating_sso {
namespace {
using testing::_;
constexpr char kPersistentCookieLine[] = "CookieName=CookieValue; max-age=3600";
constexpr char kSessionCookieLine[] = "CookieName=CookieValue";
constexpr char kCookieName[] = "CookieName";
constexpr char kCookieUniqueKey[] = "trueCookieNameexample.com/28888";
class CookieChangeListener : public network::mojom::CookieChangeListener {
public:
CookieChangeListener(
network::mojom::CookieManager* cookie_manager,
base::RepeatingCallback<void(const net::CookieChangeInfo&)> callback)
: callback_(std::move(callback)), receiver_(this) {
cookie_manager->AddGlobalChangeListener(
receiver_.BindNewPipeAndPassRemote());
}
CookieChangeListener(
network::mojom::CookieManager* cookie_manager,
const GURL& url,
base::RepeatingCallback<void(const net::CookieChangeInfo&)> callback)
: callback_(std::move(callback)), receiver_(this) {
cookie_manager->AddCookieChangeListener(
url, std::nullopt, receiver_.BindNewPipeAndPassRemote());
}
void OnCookieChange(const net::CookieChangeInfo& change) override {
callback_.Run(change);
}
private:
base::RepeatingCallback<void(const net::CookieChangeInfo&)> callback_;
mojo::Receiver<network::mojom::CookieChangeListener> receiver_;
};
std::optional<net::CanonicalCookie> GetCookie(
network::mojom::CookieManager* cookie_manager,
const std::string& name) {
base::test::TestFuture<const std::vector<net::CanonicalCookie>&> future;
cookie_manager->GetAllCookies(future.GetCallback());
for (const net::CanonicalCookie& cookie : future.Take()) {
if (cookie.Name() == name) {
return std::make_optional<net::CanonicalCookie>(cookie);
}
}
return std::nullopt;
}
bool SetCookie(network::mojom::CookieManager* cookie_manager,
const GURL& url,
const net::CanonicalCookie& cookie) {
base::test::TestFuture<net::CookieAccessResult> future;
cookie_manager->SetCanonicalCookie(cookie, url,
net::CookieOptions::MakeAllInclusive(),
future.GetCallback());
return future.Take().status.IsInclude();
}
bool SetCookie(network::mojom::CookieManager* cookie_manager,
const net::CanonicalCookie& cookie) {
GURL url = net::cookie_util::SimulatedCookieSource(cookie, "https");
return SetCookie(cookie_manager, url, cookie);
}
bool SetCookie(network::mojom::CookieManager* cookie_manager,
const GURL& url,
const std::string& cookie_line) {
auto cookie = net::CanonicalCookie::CreateForTesting(
url, cookie_line, base::Time::Now(),
std::nullopt,
std::nullopt, net::CookieSourceType::kHTTP);
return SetCookie(cookie_manager, url, *cookie);
}
uint32_t DeleteCookies(network::mojom::CookieManager* cookie_manager,
network::mojom::CookieDeletionFilter filter) {
base::test::TestFuture<uint32_t> future;
cookie_manager->DeleteCookies(
network::mojom::CookieDeletionFilter::New(filter), future.GetCallback());
return future.Get();
}
}
class FloatingSsoTest : public policy::PolicyTest {
public:
FloatingSsoTest() {
feature_list_.InitAndEnableFeature(ash::features::kFloatingSso);
}
~FloatingSsoTest() override = default;
void SetUpOnMainThread() override {
network::mojom::NetworkContext* network_context =
profile()->GetDefaultStoragePartition()->GetNetworkContext();
network_context->GetCookieManager(
cookie_manager_.BindNewPipeAndPassReceiver());
}
protected:
void SetFloatingSsoEnabledPolicy(bool policy_value) {
policy::PolicyTest::SetPolicy(&policies_, policy::key::kFloatingSsoEnabled,
base::Value(policy_value));
provider_.UpdateChromePolicy(policies_);
}
void SetFloatingWorkspacePolicy(bool policy_value) {
policy::PolicyTest::SetPolicy(&policies_,
policy::key::kFloatingWorkspaceV2Enabled,
base::Value(policy_value));
provider_.UpdateChromePolicy(policies_);
ASSERT_EQ(ash::floating_workspace_util::IsFloatingWorkspaceV2Enabled(),
policy_value);
}
void SetSyncEverythingPref(bool pref_value) {
profile()->GetPrefs()->SetBoolean(
syncer::prefs::internal::kSyncKeepEverythingSynced, pref_value);
}
void SetSyncCookiesPref(bool pref_value) {
profile()->GetPrefs()->SetBoolean(syncer::prefs::internal::kSyncCookies,
pref_value);
}
void SetSyncDisabledPolicy(bool policy_value) {
policy::PolicyTest::SetPolicy(&policies_, policy::key::kSyncDisabled,
base::Value(policy_value));
provider_.UpdateChromePolicy(policies_);
}
void SetFloatingSsoDomainBlocklistPolicy(const std::string& domain) {
base::Value::List domains;
domains.Append(domain);
policy::PolicyTest::SetPolicy(&policies_,
policy::key::kFloatingSsoDomainBlocklist,
base::Value(std::move(domains)));
provider_.UpdateChromePolicy(policies_);
}
void SetFloatingSsoDomainBlocklistExceptionsPolicy(
const std::string& domain) {
base::Value::List domains;
if (!domain.empty()) {
domains.Append(domain);
}
policy::PolicyTest::SetPolicy(
&policies_, policy::key::kFloatingSsoDomainBlocklistExceptions,
base::Value(std::move(domains)));
provider_.UpdateChromePolicy(policies_);
}
void SetFloatingSsoSessionCookiesIncludedPolicy(bool policy_value) {
policy::PolicyTest::SetPolicy(
&policies_, policy::key::kFloatingSsoSessionCookiesIncluded,
base::Value(policy_value));
provider_.UpdateChromePolicy(policies_);
}
void EnableAllFloatingSsoSettings() {
SetFloatingSsoEnabledPolicy(true);
SetSyncCookiesPref(true);
SetSyncDisabledPolicy(false);
}
bool IsFloatingSsoServiceRegistered() {
std::vector<raw_ptr<DependencyNode, VectorExperimental>> nodes;
const bool success = BrowserContextDependencyManager::GetInstance()
->GetDependencyGraphForTesting()
.GetConstructionOrder(&nodes);
EXPECT_TRUE(success);
return base::Contains(
nodes, "FloatingSsoService",
[](const DependencyNode* node) -> std::string_view {
return static_cast<const KeyedServiceBaseFactory*>(node)->name();
});
}
bool IsFloatingSsoSessionCookiesIncludedPolicyManaged() {
const PrefService::Preference* floating_sso_session_cookies_pref =
profile()->GetPrefs()->FindPreference(
::prefs::kFloatingSsoSessionCookiesIncluded);
return CHECK_DEREF(floating_sso_session_cookies_pref).IsManaged();
}
Profile* profile() { return browser()->profile(); }
FloatingSsoService& floating_sso_service() {
return CHECK_DEREF(FloatingSsoServiceFactory::GetForProfile(profile()));
}
network::mojom::CookieManager* cookie_manager() {
return cookie_manager_.get();
}
const FloatingSsoSyncBridge::CookieSpecificsEntries& GetStoreEntries() {
return floating_sso_service()
.GetBridgeForTesting()
->CookieSpecificsInStore();
}
void AddCookieAndWaitForCommit(network::mojom::CookieManager* cookie_manager,
const GURL& url,
const std::string& cookie_line) {
base::test::TestFuture<void> commit_future;
floating_sso_service()
.GetBridgeForTesting()
->SetOnStoreCommitCallbackForTest(commit_future.GetRepeatingCallback());
base::test::TestFuture<const net::CookieChangeInfo&> cookie_change_future;
CookieChangeListener listener(cookie_manager, url,
cookie_change_future.GetRepeatingCallback());
ASSERT_TRUE(SetCookie(cookie_manager, url, cookie_line));
EXPECT_EQ(cookie_change_future.Take().cause,
net::CookieChangeCause::INSERTED);
commit_future.Get();
}
void DeleteCookieAndWaitForCommit(
network::mojom::CookieManager* cookie_manager,
const GURL& url,
const std::string& cookie_name) {
base::test::TestFuture<void> commit_future;
floating_sso_service()
.GetBridgeForTesting()
->SetOnStoreCommitCallbackForTest(commit_future.GetRepeatingCallback());
base::test::TestFuture<const net::CookieChangeInfo&> cookie_change_future;
CookieChangeListener listener(cookie_manager, url,
cookie_change_future.GetRepeatingCallback());
network::mojom::CookieDeletionFilter filter;
filter.cookie_name = cookie_name;
ASSERT_EQ(DeleteCookies(cookie_manager, filter), 1u);
EXPECT_EQ(cookie_change_future.Take().cause,
net::CookieChangeCause::EXPLICIT);
commit_future.Get();
}
void UpdateCookieAndWaitForCommit(
network::mojom::CookieManager* cookie_manager,
const GURL& url,
const std::string& cookie_name) {
base::test::TestFuture<void> commit_future;
floating_sso_service()
.GetBridgeForTesting()
->SetOnStoreCommitCallbackForTest(base::BarrierClosure(
2, commit_future.GetRepeatingCallback()));
base::test::TestFuture<std::vector<net::CookieChangeInfo>>
cookie_change_future;
CookieChangeListener listener(
cookie_manager, url,
base::BarrierCallback<const net::CookieChangeInfo&>(
2, cookie_change_future.GetRepeatingCallback()));
auto cookie = GetCookie(cookie_manager, cookie_name);
ASSERT_TRUE(cookie.has_value());
cookie.value().SetLastAccessDate(base::Time::Now());
cookie_manager->SetCanonicalCookie(*cookie, url,
net::CookieOptions::MakeAllInclusive(),
base::DoNothing());
EXPECT_THAT(cookie_change_future.Take(),
testing::ElementsAre(
testing::Field("cause", &net::CookieChangeInfo::cause,
net::CookieChangeCause::OVERWRITE),
testing::Field(
"cause", &net::CookieChangeInfo::cause,
net::CookieChangeCause::INSERTED_NO_CHANGE_OVERWRITE)));
commit_future.Get();
}
mojo::Remote<network::mojom::CookieManager> cookie_manager_;
base::test::ScopedFeatureList feature_list_;
const GURL kNonGoogleURL = GURL("https://example.com:8888");
policy::PolicyMap policies_;
};
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, ServiceRegistered) {
ASSERT_TRUE(IsFloatingSsoServiceRegistered());
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, FloatingSsoPolicyDisabled) {
auto& service = floating_sso_service();
SetFloatingSsoEnabledPolicy(false);
SetSyncCookiesPref(true);
SetSyncDisabledPolicy(false);
ASSERT_FALSE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(
SetCookie(cookie_manager(), kNonGoogleURL, kPersistentCookieLine));
auto store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 0u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, SyncCookiesPrefDisabled) {
auto& service = floating_sso_service();
SetFloatingSsoEnabledPolicy(true);
SetSyncEverythingPref(false);
SetSyncCookiesPref(false);
SetSyncDisabledPolicy(false);
ASSERT_FALSE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(
SetCookie(cookie_manager(), kNonGoogleURL, kPersistentCookieLine));
auto store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 0u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, SyncDisabled) {
auto& service = floating_sso_service();
SetFloatingSsoEnabledPolicy(true);
SetSyncCookiesPref(true);
SetSyncDisabledPolicy(true);
ASSERT_FALSE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(
SetCookie(cookie_manager(), kNonGoogleURL, kPersistentCookieLine));
auto store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 0u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, FloatingSsoRespectsSyncEverythingPref) {
auto& service = floating_sso_service();
SetFloatingSsoEnabledPolicy(true);
SetSyncEverythingPref(true);
SetSyncCookiesPref(false);
SetSyncDisabledPolicy(false);
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
AddCookieAndWaitForCommit(cookie_manager(), kNonGoogleURL,
kPersistentCookieLine);
const auto& store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 1u);
EXPECT_TRUE(store_entries.contains(kCookieUniqueKey));
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, FloatingSsoStopsListeningAndResumes) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
AddCookieAndWaitForCommit(cookie_manager(), kNonGoogleURL,
kPersistentCookieLine);
const auto& store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 1u);
EXPECT_TRUE(store_entries.contains(kCookieUniqueKey));
SetFloatingSsoEnabledPolicy(false);
base::test::TestFuture<const net::CookieChangeInfo&> cookie_change_future;
CookieChangeListener listener(cookie_manager(), kNonGoogleURL,
cookie_change_future.GetRepeatingCallback());
ASSERT_TRUE(SetCookie(cookie_manager(), kNonGoogleURL,
"CookieNameNew=CookieValueNew; max-age=3600"));
EXPECT_EQ(cookie_change_future.Take().cause,
net::CookieChangeCause::INSERTED);
EXPECT_EQ(store_entries.size(), 1u);
base::test::TestFuture<void> commit_future;
floating_sso_service().GetBridgeForTesting()->SetOnStoreCommitCallbackForTest(
commit_future.GetRepeatingCallback());
SetFloatingSsoEnabledPolicy(true);
commit_future.Get();
EXPECT_EQ(store_entries.size(), 2u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, FiltersOutGoogleCookies) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://google.com"),
kPersistentCookieLine));
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://accounts.google.com"),
kPersistentCookieLine));
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://youtube.com"),
kPersistentCookieLine));
auto store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 0u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest,
SessionCookiesIncludedEnabledFloatingSsoEnabled) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingSsoSessionCookiesIncludedPolicy(true);
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(IsFloatingSsoSessionCookiesIncludedPolicyManaged());
const auto& store_entries = GetStoreEntries();
ASSERT_TRUE(store_entries.empty());
AddCookieAndWaitForCommit(cookie_manager(), kNonGoogleURL,
kSessionCookieLine);
EXPECT_EQ(store_entries.size(), 1u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest,
SessionCookiesIncludedEnabledFloatingSsoDisabled) {
auto& service = floating_sso_service();
SetFloatingSsoEnabledPolicy(false);
SetSyncCookiesPref(true);
SetSyncDisabledPolicy(false);
SetFloatingSsoSessionCookiesIncludedPolicy(true);
ASSERT_FALSE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(IsFloatingSsoSessionCookiesIncludedPolicyManaged());
const auto& store_entries = GetStoreEntries();
ASSERT_TRUE(store_entries.empty());
ASSERT_TRUE(SetCookie(cookie_manager(), kNonGoogleURL, kSessionCookieLine));
EXPECT_EQ(store_entries.size(), 0u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest,
SessionCookiesIncludedDisabledFloatingSsoEnabled) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingSsoSessionCookiesIncludedPolicy(false);
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(IsFloatingSsoSessionCookiesIncludedPolicyManaged());
const auto& store_entries = GetStoreEntries();
ASSERT_TRUE(store_entries.empty());
ASSERT_TRUE(SetCookie(cookie_manager(), kNonGoogleURL, kSessionCookieLine));
EXPECT_EQ(store_entries.size(), 0u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, SessionCookiesIncludedUnsetFWSEnabled) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingWorkspacePolicy(true);
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_FALSE(IsFloatingSsoSessionCookiesIncludedPolicyManaged());
const auto& store_entries = GetStoreEntries();
ASSERT_TRUE(store_entries.empty());
AddCookieAndWaitForCommit(cookie_manager(), kNonGoogleURL,
kSessionCookieLine);
EXPECT_EQ(store_entries.size(), 1u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest,
SessionCookiesIncludedUnsetFWSDisabled) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingWorkspacePolicy(false);
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_FALSE(IsFloatingSsoSessionCookiesIncludedPolicyManaged());
const auto& store_entries = GetStoreEntries();
ASSERT_TRUE(store_entries.empty());
ASSERT_TRUE(SetCookie(cookie_manager(), kNonGoogleURL, kSessionCookieLine));
EXPECT_EQ(store_entries.size(), 0u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, FiltersOutCookiesWithNonHttpSource) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
const auto& store_entries = GetStoreEntries();
ASSERT_EQ(store_entries.size(), 0u);
for (net::CookieSourceType source :
base::EnumSet<net::CookieSourceType, net::CookieSourceType::kUnknown,
net::CookieSourceType::kMaxValue>::All()) {
if (source == net::CookieSourceType::kHTTP) {
continue;
}
const GURL url("https://example.com");
std::unique_ptr<net::CanonicalCookie> cookie =
net::CanonicalCookie::CreateForTesting(
url, kPersistentCookieLine, base::Time::Now(),
std::nullopt,
std::nullopt, source);
ASSERT_TRUE(SetCookie(cookie_manager(), url, *cookie));
EXPECT_EQ(store_entries.size(), 0u);
}
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest,
FiltersCookiesWithBlocklistBasicPattern) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingSsoDomainBlocklistPolicy("example.com");
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://example.com"),
kPersistentCookieLine));
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("http://example.com"),
kPersistentCookieLine));
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://www.example.com"),
kPersistentCookieLine));
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://sub.www.example.com"),
kPersistentCookieLine));
auto store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 0u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest,
FiltersCookiesWithBlocklistSubdomainPattern) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingSsoDomainBlocklistPolicy("mail.example.com");
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://mail.example.com"),
kPersistentCookieLine));
const auto& store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 0u);
AddCookieAndWaitForCommit(cookie_manager(), GURL("http://example.com"),
kPersistentCookieLine);
AddCookieAndWaitForCommit(cookie_manager(), GURL("https://www.example.com"),
kPersistentCookieLine);
EXPECT_EQ(store_entries.size(), 2u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, FiltersCookiesWithBlocklistDotPattern) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingSsoDomainBlocklistPolicy(".example.com");
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://example.com"),
kPersistentCookieLine));
const auto& store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 0u);
AddCookieAndWaitForCommit(cookie_manager(), GURL("https://mail.example.com"),
kPersistentCookieLine);
EXPECT_EQ(store_entries.size(), 1u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest,
AllowSpecificDomainsWithWildcardBlocking) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingSsoDomainBlocklistPolicy("*");
SetFloatingSsoDomainBlocklistExceptionsPolicy("example.com");
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://mail.com"),
kPersistentCookieLine));
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://test.com"),
kPersistentCookieLine));
const auto& store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 0u);
AddCookieAndWaitForCommit(cookie_manager(), GURL("https://example.com"),
kPersistentCookieLine);
EXPECT_EQ(store_entries.size(), 1u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, ExceptionListTakesPrecedence) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingSsoDomainBlocklistPolicy("example.com");
SetFloatingSsoDomainBlocklistExceptionsPolicy("example.com");
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
AddCookieAndWaitForCommit(cookie_manager(), GURL("https://example.com"),
kPersistentCookieLine);
auto store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 1u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest,
FiltersOutGoogleCookiesDespiteException) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingSsoDomainBlocklistExceptionsPolicy("google.com");
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://google.com"),
kPersistentCookieLine));
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://accounts.google.com"),
kPersistentCookieLine));
auto store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 0u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, RespectsBlockAndExemptListUpdates) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingSsoDomainBlocklistPolicy("*");
SetFloatingSsoDomainBlocklistExceptionsPolicy("example.com");
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://mail.com"),
kPersistentCookieLine));
AddCookieAndWaitForCommit(cookie_manager(), GURL("https://example.com"),
kPersistentCookieLine);
const auto& store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 1u);
constexpr char kExampleCookieUniqueKey[] = "trueCookieNameexample.com/2443";
EXPECT_TRUE(store_entries.contains(kExampleCookieUniqueKey));
SetFloatingSsoDomainBlocklistPolicy("example.com");
SetFloatingSsoDomainBlocklistExceptionsPolicy("");
AddCookieAndWaitForCommit(cookie_manager(), GURL("https://sub.mail.com/"),
kPersistentCookieLine);
ASSERT_TRUE(SetCookie(cookie_manager(), GURL("https://example.com"),
kPersistentCookieLine));
EXPECT_EQ(store_entries.size(), 2u);
EXPECT_TRUE(store_entries.contains(kExampleCookieUniqueKey));
EXPECT_TRUE(store_entries.contains("trueCookieNamesub.mail.com/2443"));
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, CookiesFromSyncBlocked) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
SetFloatingSsoDomainBlocklistPolicy("example.com");
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
base::test::TestFuture<const net::CookieChangeInfo&> cookie_change_future;
CookieChangeListener listener(cookie_manager(),
cookie_change_future.GetRepeatingCallback());
FloatingSsoSyncBridge& bridge =
CHECK_DEREF(floating_sso_service().GetBridgeForTesting());
syncer::EntityChangeList change_list;
change_list.push_back(syncer::EntityChange::CreateAdd(
kUniqueKeysForTests[1],
CreateEntityDataForTest(CreatePredefinedCookieSpecificsForTest(
1, base::Time::Now(), true))));
constexpr char kTestCookieUniqueKey[] = "trueCookieNametest.com/2443";
change_list.push_back(syncer::EntityChange::CreateAdd(
kTestCookieUniqueKey,
CreateEntityDataForTest(
CreateCookieSpecificsForTest(kTestCookieUniqueKey, kCookieName,
base::Time::Now(),
true, "www.test.com"))));
bridge.ApplyIncrementalSyncChanges(bridge.CreateMetadataChangeList(),
std::move(change_list));
EXPECT_EQ(cookie_change_future.Take().cause,
net::CookieChangeCause::INSERTED);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, KeepsThirdPartyCookies) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
AddCookieAndWaitForCommit(
cookie_manager(), kNonGoogleURL,
"CookieName=CookieValue; SameSite=None; Secure; max-age=3600");
auto store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 1u);
EXPECT_TRUE(store_entries.contains(kCookieUniqueKey));
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, AddsAndDeletesCookiesToStore) {
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
AddCookieAndWaitForCommit(cookie_manager(), kNonGoogleURL,
kPersistentCookieLine);
const auto& store_entries = GetStoreEntries();
EXPECT_EQ(store_entries.size(), 1u);
EXPECT_TRUE(store_entries.contains(kCookieUniqueKey));
UpdateCookieAndWaitForCommit(cookie_manager(), kNonGoogleURL, kCookieName);
EXPECT_EQ(store_entries.size(), 1u);
DeleteCookieAndWaitForCommit(cookie_manager(), kNonGoogleURL, kCookieName);
EXPECT_EQ(store_entries.size(), 0u);
}
IN_PROC_BROWSER_TEST_F(FloatingSsoTest, ApplyingChangesFromSync) {
sync_pb::CookieSpecifics existing_local_cookie_specifics =
CreatePredefinedCookieSpecificsForTest(
0, base::Time::Now(), true);
std::unique_ptr<net::CanonicalCookie> existing_local_cookie =
FromSyncProto(existing_local_cookie_specifics);
ASSERT_TRUE(existing_local_cookie);
ASSERT_TRUE(SetCookie(cookie_manager(), *existing_local_cookie));
auto& service = floating_sso_service();
EnableAllFloatingSsoSettings();
ASSERT_TRUE(service.IsBoundToCookieManagerForTesting());
base::test::TestFuture<std::vector<net::CookieChangeInfo>>
cookie_change_future;
CookieChangeListener listener(
cookie_manager(),
base::BarrierCallback<const net::CookieChangeInfo&>(
2, cookie_change_future.GetRepeatingCallback()));
syncer::EntityChangeList no_op_change_list;
no_op_change_list.push_back(syncer::EntityChange::CreateAdd(
kUniqueKeysForTests[2],
CreateEntityDataForTest(CreatePredefinedCookieSpecificsForTest(
2, base::Time::Now(), false))));
FloatingSsoSyncBridge& bridge =
CHECK_DEREF(floating_sso_service().GetBridgeForTesting());
bridge.ApplyIncrementalSyncChanges(bridge.CreateMetadataChangeList(),
std::move(no_op_change_list));
syncer::EntityChangeList change_list;
change_list.push_back(syncer::EntityChange::CreateDelete(
existing_local_cookie_specifics.unique_key(),
CreateEntityDataForTest(sync_pb::CookieSpecifics())));
change_list.push_back(syncer::EntityChange::CreateAdd(
kUniqueKeysForTests[1],
CreateEntityDataForTest(CreatePredefinedCookieSpecificsForTest(
1, base::Time::Now(), true))));
bridge.ApplyIncrementalSyncChanges(bridge.CreateMetadataChangeList(),
std::move(change_list));
EXPECT_THAT(cookie_change_future.Take(),
testing::UnorderedElementsAre(
testing::Field("cause", &net::CookieChangeInfo::cause,
net::CookieChangeCause::EXPLICIT),
testing::Field("cause", &net::CookieChangeInfo::cause,
net::CookieChangeCause::INSERTED)));
}
}