1 // Copyright 2018 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/public/browser/clear_site_data_utils.h"
6
7 #include "base/scoped_observer.h"
8 #include "content/public/browser/browser_context.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "content/public/browser/browsing_data_filter_builder.h"
11 #include "content/public/browser/browsing_data_remover.h"
12 #include "content/public/browser/web_contents.h"
13 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
14
15 namespace content {
16
17 namespace {
18
19 // Finds the BrowserContext associated with the request and requests
20 // the actual clearing of data for |origin|. The data types to be deleted
21 // are determined by |clear_cookies|, |clear_storage|, and |clear_cache|.
22 // |web_contents_getter| identifies the WebContents from which the request
23 // originated. Must be run on the UI thread. The |callback| will be executed
24 // on the IO thread.
25 class SiteDataClearer : public BrowsingDataRemover::Observer {
26 public:
SiteDataClearer(BrowserContext * browser_context,const url::Origin & origin,bool clear_cookies,bool clear_storage,bool clear_cache,bool avoid_closing_connections,base::OnceClosure callback)27 SiteDataClearer(BrowserContext* browser_context,
28 const url::Origin& origin,
29 bool clear_cookies,
30 bool clear_storage,
31 bool clear_cache,
32 bool avoid_closing_connections,
33 base::OnceClosure callback)
34 : origin_(origin),
35 clear_cookies_(clear_cookies),
36 clear_storage_(clear_storage),
37 clear_cache_(clear_cache),
38 avoid_closing_connections_(avoid_closing_connections),
39 callback_(std::move(callback)),
40 pending_task_count_(0),
41 remover_(nullptr),
42 scoped_observer_(this) {
43 remover_ = BrowserContext::GetBrowsingDataRemover(browser_context);
44 DCHECK(remover_);
45 scoped_observer_.Add(remover_);
46 }
47
~SiteDataClearer()48 ~SiteDataClearer() override {
49 // This SiteDataClearer class is self-owned, and the only way for it to be
50 // destroyed should be the "delete this" part in
51 // OnBrowsingDataRemoverDone() function, and it invokes the |callback_|. So
52 // when this destructor is called, the |callback_| should be null.
53 DCHECK(!callback_);
54 }
55
RunAndDestroySelfWhenDone()56 void RunAndDestroySelfWhenDone() {
57 DCHECK_CURRENTLY_ON(BrowserThread::UI);
58 // Cookies and channel IDs are scoped to
59 // a) eTLD+1 of |origin|'s host if |origin|'s host is a registrable domain
60 // or a subdomain thereof
61 // b) |origin|'s host exactly if it is an IP address or an internal hostname
62 // (e.g. "localhost" or "fileserver").
63 // TODO(msramek): What about plugin data?
64 if (clear_cookies_) {
65 std::string domain = GetDomainAndRegistry(
66 origin_.host(),
67 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
68
69 if (domain.empty())
70 domain = origin_.host(); // IP address or internal hostname.
71
72 std::unique_ptr<BrowsingDataFilterBuilder> domain_filter_builder(
73 BrowsingDataFilterBuilder::Create(
74 BrowsingDataFilterBuilder::WHITELIST));
75 domain_filter_builder->AddRegisterableDomain(domain);
76
77 pending_task_count_++;
78 int remove_mask = BrowsingDataRemover::DATA_TYPE_COOKIES;
79 if (avoid_closing_connections_) {
80 remove_mask |= BrowsingDataRemover::DATA_TYPE_AVOID_CLOSING_CONNECTIONS;
81 }
82 remover_->RemoveWithFilterAndReply(
83 base::Time(), base::Time::Max(), remove_mask,
84 BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
85 BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
86 std::move(domain_filter_builder), this);
87 }
88
89 // Delete origin-scoped data.
90 int remove_mask = 0;
91 if (clear_storage_)
92 remove_mask |= BrowsingDataRemover::DATA_TYPE_DOM_STORAGE;
93 if (clear_cache_)
94 remove_mask |= BrowsingDataRemover::DATA_TYPE_CACHE;
95
96 if (remove_mask) {
97 std::unique_ptr<BrowsingDataFilterBuilder> origin_filter_builder(
98 BrowsingDataFilterBuilder::Create(
99 BrowsingDataFilterBuilder::WHITELIST));
100 origin_filter_builder->AddOrigin(origin_);
101
102 pending_task_count_++;
103 remover_->RemoveWithFilterAndReply(
104 base::Time(), base::Time::Max(), remove_mask,
105 BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
106 BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
107 std::move(origin_filter_builder), this);
108 }
109
110 DCHECK_GT(pending_task_count_, 0);
111 }
112
113 private:
114 // BrowsingDataRemover::Observer:
OnBrowsingDataRemoverDone()115 void OnBrowsingDataRemoverDone() override {
116 DCHECK(pending_task_count_);
117 if (--pending_task_count_)
118 return;
119
120 std::move(callback_).Run();
121 delete this;
122 }
123
124 url::Origin origin_;
125 bool clear_cookies_;
126 bool clear_storage_;
127 bool clear_cache_;
128 bool avoid_closing_connections_;
129 base::OnceClosure callback_;
130 int pending_task_count_;
131 BrowsingDataRemover* remover_;
132 ScopedObserver<BrowsingDataRemover, BrowsingDataRemover::Observer>
133 scoped_observer_;
134 };
135
136 } // namespace
137
ClearSiteData(const base::RepeatingCallback<BrowserContext * ()> & browser_context_getter,const url::Origin & origin,bool clear_cookies,bool clear_storage,bool clear_cache,bool avoid_closing_connections,base::OnceClosure callback)138 void ClearSiteData(
139 const base::RepeatingCallback<BrowserContext*()>& browser_context_getter,
140 const url::Origin& origin,
141 bool clear_cookies,
142 bool clear_storage,
143 bool clear_cache,
144 bool avoid_closing_connections,
145 base::OnceClosure callback) {
146 DCHECK_CURRENTLY_ON(BrowserThread::UI);
147 BrowserContext* browser_context = browser_context_getter.Run();
148 if (!browser_context) {
149 std::move(callback).Run();
150 return;
151 }
152 (new SiteDataClearer(browser_context, origin, clear_cookies, clear_storage,
153 clear_cache, avoid_closing_connections,
154 std::move(callback)))
155 ->RunAndDestroySelfWhenDone();
156 }
157
158 } // namespace content
159