Skip to content

Commit

Permalink
Add FirstPartySet-querying methods to PreloadedFirstPartySets.
Browse files Browse the repository at this point in the history
These methods will be called in later CLs by the implementation of the
SameParty attribute.

Bug: 1143756
Change-Id: Id256e2a3971dccd4339f167516275a8dbcb46167
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2576110
Reviewed-by: Eric Orth <ericorth@chromium.org>
Reviewed-by: Lily Chen <chlily@chromium.org>
Commit-Queue: Chris Fredrickson <cfredric@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834945}
  • Loading branch information
cfredric authored and Chromium LUCI CQ committed Dec 8, 2020
1 parent e284037 commit 65d8457
Show file tree
Hide file tree
Showing 3 changed files with 303 additions and 2 deletions.
23 changes: 23 additions & 0 deletions services/network/first_party_sets/preloaded_first_party_sets.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,29 @@ PreloadedFirstPartySets::ParseAndSet(base::StringPiece raw_sets) {
return &sets_;
}

bool PreloadedFirstPartySets::IsContextSamePartyWithSite(
const net::SchemefulSite& site,
const net::SchemefulSite& top_frame_site,
const std::set<net::SchemefulSite>& party_context) const {
const auto it = sets_.find(site);
if (it == sets_.end())
return false;
const net::SchemefulSite& site_owner = it->second;
const auto is_owned_by_site_owner =
[this, &site_owner](const net::SchemefulSite& context_site) {
const auto context_owner = sets_.find(context_site);
return context_owner != sets_.end() &&
context_owner->second == site_owner;
};
return is_owned_by_site_owner(top_frame_site) &&
base::ranges::all_of(party_context, is_owned_by_site_owner);
}

bool PreloadedFirstPartySets::IsInNontrivialFirstPartySet(
const net::SchemefulSite& site) const {
return base::Contains(sets_, site);
}

void PreloadedFirstPartySets::ApplyManuallySpecifiedSet() {
if (!manually_specified_set_)
return;
Expand Down
17 changes: 15 additions & 2 deletions services/network/first_party_sets/preloaded_first_party_sets.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@

#include <map>
#include <memory>
#include <set>

#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "net/base/schemeful_site.h"
#include "services/network/first_party_sets/first_party_set_parser.h"

namespace network {

Expand Down Expand Up @@ -40,6 +39,20 @@ class PreloadedFirstPartySets {
base::flat_map<net::SchemefulSite, net::SchemefulSite>* ParseAndSet(
base::StringPiece raw_sets);

// Returns whether the `site` is same-party with the `party_context` and
// `top_frame_site`. That is, is the `site`'s owner the same as the owners of
// every member of `party_context` and of `top_frame_site`? Note: if `site` is
// not a member of a First-Party Set (with more than one member), then this
// returns false.
bool IsContextSamePartyWithSite(
const net::SchemefulSite& site,
const net::SchemefulSite& top_frame_site,
const std::set<net::SchemefulSite>& party_context) const;

// Returns whether the `site` is a member of a non-trivial (i.e.
// non-singleton) First-Party Set.
bool IsInNontrivialFirstPartySet(const net::SchemefulSite& site) const;

int64_t size() const { return sets_.size(); }

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

using ::testing::IsEmpty;
using ::testing::Not;
using ::testing::Pair;
using ::testing::Pointee;
using ::testing::UnorderedElementsAre;
using ::testing::Value;

// Some of these tests overlap with FirstPartySetParser unittests, but
// overlapping test coverage isn't the worst thing.
Expand Down Expand Up @@ -459,4 +462,266 @@ TEST(PreloadedFirstPartySets, SetsManuallySpecified_PrunesInducedSingletons) {
SerializesTo("https://example.test")))));
}

class PreloadedFirstPartySetsTest : public ::testing::Test {
public:
PreloadedFirstPartySetsTest() {
const std::string input = R"(
[
{
"owner": "https://example.test",
"members": ["https://member1.test", "https://member3.test"]
},
{
"owner": "https://foo.test",
"members": ["https://member2.test"]
}
]
)";
CHECK(base::JSONReader::Read(input));

CHECK(Value(
sets().ParseAndSet(input),
Pointee(UnorderedElementsAre(Pair(SerializesTo("https://example.test"),
SerializesTo("https://example.test")),
Pair(SerializesTo("https://member1.test"),
SerializesTo("https://example.test")),
Pair(SerializesTo("https://member3.test"),
SerializesTo("https://example.test")),
Pair(SerializesTo("https://foo.test"),
SerializesTo("https://foo.test")),
Pair(SerializesTo("https://member2.test"),
SerializesTo("https://foo.test"))))));
}

PreloadedFirstPartySets& sets() { return sets_; }

protected:
PreloadedFirstPartySets sets_;
};

TEST_F(PreloadedFirstPartySetsTest, IsContextSamePartyWithSite_EmptyContext) {
net::SchemefulSite top_frame(GURL("https://example.test"));
EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://nonmember.test")), top_frame, {}));

EXPECT_TRUE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://example.test")), top_frame, {}));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("http://example.test")), top_frame, {}));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://nonmember.test")), {}));
EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://nonmember.test")),
net::SchemefulSite(GURL("https://example.test")), {}));
}

TEST_F(PreloadedFirstPartySetsTest,
IsContextSamePartyWithSite_ContextIsNonmember) {
net::SchemefulSite top_frame(GURL("https://example.test"));
std::set<net::SchemefulSite> context({
net::SchemefulSite(GURL("https://nonmember.test")),
});

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("http://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member1.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://foo.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member2.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context));
}

TEST_F(PreloadedFirstPartySetsTest, IsContextSamePartyWithSite_ContextIsOwner) {
net::SchemefulSite top_frame(GURL("https://example.test"));
std::set<net::SchemefulSite> context(
{net::SchemefulSite(GURL("https://example.test"))});

EXPECT_TRUE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("http://example.test")), top_frame, context));

EXPECT_TRUE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member1.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://foo.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member2.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context));
}

TEST_F(PreloadedFirstPartySetsTest,
IsContextSamePartyWithSite_ContextIsMember) {
net::SchemefulSite top_frame(GURL("https://example.test"));
std::set<net::SchemefulSite> context(
{net::SchemefulSite(GURL("https://member1.test"))});

EXPECT_TRUE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("http://example.test")), top_frame, context));

EXPECT_TRUE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://example.test")), top_frame, context));

EXPECT_TRUE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member1.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://foo.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member2.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context));
}

TEST_F(PreloadedFirstPartySetsTest,
IsContextSamePartyWithSite_ContextIsOwnerAndMember) {
net::SchemefulSite top_frame(GURL("https://example.test"));
std::set<net::SchemefulSite> context({
net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://member1.test")),
});

EXPECT_TRUE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("http://example.test")), top_frame, context));

EXPECT_TRUE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member1.test")), top_frame, context));

EXPECT_TRUE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member3.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://foo.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member2.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context));
}

TEST_F(PreloadedFirstPartySetsTest,
IsContextSamePartyWithSite_ContextMixesParties) {
net::SchemefulSite top_frame(GURL("https://example.test"));
std::set<net::SchemefulSite> context({
net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://member1.test")),
net::SchemefulSite(GURL("https://foo.test")),
});

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("http://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member1.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://foo.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member2.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context));
}

TEST_F(PreloadedFirstPartySetsTest,
IsContextSamePartyWithSite_ContextMixesMembersAndNonmembers) {
net::SchemefulSite top_frame(GURL("https://example.test"));
std::set<net::SchemefulSite> context({
net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://member1.test")),
net::SchemefulSite(GURL("http://nonmember.test")),
});

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("http://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member1.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://foo.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member2.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context));
}

TEST_F(PreloadedFirstPartySetsTest,
IsContextSamePartyWithSite_ContextMixesSchemes) {
net::SchemefulSite top_frame(GURL("https://example.test"));
std::set<net::SchemefulSite> context({
net::SchemefulSite(GURL("https://example.test")),
net::SchemefulSite(GURL("https://member1.test")),
net::SchemefulSite(GURL("http://example.test")),
});

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("http://example.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member1.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://foo.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://member2.test")), top_frame, context));

EXPECT_FALSE(sets().IsContextSamePartyWithSite(
net::SchemefulSite(GURL("https://nonmember.test")), top_frame, context));
}

TEST_F(PreloadedFirstPartySetsTest, IsInNontrivialFirstPartySet) {
EXPECT_TRUE(sets().IsInNontrivialFirstPartySet(
net::SchemefulSite(GURL("https://example.test"))));

EXPECT_FALSE(sets().IsInNontrivialFirstPartySet(
net::SchemefulSite(GURL("http://example.test"))));

EXPECT_TRUE(sets().IsInNontrivialFirstPartySet(
net::SchemefulSite(GURL("https://member1.test"))));

EXPECT_FALSE(sets().IsInNontrivialFirstPartySet(
net::SchemefulSite(GURL("https://nonmember.test"))));
}

} // namespace network

0 comments on commit 65d8457

Please sign in to comment.