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(), ¬ifier, filter);
1474 PopulateDatabaseInfoWithFilter(data_container(), ¬ifier, filter);
1475 PopulateLocalStorageInfoWithFilter(data_container(), ¬ifier, filter);
1476 PopulateSessionStorageInfoWithFilter(data_container(), ¬ifier, filter);
1477 PopulateAppCacheInfoWithFilter(data_container(), ¬ifier, filter);
1478 PopulateIndexedDBInfoWithFilter(data_container(), ¬ifier, filter);
1479 PopulateFileSystemInfoWithFilter(data_container(), ¬ifier, filter);
1480 PopulateQuotaInfoWithFilter(data_container(), ¬ifier, filter);
1481 PopulateServiceWorkerUsageInfoWithFilter(data_container(), ¬ifier, filter);
1482 PopulateSharedWorkerInfoWithFilter(data_container(), ¬ifier, filter);
1483 PopulateCacheStorageUsageInfoWithFilter(data_container(), ¬ifier, filter);
1484 PopulateMediaLicenseInfoWithFilter(data_container(), ¬ifier, 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, ¬ifier, base::string16());
1519 }
1520
PopulateCookieInfo(LocalDataContainer * container)1521 void CookiesTreeModel::PopulateCookieInfo(LocalDataContainer* container) {
1522 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1523 PopulateCookieInfoWithFilter(container, ¬ifier, base::string16());
1524 }
1525
PopulateDatabaseInfo(LocalDataContainer * container)1526 void CookiesTreeModel::PopulateDatabaseInfo(LocalDataContainer* container) {
1527 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1528 PopulateDatabaseInfoWithFilter(container, ¬ifier, base::string16());
1529 }
1530
PopulateLocalStorageInfo(LocalDataContainer * container)1531 void CookiesTreeModel::PopulateLocalStorageInfo(LocalDataContainer* container) {
1532 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1533 PopulateLocalStorageInfoWithFilter(container, ¬ifier, base::string16());
1534 }
1535
PopulateSessionStorageInfo(LocalDataContainer * container)1536 void CookiesTreeModel::PopulateSessionStorageInfo(
1537 LocalDataContainer* container) {
1538 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1539 PopulateSessionStorageInfoWithFilter(container, ¬ifier, base::string16());
1540 }
1541
PopulateIndexedDBInfo(LocalDataContainer * container)1542 void CookiesTreeModel::PopulateIndexedDBInfo(LocalDataContainer* container) {
1543 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1544 PopulateIndexedDBInfoWithFilter(container, ¬ifier, base::string16());
1545 }
1546
PopulateFileSystemInfo(LocalDataContainer * container)1547 void CookiesTreeModel::PopulateFileSystemInfo(LocalDataContainer* container) {
1548 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1549 PopulateFileSystemInfoWithFilter(container, ¬ifier, base::string16());
1550 }
1551
PopulateQuotaInfo(LocalDataContainer * container)1552 void CookiesTreeModel::PopulateQuotaInfo(LocalDataContainer* container) {
1553 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1554 PopulateQuotaInfoWithFilter(container, ¬ifier, base::string16());
1555 }
1556
PopulateServiceWorkerUsageInfo(LocalDataContainer * container)1557 void CookiesTreeModel::PopulateServiceWorkerUsageInfo(
1558 LocalDataContainer* container) {
1559 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1560 PopulateServiceWorkerUsageInfoWithFilter(
1561 container, ¬ifier, base::string16());
1562 }
1563
PopulateSharedWorkerInfo(LocalDataContainer * container)1564 void CookiesTreeModel::PopulateSharedWorkerInfo(LocalDataContainer* container) {
1565 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1566 PopulateSharedWorkerInfoWithFilter(container, ¬ifier, base::string16());
1567 }
1568
PopulateCacheStorageUsageInfo(LocalDataContainer * container)1569 void CookiesTreeModel::PopulateCacheStorageUsageInfo(
1570 LocalDataContainer* container) {
1571 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1572 PopulateCacheStorageUsageInfoWithFilter(container, ¬ifier,
1573 base::string16());
1574 }
1575
PopulateMediaLicenseInfo(LocalDataContainer * container)1576 void CookiesTreeModel::PopulateMediaLicenseInfo(LocalDataContainer* container) {
1577 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1578 PopulateMediaLicenseInfoWithFilter(container, ¬ifier, 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