[go: nahoru, domu]

blob: 8a62232523953e85d1638b45471fe910bab075f1 [file] [log] [blame]
Shuran Huang71a22ff2022-02-11 14:54:101// Copyright 2022 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Shuran Huang10398152022-03-28 21:52:185#include "content/browser/first_party_sets/first_party_sets_loader.h"
Shuran Huang71a22ff2022-02-11 14:54:106
Chris Fredrickson4ef2d242022-09-06 22:47:187#include <iterator>
Lei Zhangbd722512022-03-14 23:21:588#include <set>
Chris Fredrickson878d06b2022-09-08 15:20:379#include <sstream>
Shuran Huang71a22ff2022-02-11 14:54:1010#include <utility>
11#include <vector>
12
13#include "base/check.h"
14#include "base/containers/contains.h"
15#include "base/containers/flat_map.h"
Shuran Huang71a22ff2022-02-11 14:54:1016#include "base/files/file_util.h"
Shuran Huang71a22ff2022-02-11 14:54:1017#include "base/metrics/histogram_functions.h"
Chris Fredrickson4ef2d242022-09-06 22:47:1818#include "base/ranges/algorithm.h"
Shuran Huang71a22ff2022-02-11 14:54:1019#include "base/sequence_checker.h"
Shuran Huang71a22ff2022-02-11 14:54:1020#include "base/task/thread_pool.h"
Shuran Huang10398152022-03-28 21:52:1821#include "content/browser/first_party_sets/first_party_set_parser.h"
Chris Fredrickson8db7bf542022-09-06 17:47:2022#include "content/browser/first_party_sets/local_set_declaration.h"
Shuran Huang71a22ff2022-02-11 14:54:1023#include "net/base/schemeful_site.h"
Chris Fredrickson33273122022-08-31 22:41:0024#include "net/first_party_sets/first_party_set_entry.h"
Chris Fredrickson878d06b2022-09-08 15:20:3725#include "net/first_party_sets/public_sets.h"
Shuran Huang71a22ff2022-02-11 14:54:1026#include "third_party/abseil-cpp/absl/types/optional.h"
27
Shuran Huang10398152022-03-28 21:52:1828namespace content {
Shuran Huang71a22ff2022-02-11 14:54:1029
30namespace {
31
Shuran Huang71a22ff2022-02-11 14:54:1032std::string ReadSetsFile(base::File sets_file) {
33 std::string raw_sets;
34 base::ScopedFILE file(FileToFILE(std::move(sets_file), "r"));
35 return base::ReadStreamToString(file.get(), &raw_sets) ? raw_sets : "";
36}
37
38} // namespace
39
40FirstPartySetsLoader::FirstPartySetsLoader(
Kirubel Aklilu6d1ef6b92022-07-08 13:40:1941 LoadCompleteOnceCallback on_load_complete)
42 : on_load_complete_(std::move(on_load_complete)) {}
Shuran Huang71a22ff2022-02-11 14:54:1043
44FirstPartySetsLoader::~FirstPartySetsLoader() {
45 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
46}
47
48void FirstPartySetsLoader::SetManuallySpecifiedSet(
Chris Fredrickson8db7bf542022-09-06 17:47:2049 const LocalSetDeclaration& local_set) {
Shuran Huang71a22ff2022-02-11 14:54:1050 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Chris Fredrickson8db7bf542022-09-06 17:47:2051 manually_specified_set_ = local_set;
cfredriccc53588b2022-03-04 19:09:0052 UmaHistogramTimes(
Chris Fredrickson92e21d02022-04-22 21:16:1953 "Cookie.FirstPartySets.InitializationDuration.ReadCommandLineSet2",
cfredriccc53588b2022-03-04 19:09:0054 construction_timer_.Elapsed());
Shuran Huang71a22ff2022-02-11 14:54:1055
Shuran Huang71a22ff2022-02-11 14:54:1056 MaybeFinishLoading();
57}
58
59void FirstPartySetsLoader::SetComponentSets(base::File sets_file) {
60 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
61 if (component_sets_parse_progress_ != Progress::kNotStarted) {
62 DisposeFile(std::move(sets_file));
63 return;
64 }
65
66 component_sets_parse_progress_ = Progress::kStarted;
67
68 if (!sets_file.IsValid()) {
69 OnReadSetsFile("");
70 return;
71 }
72
73 // We use USER_BLOCKING here since First-Party Set initialization blocks
74 // network navigations at startup.
75 base::ThreadPool::PostTaskAndReplyWithResult(
76 FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
77 base::BindOnce(&ReadSetsFile, std::move(sets_file)),
78 base::BindOnce(&FirstPartySetsLoader::OnReadSetsFile,
79 weak_factory_.GetWeakPtr()));
80}
81
82void FirstPartySetsLoader::OnReadSetsFile(const std::string& raw_sets) {
83 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
84 DCHECK_EQ(component_sets_parse_progress_, Progress::kStarted);
85
cfredric6b6174462022-02-16 18:12:4886 std::istringstream stream(raw_sets);
Chris Fredricksond149b842022-08-17 21:41:0087 FirstPartySetParser::SetsAndAliases public_sets =
Chris Fredricksonf9de3452022-09-12 21:46:5688 FirstPartySetParser::ParseSetsFromStream(stream, /*emit_errors=*/false);
Chris Fredricksondd2f30962022-08-18 13:48:2789 sets_ = std::move(public_sets.first);
90 aliases_ = std::move(public_sets.second);
Shuran Huang71a22ff2022-02-11 14:54:1091
Shuran Huang71a22ff2022-02-11 14:54:1092 component_sets_parse_progress_ = Progress::kFinished;
cfredriccc53588b2022-03-04 19:09:0093 UmaHistogramTimes(
Chris Fredrickson92e21d02022-04-22 21:16:1994 "Cookie.FirstPartySets.InitializationDuration.ReadComponentSets2",
cfredriccc53588b2022-03-04 19:09:0095 construction_timer_.Elapsed());
Shuran Huang71a22ff2022-02-11 14:54:1096 MaybeFinishLoading();
97}
98
99void FirstPartySetsLoader::DisposeFile(base::File sets_file) {
100 if (sets_file.IsValid()) {
101 base::ThreadPool::PostTask(
102 FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
103 base::BindOnce(
104 [](base::File sets_file) {
105 // Run `sets_file`'s dtor in the threadpool.
106 },
107 std::move(sets_file)));
108 }
109}
110
111void FirstPartySetsLoader::ApplyManuallySpecifiedSet() {
112 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Kirubel Aklilu728454622022-04-15 19:04:18113 DCHECK(HasAllInputs());
Chris Fredrickson8db7bf542022-09-06 17:47:20114 if (manually_specified_set_->empty())
Shuran Huang71a22ff2022-02-11 14:54:10115 return;
Chris Fredricksonfcbdaac2022-08-10 16:38:42116 const net::SchemefulSite& manual_owner =
Chris Fredrickson8db7bf542022-09-06 17:47:20117 manually_specified_set_->GetPrimary();
Chris Fredrickson4ef2d242022-09-06 22:47:18118 FlattenedSets manual_sites = manually_specified_set_->GetSet();
Shuran Huang71a22ff2022-02-11 14:54:10119
Kirubel Aklilu6d1ef6b92022-07-08 13:40:19120 // Erase the intersection between |sets_| and |manually_specified_set_| and
Kirubel Aklilu728454622022-04-15 19:04:18121 // any members whose owner was in the intersection.
Chris Fredricksonfcbdaac2022-08-10 16:38:42122 base::EraseIf(
123 sets_, [&](const std::pair<net::SchemefulSite, net::FirstPartySetEntry>&
124 public_site_and_entry) {
125 const net::SchemefulSite& public_site = public_site_and_entry.first;
126 const net::SchemefulSite& public_owner =
127 public_site_and_entry.second.primary();
128 return public_site == manual_owner || public_owner == manual_owner ||
129 base::ranges::any_of(
130 manual_sites, [&](const std::pair<net::SchemefulSite,
131 net::FirstPartySetEntry>&
132 manual_site_and_entry) {
133 const net::SchemefulSite& manual_site =
134 manual_site_and_entry.first;
135 return manual_site == public_site ||
136 manual_site == public_owner;
137 });
138 });
Shuran Huang71a22ff2022-02-11 14:54:10139
Kirubel Aklilu6d1ef6b92022-07-08 13:40:19140 // Next, we must add the manually specified set to |sets_|.
Chris Fredrickson4ef2d242022-09-06 22:47:18141 base::ranges::move(manual_sites, std::inserter(sets_, sets_.end()));
Kirubel Aklilu289d61f2022-05-02 18:36:23142 // Now remove singleton sets, which are sets that just contain sites that
143 // *are* owners, but no longer have any (other) members.
144 std::set<net::SchemefulSite> owners_with_members;
145 for (const auto& it : sets_) {
Chris Fredricksonc2efa96f2022-08-04 20:40:44146 if (it.first != it.second.primary())
147 owners_with_members.insert(it.second.primary());
Kirubel Aklilu289d61f2022-05-02 18:36:23148 }
149 base::EraseIf(sets_, [&owners_with_members](const auto& p) {
Chris Fredricksonc2efa96f2022-08-04 20:40:44150 return p.first == p.second.primary() &&
151 !base::Contains(owners_with_members, p.first);
Kirubel Aklilu289d61f2022-05-02 18:36:23152 });
Chris Fredricksonf9de3452022-09-12 21:46:56153
154 // TODO(https://crbug.com/1349781): merge aliases.
Kirubel Aklilu289d61f2022-05-02 18:36:23155}
156
Shuran Huang71a22ff2022-02-11 14:54:10157void FirstPartySetsLoader::MaybeFinishLoading() {
158 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Kirubel Aklilu728454622022-04-15 19:04:18159 if (!HasAllInputs())
Shuran Huang71a22ff2022-02-11 14:54:10160 return;
cfredric0c632ce02022-03-03 19:14:52161 ApplyManuallySpecifiedSet();
Chris Fredrickson878d06b2022-09-08 15:20:37162 std::move(on_load_complete_)
163 .Run(net::PublicSets(std::move(sets_), std::move(aliases_)));
Shuran Huang71a22ff2022-02-11 14:54:10164}
165
Kirubel Aklilu728454622022-04-15 19:04:18166bool FirstPartySetsLoader::HasAllInputs() const {
167 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
168 return component_sets_parse_progress_ == Progress::kFinished &&
169 manually_specified_set_.has_value();
170}
171
Kirubel Aklilu583f57ab2022-04-12 16:10:50172} // namespace content