1 // Copyright (c) 2012 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 "chrome/browser/browsing_data/cookies_tree_model.h"
6 
7 #include <stddef.h>
8 
9 #include <algorithm>
10 #include <functional>
11 #include <map>
12 #include <numeric>
13 #include <utility>
14 #include <vector>
15 
16 #include "base/bind.h"
17 #include "base/callback_helpers.h"
18 #include "base/memory/ptr_util.h"
19 #include "base/run_loop.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "build/build_config.h"
23 #include "chrome/browser/browsing_data/browsing_data_file_system_util.h"
24 #include "chrome/browser/browsing_data/browsing_data_quota_helper.h"
25 #include "chrome/browser/content_settings/cookie_settings_factory.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/grit/generated_resources.h"
28 #include "chrome/grit/theme_resources.h"
29 #include "components/browsing_data/content/appcache_helper.h"
30 #include "components/browsing_data/content/cache_storage_helper.h"
31 #include "components/browsing_data/content/cookie_helper.h"
32 #include "components/browsing_data/content/database_helper.h"
33 #include "components/browsing_data/content/file_system_helper.h"
34 #include "components/browsing_data/content/indexed_db_helper.h"
35 #include "components/browsing_data/content/local_storage_helper.h"
36 #include "components/browsing_data/content/service_worker_helper.h"
37 #include "components/browsing_data/content/shared_worker_helper.h"
38 #include "components/content_settings/core/browser/cookie_settings.h"
39 #include "components/permissions/permissions_client.h"
40 #include "components/vector_icons/vector_icons.h"
41 #include "content/public/browser/storage_partition.h"
42 #include "content/public/browser/storage_usage_info.h"
43 #include "content/public/common/url_constants.h"
44 #include "extensions/buildflags/buildflags.h"
45 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
46 #include "net/cookies/canonical_cookie.h"
47 #include "net/cookies/cookie_util.h"
48 #include "ui/base/l10n/l10n_util.h"
49 #include "ui/base/resource/resource_bundle.h"
50 #include "ui/gfx/color_palette.h"
51 #include "ui/gfx/image/image_skia.h"
52 #include "ui/gfx/paint_vector_icon.h"
53 #include "ui/resources/grit/ui_resources.h"
54 #include "url/gurl.h"
55 #include "url/origin.h"
56 
57 #if BUILDFLAG(ENABLE_EXTENSIONS)
58 #include "chrome/browser/extensions/extension_special_storage_policy.h"
59 #include "extensions/common/extension_set.h"
60 #endif
61 
62 #if !defined(OS_ANDROID)
63 #include "chrome/browser/browsing_data/access_context_audit_service.h"
64 #include "chrome/browser/browsing_data/access_context_audit_service_factory.h"
65 #endif  // !defined(OS_ANDROID)
66 
67 namespace {
68 
69 struct NodeTitleComparator {
operator ()__anone62369780111::NodeTitleComparator70   bool operator()(const std::unique_ptr<CookieTreeNode>& lhs,
71                   const std::unique_ptr<CookieTreeNode>& rhs) {
72     return lhs->GetTitle() < rhs->GetTitle();
73   }
74 };
75 
76 // Comparison functor, for use in CookieTreeRootNode.
77 struct HostNodeComparator {
operator ()__anone62369780111::HostNodeComparator78   bool operator()(const std::unique_ptr<CookieTreeNode>& lhs,
79                   const std::unique_ptr<CookieTreeHostNode>& rhs) {
80     // This comparator is only meant to compare CookieTreeHostNode types. Make
81     // sure we check this, as the static cast below is dangerous if we get the
82     // wrong object type.
83     CHECK_EQ(CookieTreeNode::DetailedInfo::TYPE_HOST,
84              lhs->GetDetailedInfo().node_type);
85     CHECK_EQ(CookieTreeNode::DetailedInfo::TYPE_HOST,
86              rhs->GetDetailedInfo().node_type);
87 
88     const CookieTreeHostNode* ltn =
89         static_cast<const CookieTreeHostNode*>(lhs.get());
90     const CookieTreeHostNode* rtn = rhs.get();
91 
92     // We want to order by registry controlled domain, so we would get
93     // google.com, ad.google.com, www.google.com,
94     // microsoft.com, ad.microsoft.com. CanonicalizeHost transforms the origins
95     // into a form like google.com.www so that string comparisons work.
96     return ltn->canonicalized_host() < rtn->canonicalized_host();
97   }
98 };
99 
CanonicalizeHost(const GURL & url)100 std::string CanonicalizeHost(const GURL& url) {
101   // The canonicalized representation makes the registry controlled domain come
102   // first, and then adds subdomains in reverse order, e.g.  1.mail.google.com
103   // would become google.com.mail.1, and then a standard string comparison works
104   // to order hosts by registry controlled domain first. Leading dots are
105   // ignored, ".google.com" is the same as "google.com".
106   if (url.SchemeIsFile()) {
107     return std::string(url::kFileScheme) + url::kStandardSchemeSeparator;
108   }
109 
110   std::string retval = net::registry_controlled_domains::GetDomainAndRegistry(
111       url, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
112   std::string host = url.host();
113   if (retval.empty())  // Is an IP address or other special origin.
114     return host;
115 
116   std::string::size_type position = host.rfind(retval);
117 
118   // The host may be the registry controlled domain, in which case fail fast.
119   if (position == 0 || position == std::string::npos)
120     return host;
121 
122   // If host is www.google.com, retval will contain google.com at this point.
123   // Start operating to the left of the registry controlled domain, e.g. in
124   // the www.google.com example, start at index 3.
125   --position;
126 
127   // If position == 0, that means it's a dot; this will be ignored to treat
128   // ".google.com" the same as "google.com".
129   while (position > 0) {
130     retval += std::string(".");
131     // Copy up to the next dot. host[position] is a dot so start after it.
132     std::string::size_type next_dot = host.rfind(".", position - 1);
133     if (next_dot == std::string::npos) {
134       retval += host.substr(0, position);
135       break;
136     }
137     retval += host.substr(next_dot + 1, position - (next_dot + 1));
138     position = next_dot;
139   }
140   return retval;
141 }
142 
143 #if BUILDFLAG(ENABLE_EXTENSIONS)
TypeIsProtected(CookieTreeNode::DetailedInfo::NodeType type)144 bool TypeIsProtected(CookieTreeNode::DetailedInfo::NodeType type) {
145   switch (type) {
146     // Fall through each below cases to return true.
147     case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
148     case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
149     case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
150     case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
151     case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
152     case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM:
153     case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER:
154     case CookieTreeNode::DetailedInfo::TYPE_SHARED_WORKER:
155     case CookieTreeNode::DetailedInfo::TYPE_CACHE_STORAGE:
156       return true;
157 
158     // Fall through each below cases to return false.
159     case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
160     case CookieTreeNode::DetailedInfo::TYPE_QUOTA:
161     case CookieTreeNode::DetailedInfo::TYPE_MEDIA_LICENSE:
162       return false;
163     default:
164       break;
165   }
166   return false;
167 }
168 #endif
169 
170 // This function returns the local data container associated with a leaf tree
171 // node. The app node is assumed to be 3 levels above the leaf because of the
172 // following structure:
173 //   root -> origin -> storage type -> leaf node
GetLocalDataContainerForNode(CookieTreeNode * node)174 LocalDataContainer* GetLocalDataContainerForNode(CookieTreeNode* node) {
175   CookieTreeHostNode* host = static_cast<CookieTreeHostNode*>(
176       node->parent()->parent());
177   CHECK_EQ(host->GetDetailedInfo().node_type,
178            CookieTreeNode::DetailedInfo::TYPE_HOST);
179   return node->GetModel()->data_container();
180 }
181 
182 }  // namespace
183 
DetailedInfo()184 CookieTreeNode::DetailedInfo::DetailedInfo() : node_type(TYPE_NONE) {}
185 
186 CookieTreeNode::DetailedInfo::DetailedInfo(const DetailedInfo& other) = default;
187 
188 CookieTreeNode::DetailedInfo::~DetailedInfo() = default;
189 
Init(NodeType type)190 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::Init(
191     NodeType type) {
192   DCHECK_EQ(TYPE_NONE, node_type);
193   node_type = type;
194   return *this;
195 }
196 
InitHost(const GURL & origin)197 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitHost(
198     const GURL& origin) {
199   Init(TYPE_HOST);
200   this->origin = url::Origin::Create(origin);
201   return *this;
202 }
203 
InitCookie(const net::CanonicalCookie * cookie)204 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitCookie(
205     const net::CanonicalCookie* cookie) {
206   Init(TYPE_COOKIE);
207   this->cookie = cookie;
208   return *this;
209 }
210 
InitDatabase(const content::StorageUsageInfo * usage_info)211 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitDatabase(
212     const content::StorageUsageInfo* usage_info) {
213   Init(TYPE_DATABASE);
214   this->usage_info = usage_info;
215   origin = usage_info->origin;
216   return *this;
217 }
218 
InitLocalStorage(const content::StorageUsageInfo * usage_info)219 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitLocalStorage(
220     const content::StorageUsageInfo* usage_info) {
221   Init(TYPE_LOCAL_STORAGE);
222   this->usage_info = usage_info;
223   origin = usage_info->origin;
224   return *this;
225 }
226 
InitSessionStorage(const content::StorageUsageInfo * usage_info)227 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitSessionStorage(
228     const content::StorageUsageInfo* usage_info) {
229   Init(TYPE_SESSION_STORAGE);
230   this->usage_info = usage_info;
231   origin = usage_info->origin;
232   return *this;
233 }
234 
InitAppCache(const content::StorageUsageInfo * usage_info)235 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitAppCache(
236     const content::StorageUsageInfo* usage_info) {
237   Init(TYPE_APPCACHE);
238   this->usage_info = usage_info;
239   origin = usage_info->origin;
240   return *this;
241 }
242 
InitIndexedDB(const content::StorageUsageInfo * usage_info)243 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitIndexedDB(
244     const content::StorageUsageInfo* usage_info) {
245   Init(TYPE_INDEXED_DB);
246   this->usage_info = usage_info;
247   this->origin = usage_info->origin;
248   return *this;
249 }
250 
InitFileSystem(const browsing_data::FileSystemHelper::FileSystemInfo * file_system_info)251 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitFileSystem(
252     const browsing_data::FileSystemHelper::FileSystemInfo* file_system_info) {
253   Init(TYPE_FILE_SYSTEM);
254   this->file_system_info = file_system_info;
255   this->origin = file_system_info->origin;
256   return *this;
257 }
258 
InitQuota(const BrowsingDataQuotaHelper::QuotaInfo * quota_info)259 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitQuota(
260     const BrowsingDataQuotaHelper::QuotaInfo* quota_info) {
261   Init(TYPE_QUOTA);
262   this->quota_info = quota_info;
263   return *this;
264 }
265 
InitServiceWorker(const content::StorageUsageInfo * usage_info)266 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitServiceWorker(
267     const content::StorageUsageInfo* usage_info) {
268   Init(TYPE_SERVICE_WORKER);
269   this->usage_info = usage_info;
270   this->origin = usage_info->origin;
271   return *this;
272 }
273 
InitSharedWorker(const browsing_data::SharedWorkerHelper::SharedWorkerInfo * shared_worker_info)274 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitSharedWorker(
275     const browsing_data::SharedWorkerHelper::SharedWorkerInfo*
276         shared_worker_info) {
277   Init(TYPE_SHARED_WORKER);
278   this->shared_worker_info = shared_worker_info;
279   this->origin = url::Origin::Create(shared_worker_info->worker.GetOrigin());
280   return *this;
281 }
282 
InitCacheStorage(const content::StorageUsageInfo * usage_info)283 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitCacheStorage(
284     const content::StorageUsageInfo* usage_info) {
285   Init(TYPE_CACHE_STORAGE);
286   this->usage_info = usage_info;
287   this->origin = usage_info->origin;
288   return *this;
289 }
290 
InitMediaLicense(const BrowsingDataMediaLicenseHelper::MediaLicenseInfo * media_license_info)291 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitMediaLicense(
292     const BrowsingDataMediaLicenseHelper::MediaLicenseInfo*
293         media_license_info) {
294   Init(TYPE_MEDIA_LICENSE);
295   this->media_license_info = media_license_info;
296   this->origin = url::Origin::Create(media_license_info->origin);
297   return *this;
298 }
299 
300 ///////////////////////////////////////////////////////////////////////////////
301 // CookieTreeNode, public:
302 
DeleteStoredObjects()303 void CookieTreeNode::DeleteStoredObjects() {
304   for (const auto& child : children())
305     child->DeleteStoredObjects();
306 }
307 
GetModel() const308 CookiesTreeModel* CookieTreeNode::GetModel() const {
309   if (parent())
310     return parent()->GetModel();
311   return nullptr;
312 }
313 
InclusiveSize() const314 int64_t CookieTreeNode::InclusiveSize() const {
315   return 0;
316 }
317 
NumberOfCookies() const318 int CookieTreeNode::NumberOfCookies() const {
319   return std::accumulate(children().cbegin(), children().cend(), 0,
320                          [](int total, const auto& child) {
321                            return total + child->NumberOfCookies();
322                          });
323 }
324 
AddChildSortedByTitle(std::unique_ptr<CookieTreeNode> new_child)325 void CookieTreeNode::AddChildSortedByTitle(
326     std::unique_ptr<CookieTreeNode> new_child) {
327   DCHECK(new_child);
328   auto iter = std::lower_bound(children().begin(), children().end(), new_child,
329                                NodeTitleComparator());
330   GetModel()->Add(this, std::move(new_child),
331                   size_t{iter - children().begin()});
332 }
333 
334 #if !defined(OS_ANDROID)
ReportDeletionToAuditService(const url::Origin & origin,AccessContextAuditDatabase::StorageAPIType type)335 void CookieTreeNode::ReportDeletionToAuditService(
336     const url::Origin& origin,
337     AccessContextAuditDatabase::StorageAPIType type) {
338   auto* audit_service = GetModel()->access_context_audit_service();
339   if (audit_service)
340     audit_service->RemoveAllRecordsForOriginKeyedStorage(origin, type);
341 }
342 #endif  // !defined(OS_ANDROID)
343 
344 ///////////////////////////////////////////////////////////////////////////////
345 // CookieTreeCookieNode
346 
347 class CookieTreeCookieNode : public CookieTreeNode {
348  public:
349   friend class CookieTreeCookiesNode;
350 
351   // The cookie should remain valid at least as long as the
352   // CookieTreeCookieNode is valid.
CookieTreeCookieNode(std::list<net::CanonicalCookie>::iterator cookie)353   explicit CookieTreeCookieNode(
354       std::list<net::CanonicalCookie>::iterator cookie)
355       : CookieTreeNode(base::UTF8ToUTF16(cookie->Name())), cookie_(cookie) {}
356 
357   ~CookieTreeCookieNode() override = default;
358 
359   // CookieTreeNode methods:
DeleteStoredObjects()360   void DeleteStoredObjects() override {
361     LocalDataContainer* container = GetLocalDataContainerForNode(this);
362     container->cookie_helper_->DeleteCookie(*cookie_);
363     container->cookie_list_.erase(cookie_);
364   }
GetDetailedInfo() const365   DetailedInfo GetDetailedInfo() const override {
366     return DetailedInfo().InitCookie(&*cookie_);
367   }
368 
NumberOfCookies() const369   int NumberOfCookies() const override { return 1; }
370 
371  private:
372   // |cookie_| is expected to remain valid as long as the CookieTreeCookieNode
373   // is valid.
374   std::list<net::CanonicalCookie>::iterator cookie_;
375 
376   DISALLOW_COPY_AND_ASSIGN(CookieTreeCookieNode);
377 };
378 
379 ///////////////////////////////////////////////////////////////////////////////
380 // CookieTreeAppCacheNode
381 
382 class CookieTreeAppCacheNode : public CookieTreeNode {
383  public:
384   friend class CookieTreeAppCachesNode;
385 
386   // |appcache_info| should remain valid at least as long as the
387   // CookieTreeAppCacheNode is valid.
CookieTreeAppCacheNode(std::list<content::StorageUsageInfo>::iterator usage_info)388   explicit CookieTreeAppCacheNode(
389       std::list<content::StorageUsageInfo>::iterator usage_info)
390       : CookieTreeNode(base::UTF8ToUTF16(usage_info->origin.Serialize())),
391         usage_info_(usage_info) {}
392   ~CookieTreeAppCacheNode() override = default;
393 
DeleteStoredObjects()394   void DeleteStoredObjects() override {
395     LocalDataContainer* container = GetLocalDataContainerForNode(this);
396 
397     if (container) {
398       container->appcache_helper_->DeleteAppCaches(usage_info_->origin);
399       container->appcache_info_list_.erase(usage_info_);
400     }
401   }
GetDetailedInfo() const402   DetailedInfo GetDetailedInfo() const override {
403     return DetailedInfo().InitAppCache(&*usage_info_);
404   }
405 
InclusiveSize() const406   int64_t InclusiveSize() const override {
407     return usage_info_->total_size_bytes;
408   }
409 
410  private:
411   // |usage_info_| is expected to remain valid as long as this node is valid.
412   std::list<content::StorageUsageInfo>::iterator usage_info_;
413 
414   DISALLOW_COPY_AND_ASSIGN(CookieTreeAppCacheNode);
415 };
416 
417 ///////////////////////////////////////////////////////////////////////////////
418 // CookieTreeDatabaseNode
419 
420 class CookieTreeDatabaseNode : public CookieTreeNode {
421  public:
422   friend class CookieTreeDatabasesNode;
423 
424   // |usage_info| should remain valid at least as long as the
425   // CookieTreeDatabaseNode is valid.
CookieTreeDatabaseNode(std::list<content::StorageUsageInfo>::iterator usage_info)426   explicit CookieTreeDatabaseNode(
427       std::list<content::StorageUsageInfo>::iterator usage_info)
428       : CookieTreeNode(base::UTF8ToUTF16(usage_info->origin.Serialize())),
429         usage_info_(usage_info) {}
430 
431   ~CookieTreeDatabaseNode() override = default;
432 
DeleteStoredObjects()433   void DeleteStoredObjects() override {
434     LocalDataContainer* container = GetLocalDataContainerForNode(this);
435 
436     if (container) {
437 #if !defined(OS_ANDROID)
438       ReportDeletionToAuditService(
439           usage_info_->origin,
440           AccessContextAuditDatabase::StorageAPIType::kWebDatabase);
441 #endif  // !defined(OS_ANDROID)
442 
443       container->database_helper_->DeleteDatabase(usage_info_->origin);
444       container->database_info_list_.erase(usage_info_);
445     }
446   }
447 
GetDetailedInfo() const448   DetailedInfo GetDetailedInfo() const override {
449     return DetailedInfo().InitDatabase(&*usage_info_);
450   }
451 
InclusiveSize() const452   int64_t InclusiveSize() const override {
453     return usage_info_->total_size_bytes;
454   }
455 
456  private:
457   // |database_info_| is expected to remain valid as long as the
458   // CookieTreeDatabaseNode is valid.
459   std::list<content::StorageUsageInfo>::iterator usage_info_;
460 
461   DISALLOW_COPY_AND_ASSIGN(CookieTreeDatabaseNode);
462 };
463 
464 ///////////////////////////////////////////////////////////////////////////////
465 // CookieTreeLocalStorageNode
466 
467 class CookieTreeLocalStorageNode : public CookieTreeNode {
468  public:
469   // |usage_info| should remain valid at least as long as the
470   // CookieTreeLocalStorageNode is valid.
CookieTreeLocalStorageNode(std::list<content::StorageUsageInfo>::iterator local_storage_info)471   explicit CookieTreeLocalStorageNode(
472       std::list<content::StorageUsageInfo>::iterator local_storage_info)
473       : CookieTreeNode(
474             base::UTF8ToUTF16(local_storage_info->origin.Serialize())),
475         local_storage_info_(local_storage_info) {}
476 
477   ~CookieTreeLocalStorageNode() override = default;
478 
479   // CookieTreeNode methods:
DeleteStoredObjects()480   void DeleteStoredObjects() override {
481     LocalDataContainer* container = GetLocalDataContainerForNode(this);
482 
483     if (container) {
484 #if !defined(OS_ANDROID)
485       ReportDeletionToAuditService(
486           local_storage_info_->origin,
487           AccessContextAuditDatabase::StorageAPIType::kLocalStorage);
488 #endif  // !defined(OS_ANDROID)
489 
490       container->local_storage_helper_->DeleteOrigin(
491           local_storage_info_->origin, base::DoNothing());
492       container->local_storage_info_list_.erase(local_storage_info_);
493     }
494   }
GetDetailedInfo() const495   DetailedInfo GetDetailedInfo() const override {
496     return DetailedInfo().InitLocalStorage(&*local_storage_info_);
497   }
498 
InclusiveSize() const499   int64_t InclusiveSize() const override {
500     return local_storage_info_->total_size_bytes;
501   }
502 
503  private:
504   // |local_storage_info_| is expected to remain valid as long as the
505   // CookieTreeLocalStorageNode is valid.
506   std::list<content::StorageUsageInfo>::iterator local_storage_info_;
507 
508   DISALLOW_COPY_AND_ASSIGN(CookieTreeLocalStorageNode);
509 };
510 
511 ///////////////////////////////////////////////////////////////////////////////
512 // CookieTreeSessionStorageNode
513 
514 class CookieTreeSessionStorageNode : public CookieTreeNode {
515  public:
516   // |session_storage_info| should remain valid at least as long as the
517   // CookieTreeSessionStorageNode is valid.
CookieTreeSessionStorageNode(std::list<content::StorageUsageInfo>::iterator session_storage_info)518   explicit CookieTreeSessionStorageNode(
519       std::list<content::StorageUsageInfo>::iterator session_storage_info)
520       : CookieTreeNode(
521             base::UTF8ToUTF16(session_storage_info->origin.Serialize())),
522         session_storage_info_(session_storage_info) {}
523 
524   ~CookieTreeSessionStorageNode() override = default;
525 
526   // CookieTreeNode methods:
DeleteStoredObjects()527   void DeleteStoredObjects() override {
528     LocalDataContainer* container = GetLocalDataContainerForNode(this);
529 
530     if (container) {
531       // TODO(rsesek): There's no easy way to get the namespace_id for a session
532       // storage, nor is there an easy way to clear session storage just by
533       // origin. This is probably okay since session storage is not persistent.
534       // http://crbug.com/168996
535       container->session_storage_info_list_.erase(session_storage_info_);
536     }
537   }
GetDetailedInfo() const538   DetailedInfo GetDetailedInfo() const override {
539     return DetailedInfo().InitSessionStorage(&*session_storage_info_);
540   }
541 
542  private:
543   // |session_storage_info_| is expected to remain valid as long as the
544   // CookieTreeSessionStorageNode is valid.
545   std::list<content::StorageUsageInfo>::iterator session_storage_info_;
546 
547   DISALLOW_COPY_AND_ASSIGN(CookieTreeSessionStorageNode);
548 };
549 
550 ///////////////////////////////////////////////////////////////////////////////
551 // CookieTreeIndexedDBNode
552 
553 class CookieTreeIndexedDBNode : public CookieTreeNode {
554  public:
555   // |usage_info| should remain valid at least as long as the
556   // CookieTreeIndexedDBNode is valid.
CookieTreeIndexedDBNode(std::list<content::StorageUsageInfo>::iterator usage_info)557   explicit CookieTreeIndexedDBNode(
558       std::list<content::StorageUsageInfo>::iterator usage_info)
559       : CookieTreeNode(base::UTF8ToUTF16(usage_info->origin.Serialize())),
560         usage_info_(usage_info) {}
561 
562   ~CookieTreeIndexedDBNode() override = default;
563 
564   // CookieTreeNode methods:
DeleteStoredObjects()565   void DeleteStoredObjects() override {
566     LocalDataContainer* container = GetLocalDataContainerForNode(this);
567 
568     if (container) {
569 #if !defined(OS_ANDROID)
570       ReportDeletionToAuditService(
571           usage_info_->origin,
572           AccessContextAuditDatabase::StorageAPIType::kIndexedDB);
573 #endif  // !defined(OS_ANDROID)
574 
575       container->indexed_db_helper_->DeleteIndexedDB(usage_info_->origin,
576                                                      base::DoNothing());
577       container->indexed_db_info_list_.erase(usage_info_);
578     }
579   }
580 
GetDetailedInfo() const581   DetailedInfo GetDetailedInfo() const override {
582     return DetailedInfo().InitIndexedDB(&*usage_info_);
583   }
584 
InclusiveSize() const585   int64_t InclusiveSize() const override {
586     return usage_info_->total_size_bytes;
587   }
588 
589  private:
590   // |usage_info_| is expected to remain valid as long as the
591   // CookieTreeIndexedDBNode is valid.
592   std::list<content::StorageUsageInfo>::iterator usage_info_;
593 
594   DISALLOW_COPY_AND_ASSIGN(CookieTreeIndexedDBNode);
595 };
596 
597 ///////////////////////////////////////////////////////////////////////////////
598 // CookieTreeFileSystemNode
599 
600 class CookieTreeFileSystemNode : public CookieTreeNode {
601  public:
602   friend class CookieTreeFileSystemsNode;
603 
604   // |file_system_info| should remain valid at least as long as the
605   // CookieTreeFileSystemNode is valid.
CookieTreeFileSystemNode(std::list<browsing_data::FileSystemHelper::FileSystemInfo>::iterator file_system_info)606   explicit CookieTreeFileSystemNode(
607       std::list<browsing_data::FileSystemHelper::FileSystemInfo>::iterator
608           file_system_info)
609       : CookieTreeNode(base::UTF8ToUTF16(file_system_info->origin.Serialize())),
610         file_system_info_(file_system_info) {}
611   ~CookieTreeFileSystemNode() override = default;
612 
DeleteStoredObjects()613   void DeleteStoredObjects() override {
614     LocalDataContainer* container = GetLocalDataContainerForNode(this);
615 
616     if (container) {
617 #if !defined(OS_ANDROID)
618       ReportDeletionToAuditService(
619           file_system_info_->origin,
620           AccessContextAuditDatabase::StorageAPIType::kFileSystem);
621 #endif  // !defined(OS_ANDROID)
622 
623       container->file_system_helper_->DeleteFileSystemOrigin(
624           file_system_info_->origin);
625       container->file_system_info_list_.erase(file_system_info_);
626     }
627   }
628 
GetDetailedInfo() const629   DetailedInfo GetDetailedInfo() const override {
630     return DetailedInfo().InitFileSystem(&*file_system_info_);
631   }
632 
InclusiveSize() const633   int64_t InclusiveSize() const override {
634     int64_t size = 0;
635     for (auto const& usage : file_system_info_->usage_map) {
636       size += usage.second;
637     }
638     return size;
639   }
640 
641  private:
642   // file_system_info_ expected to remain valid as long as the
643   // CookieTreeFileSystemNode is valid.
644   std::list<browsing_data::FileSystemHelper::FileSystemInfo>::iterator
645       file_system_info_;
646 
647   DISALLOW_COPY_AND_ASSIGN(CookieTreeFileSystemNode);
648 };
649 
650 ///////////////////////////////////////////////////////////////////////////////
651 // CookieTreeQuotaNode
652 
653 class CookieTreeQuotaNode : public CookieTreeNode {
654  public:
655   // |quota_info| should remain valid at least as long as the
656   // CookieTreeQuotaNode is valid.
CookieTreeQuotaNode(std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)657   explicit CookieTreeQuotaNode(
658       std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)
659       : CookieTreeNode(base::UTF8ToUTF16(quota_info->host)),
660         quota_info_(quota_info) {}
661 
662   ~CookieTreeQuotaNode() override = default;
663 
DeleteStoredObjects()664   void DeleteStoredObjects() override {
665     // Calling this function may cause unexpected over-quota state of origin.
666     // However, it'll caused no problem, just prevent usage growth of the
667     // origin.
668     LocalDataContainer* container = GetModel()->data_container();
669 
670     if (container) {
671       container->quota_helper_->RevokeHostQuota(quota_info_->host);
672       container->quota_info_list_.erase(quota_info_);
673     }
674   }
GetDetailedInfo() const675   DetailedInfo GetDetailedInfo() const override {
676     return DetailedInfo().InitQuota(&*quota_info_);
677   }
678 
679  private:
680   // |quota_info_| is expected to remain valid as long as the
681   // CookieTreeQuotaNode is valid.
682   std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info_;
683 
684   DISALLOW_COPY_AND_ASSIGN(CookieTreeQuotaNode);
685 };
686 
687 ///////////////////////////////////////////////////////////////////////////////
688 // CookieTreeServiceWorkerNode
689 
690 class CookieTreeServiceWorkerNode : public CookieTreeNode {
691  public:
692   // |usage_info| should remain valid at least as long as the
693   // CookieTreeServiceWorkerNode is valid.
CookieTreeServiceWorkerNode(std::list<content::StorageUsageInfo>::iterator usage_info)694   explicit CookieTreeServiceWorkerNode(
695       std::list<content::StorageUsageInfo>::iterator usage_info)
696       : CookieTreeNode(base::UTF8ToUTF16(usage_info->origin.Serialize())),
697         usage_info_(usage_info) {}
698 
~CookieTreeServiceWorkerNode()699   ~CookieTreeServiceWorkerNode() override {}
700 
701   // CookieTreeNode methods:
DeleteStoredObjects()702   void DeleteStoredObjects() override {
703     LocalDataContainer* container = GetLocalDataContainerForNode(this);
704 
705     if (container) {
706 #if !defined(OS_ANDROID)
707       ReportDeletionToAuditService(
708           usage_info_->origin,
709           AccessContextAuditDatabase::StorageAPIType::kServiceWorker);
710 #endif  // !defined(OS_ANDROID)
711 
712       container->service_worker_helper_->DeleteServiceWorkers(
713           usage_info_->origin);
714       container->service_worker_info_list_.erase(usage_info_);
715     }
716   }
717 
GetDetailedInfo() const718   DetailedInfo GetDetailedInfo() const override {
719     return DetailedInfo().InitServiceWorker(&*usage_info_);
720   }
721 
InclusiveSize() const722   int64_t InclusiveSize() const override {
723     return usage_info_->total_size_bytes;
724   }
725 
726  private:
727   // |usage_info_| is expected to remain valid as long as the
728   // CookieTreeServiceWorkerNode is valid.
729   std::list<content::StorageUsageInfo>::iterator usage_info_;
730 
731   DISALLOW_COPY_AND_ASSIGN(CookieTreeServiceWorkerNode);
732 };
733 
734 ///////////////////////////////////////////////////////////////////////////////
735 // CookieTreeSharedWorkerNode
736 
737 class CookieTreeSharedWorkerNode : public CookieTreeNode {
738  public:
739   // |shared_worker_info| should remain valid at least as long as the
740   // CookieTreeSharedWorkerNode is valid.
CookieTreeSharedWorkerNode(std::list<browsing_data::SharedWorkerHelper::SharedWorkerInfo>::iterator shared_worker_info)741   explicit CookieTreeSharedWorkerNode(
742       std::list<browsing_data::SharedWorkerHelper::SharedWorkerInfo>::iterator
743           shared_worker_info)
744       : CookieTreeNode(base::UTF8ToUTF16(shared_worker_info->worker.spec())),
745         shared_worker_info_(shared_worker_info) {}
746 
747   ~CookieTreeSharedWorkerNode() override = default;
748 
749   // CookieTreeNode methods:
DeleteStoredObjects()750   void DeleteStoredObjects() override {
751     LocalDataContainer* container = GetLocalDataContainerForNode(this);
752 
753     if (container) {
754       container->shared_worker_helper_->DeleteSharedWorker(
755           shared_worker_info_->worker, shared_worker_info_->name,
756           shared_worker_info_->constructor_origin);
757       container->shared_worker_info_list_.erase(shared_worker_info_);
758     }
759   }
760 
GetDetailedInfo() const761   DetailedInfo GetDetailedInfo() const override {
762     return DetailedInfo().InitSharedWorker(&*shared_worker_info_);
763   }
764 
765  private:
766   // |shared_worker_info_| is expected to remain valid as long as the
767   // CookieTreeSharedWorkerNode is valid.
768   std::list<browsing_data::SharedWorkerHelper::SharedWorkerInfo>::iterator
769       shared_worker_info_;
770 
771   DISALLOW_COPY_AND_ASSIGN(CookieTreeSharedWorkerNode);
772 };
773 
774 ///////////////////////////////////////////////////////////////////////////////
775 // CookieTreeCacheStorageNode
776 
777 class CookieTreeCacheStorageNode : public CookieTreeNode {
778  public:
779   // |usage_info| should remain valid at least as long as the
780   // CookieTreeCacheStorageNode is valid.
CookieTreeCacheStorageNode(std::list<content::StorageUsageInfo>::iterator usage_info)781   explicit CookieTreeCacheStorageNode(
782       std::list<content::StorageUsageInfo>::iterator usage_info)
783       : CookieTreeNode(base::UTF8ToUTF16(usage_info->origin.Serialize())),
784         usage_info_(usage_info) {}
785 
786   ~CookieTreeCacheStorageNode() override = default;
787 
788   // CookieTreeNode methods:
DeleteStoredObjects()789   void DeleteStoredObjects() override {
790     LocalDataContainer* container = GetLocalDataContainerForNode(this);
791 
792     if (container) {
793 #if !defined(OS_ANDROID)
794       ReportDeletionToAuditService(
795           usage_info_->origin,
796           AccessContextAuditDatabase::StorageAPIType::kCacheStorage);
797 #endif  // !defined(OS_ANDROID)
798 
799       container->cache_storage_helper_->DeleteCacheStorage(usage_info_->origin);
800       container->cache_storage_info_list_.erase(usage_info_);
801     }
802   }
803 
GetDetailedInfo() const804   DetailedInfo GetDetailedInfo() const override {
805     return DetailedInfo().InitCacheStorage(&*usage_info_);
806   }
807 
InclusiveSize() const808   int64_t InclusiveSize() const override {
809     return usage_info_->total_size_bytes;
810   }
811 
812  private:
813   // |usage_info_| is expected to remain valid as long as the
814   // CookieTreeCacheStorageNode is valid.
815   std::list<content::StorageUsageInfo>::iterator usage_info_;
816 
817   DISALLOW_COPY_AND_ASSIGN(CookieTreeCacheStorageNode);
818 };
819 
820 ///////////////////////////////////////////////////////////////////////////////
821 // CookieTreeMediaLicenseNode
822 
823 class CookieTreeMediaLicenseNode : public CookieTreeNode {
824  public:
825   friend class CookieTreeMediaLicensesNode;
826 
827   // |media_license_info| is expected to remain valid as long as the
828   // CookieTreeMediaLicenseNode is valid.
CookieTreeMediaLicenseNode(const std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>::iterator media_license_info)829   explicit CookieTreeMediaLicenseNode(
830       const std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>::
831           iterator media_license_info)
832       : CookieTreeNode(base::UTF8ToUTF16(media_license_info->origin.spec())),
833         media_license_info_(media_license_info) {}
834 
835   ~CookieTreeMediaLicenseNode() override = default;
836 
DeleteStoredObjects()837   void DeleteStoredObjects() override {
838     LocalDataContainer* container = GetLocalDataContainerForNode(this);
839 
840     if (container) {
841       container->media_license_helper_->DeleteMediaLicenseOrigin(
842           media_license_info_->origin);
843       container->media_license_info_list_.erase(media_license_info_);
844     }
845   }
846 
GetDetailedInfo() const847   DetailedInfo GetDetailedInfo() const override {
848     return DetailedInfo().InitMediaLicense(&*media_license_info_);
849   }
850 
InclusiveSize() const851   int64_t InclusiveSize() const override { return media_license_info_->size; }
852 
853  private:
854   // |media_license_info_| is expected to remain valid as long as the
855   // CookieTreeMediaLicenseNode is valid.
856   std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>::iterator
857       media_license_info_;
858 
859   DISALLOW_COPY_AND_ASSIGN(CookieTreeMediaLicenseNode);
860 };
861 
862 ///////////////////////////////////////////////////////////////////////////////
863 // CookieTreeRootNode, public:
864 
CookieTreeRootNode(CookiesTreeModel * model)865 CookieTreeRootNode::CookieTreeRootNode(CookiesTreeModel* model)
866     : model_(model) {
867 }
868 
869 CookieTreeRootNode::~CookieTreeRootNode() = default;
870 
GetOrCreateHostNode(const GURL & url)871 CookieTreeHostNode* CookieTreeRootNode::GetOrCreateHostNode(const GURL& url) {
872   std::unique_ptr<CookieTreeHostNode> host_node =
873       std::make_unique<CookieTreeHostNode>(url);
874 
875   // First see if there is an existing match.
876   auto host_node_iterator = std::lower_bound(
877       children().begin(), children().end(), host_node, HostNodeComparator());
878   if (host_node_iterator != children().end() &&
879       CookieTreeHostNode::TitleForUrl(url) ==
880           (*host_node_iterator)->GetTitle()) {
881     CookieTreeHostNode* found_node =
882         static_cast<CookieTreeHostNode*>(host_node_iterator->get());
883     // Cookies node will create fake url with http scheme, so update the url if
884     // there is a more valid url.
885     if (found_node->GetDetailedInfo().origin.GetURL().SchemeIs(
886             url::kHttpScheme) &&
887         url.SchemeIs(url::kHttpsScheme))
888       found_node->UpdateHostUrl(url);
889     return found_node;
890   }
891   // Node doesn't exist, insert the new one into the (ordered) children.
892   DCHECK(model_);
893   return static_cast<CookieTreeHostNode*>(
894       model_->Add(this, std::move(host_node),
895                   size_t{host_node_iterator - children().begin()}));
896 }
897 
GetModel() const898 CookiesTreeModel* CookieTreeRootNode::GetModel() const {
899   return model_;
900 }
901 
GetDetailedInfo() const902 CookieTreeNode::DetailedInfo CookieTreeRootNode::GetDetailedInfo() const {
903   return DetailedInfo().Init(DetailedInfo::TYPE_ROOT);
904 }
905 
906 ///////////////////////////////////////////////////////////////////////////////
907 // CookieTreeCookiesNode
908 
909 class CookieTreeCookiesNode : public CookieTreeNode {
910  public:
CookieTreeCookiesNode()911   CookieTreeCookiesNode()
912       : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIES)) {}
913 
914   ~CookieTreeCookiesNode() override = default;
915 
GetDetailedInfo() const916   DetailedInfo GetDetailedInfo() const override {
917     return DetailedInfo().Init(DetailedInfo::TYPE_COOKIES);
918   }
919 
AddCookieNode(std::unique_ptr<CookieTreeCookieNode> child)920   void AddCookieNode(std::unique_ptr<CookieTreeCookieNode> child) {
921     AddChildSortedByTitle(std::move(child));
922   }
923 
924  private:
925   DISALLOW_COPY_AND_ASSIGN(CookieTreeCookiesNode);
926 };
927 
928 ///////////////////////////////////////////////////////////////////////////////
929 // CookieTreeCollectionNode
930 
931 class CookieTreeCollectionNode : public CookieTreeNode {
932  public:
CookieTreeCollectionNode(const base::string16 & title)933   explicit CookieTreeCollectionNode(const base::string16& title)
934       : CookieTreeNode(title) {}
935 
936   ~CookieTreeCollectionNode() override = default;
937 
InclusiveSize() const938   int64_t InclusiveSize() const final {
939     return std::accumulate(children().cbegin(), children().cend(), int64_t{0},
940                            [](int64_t total, const auto& child) {
941                              return total + child->InclusiveSize();
942                            });
943   }
944 
945  private:
946   DISALLOW_COPY_AND_ASSIGN(CookieTreeCollectionNode);
947 };
948 
949 ///////////////////////////////////////////////////////////////////////////////
950 // CookieTreeAppCachesNode
951 
952 class CookieTreeAppCachesNode : public CookieTreeCollectionNode {
953  public:
CookieTreeAppCachesNode()954   CookieTreeAppCachesNode()
955       : CookieTreeCollectionNode(
956             l10n_util::GetStringUTF16(IDS_COOKIES_APPLICATION_CACHES)) {}
957 
958   ~CookieTreeAppCachesNode() override = default;
959 
GetDetailedInfo() const960   DetailedInfo GetDetailedInfo() const override {
961     return DetailedInfo().Init(DetailedInfo::TYPE_APPCACHES);
962   }
963 
AddAppCacheNode(std::unique_ptr<CookieTreeAppCacheNode> child)964   void AddAppCacheNode(std::unique_ptr<CookieTreeAppCacheNode> child) {
965     AddChildSortedByTitle(std::move(child));
966   }
967 
968  private:
969   DISALLOW_COPY_AND_ASSIGN(CookieTreeAppCachesNode);
970 };
971 
972 ///////////////////////////////////////////////////////////////////////////////
973 // CookieTreeDatabasesNode
974 
975 class CookieTreeDatabasesNode : public CookieTreeCollectionNode {
976  public:
CookieTreeDatabasesNode()977   CookieTreeDatabasesNode()
978       : CookieTreeCollectionNode(
979             l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASES)) {}
980 
981   ~CookieTreeDatabasesNode() override = default;
982 
GetDetailedInfo() const983   DetailedInfo GetDetailedInfo() const override {
984     return DetailedInfo().Init(DetailedInfo::TYPE_DATABASES);
985   }
986 
AddDatabaseNode(std::unique_ptr<CookieTreeDatabaseNode> child)987   void AddDatabaseNode(std::unique_ptr<CookieTreeDatabaseNode> child) {
988     AddChildSortedByTitle(std::move(child));
989   }
990 
991  private:
992   DISALLOW_COPY_AND_ASSIGN(CookieTreeDatabasesNode);
993 };
994 
995 ///////////////////////////////////////////////////////////////////////////////
996 // CookieTreeLocalStoragesNode
997 
998 class CookieTreeLocalStoragesNode : public CookieTreeCollectionNode {
999  public:
CookieTreeLocalStoragesNode()1000   CookieTreeLocalStoragesNode()
1001       : CookieTreeCollectionNode(
1002             l10n_util::GetStringUTF16(IDS_COOKIES_LOCAL_STORAGE)) {}
1003 
1004   ~CookieTreeLocalStoragesNode() override = default;
1005 
GetDetailedInfo() const1006   DetailedInfo GetDetailedInfo() const override {
1007     return DetailedInfo().Init(DetailedInfo::TYPE_LOCAL_STORAGES);
1008   }
1009 
AddLocalStorageNode(std::unique_ptr<CookieTreeLocalStorageNode> child)1010   void AddLocalStorageNode(std::unique_ptr<CookieTreeLocalStorageNode> child) {
1011     AddChildSortedByTitle(std::move(child));
1012   }
1013 
1014  private:
1015   DISALLOW_COPY_AND_ASSIGN(CookieTreeLocalStoragesNode);
1016 };
1017 
1018 ///////////////////////////////////////////////////////////////////////////////
1019 // CookieTreeSessionStoragesNode
1020 
1021 class CookieTreeSessionStoragesNode : public CookieTreeNode {
1022  public:
CookieTreeSessionStoragesNode()1023   CookieTreeSessionStoragesNode()
1024       : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SESSION_STORAGE)) {
1025   }
1026 
1027   ~CookieTreeSessionStoragesNode() override = default;
1028 
GetDetailedInfo() const1029   DetailedInfo GetDetailedInfo() const override {
1030     return DetailedInfo().Init(DetailedInfo::TYPE_SESSION_STORAGES);
1031   }
1032 
AddSessionStorageNode(std::unique_ptr<CookieTreeSessionStorageNode> child)1033   void AddSessionStorageNode(
1034       std::unique_ptr<CookieTreeSessionStorageNode> child) {
1035     AddChildSortedByTitle(std::move(child));
1036   }
1037 
1038  private:
1039   DISALLOW_COPY_AND_ASSIGN(CookieTreeSessionStoragesNode);
1040 };
1041 
1042 ///////////////////////////////////////////////////////////////////////////////
1043 // CookieTreeIndexedDBsNode
1044 
1045 class CookieTreeIndexedDBsNode : public CookieTreeCollectionNode {
1046  public:
CookieTreeIndexedDBsNode()1047   CookieTreeIndexedDBsNode()
1048       : CookieTreeCollectionNode(
1049             l10n_util::GetStringUTF16(IDS_COOKIES_INDEXED_DBS)) {}
1050 
1051   ~CookieTreeIndexedDBsNode() override = default;
1052 
GetDetailedInfo() const1053   DetailedInfo GetDetailedInfo() const override {
1054     return DetailedInfo().Init(DetailedInfo::TYPE_INDEXED_DBS);
1055   }
1056 
AddIndexedDBNode(std::unique_ptr<CookieTreeIndexedDBNode> child)1057   void AddIndexedDBNode(std::unique_ptr<CookieTreeIndexedDBNode> child) {
1058     AddChildSortedByTitle(std::move(child));
1059   }
1060 
1061  private:
1062   DISALLOW_COPY_AND_ASSIGN(CookieTreeIndexedDBsNode);
1063 };
1064 
1065 ///////////////////////////////////////////////////////////////////////////////
1066 // CookieTreeFileSystemsNode
1067 
1068 class CookieTreeFileSystemsNode : public CookieTreeCollectionNode {
1069  public:
CookieTreeFileSystemsNode()1070   CookieTreeFileSystemsNode()
1071       : CookieTreeCollectionNode(
1072             l10n_util::GetStringUTF16(IDS_COOKIES_FILE_SYSTEMS)) {}
1073 
1074   ~CookieTreeFileSystemsNode() override = default;
1075 
GetDetailedInfo() const1076   DetailedInfo GetDetailedInfo() const override {
1077     return DetailedInfo().Init(DetailedInfo::TYPE_FILE_SYSTEMS);
1078   }
1079 
AddFileSystemNode(std::unique_ptr<CookieTreeFileSystemNode> child)1080   void AddFileSystemNode(std::unique_ptr<CookieTreeFileSystemNode> child) {
1081     AddChildSortedByTitle(std::move(child));
1082   }
1083 
1084  private:
1085   DISALLOW_COPY_AND_ASSIGN(CookieTreeFileSystemsNode);
1086 };
1087 
1088 ///////////////////////////////////////////////////////////////////////////////
1089 // CookieTreeServiceWorkersNode
1090 
1091 class CookieTreeServiceWorkersNode : public CookieTreeCollectionNode {
1092  public:
CookieTreeServiceWorkersNode()1093   CookieTreeServiceWorkersNode()
1094       : CookieTreeCollectionNode(
1095             l10n_util::GetStringUTF16(IDS_COOKIES_SERVICE_WORKERS)) {}
1096 
1097   ~CookieTreeServiceWorkersNode() override = default;
1098 
GetDetailedInfo() const1099   DetailedInfo GetDetailedInfo() const override {
1100     return DetailedInfo().Init(DetailedInfo::TYPE_SERVICE_WORKERS);
1101   }
1102 
AddServiceWorkerNode(std::unique_ptr<CookieTreeServiceWorkerNode> child)1103   void AddServiceWorkerNode(
1104       std::unique_ptr<CookieTreeServiceWorkerNode> child) {
1105     AddChildSortedByTitle(std::move(child));
1106   }
1107 
1108  private:
1109   DISALLOW_COPY_AND_ASSIGN(CookieTreeServiceWorkersNode);
1110 };
1111 
1112 ///////////////////////////////////////////////////////////////////////////////
1113 // CookieTreeSharedWorkersNode
1114 
1115 class CookieTreeSharedWorkersNode : public CookieTreeNode {
1116  public:
CookieTreeSharedWorkersNode()1117   CookieTreeSharedWorkersNode()
1118       : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SHARED_WORKERS)) {}
1119 
1120   ~CookieTreeSharedWorkersNode() override = default;
1121 
GetDetailedInfo() const1122   DetailedInfo GetDetailedInfo() const override {
1123     return DetailedInfo().Init(DetailedInfo::TYPE_SHARED_WORKERS);
1124   }
1125 
AddSharedWorkerNode(std::unique_ptr<CookieTreeSharedWorkerNode> child)1126   void AddSharedWorkerNode(std::unique_ptr<CookieTreeSharedWorkerNode> child) {
1127     AddChildSortedByTitle(std::move(child));
1128   }
1129 
1130  private:
1131   DISALLOW_COPY_AND_ASSIGN(CookieTreeSharedWorkersNode);
1132 };
1133 
1134 ///////////////////////////////////////////////////////////////////////////////
1135 // CookieTreeCacheStoragesNode
1136 
1137 class CookieTreeCacheStoragesNode : public CookieTreeCollectionNode {
1138  public:
CookieTreeCacheStoragesNode()1139   CookieTreeCacheStoragesNode()
1140       : CookieTreeCollectionNode(
1141             l10n_util::GetStringUTF16(IDS_COOKIES_CACHE_STORAGE)) {}
1142 
1143   ~CookieTreeCacheStoragesNode() override = default;
1144 
GetDetailedInfo() const1145   DetailedInfo GetDetailedInfo() const override {
1146     return DetailedInfo().Init(DetailedInfo::TYPE_CACHE_STORAGES);
1147   }
1148 
AddCacheStorageNode(std::unique_ptr<CookieTreeCacheStorageNode> child)1149   void AddCacheStorageNode(std::unique_ptr<CookieTreeCacheStorageNode> child) {
1150     AddChildSortedByTitle(std::move(child));
1151   }
1152 
1153  private:
1154   DISALLOW_COPY_AND_ASSIGN(CookieTreeCacheStoragesNode);
1155 };
1156 
1157 ///////////////////////////////////////////////////////////////////////////////
1158 // CookieTreeMediaLicensesNode
1159 
1160 class CookieTreeMediaLicensesNode : public CookieTreeCollectionNode {
1161  public:
CookieTreeMediaLicensesNode()1162   CookieTreeMediaLicensesNode()
1163       : CookieTreeCollectionNode(
1164             l10n_util::GetStringUTF16(IDS_COOKIES_MEDIA_LICENSES)) {}
1165 
1166   ~CookieTreeMediaLicensesNode() override = default;
1167 
GetDetailedInfo() const1168   DetailedInfo GetDetailedInfo() const override {
1169     return DetailedInfo().Init(DetailedInfo::TYPE_MEDIA_LICENSES);
1170   }
1171 
AddMediaLicenseNode(std::unique_ptr<CookieTreeMediaLicenseNode> child)1172   void AddMediaLicenseNode(std::unique_ptr<CookieTreeMediaLicenseNode> child) {
1173     AddChildSortedByTitle(std::move(child));
1174   }
1175 
1176  private:
1177   DISALLOW_COPY_AND_ASSIGN(CookieTreeMediaLicensesNode);
1178 };
1179 
1180 ///////////////////////////////////////////////////////////////////////////////
1181 // CookieTreeHostNode, public:
1182 
1183 // static
TitleForUrl(const GURL & url)1184 base::string16 CookieTreeHostNode::TitleForUrl(const GURL& url) {
1185   const std::string file_origin_node_name(
1186       std::string(url::kFileScheme) + url::kStandardSchemeSeparator);
1187   return base::UTF8ToUTF16(url.SchemeIsFile()
1188                                ? file_origin_node_name
1189                                : url::Origin::Create(url).host());
1190 }
1191 
CookieTreeHostNode(const GURL & url)1192 CookieTreeHostNode::CookieTreeHostNode(const GURL& url)
1193     : CookieTreeNode(TitleForUrl(url)),
1194       url_(url),
1195       canonicalized_host_(CanonicalizeHost(url)) {}
1196 
1197 CookieTreeHostNode::~CookieTreeHostNode() = default;
1198 
GetHost() const1199 std::string CookieTreeHostNode::GetHost() const {
1200   const std::string file_origin_node_name(
1201       std::string(url::kFileScheme) + url::kStandardSchemeSeparator);
1202   return url_.SchemeIsFile() ? file_origin_node_name : url_.host();
1203 }
1204 
UpdateHostUrl(const GURL & url)1205 void CookieTreeHostNode::UpdateHostUrl(const GURL& url) {
1206   this->url_ = url;
1207 }
1208 
GetDetailedInfo() const1209 CookieTreeNode::DetailedInfo CookieTreeHostNode::GetDetailedInfo() const {
1210   return DetailedInfo().InitHost(url_);
1211 }
1212 
GetOrCreateCookiesNode()1213 CookieTreeCookiesNode* CookieTreeHostNode::GetOrCreateCookiesNode() {
1214   if (cookies_child_)
1215     return cookies_child_;
1216   cookies_child_ = new CookieTreeCookiesNode;
1217   AddChildSortedByTitle(base::WrapUnique(cookies_child_));
1218   return cookies_child_;
1219 }
1220 
GetOrCreateDatabasesNode()1221 CookieTreeDatabasesNode* CookieTreeHostNode::GetOrCreateDatabasesNode() {
1222   if (databases_child_)
1223     return databases_child_;
1224   databases_child_ = new CookieTreeDatabasesNode;
1225   AddChildSortedByTitle(base::WrapUnique(databases_child_));
1226   return databases_child_;
1227 }
1228 
1229 CookieTreeLocalStoragesNode*
GetOrCreateLocalStoragesNode()1230     CookieTreeHostNode::GetOrCreateLocalStoragesNode() {
1231   if (local_storages_child_)
1232     return local_storages_child_;
1233   local_storages_child_ = new CookieTreeLocalStoragesNode;
1234   AddChildSortedByTitle(base::WrapUnique(local_storages_child_));
1235   return local_storages_child_;
1236 }
1237 
1238 CookieTreeSessionStoragesNode*
GetOrCreateSessionStoragesNode()1239     CookieTreeHostNode::GetOrCreateSessionStoragesNode() {
1240   if (session_storages_child_)
1241     return session_storages_child_;
1242   session_storages_child_ = new CookieTreeSessionStoragesNode;
1243   AddChildSortedByTitle(base::WrapUnique(session_storages_child_));
1244   return session_storages_child_;
1245 }
1246 
GetOrCreateAppCachesNode()1247 CookieTreeAppCachesNode* CookieTreeHostNode::GetOrCreateAppCachesNode() {
1248   if (appcaches_child_)
1249     return appcaches_child_;
1250   appcaches_child_ = new CookieTreeAppCachesNode;
1251   AddChildSortedByTitle(base::WrapUnique(appcaches_child_));
1252   return appcaches_child_;
1253 }
1254 
GetOrCreateIndexedDBsNode()1255 CookieTreeIndexedDBsNode* CookieTreeHostNode::GetOrCreateIndexedDBsNode() {
1256   if (indexed_dbs_child_)
1257     return indexed_dbs_child_;
1258   indexed_dbs_child_ = new CookieTreeIndexedDBsNode;
1259   AddChildSortedByTitle(base::WrapUnique(indexed_dbs_child_));
1260   return indexed_dbs_child_;
1261 }
1262 
GetOrCreateFileSystemsNode()1263 CookieTreeFileSystemsNode* CookieTreeHostNode::GetOrCreateFileSystemsNode() {
1264   if (file_systems_child_)
1265     return file_systems_child_;
1266   file_systems_child_ = new CookieTreeFileSystemsNode;
1267   AddChildSortedByTitle(base::WrapUnique(file_systems_child_));
1268   return file_systems_child_;
1269 }
1270 
UpdateOrCreateQuotaNode(std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)1271 CookieTreeQuotaNode* CookieTreeHostNode::UpdateOrCreateQuotaNode(
1272     std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info) {
1273   if (quota_child_)
1274     return quota_child_;
1275   quota_child_ = new CookieTreeQuotaNode(quota_info);
1276   AddChildSortedByTitle(base::WrapUnique(quota_child_));
1277   return quota_child_;
1278 }
1279 
1280 CookieTreeServiceWorkersNode*
GetOrCreateServiceWorkersNode()1281 CookieTreeHostNode::GetOrCreateServiceWorkersNode() {
1282   if (service_workers_child_)
1283     return service_workers_child_;
1284   service_workers_child_ = new CookieTreeServiceWorkersNode;
1285   AddChildSortedByTitle(base::WrapUnique(service_workers_child_));
1286   return service_workers_child_;
1287 }
1288 
1289 CookieTreeSharedWorkersNode*
GetOrCreateSharedWorkersNode()1290 CookieTreeHostNode::GetOrCreateSharedWorkersNode() {
1291   if (shared_workers_child_)
1292     return shared_workers_child_;
1293   shared_workers_child_ = new CookieTreeSharedWorkersNode;
1294   AddChildSortedByTitle(base::WrapUnique(shared_workers_child_));
1295   return shared_workers_child_;
1296 }
1297 
1298 CookieTreeCacheStoragesNode*
GetOrCreateCacheStoragesNode()1299 CookieTreeHostNode::GetOrCreateCacheStoragesNode() {
1300   if (cache_storages_child_)
1301     return cache_storages_child_;
1302   cache_storages_child_ = new CookieTreeCacheStoragesNode;
1303   AddChildSortedByTitle(base::WrapUnique(cache_storages_child_));
1304   return cache_storages_child_;
1305 }
1306 
1307 CookieTreeMediaLicensesNode*
GetOrCreateMediaLicensesNode()1308 CookieTreeHostNode::GetOrCreateMediaLicensesNode() {
1309   if (media_licenses_child_)
1310     return media_licenses_child_;
1311   media_licenses_child_ = new CookieTreeMediaLicensesNode();
1312   AddChildSortedByTitle(base::WrapUnique(media_licenses_child_));
1313   return media_licenses_child_;
1314 }
1315 
CreateContentException(content_settings::CookieSettings * cookie_settings,ContentSetting setting) const1316 void CookieTreeHostNode::CreateContentException(
1317     content_settings::CookieSettings* cookie_settings,
1318     ContentSetting setting) const {
1319   DCHECK(setting == CONTENT_SETTING_ALLOW ||
1320          setting == CONTENT_SETTING_BLOCK ||
1321          setting == CONTENT_SETTING_SESSION_ONLY);
1322   if (CanCreateContentException()) {
1323     cookie_settings->ResetCookieSetting(url_);
1324     cookie_settings->SetCookieSetting(url_, setting);
1325   }
1326 }
1327 
CanCreateContentException() const1328 bool CookieTreeHostNode::CanCreateContentException() const {
1329   return !url_.SchemeIsFile();
1330 }
1331 
InclusiveSize() const1332 int64_t CookieTreeHostNode::InclusiveSize() const {
1333   return std::accumulate(children().cbegin(), children().cend(), int64_t{0},
1334                          [](int64_t total, const auto& child) {
1335                            return total + child->InclusiveSize();
1336                          });
1337 }
1338 
1339 ///////////////////////////////////////////////////////////////////////////////
1340 // ScopedBatchUpdateNotifier
ScopedBatchUpdateNotifier(CookiesTreeModel * model,CookieTreeNode * node)1341 CookiesTreeModel::ScopedBatchUpdateNotifier::ScopedBatchUpdateNotifier(
1342     CookiesTreeModel* model,
1343     CookieTreeNode* node)
1344     : model_(model), node_(node) {
1345   model_->RecordBatchSeen();
1346 }
1347 
~ScopedBatchUpdateNotifier()1348 CookiesTreeModel::ScopedBatchUpdateNotifier::~ScopedBatchUpdateNotifier() {
1349   if (batch_in_progress_) {
1350     model_->NotifyObserverTreeNodeChanged(node_);
1351     model_->NotifyObserverEndBatch();
1352   } else {
1353     // If no batch started, and this is the last batch, give the model a chance
1354     // to send out a final notification.
1355     model_->MaybeNotifyBatchesEnded();
1356   }
1357 }
1358 
StartBatchUpdate()1359 void CookiesTreeModel::ScopedBatchUpdateNotifier::StartBatchUpdate() {
1360   if (!batch_in_progress_) {
1361     model_->NotifyObserverBeginBatch();
1362     batch_in_progress_ = true;
1363   }
1364 }
1365 
1366 ///////////////////////////////////////////////////////////////////////////////
1367 // CookiesTreeModel, public:
CookiesTreeModel(std::unique_ptr<LocalDataContainer> data_container,ExtensionSpecialStoragePolicy * special_storage_policy)1368 CookiesTreeModel::CookiesTreeModel(
1369     std::unique_ptr<LocalDataContainer> data_container,
1370     ExtensionSpecialStoragePolicy* special_storage_policy)
1371     : CookiesTreeModel(std::move(data_container),
1372                        special_storage_policy,
1373                        nullptr) {}
1374 
CookiesTreeModel(std::unique_ptr<LocalDataContainer> data_container,ExtensionSpecialStoragePolicy * special_storage_policy,AccessContextAuditService * access_context_audit_service)1375 CookiesTreeModel::CookiesTreeModel(
1376     std::unique_ptr<LocalDataContainer> data_container,
1377     ExtensionSpecialStoragePolicy* special_storage_policy,
1378     AccessContextAuditService* access_context_audit_service)
1379     : ui::TreeNodeModel<CookieTreeNode>(
1380           std::make_unique<CookieTreeRootNode>(this)),
1381 #if BUILDFLAG(ENABLE_EXTENSIONS)
1382       special_storage_policy_(special_storage_policy),
1383 #endif
1384       data_container_(std::move(data_container)),
1385       access_context_audit_service_(access_context_audit_service) {
1386   data_container_->Init(this);
1387 }
1388 
1389 CookiesTreeModel::~CookiesTreeModel() = default;
1390 
1391 // static
GetSendForMessageID(const net::CanonicalCookie & cookie)1392 int CookiesTreeModel::GetSendForMessageID(const net::CanonicalCookie& cookie) {
1393   if (cookie.IsSecure()) {
1394     if (!cookie.IsEffectivelySameSiteNone())
1395       return IDS_COOKIES_COOKIE_SENDFOR_SECURE_SAME_SITE;
1396     return IDS_COOKIES_COOKIE_SENDFOR_SECURE;
1397   }
1398   if (!cookie.IsEffectivelySameSiteNone())
1399     return IDS_COOKIES_COOKIE_SENDFOR_SAME_SITE;
1400   return IDS_COOKIES_COOKIE_SENDFOR_ANY;
1401 }
1402 
1403 ///////////////////////////////////////////////////////////////////////////////
1404 // CookiesTreeModel, TreeModel methods (public):
1405 
1406 // TreeModel methods:
1407 // Returns the set of icons for the nodes in the tree. You only need override
1408 // this if you don't want to use the default folder icons.
GetIcons(std::vector<gfx::ImageSkia> * icons)1409 void CookiesTreeModel::GetIcons(std::vector<gfx::ImageSkia>* icons) {
1410   icons->push_back(gfx::CreateVectorIcon(vector_icons::kCookieIcon, 18,
1411                                          gfx::kChromeIconGrey));
1412   icons->push_back(*ui::ResourceBundle::GetSharedInstance()
1413                         .GetNativeImageNamed(IDR_COOKIE_STORAGE_ICON)
1414                         .ToImageSkia());
1415 }
1416 
1417 // Returns the index of the icon to use for |node|. Return -1 to use the
1418 // default icon. The index is relative to the list of icons returned from
1419 // GetIcons.
GetIconIndex(ui::TreeModelNode * node)1420 int CookiesTreeModel::GetIconIndex(ui::TreeModelNode* node) {
1421   CookieTreeNode* ct_node = static_cast<CookieTreeNode*>(node);
1422   switch (ct_node->GetDetailedInfo().node_type) {
1423     case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
1424       return COOKIE;
1425 
1426     // Fall through each below cases to return DATABASE.
1427     case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
1428     case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
1429     case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
1430     case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
1431     case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
1432     case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM:
1433     case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER:
1434     case CookieTreeNode::DetailedInfo::TYPE_SHARED_WORKER:
1435     case CookieTreeNode::DetailedInfo::TYPE_CACHE_STORAGE:
1436     case CookieTreeNode::DetailedInfo::TYPE_MEDIA_LICENSE:
1437       return DATABASE;
1438     case CookieTreeNode::DetailedInfo::TYPE_HOST:
1439     case CookieTreeNode::DetailedInfo::TYPE_QUOTA:
1440       return -1;
1441     default:
1442       break;
1443   }
1444   return -1;
1445 }
1446 
DeleteAllStoredObjects()1447 void CookiesTreeModel::DeleteAllStoredObjects() {
1448   NotifyObserverBeginBatch();
1449   CookieTreeNode* root = GetRoot();
1450   root->DeleteStoredObjects();
1451   root->DeleteAll();
1452   NotifyObserverTreeNodeChanged(root);
1453   NotifyObserverEndBatch();
1454 }
1455 
DeleteCookieNode(CookieTreeNode * cookie_node)1456 void CookiesTreeModel::DeleteCookieNode(CookieTreeNode* cookie_node) {
1457   if (cookie_node == GetRoot())
1458     return;
1459   cookie_node->DeleteStoredObjects();
1460   CookieTreeNode* parent_node = cookie_node->parent();
1461   Remove(parent_node, cookie_node);
1462   if (parent_node->children().empty())
1463     DeleteCookieNode(parent_node);
1464 }
1465 
UpdateSearchResults(const base::string16 & filter)1466 void CookiesTreeModel::UpdateSearchResults(const base::string16& filter) {
1467   CookieTreeNode* root = GetRoot();
1468   SetBatchExpectation(1, true);
1469   ScopedBatchUpdateNotifier notifier(this, root);
1470   notifier.StartBatchUpdate();
1471   root->DeleteAll();
1472 
1473   PopulateCookieInfoWithFilter(data_container(), &notifier, filter);
1474   PopulateDatabaseInfoWithFilter(data_container(), &notifier, filter);
1475   PopulateLocalStorageInfoWithFilter(data_container(), &notifier, filter);
1476   PopulateSessionStorageInfoWithFilter(data_container(), &notifier, filter);
1477   PopulateAppCacheInfoWithFilter(data_container(), &notifier, filter);
1478   PopulateIndexedDBInfoWithFilter(data_container(), &notifier, filter);
1479   PopulateFileSystemInfoWithFilter(data_container(), &notifier, filter);
1480   PopulateQuotaInfoWithFilter(data_container(), &notifier, filter);
1481   PopulateServiceWorkerUsageInfoWithFilter(data_container(), &notifier, filter);
1482   PopulateSharedWorkerInfoWithFilter(data_container(), &notifier, filter);
1483   PopulateCacheStorageUsageInfoWithFilter(data_container(), &notifier, filter);
1484   PopulateMediaLicenseInfoWithFilter(data_container(), &notifier, filter);
1485 }
1486 
1487 #if BUILDFLAG(ENABLE_EXTENSIONS)
ExtensionsProtectingNode(const CookieTreeNode & cookie_node)1488 const extensions::ExtensionSet* CookiesTreeModel::ExtensionsProtectingNode(
1489     const CookieTreeNode& cookie_node) {
1490   if (!special_storage_policy_.get())
1491     return nullptr;
1492 
1493   CookieTreeNode::DetailedInfo info = cookie_node.GetDetailedInfo();
1494 
1495   if (!TypeIsProtected(info.node_type))
1496     return nullptr;
1497 
1498   DCHECK(!info.origin.opaque());
1499   return special_storage_policy_->ExtensionsProtectingOrigin(
1500       info.origin.GetURL());
1501 }
1502 #endif
1503 
AddCookiesTreeObserver(Observer * observer)1504 void CookiesTreeModel::AddCookiesTreeObserver(Observer* observer) {
1505   cookies_observer_list_.AddObserver(observer);
1506   // Call super so that TreeNodeModel can notify, too.
1507   ui::TreeNodeModel<CookieTreeNode>::AddObserver(observer);
1508 }
1509 
RemoveCookiesTreeObserver(Observer * observer)1510 void CookiesTreeModel::RemoveCookiesTreeObserver(Observer* observer) {
1511   cookies_observer_list_.RemoveObserver(observer);
1512   // Call super so that TreeNodeModel doesn't have dead pointers.
1513   ui::TreeNodeModel<CookieTreeNode>::RemoveObserver(observer);
1514 }
1515 
PopulateAppCacheInfo(LocalDataContainer * container)1516 void CookiesTreeModel::PopulateAppCacheInfo(LocalDataContainer* container) {
1517   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1518   PopulateAppCacheInfoWithFilter(container, &notifier, base::string16());
1519 }
1520 
PopulateCookieInfo(LocalDataContainer * container)1521 void CookiesTreeModel::PopulateCookieInfo(LocalDataContainer* container) {
1522   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1523   PopulateCookieInfoWithFilter(container, &notifier, base::string16());
1524 }
1525 
PopulateDatabaseInfo(LocalDataContainer * container)1526 void CookiesTreeModel::PopulateDatabaseInfo(LocalDataContainer* container) {
1527   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1528   PopulateDatabaseInfoWithFilter(container, &notifier, base::string16());
1529 }
1530 
PopulateLocalStorageInfo(LocalDataContainer * container)1531 void CookiesTreeModel::PopulateLocalStorageInfo(LocalDataContainer* container) {
1532   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1533   PopulateLocalStorageInfoWithFilter(container, &notifier, base::string16());
1534 }
1535 
PopulateSessionStorageInfo(LocalDataContainer * container)1536 void CookiesTreeModel::PopulateSessionStorageInfo(
1537       LocalDataContainer* container) {
1538   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1539   PopulateSessionStorageInfoWithFilter(container, &notifier, base::string16());
1540 }
1541 
PopulateIndexedDBInfo(LocalDataContainer * container)1542 void CookiesTreeModel::PopulateIndexedDBInfo(LocalDataContainer* container) {
1543   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1544   PopulateIndexedDBInfoWithFilter(container, &notifier, base::string16());
1545 }
1546 
PopulateFileSystemInfo(LocalDataContainer * container)1547 void CookiesTreeModel::PopulateFileSystemInfo(LocalDataContainer* container) {
1548   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1549   PopulateFileSystemInfoWithFilter(container, &notifier, base::string16());
1550 }
1551 
PopulateQuotaInfo(LocalDataContainer * container)1552 void CookiesTreeModel::PopulateQuotaInfo(LocalDataContainer* container) {
1553   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1554   PopulateQuotaInfoWithFilter(container, &notifier, base::string16());
1555 }
1556 
PopulateServiceWorkerUsageInfo(LocalDataContainer * container)1557 void CookiesTreeModel::PopulateServiceWorkerUsageInfo(
1558     LocalDataContainer* container) {
1559   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1560   PopulateServiceWorkerUsageInfoWithFilter(
1561       container, &notifier, base::string16());
1562 }
1563 
PopulateSharedWorkerInfo(LocalDataContainer * container)1564 void CookiesTreeModel::PopulateSharedWorkerInfo(LocalDataContainer* container) {
1565   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1566   PopulateSharedWorkerInfoWithFilter(container, &notifier, base::string16());
1567 }
1568 
PopulateCacheStorageUsageInfo(LocalDataContainer * container)1569 void CookiesTreeModel::PopulateCacheStorageUsageInfo(
1570     LocalDataContainer* container) {
1571   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1572   PopulateCacheStorageUsageInfoWithFilter(container, &notifier,
1573                                           base::string16());
1574 }
1575 
PopulateMediaLicenseInfo(LocalDataContainer * container)1576 void CookiesTreeModel::PopulateMediaLicenseInfo(LocalDataContainer* container) {
1577   ScopedBatchUpdateNotifier notifier(this, GetRoot());
1578   PopulateMediaLicenseInfoWithFilter(container, &notifier, base::string16());
1579 }
1580 
PopulateAppCacheInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1581 void CookiesTreeModel::PopulateAppCacheInfoWithFilter(
1582     LocalDataContainer* container,
1583     ScopedBatchUpdateNotifier* notifier,
1584     const base::string16& filter) {
1585   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1586 
1587   if (container->appcache_info_list_.empty())
1588     return;
1589 
1590   notifier->StartBatchUpdate();
1591   for (auto it = container->appcache_info_list_.begin();
1592        it != container->appcache_info_list_.end(); ++it) {
1593     const GURL url = it->origin.GetURL();
1594     if (filter.empty() || (CookieTreeHostNode::TitleForUrl(url).find(filter) !=
1595                            base::string16::npos)) {
1596       CookieTreeHostNode* host_node = root->GetOrCreateHostNode(url);
1597       CookieTreeAppCachesNode* appcaches_node =
1598           host_node->GetOrCreateAppCachesNode();
1599       appcaches_node->AddAppCacheNode(
1600           std::make_unique<CookieTreeAppCacheNode>(it));
1601     }
1602   }
1603 }
1604 
PopulateCookieInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1605 void CookiesTreeModel::PopulateCookieInfoWithFilter(
1606     LocalDataContainer* container,
1607     ScopedBatchUpdateNotifier* notifier,
1608     const base::string16& filter) {
1609   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1610 
1611   notifier->StartBatchUpdate();
1612   for (auto it = container->cookie_list_.begin();
1613        it != container->cookie_list_.end(); ++it) {
1614     // Cookies ignore schemes, so group all HTTP and HTTPS cookies together.
1615     // TODO(crbug.com/1031721): This will not be true when Scheme-Bound Cookies
1616     // is implemented. Investigate whether passing it->SourceScheme() instead of
1617     // false is appropriate here.
1618     GURL source = (it->Domain() == ".")
1619                       ? GURL("http://./")
1620                       : net::cookie_util::CookieOriginToURL(
1621                             it->Domain(), false /* is_https */);
1622 
1623     if (filter.empty() || (CookieTreeHostNode::TitleForUrl(source)
1624                                .find(filter) != base::string16::npos)) {
1625       CookieTreeHostNode* host_node = root->GetOrCreateHostNode(source);
1626       CookieTreeCookiesNode* cookies_node =
1627           host_node->GetOrCreateCookiesNode();
1628       cookies_node->AddCookieNode(std::make_unique<CookieTreeCookieNode>(it));
1629     }
1630   }
1631 }
1632 
PopulateDatabaseInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1633 void CookiesTreeModel::PopulateDatabaseInfoWithFilter(
1634     LocalDataContainer* container,
1635     ScopedBatchUpdateNotifier* notifier,
1636     const base::string16& filter) {
1637   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1638 
1639   if (container->database_info_list_.empty())
1640     return;
1641 
1642   notifier->StartBatchUpdate();
1643   for (auto database_info = container->database_info_list_.begin();
1644        database_info != container->database_info_list_.end(); ++database_info) {
1645     if (filter.empty() ||
1646         (CookieTreeHostNode::TitleForUrl(database_info->origin.GetURL())
1647              .find(filter) != base::string16::npos)) {
1648       CookieTreeHostNode* host_node =
1649           root->GetOrCreateHostNode(database_info->origin.GetURL());
1650       CookieTreeDatabasesNode* databases_node =
1651           host_node->GetOrCreateDatabasesNode();
1652       databases_node->AddDatabaseNode(
1653           std::make_unique<CookieTreeDatabaseNode>(database_info));
1654     }
1655   }
1656 }
1657 
PopulateLocalStorageInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1658 void CookiesTreeModel::PopulateLocalStorageInfoWithFilter(
1659     LocalDataContainer* container,
1660     ScopedBatchUpdateNotifier* notifier,
1661     const base::string16& filter) {
1662   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1663 
1664   if (container->local_storage_info_list_.empty())
1665     return;
1666 
1667   notifier->StartBatchUpdate();
1668   for (auto local_storage_info = container->local_storage_info_list_.begin();
1669        local_storage_info != container->local_storage_info_list_.end();
1670        ++local_storage_info) {
1671     const GURL& origin(local_storage_info->origin.GetURL());
1672 
1673     if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin)
1674                                .find(filter) != std::string::npos)) {
1675       CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1676       CookieTreeLocalStoragesNode* local_storages_node =
1677           host_node->GetOrCreateLocalStoragesNode();
1678       local_storages_node->AddLocalStorageNode(
1679           std::make_unique<CookieTreeLocalStorageNode>(local_storage_info));
1680     }
1681   }
1682 }
1683 
PopulateSessionStorageInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1684 void CookiesTreeModel::PopulateSessionStorageInfoWithFilter(
1685     LocalDataContainer* container,
1686     ScopedBatchUpdateNotifier* notifier,
1687     const base::string16& filter) {
1688   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1689 
1690   if (container->session_storage_info_list_.empty())
1691     return;
1692 
1693   notifier->StartBatchUpdate();
1694   for (auto session_storage_info =
1695            container->session_storage_info_list_.begin();
1696        session_storage_info != container->session_storage_info_list_.end();
1697        ++session_storage_info) {
1698     const GURL& origin = session_storage_info->origin.GetURL();
1699 
1700     if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin)
1701                                .find(filter) != base::string16::npos)) {
1702       CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1703       CookieTreeSessionStoragesNode* session_storages_node =
1704           host_node->GetOrCreateSessionStoragesNode();
1705       session_storages_node->AddSessionStorageNode(
1706           std::make_unique<CookieTreeSessionStorageNode>(session_storage_info));
1707     }
1708   }
1709 }
1710 
PopulateIndexedDBInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1711 void CookiesTreeModel::PopulateIndexedDBInfoWithFilter(
1712     LocalDataContainer* container,
1713     ScopedBatchUpdateNotifier* notifier,
1714     const base::string16& filter) {
1715   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1716 
1717   if (container->indexed_db_info_list_.empty())
1718     return;
1719 
1720   notifier->StartBatchUpdate();
1721   for (auto indexed_db_info = container->indexed_db_info_list_.begin();
1722        indexed_db_info != container->indexed_db_info_list_.end();
1723        ++indexed_db_info) {
1724     const url::Origin& origin = indexed_db_info->origin;
1725 
1726     if (filter.empty() ||
1727         (CookieTreeHostNode::TitleForUrl(origin.GetURL()).find(filter) !=
1728          base::string16::npos)) {
1729       CookieTreeHostNode* host_node =
1730           root->GetOrCreateHostNode(origin.GetURL());
1731       CookieTreeIndexedDBsNode* indexed_dbs_node =
1732           host_node->GetOrCreateIndexedDBsNode();
1733       indexed_dbs_node->AddIndexedDBNode(
1734           std::make_unique<CookieTreeIndexedDBNode>(indexed_db_info));
1735     }
1736   }
1737 }
1738 
PopulateServiceWorkerUsageInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1739 void CookiesTreeModel::PopulateServiceWorkerUsageInfoWithFilter(
1740     LocalDataContainer* container,
1741     ScopedBatchUpdateNotifier* notifier,
1742     const base::string16& filter) {
1743   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1744 
1745   if (container->service_worker_info_list_.empty())
1746     return;
1747 
1748   notifier->StartBatchUpdate();
1749   for (auto service_worker_info = container->service_worker_info_list_.begin();
1750        service_worker_info != container->service_worker_info_list_.end();
1751        ++service_worker_info) {
1752     const url::Origin& origin = service_worker_info->origin;
1753 
1754     if (filter.empty() ||
1755         (CookieTreeHostNode::TitleForUrl(origin.GetURL()).find(filter) !=
1756          base::string16::npos)) {
1757       CookieTreeHostNode* host_node =
1758           root->GetOrCreateHostNode(origin.GetURL());
1759       CookieTreeServiceWorkersNode* service_workers_node =
1760           host_node->GetOrCreateServiceWorkersNode();
1761       service_workers_node->AddServiceWorkerNode(
1762           std::make_unique<CookieTreeServiceWorkerNode>(service_worker_info));
1763     }
1764   }
1765 }
1766 
PopulateSharedWorkerInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1767 void CookiesTreeModel::PopulateSharedWorkerInfoWithFilter(
1768     LocalDataContainer* container,
1769     ScopedBatchUpdateNotifier* notifier,
1770     const base::string16& filter) {
1771   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1772 
1773   if (container->shared_worker_info_list_.empty())
1774     return;
1775 
1776   notifier->StartBatchUpdate();
1777   for (auto shared_worker_info = container->shared_worker_info_list_.begin();
1778        shared_worker_info != container->shared_worker_info_list_.end();
1779        ++shared_worker_info) {
1780     const GURL& worker = shared_worker_info->worker;
1781 
1782     if (filter.empty() || (CookieTreeHostNode::TitleForUrl(worker).find(
1783                                filter) != base::string16::npos)) {
1784       CookieTreeHostNode* host_node = root->GetOrCreateHostNode(worker);
1785       CookieTreeSharedWorkersNode* shared_workers_node =
1786           host_node->GetOrCreateSharedWorkersNode();
1787       shared_workers_node->AddSharedWorkerNode(
1788           std::make_unique<CookieTreeSharedWorkerNode>(shared_worker_info));
1789     }
1790   }
1791 }
1792 
PopulateCacheStorageUsageInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1793 void CookiesTreeModel::PopulateCacheStorageUsageInfoWithFilter(
1794     LocalDataContainer* container,
1795     ScopedBatchUpdateNotifier* notifier,
1796     const base::string16& filter) {
1797   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1798 
1799   if (container->cache_storage_info_list_.empty())
1800     return;
1801 
1802   notifier->StartBatchUpdate();
1803   for (auto cache_storage_info = container->cache_storage_info_list_.begin();
1804        cache_storage_info != container->cache_storage_info_list_.end();
1805        ++cache_storage_info) {
1806     const url::Origin& origin = cache_storage_info->origin;
1807 
1808     if (filter.empty() ||
1809         (CookieTreeHostNode::TitleForUrl(origin.GetURL()).find(filter) !=
1810          base::string16::npos)) {
1811       CookieTreeHostNode* host_node =
1812           root->GetOrCreateHostNode(origin.GetURL());
1813       CookieTreeCacheStoragesNode* cache_storages_node =
1814           host_node->GetOrCreateCacheStoragesNode();
1815       cache_storages_node->AddCacheStorageNode(
1816           std::make_unique<CookieTreeCacheStorageNode>(cache_storage_info));
1817     }
1818   }
1819 }
1820 
PopulateFileSystemInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1821 void CookiesTreeModel::PopulateFileSystemInfoWithFilter(
1822     LocalDataContainer* container,
1823     ScopedBatchUpdateNotifier* notifier,
1824     const base::string16& filter) {
1825   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1826 
1827   if (container->file_system_info_list_.empty())
1828     return;
1829 
1830   notifier->StartBatchUpdate();
1831   for (auto file_system_info = container->file_system_info_list_.begin();
1832        file_system_info != container->file_system_info_list_.end();
1833        ++file_system_info) {
1834     GURL origin = file_system_info->origin.GetURL();
1835 
1836     if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin)
1837                                .find(filter) != base::string16::npos)) {
1838       CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1839       CookieTreeFileSystemsNode* file_systems_node =
1840           host_node->GetOrCreateFileSystemsNode();
1841       file_systems_node->AddFileSystemNode(
1842           std::make_unique<CookieTreeFileSystemNode>(file_system_info));
1843     }
1844   }
1845 }
1846 
PopulateQuotaInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1847 void CookiesTreeModel::PopulateQuotaInfoWithFilter(
1848     LocalDataContainer* container,
1849     ScopedBatchUpdateNotifier* notifier,
1850     const base::string16& filter) {
1851   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1852 
1853   if (container->quota_info_list_.empty())
1854     return;
1855 
1856   notifier->StartBatchUpdate();
1857   for (auto quota_info = container->quota_info_list_.begin();
1858        quota_info != container->quota_info_list_.end(); ++quota_info) {
1859     if (filter.empty() || (base::UTF8ToUTF16(quota_info->host).find(filter) !=
1860                            base::string16::npos)) {
1861       CookieTreeHostNode* host_node =
1862           root->GetOrCreateHostNode(GURL("http://" + quota_info->host));
1863       host_node->UpdateOrCreateQuotaNode(quota_info);
1864     }
1865   }
1866 }
1867 
PopulateMediaLicenseInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1868 void CookiesTreeModel::PopulateMediaLicenseInfoWithFilter(
1869     LocalDataContainer* container,
1870     ScopedBatchUpdateNotifier* notifier,
1871     const base::string16& filter) {
1872   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1873 
1874   if (container->media_license_info_list_.empty())
1875     return;
1876 
1877   notifier->StartBatchUpdate();
1878   for (auto media_license_info = container->media_license_info_list_.begin();
1879        media_license_info != container->media_license_info_list_.end();
1880        ++media_license_info) {
1881     GURL origin(media_license_info->origin);
1882 
1883     if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin).find(
1884                                filter) != base::string16::npos)) {
1885       CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1886       CookieTreeMediaLicensesNode* media_licenses_node =
1887           host_node->GetOrCreateMediaLicensesNode();
1888       media_licenses_node->AddMediaLicenseNode(
1889           std::make_unique<CookieTreeMediaLicenseNode>(media_license_info));
1890     }
1891   }
1892 }
1893 
SetBatchExpectation(int batches_expected,bool reset)1894 void CookiesTreeModel::SetBatchExpectation(int batches_expected, bool reset) {
1895   batches_expected_ = batches_expected;
1896   if (reset) {
1897     batches_seen_ = 0;
1898     batches_started_ = 0;
1899     batches_ended_ = 0;
1900   } else {
1901     MaybeNotifyBatchesEnded();
1902   }
1903 }
1904 
RecordBatchSeen()1905 void CookiesTreeModel::RecordBatchSeen() {
1906   batches_seen_++;
1907 }
1908 
NotifyObserverBeginBatch()1909 void CookiesTreeModel::NotifyObserverBeginBatch() {
1910   // Only notify the model once if we're batching in a nested manner.
1911   if (batches_started_++ == 0) {
1912     for (Observer& observer : cookies_observer_list_)
1913       observer.TreeModelBeginBatch(this);
1914   }
1915 }
1916 
NotifyObserverEndBatch()1917 void CookiesTreeModel::NotifyObserverEndBatch() {
1918   batches_ended_++;
1919   MaybeNotifyBatchesEnded();
1920 }
1921 
MaybeNotifyBatchesEnded()1922 void CookiesTreeModel::MaybeNotifyBatchesEnded() {
1923   // Only notify the observers if this is the outermost call to EndBatch() if
1924   // called in a nested manner.
1925   if (batches_ended_ == batches_started_ &&
1926       batches_seen_ == batches_expected_) {
1927     for (Observer& observer : cookies_observer_list_)
1928       observer.TreeModelEndBatch(this);
1929     SetBatchExpectation(0, true);
1930   }
1931 }
1932 
1933 // static
1934 browsing_data::CookieHelper::IsDeletionDisabledCallback
GetCookieDeletionDisabledCallback(Profile * profile)1935 CookiesTreeModel::GetCookieDeletionDisabledCallback(Profile* profile) {
1936 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
1937   if (profile->IsChild()) {
1938     return base::BindRepeating(
1939         [](permissions::PermissionsClient* client,
1940            content::BrowserContext* browser_context, const GURL& url) {
1941           return client->IsCookieDeletionDisabled(browser_context, url);
1942         },
1943         permissions::PermissionsClient::Get(), profile);
1944   }
1945 #endif
1946   return base::NullCallback();
1947 }
1948 
1949 // static
CreateForProfile(Profile * profile)1950 std::unique_ptr<CookiesTreeModel> CookiesTreeModel::CreateForProfile(
1951     Profile* profile) {
1952   auto* storage_partition =
1953       content::BrowserContext::GetDefaultStoragePartition(profile);
1954   auto* file_system_context = storage_partition->GetFileSystemContext();
1955 
1956   auto container = std::make_unique<LocalDataContainer>(
1957       new browsing_data::CookieHelper(
1958           storage_partition, GetCookieDeletionDisabledCallback(profile)),
1959       new browsing_data::DatabaseHelper(profile),
1960       new browsing_data::LocalStorageHelper(profile),
1961       /*session_storage_helper=*/nullptr,
1962       new browsing_data::AppCacheHelper(
1963           storage_partition->GetAppCacheService()),
1964       new browsing_data::IndexedDBHelper(storage_partition),
1965       browsing_data::FileSystemHelper::Create(
1966           file_system_context,
1967           browsing_data_file_system_util::GetAdditionalFileSystemTypes()),
1968       BrowsingDataQuotaHelper::Create(profile),
1969       new browsing_data::ServiceWorkerHelper(
1970           storage_partition->GetServiceWorkerContext()),
1971       new browsing_data::SharedWorkerHelper(storage_partition,
1972                                             profile->GetResourceContext()),
1973       new browsing_data::CacheStorageHelper(
1974           storage_partition->GetCacheStorageContext()),
1975       BrowsingDataMediaLicenseHelper::Create(file_system_context));
1976 
1977 #if !defined(OS_ANDROID)
1978   return std::make_unique<CookiesTreeModel>(
1979       std::move(container), profile->GetExtensionSpecialStoragePolicy(),
1980       AccessContextAuditServiceFactory::GetForProfile(profile));
1981 #else
1982   return std::make_unique<CookiesTreeModel>(
1983       std::move(container), profile->GetExtensionSpecialStoragePolicy());
1984 #endif  // defined(OS_ANDROID)
1985 }
1986