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