Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / browsing_data / cookies_tree_model.cc
blob8deb087ada30b5d027e63159f07750d21d53f6fe
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.
5 #include "chrome/browser/browsing_data/cookies_tree_model.h"
7 #include <algorithm>
8 #include <functional>
9 #include <map>
10 #include <vector>
12 #include "base/bind.h"
13 #include "base/memory/linked_ptr.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/browser/browsing_data/browsing_data_channel_id_helper.h"
17 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
18 #include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h"
19 #include "chrome/browser/content_settings/cookie_settings.h"
20 #include "chrome/grit/generated_resources.h"
21 #include "content/public/common/url_constants.h"
22 #include "grit/theme_resources.h"
23 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
24 #include "net/cookies/canonical_cookie.h"
25 #include "net/url_request/url_request_context.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/gfx/image/image_skia.h"
29 #include "ui/resources/grit/ui_resources.h"
31 #if defined(ENABLE_EXTENSIONS)
32 #include "chrome/browser/extensions/extension_special_storage_policy.h"
33 #include "extensions/common/extension_set.h"
34 #endif
36 namespace {
38 struct NodeTitleComparator {
39 bool operator()(const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
40 return lhs->GetTitle() < rhs->GetTitle();
44 // Comparison functor, for use in CookieTreeRootNode.
45 struct HostNodeComparator {
46 bool operator()(const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
47 // This comparator is only meant to compare CookieTreeHostNode types. Make
48 // sure we check this, as the static cast below is dangerous if we get the
49 // wrong object type.
50 CHECK_EQ(CookieTreeNode::DetailedInfo::TYPE_HOST,
51 lhs->GetDetailedInfo().node_type);
52 CHECK_EQ(CookieTreeNode::DetailedInfo::TYPE_HOST,
53 rhs->GetDetailedInfo().node_type);
55 const CookieTreeHostNode* ltn =
56 static_cast<const CookieTreeHostNode*>(lhs);
57 const CookieTreeHostNode* rtn =
58 static_cast<const CookieTreeHostNode*>(rhs);
60 // We want to order by registry controlled domain, so we would get
61 // google.com, ad.google.com, www.google.com,
62 // microsoft.com, ad.microsoft.com. CanonicalizeHost transforms the origins
63 // into a form like google.com.www so that string comparisons work.
64 return (ltn->canonicalized_host() <
65 rtn->canonicalized_host());
69 std::string CanonicalizeHost(const GURL& url) {
70 // The canonicalized representation makes the registry controlled domain
71 // come first, and then adds subdomains in reverse order, e.g.
72 // 1.mail.google.com would become google.com.mail.1, and then a standard
73 // string comparison works to order hosts by registry controlled domain
74 // first. Leading dots are ignored, ".google.com" is the same as
75 // "google.com".
77 if (url.SchemeIsFile()) {
78 return std::string(url::kFileScheme) +
79 url::kStandardSchemeSeparator;
82 std::string host = url.host();
83 std::string retval =
84 net::registry_controlled_domains::GetDomainAndRegistry(
85 host,
86 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
87 if (!retval.length()) // Is an IP address or other special origin.
88 return host;
90 std::string::size_type position = host.rfind(retval);
92 // The host may be the registry controlled domain, in which case fail fast.
93 if (position == 0 || position == std::string::npos)
94 return host;
96 // If host is www.google.com, retval will contain google.com at this point.
97 // Start operating to the left of the registry controlled domain, e.g. in
98 // the www.google.com example, start at index 3.
99 --position;
101 // If position == 0, that means it's a dot; this will be ignored to treat
102 // ".google.com" the same as "google.com".
103 while (position > 0) {
104 retval += std::string(".");
105 // Copy up to the next dot. host[position] is a dot so start after it.
106 std::string::size_type next_dot = host.rfind(".", position - 1);
107 if (next_dot == std::string::npos) {
108 retval += host.substr(0, position);
109 break;
111 retval += host.substr(next_dot + 1, position - (next_dot + 1));
112 position = next_dot;
114 return retval;
117 #if defined(ENABLE_EXTENSIONS)
118 bool TypeIsProtected(CookieTreeNode::DetailedInfo::NodeType type) {
119 switch (type) {
120 case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
121 return false;
122 case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
123 return true;
124 case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
125 return true;
126 case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
127 return true;
128 case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
129 return true;
130 case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
131 return true;
132 case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM:
133 return true;
134 case CookieTreeNode::DetailedInfo::TYPE_QUOTA:
135 return false;
136 case CookieTreeNode::DetailedInfo::TYPE_CHANNEL_ID:
137 return false;
138 case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER:
139 return true;
140 case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO:
141 return false;
142 default:
143 break;
145 return false;
147 #endif
149 // This function returns the local data container associated with a leaf tree
150 // node. The app node is assumed to be 3 levels above the leaf because of the
151 // following structure:
152 // root -> origin -> storage type -> leaf node
153 LocalDataContainer* GetLocalDataContainerForNode(CookieTreeNode* node) {
154 CookieTreeHostNode* host = static_cast<CookieTreeHostNode*>(
155 node->parent()->parent());
156 CHECK_EQ(host->GetDetailedInfo().node_type,
157 CookieTreeNode::DetailedInfo::TYPE_HOST);
158 return node->GetModel()->data_container();
161 } // namespace
163 CookieTreeNode::DetailedInfo::DetailedInfo()
164 : node_type(TYPE_NONE),
165 cookie(NULL),
166 database_info(NULL),
167 local_storage_info(NULL),
168 session_storage_info(NULL),
169 appcache_info(NULL),
170 indexed_db_info(NULL),
171 file_system_info(NULL),
172 quota_info(NULL),
173 channel_id(NULL),
174 service_worker_info(NULL) {
177 CookieTreeNode::DetailedInfo::~DetailedInfo() {}
179 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::Init(
180 NodeType type) {
181 DCHECK_EQ(TYPE_NONE, node_type);
182 node_type = type;
183 return *this;
186 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitHost() {
187 Init(TYPE_HOST);
188 return *this;
191 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitCookie(
192 const net::CanonicalCookie* cookie) {
193 Init(TYPE_COOKIE);
194 this->cookie = cookie;
195 return *this;
198 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitDatabase(
199 const BrowsingDataDatabaseHelper::DatabaseInfo* database_info) {
200 Init(TYPE_DATABASE);
201 this->database_info = database_info;
202 origin = database_info->identifier.ToOrigin();
203 return *this;
206 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitLocalStorage(
207 const BrowsingDataLocalStorageHelper::LocalStorageInfo*
208 local_storage_info) {
209 Init(TYPE_LOCAL_STORAGE);
210 this->local_storage_info = local_storage_info;
211 origin = local_storage_info->origin_url;
212 return *this;
215 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitSessionStorage(
216 const BrowsingDataLocalStorageHelper::LocalStorageInfo*
217 session_storage_info) {
218 Init(TYPE_SESSION_STORAGE);
219 this->session_storage_info = session_storage_info;
220 origin = session_storage_info->origin_url;
221 return *this;
224 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitAppCache(
225 const GURL& origin,
226 const content::AppCacheInfo* appcache_info) {
227 Init(TYPE_APPCACHE);
228 this->appcache_info = appcache_info;
229 this->origin = origin;
230 return *this;
233 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitIndexedDB(
234 const content::IndexedDBInfo* indexed_db_info) {
235 Init(TYPE_INDEXED_DB);
236 this->indexed_db_info = indexed_db_info;
237 this->origin = indexed_db_info->origin_;
238 return *this;
241 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitFileSystem(
242 const BrowsingDataFileSystemHelper::FileSystemInfo* file_system_info) {
243 Init(TYPE_FILE_SYSTEM);
244 this->file_system_info = file_system_info;
245 this->origin = file_system_info->origin;
246 return *this;
249 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitQuota(
250 const BrowsingDataQuotaHelper::QuotaInfo* quota_info) {
251 Init(TYPE_QUOTA);
252 this->quota_info = quota_info;
253 return *this;
256 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitChannelID(
257 const net::ChannelIDStore::ChannelID* channel_id) {
258 Init(TYPE_CHANNEL_ID);
259 this->channel_id = channel_id;
260 return *this;
263 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitServiceWorker(
264 const content::ServiceWorkerUsageInfo* service_worker_info) {
265 Init(TYPE_SERVICE_WORKER);
266 this->service_worker_info = service_worker_info;
267 this->origin = service_worker_info->origin;
268 return *this;
271 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitFlashLSO(
272 const std::string& flash_lso_domain) {
273 Init(TYPE_FLASH_LSO);
274 this->flash_lso_domain = flash_lso_domain;
275 return *this;
278 ///////////////////////////////////////////////////////////////////////////////
279 // CookieTreeNode, public:
281 void CookieTreeNode::DeleteStoredObjects() {
282 std::for_each(children().begin(),
283 children().end(),
284 std::mem_fun(&CookieTreeNode::DeleteStoredObjects));
287 CookiesTreeModel* CookieTreeNode::GetModel() const {
288 if (parent())
289 return parent()->GetModel();
290 else
291 return NULL;
294 ///////////////////////////////////////////////////////////////////////////////
295 // CookieTreeCookieNode, public:
297 CookieTreeCookieNode::CookieTreeCookieNode(
298 std::list<net::CanonicalCookie>::iterator cookie)
299 : CookieTreeNode(base::UTF8ToUTF16(cookie->Name())),
300 cookie_(cookie) {
303 CookieTreeCookieNode::~CookieTreeCookieNode() {}
305 void CookieTreeCookieNode::DeleteStoredObjects() {
306 LocalDataContainer* container = GetLocalDataContainerForNode(this);
307 container->cookie_helper_->DeleteCookie(*cookie_);
308 container->cookie_list_.erase(cookie_);
311 CookieTreeNode::DetailedInfo CookieTreeCookieNode::GetDetailedInfo() const {
312 return DetailedInfo().InitCookie(&*cookie_);
315 ///////////////////////////////////////////////////////////////////////////////
316 // CookieTreeAppCacheNode, public:
318 CookieTreeAppCacheNode::CookieTreeAppCacheNode(
319 const GURL& origin_url,
320 std::list<content::AppCacheInfo>::iterator appcache_info)
321 : CookieTreeNode(base::UTF8ToUTF16(appcache_info->manifest_url.spec())),
322 origin_url_(origin_url),
323 appcache_info_(appcache_info) {
326 CookieTreeAppCacheNode::~CookieTreeAppCacheNode() {
329 void CookieTreeAppCacheNode::DeleteStoredObjects() {
330 LocalDataContainer* container = GetLocalDataContainerForNode(this);
332 if (container) {
333 DCHECK(container->appcache_helper_.get());
334 container->appcache_helper_
335 ->DeleteAppCacheGroup(appcache_info_->manifest_url);
336 container->appcache_info_[origin_url_].erase(appcache_info_);
340 CookieTreeNode::DetailedInfo CookieTreeAppCacheNode::GetDetailedInfo() const {
341 return DetailedInfo().InitAppCache(origin_url_, &*appcache_info_);
344 ///////////////////////////////////////////////////////////////////////////////
345 // CookieTreeDatabaseNode, public:
347 CookieTreeDatabaseNode::CookieTreeDatabaseNode(
348 std::list<BrowsingDataDatabaseHelper::DatabaseInfo>::iterator database_info)
349 : CookieTreeNode(database_info->database_name.empty() ?
350 l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME) :
351 base::UTF8ToUTF16(database_info->database_name)),
352 database_info_(database_info) {
355 CookieTreeDatabaseNode::~CookieTreeDatabaseNode() {}
357 void CookieTreeDatabaseNode::DeleteStoredObjects() {
358 LocalDataContainer* container = GetLocalDataContainerForNode(this);
360 if (container) {
361 container->database_helper_->DeleteDatabase(
362 database_info_->identifier.ToString(), database_info_->database_name);
363 container->database_info_list_.erase(database_info_);
367 CookieTreeNode::DetailedInfo CookieTreeDatabaseNode::GetDetailedInfo() const {
368 return DetailedInfo().InitDatabase(&*database_info_);
371 ///////////////////////////////////////////////////////////////////////////////
372 // CookieTreeLocalStorageNode, public:
374 CookieTreeLocalStorageNode::CookieTreeLocalStorageNode(
375 std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::iterator
376 local_storage_info)
377 : CookieTreeNode(base::UTF8ToUTF16(local_storage_info->origin_url.spec())),
378 local_storage_info_(local_storage_info) {
381 CookieTreeLocalStorageNode::~CookieTreeLocalStorageNode() {}
383 void CookieTreeLocalStorageNode::DeleteStoredObjects() {
384 LocalDataContainer* container = GetLocalDataContainerForNode(this);
386 if (container) {
387 container->local_storage_helper_->DeleteOrigin(
388 local_storage_info_->origin_url);
389 container->local_storage_info_list_.erase(local_storage_info_);
393 CookieTreeNode::DetailedInfo
394 CookieTreeLocalStorageNode::GetDetailedInfo() const {
395 return DetailedInfo().InitLocalStorage(
396 &*local_storage_info_);
399 ///////////////////////////////////////////////////////////////////////////////
400 // CookieTreeSessionStorageNode, public:
402 CookieTreeSessionStorageNode::CookieTreeSessionStorageNode(
403 std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::iterator
404 session_storage_info)
405 : CookieTreeNode(
406 base::UTF8ToUTF16(session_storage_info->origin_url.spec())),
407 session_storage_info_(session_storage_info) {
410 CookieTreeSessionStorageNode::~CookieTreeSessionStorageNode() {}
412 void CookieTreeSessionStorageNode::DeleteStoredObjects() {
413 LocalDataContainer* container = GetLocalDataContainerForNode(this);
415 if (container) {
416 // TODO(rsesek): There's no easy way to get the namespace_id for a session
417 // storage, nor is there an easy way to clear session storage just by
418 // origin. This is probably okay since session storage is not persistent.
419 // http://crbug.com/168996
420 container->session_storage_info_list_.erase(session_storage_info_);
424 CookieTreeNode::DetailedInfo
425 CookieTreeSessionStorageNode::GetDetailedInfo() const {
426 return DetailedInfo().InitSessionStorage(&*session_storage_info_);
429 ///////////////////////////////////////////////////////////////////////////////
430 // CookieTreeIndexedDBNode, public:
432 CookieTreeIndexedDBNode::CookieTreeIndexedDBNode(
433 std::list<content::IndexedDBInfo>::iterator
434 indexed_db_info)
435 : CookieTreeNode(base::UTF8ToUTF16(
436 indexed_db_info->origin_.spec())),
437 indexed_db_info_(indexed_db_info) {
440 CookieTreeIndexedDBNode::~CookieTreeIndexedDBNode() {}
442 void CookieTreeIndexedDBNode::DeleteStoredObjects() {
443 LocalDataContainer* container = GetLocalDataContainerForNode(this);
445 if (container) {
446 container->indexed_db_helper_->DeleteIndexedDB(
447 indexed_db_info_->origin_);
448 container->indexed_db_info_list_.erase(indexed_db_info_);
452 CookieTreeNode::DetailedInfo CookieTreeIndexedDBNode::GetDetailedInfo() const {
453 return DetailedInfo().InitIndexedDB(&*indexed_db_info_);
456 ///////////////////////////////////////////////////////////////////////////////
457 // CookieTreeFileSystemNode, public:
459 CookieTreeFileSystemNode::CookieTreeFileSystemNode(
460 std::list<BrowsingDataFileSystemHelper::FileSystemInfo>::iterator
461 file_system_info)
462 : CookieTreeNode(base::UTF8ToUTF16(
463 file_system_info->origin.spec())),
464 file_system_info_(file_system_info) {
467 CookieTreeFileSystemNode::~CookieTreeFileSystemNode() {}
469 void CookieTreeFileSystemNode::DeleteStoredObjects() {
470 LocalDataContainer* container = GetLocalDataContainerForNode(this);
472 if (container) {
473 container->file_system_helper_->DeleteFileSystemOrigin(
474 file_system_info_->origin);
475 container->file_system_info_list_.erase(file_system_info_);
479 CookieTreeNode::DetailedInfo CookieTreeFileSystemNode::GetDetailedInfo() const {
480 return DetailedInfo().InitFileSystem(&*file_system_info_);
483 ///////////////////////////////////////////////////////////////////////////////
484 // CookieTreeQuotaNode, public:
486 CookieTreeQuotaNode::CookieTreeQuotaNode(
487 std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)
488 : CookieTreeNode(base::UTF8ToUTF16(quota_info->host)),
489 quota_info_(quota_info) {
492 CookieTreeQuotaNode::~CookieTreeQuotaNode() {}
494 void CookieTreeQuotaNode::DeleteStoredObjects() {
495 // Calling this function may cause unexpected over-quota state of origin.
496 // However, it'll caused no problem, just prevent usage growth of the origin.
497 LocalDataContainer* container = GetModel()->data_container();
499 if (container) {
500 container->quota_helper_->RevokeHostQuota(quota_info_->host);
501 container->quota_info_list_.erase(quota_info_);
505 CookieTreeNode::DetailedInfo CookieTreeQuotaNode::GetDetailedInfo() const {
506 return DetailedInfo().InitQuota(&*quota_info_);
509 ///////////////////////////////////////////////////////////////////////////////
510 // CookieTreeChannelIDNode, public:
512 CookieTreeChannelIDNode::CookieTreeChannelIDNode(
513 net::ChannelIDStore::ChannelIDList::iterator channel_id)
514 : CookieTreeNode(base::ASCIIToUTF16(channel_id->server_identifier())),
515 channel_id_(channel_id) {
518 CookieTreeChannelIDNode::~CookieTreeChannelIDNode() {}
520 void CookieTreeChannelIDNode::DeleteStoredObjects() {
521 LocalDataContainer* container = GetLocalDataContainerForNode(this);
523 if (container) {
524 container->channel_id_helper_->DeleteChannelID(
525 channel_id_->server_identifier());
526 container->channel_id_list_.erase(channel_id_);
530 CookieTreeNode::DetailedInfo
531 CookieTreeChannelIDNode::GetDetailedInfo() const {
532 return DetailedInfo().InitChannelID(&*channel_id_);
535 ///////////////////////////////////////////////////////////////////////////////
536 // CookieTreeServiceWorkerNode, public:
538 CookieTreeServiceWorkerNode::CookieTreeServiceWorkerNode(
539 std::list<content::ServiceWorkerUsageInfo>::iterator service_worker_info)
540 : CookieTreeNode(base::UTF8ToUTF16(service_worker_info->origin.spec())),
541 service_worker_info_(service_worker_info) {
544 CookieTreeServiceWorkerNode::~CookieTreeServiceWorkerNode() {
547 void CookieTreeServiceWorkerNode::DeleteStoredObjects() {
548 LocalDataContainer* container = GetLocalDataContainerForNode(this);
550 if (container) {
551 container->service_worker_helper_->DeleteServiceWorkers(
552 service_worker_info_->origin);
553 container->service_worker_info_list_.erase(service_worker_info_);
557 CookieTreeNode::DetailedInfo CookieTreeServiceWorkerNode::GetDetailedInfo()
558 const {
559 return DetailedInfo().InitServiceWorker(&*service_worker_info_);
562 ///////////////////////////////////////////////////////////////////////////////
563 // CookieTreeRootNode, public:
565 CookieTreeRootNode::CookieTreeRootNode(CookiesTreeModel* model)
566 : model_(model) {
569 CookieTreeRootNode::~CookieTreeRootNode() {}
571 CookieTreeHostNode* CookieTreeRootNode::GetOrCreateHostNode(
572 const GURL& url) {
573 scoped_ptr<CookieTreeHostNode> host_node(
574 new CookieTreeHostNode(url));
576 // First see if there is an existing match.
577 std::vector<CookieTreeNode*>::iterator host_node_iterator =
578 std::lower_bound(children().begin(), children().end(), host_node.get(),
579 HostNodeComparator());
580 if (host_node_iterator != children().end() &&
581 CookieTreeHostNode::TitleForUrl(url) ==
582 (*host_node_iterator)->GetTitle())
583 return static_cast<CookieTreeHostNode*>(*host_node_iterator);
584 // Node doesn't exist, insert the new one into the (ordered) children.
585 DCHECK(model_);
586 model_->Add(this, host_node.get(),
587 (host_node_iterator - children().begin()));
588 return host_node.release();
591 CookiesTreeModel* CookieTreeRootNode::GetModel() const {
592 return model_;
595 CookieTreeNode::DetailedInfo CookieTreeRootNode::GetDetailedInfo() const {
596 return DetailedInfo().Init(DetailedInfo::TYPE_ROOT);
599 ///////////////////////////////////////////////////////////////////////////////
600 // CookieTreeHostNode, public:
602 // static
603 base::string16 CookieTreeHostNode::TitleForUrl(const GURL& url) {
604 const std::string file_origin_node_name(
605 std::string(url::kFileScheme) + url::kStandardSchemeSeparator);
606 return base::UTF8ToUTF16(url.SchemeIsFile() ? file_origin_node_name
607 : url.host());
610 CookieTreeHostNode::CookieTreeHostNode(const GURL& url)
611 : CookieTreeNode(TitleForUrl(url)),
612 cookies_child_(NULL),
613 databases_child_(NULL),
614 local_storages_child_(NULL),
615 session_storages_child_(NULL),
616 appcaches_child_(NULL),
617 indexed_dbs_child_(NULL),
618 file_systems_child_(NULL),
619 quota_child_(NULL),
620 channel_ids_child_(NULL),
621 service_workers_child_(NULL),
622 flash_lso_child_(NULL),
623 url_(url),
624 canonicalized_host_(CanonicalizeHost(url)) {
627 CookieTreeHostNode::~CookieTreeHostNode() {}
629 const std::string CookieTreeHostNode::GetHost() const {
630 const std::string file_origin_node_name(
631 std::string(url::kFileScheme) + url::kStandardSchemeSeparator);
632 return url_.SchemeIsFile() ? file_origin_node_name : url_.host();
635 CookieTreeNode::DetailedInfo CookieTreeHostNode::GetDetailedInfo() const {
636 return DetailedInfo().InitHost();
639 CookieTreeCookiesNode* CookieTreeHostNode::GetOrCreateCookiesNode() {
640 if (cookies_child_)
641 return cookies_child_;
642 cookies_child_ = new CookieTreeCookiesNode;
643 AddChildSortedByTitle(cookies_child_);
644 return cookies_child_;
647 CookieTreeDatabasesNode* CookieTreeHostNode::GetOrCreateDatabasesNode() {
648 if (databases_child_)
649 return databases_child_;
650 databases_child_ = new CookieTreeDatabasesNode;
651 AddChildSortedByTitle(databases_child_);
652 return databases_child_;
655 CookieTreeLocalStoragesNode*
656 CookieTreeHostNode::GetOrCreateLocalStoragesNode() {
657 if (local_storages_child_)
658 return local_storages_child_;
659 local_storages_child_ = new CookieTreeLocalStoragesNode;
660 AddChildSortedByTitle(local_storages_child_);
661 return local_storages_child_;
664 CookieTreeSessionStoragesNode*
665 CookieTreeHostNode::GetOrCreateSessionStoragesNode() {
666 if (session_storages_child_)
667 return session_storages_child_;
668 session_storages_child_ = new CookieTreeSessionStoragesNode;
669 AddChildSortedByTitle(session_storages_child_);
670 return session_storages_child_;
673 CookieTreeAppCachesNode* CookieTreeHostNode::GetOrCreateAppCachesNode() {
674 if (appcaches_child_)
675 return appcaches_child_;
676 appcaches_child_ = new CookieTreeAppCachesNode;
677 AddChildSortedByTitle(appcaches_child_);
678 return appcaches_child_;
681 CookieTreeIndexedDBsNode* CookieTreeHostNode::GetOrCreateIndexedDBsNode() {
682 if (indexed_dbs_child_)
683 return indexed_dbs_child_;
684 indexed_dbs_child_ = new CookieTreeIndexedDBsNode;
685 AddChildSortedByTitle(indexed_dbs_child_);
686 return indexed_dbs_child_;
689 CookieTreeFileSystemsNode* CookieTreeHostNode::GetOrCreateFileSystemsNode() {
690 if (file_systems_child_)
691 return file_systems_child_;
692 file_systems_child_ = new CookieTreeFileSystemsNode;
693 AddChildSortedByTitle(file_systems_child_);
694 return file_systems_child_;
697 CookieTreeQuotaNode* CookieTreeHostNode::UpdateOrCreateQuotaNode(
698 std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info) {
699 if (quota_child_)
700 return quota_child_;
701 quota_child_ = new CookieTreeQuotaNode(quota_info);
702 AddChildSortedByTitle(quota_child_);
703 return quota_child_;
706 CookieTreeChannelIDsNode*
707 CookieTreeHostNode::GetOrCreateChannelIDsNode() {
708 if (channel_ids_child_)
709 return channel_ids_child_;
710 channel_ids_child_ = new CookieTreeChannelIDsNode;
711 AddChildSortedByTitle(channel_ids_child_);
712 return channel_ids_child_;
715 CookieTreeServiceWorkersNode*
716 CookieTreeHostNode::GetOrCreateServiceWorkersNode() {
717 if (service_workers_child_)
718 return service_workers_child_;
719 service_workers_child_ = new CookieTreeServiceWorkersNode;
720 AddChildSortedByTitle(service_workers_child_);
721 return service_workers_child_;
724 CookieTreeFlashLSONode* CookieTreeHostNode::GetOrCreateFlashLSONode(
725 const std::string& domain) {
726 DCHECK_EQ(GetHost(), domain);
727 if (flash_lso_child_)
728 return flash_lso_child_;
729 flash_lso_child_ = new CookieTreeFlashLSONode(domain);
730 AddChildSortedByTitle(flash_lso_child_);
731 return flash_lso_child_;
734 void CookieTreeHostNode::CreateContentException(
735 CookieSettings* cookie_settings, ContentSetting setting) const {
736 DCHECK(setting == CONTENT_SETTING_ALLOW ||
737 setting == CONTENT_SETTING_BLOCK ||
738 setting == CONTENT_SETTING_SESSION_ONLY);
739 if (CanCreateContentException()) {
740 cookie_settings->ResetCookieSetting(
741 ContentSettingsPattern::FromURLNoWildcard(url_),
742 ContentSettingsPattern::Wildcard());
743 cookie_settings->SetCookieSetting(
744 ContentSettingsPattern::FromURL(url_),
745 ContentSettingsPattern::Wildcard(), setting);
749 bool CookieTreeHostNode::CanCreateContentException() const {
750 return !url_.SchemeIsFile();
753 ///////////////////////////////////////////////////////////////////////////////
754 // CookieTreeCookiesNode, public:
756 CookieTreeCookiesNode::CookieTreeCookiesNode()
757 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIES)) {
760 CookieTreeCookiesNode::~CookieTreeCookiesNode() {
763 CookieTreeNode::DetailedInfo CookieTreeCookiesNode::GetDetailedInfo() const {
764 return DetailedInfo().Init(DetailedInfo::TYPE_COOKIES);
767 ///////////////////////////////////////////////////////////////////////////////
768 // CookieTreeAppCachesNode, public:
770 CookieTreeAppCachesNode::CookieTreeAppCachesNode()
771 : CookieTreeNode(l10n_util::GetStringUTF16(
772 IDS_COOKIES_APPLICATION_CACHES)) {
775 CookieTreeAppCachesNode::~CookieTreeAppCachesNode() {}
777 CookieTreeNode::DetailedInfo CookieTreeAppCachesNode::GetDetailedInfo() const {
778 return DetailedInfo().Init(DetailedInfo::TYPE_APPCACHES);
781 ///////////////////////////////////////////////////////////////////////////////
782 // CookieTreeDatabasesNode, public:
784 CookieTreeDatabasesNode::CookieTreeDatabasesNode()
785 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASES)) {
788 CookieTreeDatabasesNode::~CookieTreeDatabasesNode() {}
790 CookieTreeNode::DetailedInfo CookieTreeDatabasesNode::GetDetailedInfo() const {
791 return DetailedInfo().Init(DetailedInfo::TYPE_DATABASES);
794 ///////////////////////////////////////////////////////////////////////////////
795 // CookieTreeLocalStoragesNode, public:
797 CookieTreeLocalStoragesNode::CookieTreeLocalStoragesNode()
798 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_LOCAL_STORAGE)) {
801 CookieTreeLocalStoragesNode::~CookieTreeLocalStoragesNode() {}
803 CookieTreeNode::DetailedInfo
804 CookieTreeLocalStoragesNode::GetDetailedInfo() const {
805 return DetailedInfo().Init(DetailedInfo::TYPE_LOCAL_STORAGES);
808 ///////////////////////////////////////////////////////////////////////////////
809 // CookieTreeSessionStoragesNode, public:
811 CookieTreeSessionStoragesNode::CookieTreeSessionStoragesNode()
812 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SESSION_STORAGE)) {
815 CookieTreeSessionStoragesNode::~CookieTreeSessionStoragesNode() {}
817 CookieTreeNode::DetailedInfo
818 CookieTreeSessionStoragesNode::GetDetailedInfo() const {
819 return DetailedInfo().Init(DetailedInfo::TYPE_SESSION_STORAGES);
822 ///////////////////////////////////////////////////////////////////////////////
823 // CookieTreeIndexedDBsNode, public:
825 CookieTreeIndexedDBsNode::CookieTreeIndexedDBsNode()
826 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_INDEXED_DBS)) {
829 CookieTreeIndexedDBsNode::~CookieTreeIndexedDBsNode() {}
831 CookieTreeNode::DetailedInfo
832 CookieTreeIndexedDBsNode::GetDetailedInfo() const {
833 return DetailedInfo().Init(DetailedInfo::TYPE_INDEXED_DBS);
836 ///////////////////////////////////////////////////////////////////////////////
837 // CookieTreeFileSystemsNode, public:
839 CookieTreeFileSystemsNode::CookieTreeFileSystemsNode()
840 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_FILE_SYSTEMS)) {
843 CookieTreeFileSystemsNode::~CookieTreeFileSystemsNode() {}
845 CookieTreeNode::DetailedInfo
846 CookieTreeFileSystemsNode::GetDetailedInfo() const {
847 return DetailedInfo().Init(DetailedInfo::TYPE_FILE_SYSTEMS);
850 ///////////////////////////////////////////////////////////////////////////////
851 // CookieTreeChannelIDsNode, public:
853 CookieTreeChannelIDsNode::CookieTreeChannelIDsNode()
854 : CookieTreeNode(
855 l10n_util::GetStringUTF16(IDS_COOKIES_CHANNEL_IDS)) {
858 CookieTreeChannelIDsNode::~CookieTreeChannelIDsNode() {}
860 CookieTreeNode::DetailedInfo
861 CookieTreeChannelIDsNode::GetDetailedInfo() const {
862 return DetailedInfo().Init(DetailedInfo::TYPE_CHANNEL_IDS);
865 void CookieTreeNode::AddChildSortedByTitle(CookieTreeNode* new_child) {
866 DCHECK(new_child);
867 std::vector<CookieTreeNode*>::iterator iter =
868 std::lower_bound(children().begin(), children().end(), new_child,
869 NodeTitleComparator());
870 GetModel()->Add(this, new_child, iter - children().begin());
873 ///////////////////////////////////////////////////////////////////////////////
874 // CookieTreeServiceWorkersNode, public:
876 CookieTreeServiceWorkersNode::CookieTreeServiceWorkersNode()
877 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SERVICE_WORKERS)) {
880 CookieTreeServiceWorkersNode::~CookieTreeServiceWorkersNode() {
883 CookieTreeNode::DetailedInfo CookieTreeServiceWorkersNode::GetDetailedInfo()
884 const {
885 return DetailedInfo().Init(DetailedInfo::TYPE_SERVICE_WORKERS);
888 ///////////////////////////////////////////////////////////////////////////////
889 // CookieTreeFlashLSONode
890 CookieTreeFlashLSONode::CookieTreeFlashLSONode(
891 const std::string& domain)
892 : domain_(domain) {}
893 CookieTreeFlashLSONode::~CookieTreeFlashLSONode() {}
895 void CookieTreeFlashLSONode::DeleteStoredObjects() {
896 // We are one level below the host node.
897 CookieTreeHostNode* host = static_cast<CookieTreeHostNode*>(parent());
898 CHECK_EQ(host->GetDetailedInfo().node_type,
899 CookieTreeNode::DetailedInfo::TYPE_HOST);
900 LocalDataContainer* container = GetModel()->data_container();
901 container->flash_lso_helper_->DeleteFlashLSOsForSite(domain_);
904 CookieTreeNode::DetailedInfo CookieTreeFlashLSONode::GetDetailedInfo() const {
905 return DetailedInfo().InitFlashLSO(domain_);
908 ///////////////////////////////////////////////////////////////////////////////
909 // ScopedBatchUpdateNotifier
910 CookiesTreeModel::ScopedBatchUpdateNotifier::ScopedBatchUpdateNotifier(
911 CookiesTreeModel* model, CookieTreeNode* node)
912 : model_(model), node_(node), batch_in_progress_(false) {
915 CookiesTreeModel::ScopedBatchUpdateNotifier::~ScopedBatchUpdateNotifier() {
916 if (batch_in_progress_) {
917 model_->NotifyObserverTreeNodeChanged(node_);
918 model_->NotifyObserverEndBatch();
922 void CookiesTreeModel::ScopedBatchUpdateNotifier::StartBatchUpdate() {
923 if (!batch_in_progress_) {
924 model_->NotifyObserverBeginBatch();
925 batch_in_progress_ = true;
929 ///////////////////////////////////////////////////////////////////////////////
930 // CookiesTreeModel, public:
931 CookiesTreeModel::CookiesTreeModel(
932 LocalDataContainer* data_container,
933 ExtensionSpecialStoragePolicy* special_storage_policy,
934 bool group_by_cookie_source)
935 : ui::TreeNodeModel<CookieTreeNode>(new CookieTreeRootNode(this)),
936 data_container_(data_container),
937 #if defined(ENABLE_EXTENSIONS)
938 special_storage_policy_(special_storage_policy),
939 #endif
940 group_by_cookie_source_(group_by_cookie_source),
941 batch_update_(0) {
942 data_container_->Init(this);
945 CookiesTreeModel::~CookiesTreeModel() {
948 ///////////////////////////////////////////////////////////////////////////////
949 // CookiesTreeModel, TreeModel methods (public):
951 // TreeModel methods:
952 // Returns the set of icons for the nodes in the tree. You only need override
953 // this if you don't want to use the default folder icons.
954 void CookiesTreeModel::GetIcons(std::vector<gfx::ImageSkia>* icons) {
955 icons->push_back(*ResourceBundle::GetSharedInstance().GetNativeImageNamed(
956 IDR_DEFAULT_FAVICON).ToImageSkia());
957 icons->push_back(*ResourceBundle::GetSharedInstance().GetNativeImageNamed(
958 IDR_COOKIE_ICON).ToImageSkia());
959 icons->push_back(*ResourceBundle::GetSharedInstance().GetNativeImageNamed(
960 IDR_COOKIE_STORAGE_ICON).ToImageSkia());
963 // Returns the index of the icon to use for |node|. Return -1 to use the
964 // default icon. The index is relative to the list of icons returned from
965 // GetIcons.
966 int CookiesTreeModel::GetIconIndex(ui::TreeModelNode* node) {
967 CookieTreeNode* ct_node = static_cast<CookieTreeNode*>(node);
968 switch (ct_node->GetDetailedInfo().node_type) {
969 case CookieTreeNode::DetailedInfo::TYPE_HOST:
970 return ORIGIN;
971 case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
972 return COOKIE;
973 case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
974 return DATABASE;
975 case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
976 return DATABASE; // close enough
977 case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
978 return DATABASE; // ditto
979 case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
980 return DATABASE; // ditto
981 case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
982 return DATABASE; // ditto
983 case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM:
984 return DATABASE; // ditto
985 case CookieTreeNode::DetailedInfo::TYPE_QUOTA:
986 return -1;
987 case CookieTreeNode::DetailedInfo::TYPE_CHANNEL_ID:
988 return COOKIE; // It's kinda like a cookie?
989 case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER:
990 return DATABASE; // Just like appcache
991 default:
992 break;
994 return -1;
997 void CookiesTreeModel::DeleteAllStoredObjects() {
998 NotifyObserverBeginBatch();
999 CookieTreeNode* root = GetRoot();
1000 root->DeleteStoredObjects();
1001 int num_children = root->child_count();
1002 for (int i = num_children - 1; i >= 0; --i)
1003 delete Remove(root, root->GetChild(i));
1004 NotifyObserverTreeNodeChanged(root);
1005 NotifyObserverEndBatch();
1008 void CookiesTreeModel::DeleteCookieNode(CookieTreeNode* cookie_node) {
1009 if (cookie_node == GetRoot())
1010 return;
1011 cookie_node->DeleteStoredObjects();
1012 CookieTreeNode* parent_node = cookie_node->parent();
1013 delete Remove(parent_node, cookie_node);
1014 if (parent_node->empty())
1015 DeleteCookieNode(parent_node);
1018 void CookiesTreeModel::UpdateSearchResults(const base::string16& filter) {
1019 CookieTreeNode* root = GetRoot();
1020 ScopedBatchUpdateNotifier notifier(this, root);
1021 int num_children = root->child_count();
1022 notifier.StartBatchUpdate();
1023 for (int i = num_children - 1; i >= 0; --i)
1024 delete Remove(root, root->GetChild(i));
1026 PopulateCookieInfoWithFilter(data_container(), &notifier, filter);
1027 PopulateDatabaseInfoWithFilter(data_container(), &notifier, filter);
1028 PopulateLocalStorageInfoWithFilter(data_container(), &notifier, filter);
1029 PopulateSessionStorageInfoWithFilter(data_container(), &notifier, filter);
1030 PopulateAppCacheInfoWithFilter(data_container(), &notifier, filter);
1031 PopulateIndexedDBInfoWithFilter(data_container(), &notifier, filter);
1032 PopulateFileSystemInfoWithFilter(data_container(), &notifier, filter);
1033 PopulateQuotaInfoWithFilter(data_container(), &notifier, filter);
1034 PopulateChannelIDInfoWithFilter(data_container(), &notifier, filter);
1035 PopulateServiceWorkerUsageInfoWithFilter(data_container(), &notifier, filter);
1038 #if defined(ENABLE_EXTENSIONS)
1039 const extensions::ExtensionSet* CookiesTreeModel::ExtensionsProtectingNode(
1040 const CookieTreeNode& cookie_node) {
1041 if (!special_storage_policy_.get())
1042 return NULL;
1044 CookieTreeNode::DetailedInfo info = cookie_node.GetDetailedInfo();
1046 if (!TypeIsProtected(info.node_type))
1047 return NULL;
1049 DCHECK(!info.origin.is_empty());
1050 return special_storage_policy_->ExtensionsProtectingOrigin(info.origin);
1052 #endif
1054 void CookiesTreeModel::AddCookiesTreeObserver(Observer* observer) {
1055 cookies_observer_list_.AddObserver(observer);
1056 // Call super so that TreeNodeModel can notify, too.
1057 ui::TreeNodeModel<CookieTreeNode>::AddObserver(observer);
1060 void CookiesTreeModel::RemoveCookiesTreeObserver(Observer* observer) {
1061 cookies_observer_list_.RemoveObserver(observer);
1062 // Call super so that TreeNodeModel doesn't have dead pointers.
1063 ui::TreeNodeModel<CookieTreeNode>::RemoveObserver(observer);
1066 void CookiesTreeModel::PopulateAppCacheInfo(LocalDataContainer* container) {
1067 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1068 PopulateAppCacheInfoWithFilter(container, &notifier, base::string16());
1071 void CookiesTreeModel::PopulateCookieInfo(LocalDataContainer* container) {
1072 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1073 PopulateCookieInfoWithFilter(container, &notifier, base::string16());
1076 void CookiesTreeModel::PopulateDatabaseInfo(LocalDataContainer* container) {
1077 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1078 PopulateDatabaseInfoWithFilter(container, &notifier, base::string16());
1081 void CookiesTreeModel::PopulateLocalStorageInfo(LocalDataContainer* container) {
1082 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1083 PopulateLocalStorageInfoWithFilter(container, &notifier, base::string16());
1086 void CookiesTreeModel::PopulateSessionStorageInfo(
1087 LocalDataContainer* container) {
1088 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1089 PopulateSessionStorageInfoWithFilter(container, &notifier, base::string16());
1092 void CookiesTreeModel::PopulateIndexedDBInfo(LocalDataContainer* container) {
1093 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1094 PopulateIndexedDBInfoWithFilter(container, &notifier, base::string16());
1097 void CookiesTreeModel::PopulateFileSystemInfo(LocalDataContainer* container) {
1098 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1099 PopulateFileSystemInfoWithFilter(container, &notifier, base::string16());
1102 void CookiesTreeModel::PopulateQuotaInfo(LocalDataContainer* container) {
1103 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1104 PopulateQuotaInfoWithFilter(container, &notifier, base::string16());
1107 void CookiesTreeModel::PopulateChannelIDInfo(
1108 LocalDataContainer* container) {
1109 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1110 PopulateChannelIDInfoWithFilter(container, &notifier, base::string16());
1113 void CookiesTreeModel::PopulateServiceWorkerUsageInfo(
1114 LocalDataContainer* container) {
1115 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1116 PopulateServiceWorkerUsageInfoWithFilter(
1117 container, &notifier, base::string16());
1120 void CookiesTreeModel::PopulateFlashLSOInfo(
1121 LocalDataContainer* container) {
1122 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1123 PopulateFlashLSOInfoWithFilter(container, &notifier, base::string16());
1126 void CookiesTreeModel::PopulateAppCacheInfoWithFilter(
1127 LocalDataContainer* container,
1128 ScopedBatchUpdateNotifier* notifier,
1129 const base::string16& filter) {
1130 using content::AppCacheInfo;
1131 typedef std::map<GURL, std::list<AppCacheInfo> > InfoByOrigin;
1132 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1134 if (container->appcache_info_.empty())
1135 return;
1137 notifier->StartBatchUpdate();
1138 for (InfoByOrigin::iterator origin = container->appcache_info_.begin();
1139 origin != container->appcache_info_.end(); ++origin) {
1140 base::string16 host_node_name = base::UTF8ToUTF16(origin->first.host());
1141 if (filter.empty() ||
1142 (host_node_name.find(filter) != base::string16::npos)) {
1143 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin->first);
1144 CookieTreeAppCachesNode* appcaches_node =
1145 host_node->GetOrCreateAppCachesNode();
1147 for (std::list<AppCacheInfo>::iterator info = origin->second.begin();
1148 info != origin->second.end(); ++info) {
1149 appcaches_node->AddAppCacheNode(
1150 new CookieTreeAppCacheNode(origin->first, info));
1156 void CookiesTreeModel::PopulateCookieInfoWithFilter(
1157 LocalDataContainer* container,
1158 ScopedBatchUpdateNotifier* notifier,
1159 const base::string16& filter) {
1160 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1162 notifier->StartBatchUpdate();
1163 for (CookieList::iterator it = container->cookie_list_.begin();
1164 it != container->cookie_list_.end(); ++it) {
1165 std::string source_string = it->Source();
1166 if (source_string.empty() || !group_by_cookie_source_) {
1167 std::string domain = it->Domain();
1168 if (domain.length() > 1 && domain[0] == '.')
1169 domain = domain.substr(1);
1171 // We treat secure cookies just the same as normal ones.
1172 source_string = std::string(url::kHttpScheme) +
1173 url::kStandardSchemeSeparator + domain + "/";
1176 GURL source(source_string);
1177 if (filter.empty() || (CookieTreeHostNode::TitleForUrl(source)
1178 .find(filter) != base::string16::npos)) {
1179 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(source);
1180 CookieTreeCookiesNode* cookies_node =
1181 host_node->GetOrCreateCookiesNode();
1182 CookieTreeCookieNode* new_cookie = new CookieTreeCookieNode(it);
1183 cookies_node->AddCookieNode(new_cookie);
1188 void CookiesTreeModel::PopulateDatabaseInfoWithFilter(
1189 LocalDataContainer* container,
1190 ScopedBatchUpdateNotifier* notifier,
1191 const base::string16& filter) {
1192 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1194 if (container->database_info_list_.empty())
1195 return;
1197 notifier->StartBatchUpdate();
1198 for (DatabaseInfoList::iterator database_info =
1199 container->database_info_list_.begin();
1200 database_info != container->database_info_list_.end();
1201 ++database_info) {
1202 GURL origin(database_info->identifier.ToOrigin());
1204 if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin)
1205 .find(filter) != base::string16::npos)) {
1206 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1207 CookieTreeDatabasesNode* databases_node =
1208 host_node->GetOrCreateDatabasesNode();
1209 databases_node->AddDatabaseNode(
1210 new CookieTreeDatabaseNode(database_info));
1215 void CookiesTreeModel::PopulateLocalStorageInfoWithFilter(
1216 LocalDataContainer* container,
1217 ScopedBatchUpdateNotifier* notifier,
1218 const base::string16& filter) {
1219 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1221 if (container->local_storage_info_list_.empty())
1222 return;
1224 notifier->StartBatchUpdate();
1225 for (LocalStorageInfoList::iterator local_storage_info =
1226 container->local_storage_info_list_.begin();
1227 local_storage_info != container->local_storage_info_list_.end();
1228 ++local_storage_info) {
1229 const GURL& origin(local_storage_info->origin_url);
1231 if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin)
1232 .find(filter) != std::string::npos)) {
1233 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1234 CookieTreeLocalStoragesNode* local_storages_node =
1235 host_node->GetOrCreateLocalStoragesNode();
1236 local_storages_node->AddLocalStorageNode(
1237 new CookieTreeLocalStorageNode(local_storage_info));
1242 void CookiesTreeModel::PopulateSessionStorageInfoWithFilter(
1243 LocalDataContainer* container,
1244 ScopedBatchUpdateNotifier* notifier,
1245 const base::string16& filter) {
1246 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1248 if (container->session_storage_info_list_.empty())
1249 return;
1251 notifier->StartBatchUpdate();
1252 for (LocalStorageInfoList::iterator session_storage_info =
1253 container->session_storage_info_list_.begin();
1254 session_storage_info != container->session_storage_info_list_.end();
1255 ++session_storage_info) {
1256 const GURL& origin = session_storage_info->origin_url;
1258 if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin)
1259 .find(filter) != base::string16::npos)) {
1260 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1261 CookieTreeSessionStoragesNode* session_storages_node =
1262 host_node->GetOrCreateSessionStoragesNode();
1263 session_storages_node->AddSessionStorageNode(
1264 new CookieTreeSessionStorageNode(session_storage_info));
1269 void CookiesTreeModel::PopulateIndexedDBInfoWithFilter(
1270 LocalDataContainer* container,
1271 ScopedBatchUpdateNotifier* notifier,
1272 const base::string16& filter) {
1273 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1275 if (container->indexed_db_info_list_.empty())
1276 return;
1278 notifier->StartBatchUpdate();
1279 for (IndexedDBInfoList::iterator indexed_db_info =
1280 container->indexed_db_info_list_.begin();
1281 indexed_db_info != container->indexed_db_info_list_.end();
1282 ++indexed_db_info) {
1283 const GURL& origin = indexed_db_info->origin_;
1285 if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin)
1286 .find(filter) != base::string16::npos)) {
1287 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1288 CookieTreeIndexedDBsNode* indexed_dbs_node =
1289 host_node->GetOrCreateIndexedDBsNode();
1290 indexed_dbs_node->AddIndexedDBNode(
1291 new CookieTreeIndexedDBNode(indexed_db_info));
1296 void CookiesTreeModel::PopulateChannelIDInfoWithFilter(
1297 LocalDataContainer* container,
1298 ScopedBatchUpdateNotifier* notifier,
1299 const base::string16& filter) {
1300 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1302 if (container->channel_id_list_.empty())
1303 return;
1305 notifier->StartBatchUpdate();
1306 for (ChannelIDList::iterator channel_id_info =
1307 container->channel_id_list_.begin();
1308 channel_id_info != container->channel_id_list_.end();
1309 ++channel_id_info) {
1310 GURL origin(channel_id_info->server_identifier());
1311 if (!origin.is_valid()) {
1312 // Channel ID. Make a valid URL to satisfy the
1313 // CookieTreeRootNode::GetOrCreateHostNode interface.
1314 origin = GURL(std::string(url::kHttpsScheme) +
1315 url::kStandardSchemeSeparator +
1316 channel_id_info->server_identifier() + "/");
1318 base::string16 title = CookieTreeHostNode::TitleForUrl(origin);
1319 if (filter.empty() || title.find(filter) != base::string16::npos) {
1320 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1321 CookieTreeChannelIDsNode* channel_ids_node =
1322 host_node->GetOrCreateChannelIDsNode();
1323 channel_ids_node->AddChannelIDNode(
1324 new CookieTreeChannelIDNode(channel_id_info));
1329 void CookiesTreeModel::PopulateServiceWorkerUsageInfoWithFilter(
1330 LocalDataContainer* container,
1331 ScopedBatchUpdateNotifier* notifier,
1332 const base::string16& filter) {
1333 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1335 if (container->service_worker_info_list_.empty())
1336 return;
1338 notifier->StartBatchUpdate();
1339 for (ServiceWorkerUsageInfoList::iterator service_worker_info =
1340 container->service_worker_info_list_.begin();
1341 service_worker_info != container->service_worker_info_list_.end();
1342 ++service_worker_info) {
1343 const GURL& origin = service_worker_info->origin;
1345 if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin)
1346 .find(filter) != base::string16::npos)) {
1347 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1348 CookieTreeServiceWorkersNode* service_workers_node =
1349 host_node->GetOrCreateServiceWorkersNode();
1350 service_workers_node->AddServiceWorkerNode(
1351 new CookieTreeServiceWorkerNode(service_worker_info));
1356 void CookiesTreeModel::PopulateFileSystemInfoWithFilter(
1357 LocalDataContainer* container,
1358 ScopedBatchUpdateNotifier* notifier,
1359 const base::string16& filter) {
1360 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1362 if (container->file_system_info_list_.empty())
1363 return;
1365 notifier->StartBatchUpdate();
1366 for (FileSystemInfoList::iterator file_system_info =
1367 container->file_system_info_list_.begin();
1368 file_system_info != container->file_system_info_list_.end();
1369 ++file_system_info) {
1370 GURL origin(file_system_info->origin);
1372 if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin)
1373 .find(filter) != base::string16::npos)) {
1374 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1375 CookieTreeFileSystemsNode* file_systems_node =
1376 host_node->GetOrCreateFileSystemsNode();
1377 file_systems_node->AddFileSystemNode(
1378 new CookieTreeFileSystemNode(file_system_info));
1383 void CookiesTreeModel::PopulateQuotaInfoWithFilter(
1384 LocalDataContainer* container,
1385 ScopedBatchUpdateNotifier* notifier,
1386 const base::string16& filter) {
1387 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1389 if (container->quota_info_list_.empty())
1390 return;
1392 notifier->StartBatchUpdate();
1393 for (QuotaInfoList::iterator quota_info = container->quota_info_list_.begin();
1394 quota_info != container->quota_info_list_.end();
1395 ++quota_info) {
1396 if (filter.empty() || (base::UTF8ToUTF16(quota_info->host).find(filter) !=
1397 base::string16::npos)) {
1398 CookieTreeHostNode* host_node =
1399 root->GetOrCreateHostNode(GURL("http://" + quota_info->host));
1400 host_node->UpdateOrCreateQuotaNode(quota_info);
1405 void CookiesTreeModel::PopulateFlashLSOInfoWithFilter(
1406 LocalDataContainer* container,
1407 ScopedBatchUpdateNotifier* notifier,
1408 const base::string16& filter) {
1409 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1411 if (container->flash_lso_domain_list_.empty())
1412 return;
1414 std::string filter_utf8 = base::UTF16ToUTF8(filter);
1415 notifier->StartBatchUpdate();
1416 for (std::vector<std::string>::iterator it =
1417 container->flash_lso_domain_list_.begin();
1418 it != container->flash_lso_domain_list_.end(); ++it) {
1419 if (filter_utf8.empty() || it->find(filter_utf8) != std::string::npos) {
1420 // Create a fake origin for GetOrCreateHostNode().
1421 GURL origin("http://" + *it);
1422 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1423 host_node->GetOrCreateFlashLSONode(*it);
1428 void CookiesTreeModel::NotifyObserverBeginBatch() {
1429 // Only notify the model once if we're batching in a nested manner.
1430 if (batch_update_++ == 0) {
1431 FOR_EACH_OBSERVER(Observer,
1432 cookies_observer_list_,
1433 TreeModelBeginBatch(this));
1437 void CookiesTreeModel::NotifyObserverEndBatch() {
1438 // Only notify the observers if this is the outermost call to EndBatch() if
1439 // called in a nested manner.
1440 if (--batch_update_ == 0) {
1441 FOR_EACH_OBSERVER(Observer,
1442 cookies_observer_list_,
1443 TreeModelEndBatch(this));