1 // Copyright 2019 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
5 #include "content/browser/browsing_data/same_site_data_remover_impl.h"
6
7 #include <memory>
8 #include <set>
9 #include <string>
10 #include <utility>
11 #include <vector>
12
13 #include "base/barrier_closure.h"
14 #include "base/bind.h"
15 #include "base/callback.h"
16 #include "content/public/browser/browser_context.h"
17 #include "content/public/browser/same_site_data_remover.h"
18 #include "content/public/browser/storage_partition.h"
19 #include "net/cookies/canonical_cookie.h"
20 #include "net/cookies/cookie_constants.h"
21 #include "net/cookies/cookie_monster.h"
22 #include "net/cookies/cookie_util.h"
23 #include "services/network/public/mojom/cookie_manager.mojom.h"
24 #include "url/origin.h"
25
26 namespace content {
27
28 namespace {
29
OnGetAllCookiesWithAccessSemantics(base::OnceClosure closure,network::mojom::CookieManager * cookie_manager,std::set<std::string> * same_site_none_domains,const std::vector<net::CanonicalCookie> & cookies,const std::vector<net::CookieAccessSemantics> & access_semantics_list)30 void OnGetAllCookiesWithAccessSemantics(
31 base::OnceClosure closure,
32 network::mojom::CookieManager* cookie_manager,
33 std::set<std::string>* same_site_none_domains,
34 const std::vector<net::CanonicalCookie>& cookies,
35 const std::vector<net::CookieAccessSemantics>& access_semantics_list) {
36 DCHECK(cookies.size() == access_semantics_list.size());
37 base::RepeatingClosure barrier =
38 base::BarrierClosure(cookies.size(), std::move(closure));
39 for (size_t i = 0; i < cookies.size(); ++i) {
40 const net::CanonicalCookie& cookie = cookies[i];
41 if (cookie.IsEffectivelySameSiteNone(access_semantics_list[i])) {
42 same_site_none_domains->emplace(cookie.Domain());
43 cookie_manager->DeleteCanonicalCookie(
44 cookie, base::BindOnce([](const base::RepeatingClosure& callback,
45 bool success) { callback.Run(); },
46 barrier));
47 } else {
48 barrier.Run();
49 }
50 }
51 }
52
DoesOriginMatchDomain(const std::set<std::string> & same_site_none_domains,const url::Origin & origin,storage::SpecialStoragePolicy * policy)53 bool DoesOriginMatchDomain(const std::set<std::string>& same_site_none_domains,
54 const url::Origin& origin,
55 storage::SpecialStoragePolicy* policy) {
56 for (const std::string& domain : same_site_none_domains) {
57 if (net::cookie_util::IsDomainMatch(domain, origin.host())) {
58 return true;
59 }
60 }
61 return false;
62 }
63
OnDeleteSameSiteNoneCookies(base::OnceClosure closure,std::unique_ptr<SameSiteDataRemoverImpl> remover,bool clear_storage)64 void OnDeleteSameSiteNoneCookies(
65 base::OnceClosure closure,
66 std::unique_ptr<SameSiteDataRemoverImpl> remover,
67 bool clear_storage) {
68 if (clear_storage) {
69 remover->ClearStoragePartitionData(std::move(closure));
70 } else {
71 std::move(closure).Run();
72 }
73 }
74
75 } // namespace
76
SameSiteDataRemoverImpl(BrowserContext * browser_context)77 SameSiteDataRemoverImpl::SameSiteDataRemoverImpl(
78 BrowserContext* browser_context)
79 : browser_context_(browser_context),
80 storage_partition_(
81 BrowserContext::GetDefaultStoragePartition(browser_context_)) {
82 DCHECK(browser_context_);
83 }
84
~SameSiteDataRemoverImpl()85 SameSiteDataRemoverImpl::~SameSiteDataRemoverImpl() {}
86
87 const std::set<std::string>&
GetDeletedDomainsForTesting()88 SameSiteDataRemoverImpl::GetDeletedDomainsForTesting() {
89 return same_site_none_domains_;
90 }
91
OverrideStoragePartitionForTesting(StoragePartition * storage_partition)92 void SameSiteDataRemoverImpl::OverrideStoragePartitionForTesting(
93 StoragePartition* storage_partition) {
94 storage_partition_ = storage_partition;
95 }
96
DeleteSameSiteNoneCookies(base::OnceClosure closure)97 void SameSiteDataRemoverImpl::DeleteSameSiteNoneCookies(
98 base::OnceClosure closure) {
99 same_site_none_domains_.clear();
100 auto* cookie_manager =
101 storage_partition_->GetCookieManagerForBrowserProcess();
102 cookie_manager->GetAllCookiesWithAccessSemantics(
103 base::BindOnce(&OnGetAllCookiesWithAccessSemantics, std::move(closure),
104 cookie_manager, &same_site_none_domains_));
105 }
106
ClearStoragePartitionData(base::OnceClosure closure)107 void SameSiteDataRemoverImpl::ClearStoragePartitionData(
108 base::OnceClosure closure) {
109 const uint32_t storage_partition_removal_mask =
110 content::StoragePartition::REMOVE_DATA_MASK_ALL &
111 ~content::StoragePartition::REMOVE_DATA_MASK_COOKIES;
112 const uint32_t quota_storage_removal_mask =
113 StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
114 // TODO(crbug.com/987177): Figure out how to handle protected storage.
115
116 storage_partition_->ClearData(
117 storage_partition_removal_mask, quota_storage_removal_mask,
118 base::BindRepeating(&DoesOriginMatchDomain, same_site_none_domains_),
119 nullptr, false, base::Time(), base::Time::Max(), std::move(closure));
120 }
121
122 // Defines the ClearSameSiteNoneData function declared in same_site_remover.h.
123 // Clears cookies and associated data available in third-party contexts.
ClearSameSiteNoneData(base::OnceClosure closure,BrowserContext * context,bool clear_storage)124 void ClearSameSiteNoneData(base::OnceClosure closure,
125 BrowserContext* context,
126 bool clear_storage) {
127 auto same_site_remover = std::make_unique<SameSiteDataRemoverImpl>(context);
128 SameSiteDataRemoverImpl* remover = same_site_remover.get();
129
130 remover->DeleteSameSiteNoneCookies(
131 base::BindOnce(&OnDeleteSameSiteNoneCookies, std::move(closure),
132 std::move(same_site_remover), clear_storage));
133 }
134
135 } // namespace content
136