[go: nahoru, domu]

blob: 49f6bb7ffc7ff29bbb62b481c6a655d802dc33c8 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/first_party_sets/first_party_sets_handler_database_helper.h"
#include <string>
#include "base/files/scoped_temp_dir.h"
#include "base/test/task_environment.h"
#include "base/version.h"
#include "net/base/schemeful_site.h"
#include "net/first_party_sets/first_party_set_entry.h"
#include "net/first_party_sets/first_party_sets_cache_filter.h"
#include "net/first_party_sets/first_party_sets_context_config.h"
#include "net/first_party_sets/global_first_party_sets.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
using ::testing::Eq;
using ::testing::IsEmpty;
using ::testing::Optional;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;
namespace content {
namespace {
const base::Version kVersion("1.2.3");
} // namespace
TEST(FirstPartySetsHandlerDatabaseHelper, ComputeSetsDiff_SitesJoined) {
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite foo(GURL("https://foo.test"));
net::SchemefulSite member1(GURL("https://member1.test"));
net::SchemefulSite member2(GURL("https://member2.test"));
net::SchemefulSite member3(GURL("https://member3.test"));
net::GlobalFirstPartySets old_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)},
{member3,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 1)}},
/*aliases=*/{});
net::GlobalFirstPartySets current_sets(
kVersion,
/*entries=*/
{
{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)},
{member3,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 1)},
{foo, net::FirstPartySetEntry(foo, net::SiteType::kPrimary,
absl::nullopt)},
{member2,
net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)},
},
/*aliases=*/{});
// "https://foo.test" and "https://member2.test" joined FPSs. We don't clear
// site data upon joining, so the computed diff should be empty set.
EXPECT_THAT(
FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
old_sets, /*old_config=*/net::FirstPartySetsContextConfig(),
current_sets, /*current_config=*/net::FirstPartySetsContextConfig()),
IsEmpty());
}
TEST(FirstPartySetsHandlerDatabaseHelper, ComputeSetsDiff_SitesLeft) {
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite foo(GURL("https://foo.test"));
net::SchemefulSite member1(GURL("https://member1.test"));
net::SchemefulSite member2(GURL("https://member2.test"));
net::SchemefulSite member3(GURL("https://member3.test"));
net::GlobalFirstPartySets old_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)},
{member3,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 1)},
{foo,
net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)},
{member2, net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
/*aliases=*/{});
net::GlobalFirstPartySets current_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)}},
/*aliases=*/{});
// Expected diff: "https://foo.test", "https://member2.test" and
// "https://member3.test" left FPSs.
EXPECT_THAT(
FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
old_sets, /*old_config=*/net::FirstPartySetsContextConfig(),
current_sets, /*current_config=*/net::FirstPartySetsContextConfig()),
UnorderedElementsAre(foo, member2, member3));
}
TEST(FirstPartySetsHandlerDatabaseHelper, ComputeSetsDiff_OwnerChanged) {
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite foo(GURL("https://foo.test"));
net::SchemefulSite member1(GURL("https://member1.test"));
net::SchemefulSite member2(GURL("https://member2.test"));
net::SchemefulSite member3(GURL("https://member3.test"));
net::GlobalFirstPartySets old_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)},
{foo,
net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)},
{member2, net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)},
{member3, net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 1)}},
/*aliases=*/{});
net::GlobalFirstPartySets current_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)},
{member3,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 1)},
{foo,
net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)},
{member2, net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
/*aliases=*/{});
// Expected diff: "https://member3.test" changed owner.
EXPECT_THAT(
FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
old_sets, /*old_config=*/net::FirstPartySetsContextConfig(),
current_sets, /*current_config=*/net::FirstPartySetsContextConfig()),
UnorderedElementsAre(member3));
}
TEST(FirstPartySetsHandlerDatabaseHelper, ComputeSetsDiff_OwnerLeft) {
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite foo(GURL("https://foo.test"));
net::SchemefulSite bar(GURL("https://bar.test"));
net::GlobalFirstPartySets old_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{foo, net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)},
{bar, net::FirstPartySetEntry(example, net::SiteType::kAssociated, 1)}},
/*aliases=*/{});
net::GlobalFirstPartySets current_sets(
kVersion,
/*entries=*/
{{foo,
net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)},
{bar, net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
/*aliases=*/{});
// Expected diff: "https://example.test" left FPSs, "https://foo.test" and
// "https://bar.test" changed owner.
// It would be valid to only have example.test in the diff, but our logic
// isn't sophisticated enough yet to know that foo.test and bar.test don't
// need to be included in the result.
EXPECT_THAT(
FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
old_sets, /*old_config=*/net::FirstPartySetsContextConfig(),
current_sets, /*current_config=*/net::FirstPartySetsContextConfig()),
UnorderedElementsAre(example, foo, bar));
}
TEST(FirstPartySetsHandlerDatabaseHelper, ComputeSetsDiff_OwnerMemberRotate) {
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite foo(GURL("https://foo.test"));
net::GlobalFirstPartySets old_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{foo, net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)}},
/*aliases=*/{});
net::GlobalFirstPartySets current_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)},
{foo,
net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)}},
/*aliases=*/{});
// Expected diff: "https://example.test" and "https://foo.test" changed owner.
// It would be valid to not include example.test and foo.test in the result,
// but our logic isn't sophisticated enough yet to know that.ß
EXPECT_THAT(
FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
old_sets, /*old_config=*/net::FirstPartySetsContextConfig(),
current_sets, /*current_config=*/net::FirstPartySetsContextConfig()),
UnorderedElementsAre(example, foo));
}
TEST(FirstPartySetsHandlerDatabaseHelper, ComputeSetsDiff_EmptyOldSets) {
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite member1(GURL("https://member1.test"));
// Empty old_sets.
net::GlobalFirstPartySets current_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)}},
/*aliases=*/{});
EXPECT_THAT(
FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
/*old_sets=*/net::GlobalFirstPartySets(),
/*old_config=*/net::FirstPartySetsContextConfig(), current_sets,
/*current_config=*/net::FirstPartySetsContextConfig()),
IsEmpty());
}
TEST(FirstPartySetsHandlerDatabaseHelper, ComputeSetsDiff_EmptyCurrentSets) {
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite member1(GURL("https://member1.test"));
// Empty current sets.
net::GlobalFirstPartySets old_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)}},
/*aliases=*/{});
EXPECT_THAT(FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
old_sets, /*old_config=*/net::FirstPartySetsContextConfig(),
/*current_sets=*/net::GlobalFirstPartySets(),
/*current_config=*/net::FirstPartySetsContextConfig()),
IsEmpty());
}
TEST(FirstPartySetsHandlerDatabaseHelper, ComputeSetsDiff_PolicySitesJoined) {
net::SchemefulSite foo(GURL("https://foo.test"));
net::SchemefulSite member2(GURL("https://member2.test"));
net::FirstPartySetsContextConfig current_config({
{foo,
{net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)}},
{member2, {net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
});
// "https://example.test" and "https://member2.test" joined FPSs via
// enterprise policy. We don't clear site data upon joining, so the computed
// diff should be empty.
EXPECT_THAT(FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
/*old_sets=*/net::GlobalFirstPartySets(),
/*old_config=*/current_config,
/*current_sets=*/net::GlobalFirstPartySets(), current_config),
IsEmpty());
}
TEST(FirstPartySetsHandlerDatabaseHelper,
ComputeSetsDiff_PolicyRemovedSitesJoined) {
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite foo(GURL("https://foo.test"));
net::SchemefulSite member1(GURL("https://member1.test"));
net::GlobalFirstPartySets sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)}},
/*aliases=*/{});
// "https://example.test" was removed from FPSs by policy modifications.
net::FirstPartySetsContextConfig old_config({
{foo,
{net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)}},
{member1, {net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
{example, absl::nullopt},
});
// "https://example.test" added back to FPSs.
net::FirstPartySetsContextConfig current_config({
{foo,
{net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)}},
{member1, {net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
{example, {net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
});
// We don't clear site data upon joining, so the computed diff should be
// empty.
EXPECT_THAT(
FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
/*old_sets=*/sets, old_config, /*current_sets=*/sets, current_config),
IsEmpty());
}
TEST(FirstPartySetsHandlerDatabaseHelper, ComputeSetsDiff_PolicyMemberLeft) {
net::SchemefulSite foo(GURL("https://foo.test"));
net::SchemefulSite member1(GURL("https://member1.test"));
net::SchemefulSite member2(GURL("https://member2.test"));
net::FirstPartySetsContextConfig old_config({
{foo,
{net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)}},
{member1, {net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
{member2, {net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
});
// "https://member2.test" left FPSs via enterprise policy.
net::FirstPartySetsContextConfig current_config({
{foo,
{net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)}},
{member1, {net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
});
EXPECT_THAT(FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
/*old_sets=*/net::GlobalFirstPartySets(), old_config,
/*current_sets=*/net::GlobalFirstPartySets(), current_config),
UnorderedElementsAre(member2));
}
TEST(FirstPartySetsHandlerDatabaseHelper, ComputeSetsDiff_PolicyOwnerLeft) {
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite member1(GURL("https://member1.test"));
net::SchemefulSite member2(GURL("https://member2.test"));
net::FirstPartySetsContextConfig old_config({
{example,
{net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)}},
{member1,
{net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)}},
{member2,
{net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)}},
});
net::FirstPartySetsContextConfig current_config({
{member1,
{net::FirstPartySetEntry(member1, net::SiteType::kPrimary,
absl::nullopt)}},
{member2,
{net::FirstPartySetEntry(member1, net::SiteType::kAssociated, 0)}},
});
// Expected diff: "https://example.test" left FPSs, "https://member1.test" and
// "https://member2.test" changed owner.
// It would be valid to only have example.test in the diff, but our logic
// isn't sophisticated enough yet to know that member1.test and member2.test
// don't need to be included in the result.
EXPECT_THAT(
FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
/*old_sets=*/net::GlobalFirstPartySets(), /*old_config=*/old_config,
/*current_sets=*/net::GlobalFirstPartySets(), current_config),
UnorderedElementsAre(example, member1, member2));
}
TEST(FirstPartySetsHandlerDatabaseHelper,
ComputeSetsDiff_PolicyMembersChangeSet) {
net::SchemefulSite foo(GURL("https://foo.test"));
net::SchemefulSite bar(GURL("https://bar.test"));
net::SchemefulSite member1(GURL("https://member1.test"));
net::SchemefulSite member2(GURL("https://member2.test"));
net::FirstPartySetsContextConfig old_config({
{foo,
{net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)}},
{member1, {net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
{bar,
{net::FirstPartySetEntry(bar, net::SiteType::kPrimary, absl::nullopt)}},
{member2, {net::FirstPartySetEntry(bar, net::SiteType::kAssociated, 0)}},
});
net::FirstPartySetsContextConfig current_config({
{foo,
{net::FirstPartySetEntry(foo, net::SiteType::kPrimary, absl::nullopt)}},
{member2, {net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
{bar,
{net::FirstPartySetEntry(bar, net::SiteType::kPrimary, absl::nullopt)}},
{member1, {net::FirstPartySetEntry(bar, net::SiteType::kAssociated, 0)}},
});
EXPECT_THAT(FirstPartySetsHandlerDatabaseHelper::ComputeSetsDiff(
/*old_sets=*/net::GlobalFirstPartySets(), old_config,
/*current_sets=*/net::GlobalFirstPartySets(), current_config),
UnorderedElementsAre(member1, member2));
}
class FirstPartySetsHandlerDatabaseHelperTest : public testing::Test {
public:
FirstPartySetsHandlerDatabaseHelperTest() {
EXPECT_TRUE(dir_.CreateUniqueTempDir());
db_helper_ = std::make_unique<FirstPartySetsHandlerDatabaseHelper>(
dir_.GetPath().AppendASCII("TestFirstPartySets.db"));
}
protected:
base::ScopedTempDir dir_;
base::test::TaskEnvironment env_;
std::unique_ptr<FirstPartySetsHandlerDatabaseHelper> db_helper_;
};
TEST_F(FirstPartySetsHandlerDatabaseHelperTest,
UpdateAndGetSitesToClearForContext) {
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite foo(GURL("https://foo.test"));
net::SchemefulSite member1(GURL("https://member1.test"));
net::SchemefulSite member2(GURL("https://member2.test"));
net::SchemefulSite member3(GURL("https://member3.test"));
const std::string browser_context_id("b");
db_helper_->PersistSets(
browser_context_id,
net::GlobalFirstPartySets(
base::Version("0.0.1"),
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)},
{member3,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 1)},
{foo, net::FirstPartySetEntry(foo, net::SiteType::kPrimary,
absl::nullopt)},
{member2,
net::FirstPartySetEntry(foo, net::SiteType::kAssociated, 0)}},
/*aliases=*/{}),
/*config=*/net::FirstPartySetsContextConfig());
net::GlobalFirstPartySets current_sets(
kVersion,
/*entries=*/
{{example, net::FirstPartySetEntry(example, net::SiteType::kPrimary,
absl::nullopt)},
{member1,
net::FirstPartySetEntry(example, net::SiteType::kAssociated, 0)}},
/*aliases=*/{});
std::pair<std::vector<net::SchemefulSite>, net::FirstPartySetsCacheFilter>
res = db_helper_->UpdateAndGetSitesToClearForContext(
browser_context_id, current_sets,
/*current_config=*/net::FirstPartySetsContextConfig());
// Expected diff: "https://foo.test", "https://member2.test" and
// "https://member3.test" left FPSs.
EXPECT_THAT(res.first, UnorderedElementsAre(foo, member2, member3));
EXPECT_EQ(res.second, net::FirstPartySetsCacheFilter(
/*filter=*/{{foo, 1}, {member2, 1}, {member3, 1}},
/*browser_run_id=*/1));
}
} // namespace content