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 <algorithm>
8 #include <functional>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/memory/linked_ptr.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
16 #include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h"
17 #include "chrome/browser/browsing_data/browsing_data_server_bound_cert_helper.h"
18 #include "chrome/browser/content_settings/cookie_settings.h"
19 #include "chrome/browser/extensions/extension_service.h"
20 #include "chrome/browser/extensions/extension_special_storage_policy.h"
21 #include "content/public/common/url_constants.h"
22 #include "extensions/common/extension_set.h"
23 #include "grit/generated_resources.h"
24 #include "grit/theme_resources.h"
25 #include "grit/ui_resources.h"
26 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
27 #include "net/cookies/canonical_cookie.h"
28 #include "net/url_request/url_request_context.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/resource/resource_bundle.h"
31 #include "ui/gfx/image/image_skia.h"
32
33 namespace {
34
35 struct NodeTitleComparator {
operator ()__anon8f2088c20111::NodeTitleComparator36 bool operator()(const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
37 return lhs->GetTitle() < rhs->GetTitle();
38 }
39 };
40
41 // Comparison functor, for use in CookieTreeRootNode.
42 struct HostNodeComparator {
operator ()__anon8f2088c20111::HostNodeComparator43 bool operator()(const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
44 // This comparator is only meant to compare CookieTreeHostNode types. Make
45 // sure we check this, as the static cast below is dangerous if we get the
46 // wrong object type.
47 CHECK_EQ(CookieTreeNode::DetailedInfo::TYPE_HOST,
48 lhs->GetDetailedInfo().node_type);
49 CHECK_EQ(CookieTreeNode::DetailedInfo::TYPE_HOST,
50 rhs->GetDetailedInfo().node_type);
51
52 const CookieTreeHostNode* ltn =
53 static_cast<const CookieTreeHostNode*>(lhs);
54 const CookieTreeHostNode* rtn =
55 static_cast<const CookieTreeHostNode*>(rhs);
56
57 // We want to order by registry controlled domain, so we would get
58 // google.com, ad.google.com, www.google.com,
59 // microsoft.com, ad.microsoft.com. CanonicalizeHost transforms the origins
60 // into a form like google.com.www so that string comparisons work.
61 return (ltn->canonicalized_host() <
62 rtn->canonicalized_host());
63 }
64 };
65
CanonicalizeHost(const GURL & url)66 std::string CanonicalizeHost(const GURL& url) {
67 // The canonicalized representation makes the registry controlled domain
68 // come first, and then adds subdomains in reverse order, e.g.
69 // 1.mail.google.com would become google.com.mail.1, and then a standard
70 // string comparison works to order hosts by registry controlled domain
71 // first. Leading dots are ignored, ".google.com" is the same as
72 // "google.com".
73
74 if (url.SchemeIsFile()) {
75 return std::string(url::kFileScheme) +
76 url::kStandardSchemeSeparator;
77 }
78
79 std::string host = url.host();
80 std::string retval =
81 net::registry_controlled_domains::GetDomainAndRegistry(
82 host,
83 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
84 if (!retval.length()) // Is an IP address or other special origin.
85 return host;
86
87 std::string::size_type position = host.rfind(retval);
88
89 // The host may be the registry controlled domain, in which case fail fast.
90 if (position == 0 || position == std::string::npos)
91 return host;
92
93 // If host is www.google.com, retval will contain google.com at this point.
94 // Start operating to the left of the registry controlled domain, e.g. in
95 // the www.google.com example, start at index 3.
96 --position;
97
98 // If position == 0, that means it's a dot; this will be ignored to treat
99 // ".google.com" the same as "google.com".
100 while (position > 0) {
101 retval += std::string(".");
102 // Copy up to the next dot. host[position] is a dot so start after it.
103 std::string::size_type next_dot = host.rfind(".", position - 1);
104 if (next_dot == std::string::npos) {
105 retval += host.substr(0, position);
106 break;
107 }
108 retval += host.substr(next_dot + 1, position - (next_dot + 1));
109 position = next_dot;
110 }
111 return retval;
112 }
113
TypeIsProtected(CookieTreeNode::DetailedInfo::NodeType type)114 bool TypeIsProtected(CookieTreeNode::DetailedInfo::NodeType type) {
115 switch (type) {
116 case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
117 return false;
118 case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
119 return true;
120 case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
121 return true;
122 case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
123 return true;
124 case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
125 return true;
126 case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
127 return true;
128 case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM:
129 return true;
130 case CookieTreeNode::DetailedInfo::TYPE_QUOTA:
131 return false;
132 case CookieTreeNode::DetailedInfo::TYPE_SERVER_BOUND_CERT:
133 return false;
134 case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO:
135 return false;
136 default:
137 break;
138 }
139 return false;
140 }
141
142 // This function returns the local data container associated with a leaf tree
143 // node. The app node is assumed to be 3 levels above the leaf because of the
144 // following structure:
145 // root -> origin -> storage type -> leaf node
GetLocalDataContainerForNode(CookieTreeNode * node)146 LocalDataContainer* GetLocalDataContainerForNode(CookieTreeNode* node) {
147 CookieTreeHostNode* host = static_cast<CookieTreeHostNode*>(
148 node->parent()->parent());
149 CHECK_EQ(host->GetDetailedInfo().node_type,
150 CookieTreeNode::DetailedInfo::TYPE_HOST);
151 return node->GetModel()->data_container();
152 }
153
154 } // namespace
155
DetailedInfo()156 CookieTreeNode::DetailedInfo::DetailedInfo()
157 : node_type(TYPE_NONE),
158 cookie(NULL),
159 database_info(NULL),
160 local_storage_info(NULL),
161 session_storage_info(NULL),
162 appcache_info(NULL),
163 indexed_db_info(NULL),
164 file_system_info(NULL),
165 quota_info(NULL),
166 server_bound_cert(NULL) {}
167
~DetailedInfo()168 CookieTreeNode::DetailedInfo::~DetailedInfo() {}
169
Init(NodeType type)170 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::Init(
171 NodeType type) {
172 DCHECK_EQ(TYPE_NONE, node_type);
173 node_type = type;
174 return *this;
175 }
176
InitHost()177 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitHost() {
178 Init(TYPE_HOST);
179 return *this;
180 }
181
InitCookie(const net::CanonicalCookie * cookie)182 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitCookie(
183 const net::CanonicalCookie* cookie) {
184 Init(TYPE_COOKIE);
185 this->cookie = cookie;
186 return *this;
187 }
188
InitDatabase(const BrowsingDataDatabaseHelper::DatabaseInfo * database_info)189 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitDatabase(
190 const BrowsingDataDatabaseHelper::DatabaseInfo* database_info) {
191 Init(TYPE_DATABASE);
192 this->database_info = database_info;
193 origin = database_info->identifier.ToOrigin();
194 return *this;
195 }
196
InitLocalStorage(const BrowsingDataLocalStorageHelper::LocalStorageInfo * local_storage_info)197 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitLocalStorage(
198 const BrowsingDataLocalStorageHelper::LocalStorageInfo*
199 local_storage_info) {
200 Init(TYPE_LOCAL_STORAGE);
201 this->local_storage_info = local_storage_info;
202 origin = local_storage_info->origin_url;
203 return *this;
204 }
205
InitSessionStorage(const BrowsingDataLocalStorageHelper::LocalStorageInfo * session_storage_info)206 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitSessionStorage(
207 const BrowsingDataLocalStorageHelper::LocalStorageInfo*
208 session_storage_info) {
209 Init(TYPE_SESSION_STORAGE);
210 this->session_storage_info = session_storage_info;
211 origin = session_storage_info->origin_url;
212 return *this;
213 }
214
InitAppCache(const GURL & origin,const appcache::AppCacheInfo * appcache_info)215 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitAppCache(
216 const GURL& origin,
217 const appcache::AppCacheInfo* appcache_info) {
218 Init(TYPE_APPCACHE);
219 this->appcache_info = appcache_info;
220 this->origin = origin;
221 return *this;
222 }
223
InitIndexedDB(const content::IndexedDBInfo * indexed_db_info)224 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitIndexedDB(
225 const content::IndexedDBInfo* indexed_db_info) {
226 Init(TYPE_INDEXED_DB);
227 this->indexed_db_info = indexed_db_info;
228 this->origin = indexed_db_info->origin_;
229 return *this;
230 }
231
InitFileSystem(const BrowsingDataFileSystemHelper::FileSystemInfo * file_system_info)232 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitFileSystem(
233 const BrowsingDataFileSystemHelper::FileSystemInfo* file_system_info) {
234 Init(TYPE_FILE_SYSTEM);
235 this->file_system_info = file_system_info;
236 this->origin = file_system_info->origin;
237 return *this;
238 }
239
InitQuota(const BrowsingDataQuotaHelper::QuotaInfo * quota_info)240 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitQuota(
241 const BrowsingDataQuotaHelper::QuotaInfo* quota_info) {
242 Init(TYPE_QUOTA);
243 this->quota_info = quota_info;
244 return *this;
245 }
246
InitServerBoundCert(const net::ServerBoundCertStore::ServerBoundCert * server_bound_cert)247 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitServerBoundCert(
248 const net::ServerBoundCertStore::ServerBoundCert* server_bound_cert) {
249 Init(TYPE_SERVER_BOUND_CERT);
250 this->server_bound_cert = server_bound_cert;
251 return *this;
252 }
253
InitFlashLSO(const std::string & flash_lso_domain)254 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitFlashLSO(
255 const std::string& flash_lso_domain) {
256 Init(TYPE_FLASH_LSO);
257 this->flash_lso_domain = flash_lso_domain;
258 return *this;
259 }
260
261 ///////////////////////////////////////////////////////////////////////////////
262 // CookieTreeNode, public:
263
DeleteStoredObjects()264 void CookieTreeNode::DeleteStoredObjects() {
265 std::for_each(children().begin(),
266 children().end(),
267 std::mem_fun(&CookieTreeNode::DeleteStoredObjects));
268 }
269
GetModel() const270 CookiesTreeModel* CookieTreeNode::GetModel() const {
271 if (parent())
272 return parent()->GetModel();
273 else
274 return NULL;
275 }
276
277 ///////////////////////////////////////////////////////////////////////////////
278 // CookieTreeCookieNode, public:
279
CookieTreeCookieNode(std::list<net::CanonicalCookie>::iterator cookie)280 CookieTreeCookieNode::CookieTreeCookieNode(
281 std::list<net::CanonicalCookie>::iterator cookie)
282 : CookieTreeNode(base::UTF8ToUTF16(cookie->Name())),
283 cookie_(cookie) {
284 }
285
~CookieTreeCookieNode()286 CookieTreeCookieNode::~CookieTreeCookieNode() {}
287
DeleteStoredObjects()288 void CookieTreeCookieNode::DeleteStoredObjects() {
289 LocalDataContainer* container = GetLocalDataContainerForNode(this);
290 CHECK(container);
291 container->cookie_helper_->DeleteCookie(*cookie_);
292 container->cookie_list_.erase(cookie_);
293 }
294
GetDetailedInfo() const295 CookieTreeNode::DetailedInfo CookieTreeCookieNode::GetDetailedInfo() const {
296 return DetailedInfo().InitCookie(&*cookie_);
297 }
298
299 ///////////////////////////////////////////////////////////////////////////////
300 // CookieTreeAppCacheNode, public:
301
CookieTreeAppCacheNode(const GURL & origin_url,std::list<appcache::AppCacheInfo>::iterator appcache_info)302 CookieTreeAppCacheNode::CookieTreeAppCacheNode(
303 const GURL& origin_url,
304 std::list<appcache::AppCacheInfo>::iterator appcache_info)
305 : CookieTreeNode(base::UTF8ToUTF16(appcache_info->manifest_url.spec())),
306 origin_url_(origin_url),
307 appcache_info_(appcache_info) {
308 }
309
~CookieTreeAppCacheNode()310 CookieTreeAppCacheNode::~CookieTreeAppCacheNode() {
311 }
312
DeleteStoredObjects()313 void CookieTreeAppCacheNode::DeleteStoredObjects() {
314 LocalDataContainer* container = GetLocalDataContainerForNode(this);
315
316 if (container) {
317 DCHECK(container->appcache_helper_.get());
318 container->appcache_helper_
319 ->DeleteAppCacheGroup(appcache_info_->manifest_url);
320 container->appcache_info_[origin_url_].erase(appcache_info_);
321 }
322 }
323
GetDetailedInfo() const324 CookieTreeNode::DetailedInfo CookieTreeAppCacheNode::GetDetailedInfo() const {
325 return DetailedInfo().InitAppCache(origin_url_, &*appcache_info_);
326 }
327
328 ///////////////////////////////////////////////////////////////////////////////
329 // CookieTreeDatabaseNode, public:
330
CookieTreeDatabaseNode(std::list<BrowsingDataDatabaseHelper::DatabaseInfo>::iterator database_info)331 CookieTreeDatabaseNode::CookieTreeDatabaseNode(
332 std::list<BrowsingDataDatabaseHelper::DatabaseInfo>::iterator database_info)
333 : CookieTreeNode(database_info->database_name.empty() ?
334 l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME) :
335 base::UTF8ToUTF16(database_info->database_name)),
336 database_info_(database_info) {
337 }
338
~CookieTreeDatabaseNode()339 CookieTreeDatabaseNode::~CookieTreeDatabaseNode() {}
340
DeleteStoredObjects()341 void CookieTreeDatabaseNode::DeleteStoredObjects() {
342 LocalDataContainer* container = GetLocalDataContainerForNode(this);
343
344 if (container) {
345 container->database_helper_->DeleteDatabase(
346 database_info_->identifier.ToString(), database_info_->database_name);
347 container->database_info_list_.erase(database_info_);
348 }
349 }
350
GetDetailedInfo() const351 CookieTreeNode::DetailedInfo CookieTreeDatabaseNode::GetDetailedInfo() const {
352 return DetailedInfo().InitDatabase(&*database_info_);
353 }
354
355 ///////////////////////////////////////////////////////////////////////////////
356 // CookieTreeLocalStorageNode, public:
357
CookieTreeLocalStorageNode(std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::iterator local_storage_info)358 CookieTreeLocalStorageNode::CookieTreeLocalStorageNode(
359 std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::iterator
360 local_storage_info)
361 : CookieTreeNode(base::UTF8ToUTF16(local_storage_info->origin_url.spec())),
362 local_storage_info_(local_storage_info) {
363 }
364
~CookieTreeLocalStorageNode()365 CookieTreeLocalStorageNode::~CookieTreeLocalStorageNode() {}
366
DeleteStoredObjects()367 void CookieTreeLocalStorageNode::DeleteStoredObjects() {
368 LocalDataContainer* container = GetLocalDataContainerForNode(this);
369
370 if (container) {
371 container->local_storage_helper_->DeleteOrigin(
372 local_storage_info_->origin_url);
373 container->local_storage_info_list_.erase(local_storage_info_);
374 }
375 }
376
377 CookieTreeNode::DetailedInfo
GetDetailedInfo() const378 CookieTreeLocalStorageNode::GetDetailedInfo() const {
379 return DetailedInfo().InitLocalStorage(
380 &*local_storage_info_);
381 }
382
383 ///////////////////////////////////////////////////////////////////////////////
384 // CookieTreeSessionStorageNode, public:
385
CookieTreeSessionStorageNode(std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::iterator session_storage_info)386 CookieTreeSessionStorageNode::CookieTreeSessionStorageNode(
387 std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::iterator
388 session_storage_info)
389 : CookieTreeNode(
390 base::UTF8ToUTF16(session_storage_info->origin_url.spec())),
391 session_storage_info_(session_storage_info) {
392 }
393
~CookieTreeSessionStorageNode()394 CookieTreeSessionStorageNode::~CookieTreeSessionStorageNode() {}
395
DeleteStoredObjects()396 void CookieTreeSessionStorageNode::DeleteStoredObjects() {
397 LocalDataContainer* container = GetLocalDataContainerForNode(this);
398
399 if (container) {
400 // TODO(rsesek): There's no easy way to get the namespace_id for a session
401 // storage, nor is there an easy way to clear session storage just by
402 // origin. This is probably okay since session storage is not persistent.
403 // http://crbug.com/168996
404 container->session_storage_info_list_.erase(session_storage_info_);
405 }
406 }
407
408 CookieTreeNode::DetailedInfo
GetDetailedInfo() const409 CookieTreeSessionStorageNode::GetDetailedInfo() const {
410 return DetailedInfo().InitSessionStorage(&*session_storage_info_);
411 }
412
413 ///////////////////////////////////////////////////////////////////////////////
414 // CookieTreeIndexedDBNode, public:
415
CookieTreeIndexedDBNode(std::list<content::IndexedDBInfo>::iterator indexed_db_info)416 CookieTreeIndexedDBNode::CookieTreeIndexedDBNode(
417 std::list<content::IndexedDBInfo>::iterator
418 indexed_db_info)
419 : CookieTreeNode(base::UTF8ToUTF16(
420 indexed_db_info->origin_.spec())),
421 indexed_db_info_(indexed_db_info) {
422 }
423
~CookieTreeIndexedDBNode()424 CookieTreeIndexedDBNode::~CookieTreeIndexedDBNode() {}
425
DeleteStoredObjects()426 void CookieTreeIndexedDBNode::DeleteStoredObjects() {
427 LocalDataContainer* container = GetLocalDataContainerForNode(this);
428
429 if (container) {
430 container->indexed_db_helper_->DeleteIndexedDB(
431 indexed_db_info_->origin_);
432 container->indexed_db_info_list_.erase(indexed_db_info_);
433 }
434 }
435
GetDetailedInfo() const436 CookieTreeNode::DetailedInfo CookieTreeIndexedDBNode::GetDetailedInfo() const {
437 return DetailedInfo().InitIndexedDB(&*indexed_db_info_);
438 }
439
440 ///////////////////////////////////////////////////////////////////////////////
441 // CookieTreeFileSystemNode, public:
442
CookieTreeFileSystemNode(std::list<BrowsingDataFileSystemHelper::FileSystemInfo>::iterator file_system_info)443 CookieTreeFileSystemNode::CookieTreeFileSystemNode(
444 std::list<BrowsingDataFileSystemHelper::FileSystemInfo>::iterator
445 file_system_info)
446 : CookieTreeNode(base::UTF8ToUTF16(
447 file_system_info->origin.spec())),
448 file_system_info_(file_system_info) {
449 }
450
~CookieTreeFileSystemNode()451 CookieTreeFileSystemNode::~CookieTreeFileSystemNode() {}
452
DeleteStoredObjects()453 void CookieTreeFileSystemNode::DeleteStoredObjects() {
454 LocalDataContainer* container = GetLocalDataContainerForNode(this);
455
456 if (container) {
457 container->file_system_helper_->DeleteFileSystemOrigin(
458 file_system_info_->origin);
459 container->file_system_info_list_.erase(file_system_info_);
460 }
461 }
462
GetDetailedInfo() const463 CookieTreeNode::DetailedInfo CookieTreeFileSystemNode::GetDetailedInfo() const {
464 return DetailedInfo().InitFileSystem(&*file_system_info_);
465 }
466
467 ///////////////////////////////////////////////////////////////////////////////
468 // CookieTreeQuotaNode, public:
469
CookieTreeQuotaNode(std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)470 CookieTreeQuotaNode::CookieTreeQuotaNode(
471 std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)
472 : CookieTreeNode(base::UTF8ToUTF16(quota_info->host)),
473 quota_info_(quota_info) {
474 }
475
~CookieTreeQuotaNode()476 CookieTreeQuotaNode::~CookieTreeQuotaNode() {}
477
DeleteStoredObjects()478 void CookieTreeQuotaNode::DeleteStoredObjects() {
479 // Calling this function may cause unexpected over-quota state of origin.
480 // However, it'll caused no problem, just prevent usage growth of the origin.
481 LocalDataContainer* container = GetModel()->data_container();
482
483 if (container) {
484 container->quota_helper_->RevokeHostQuota(quota_info_->host);
485 container->quota_info_list_.erase(quota_info_);
486 }
487 }
488
GetDetailedInfo() const489 CookieTreeNode::DetailedInfo CookieTreeQuotaNode::GetDetailedInfo() const {
490 return DetailedInfo().InitQuota(&*quota_info_);
491 }
492
493 ///////////////////////////////////////////////////////////////////////////////
494 // CookieTreeServerBoundCertNode, public:
495
CookieTreeServerBoundCertNode(net::ServerBoundCertStore::ServerBoundCertList::iterator cert)496 CookieTreeServerBoundCertNode::CookieTreeServerBoundCertNode(
497 net::ServerBoundCertStore::ServerBoundCertList::iterator cert)
498 : CookieTreeNode(base::ASCIIToUTF16(cert->server_identifier())),
499 server_bound_cert_(cert) {
500 }
501
~CookieTreeServerBoundCertNode()502 CookieTreeServerBoundCertNode::~CookieTreeServerBoundCertNode() {}
503
DeleteStoredObjects()504 void CookieTreeServerBoundCertNode::DeleteStoredObjects() {
505 LocalDataContainer* container = GetLocalDataContainerForNode(this);
506
507 if (container) {
508 container->server_bound_cert_helper_->DeleteServerBoundCert(
509 server_bound_cert_->server_identifier());
510 container->server_bound_cert_list_.erase(server_bound_cert_);
511 }
512 }
513
514 CookieTreeNode::DetailedInfo
GetDetailedInfo() const515 CookieTreeServerBoundCertNode::GetDetailedInfo() const {
516 return DetailedInfo().InitServerBoundCert(&*server_bound_cert_);
517 }
518
519 ///////////////////////////////////////////////////////////////////////////////
520 // CookieTreeRootNode, public:
521
CookieTreeRootNode(CookiesTreeModel * model)522 CookieTreeRootNode::CookieTreeRootNode(CookiesTreeModel* model)
523 : model_(model) {
524 }
525
~CookieTreeRootNode()526 CookieTreeRootNode::~CookieTreeRootNode() {}
527
GetOrCreateHostNode(const GURL & url)528 CookieTreeHostNode* CookieTreeRootNode::GetOrCreateHostNode(
529 const GURL& url) {
530 scoped_ptr<CookieTreeHostNode> host_node(
531 new CookieTreeHostNode(url));
532
533 // First see if there is an existing match.
534 std::vector<CookieTreeNode*>::iterator host_node_iterator =
535 std::lower_bound(children().begin(), children().end(), host_node.get(),
536 HostNodeComparator());
537 if (host_node_iterator != children().end() &&
538 CookieTreeHostNode::TitleForUrl(url) ==
539 (*host_node_iterator)->GetTitle())
540 return static_cast<CookieTreeHostNode*>(*host_node_iterator);
541 // Node doesn't exist, insert the new one into the (ordered) children.
542 DCHECK(model_);
543 model_->Add(this, host_node.get(),
544 (host_node_iterator - children().begin()));
545 return host_node.release();
546 }
547
GetModel() const548 CookiesTreeModel* CookieTreeRootNode::GetModel() const {
549 return model_;
550 }
551
GetDetailedInfo() const552 CookieTreeNode::DetailedInfo CookieTreeRootNode::GetDetailedInfo() const {
553 return DetailedInfo().Init(DetailedInfo::TYPE_ROOT);
554 }
555
556 ///////////////////////////////////////////////////////////////////////////////
557 // CookieTreeHostNode, public:
558
559 // static
TitleForUrl(const GURL & url)560 base::string16 CookieTreeHostNode::TitleForUrl(const GURL& url) {
561 const std::string file_origin_node_name(
562 std::string(url::kFileScheme) + url::kStandardSchemeSeparator);
563 return base::UTF8ToUTF16(url.SchemeIsFile() ? file_origin_node_name
564 : url.host());
565 }
566
CookieTreeHostNode(const GURL & url)567 CookieTreeHostNode::CookieTreeHostNode(const GURL& url)
568 : CookieTreeNode(TitleForUrl(url)),
569 cookies_child_(NULL),
570 databases_child_(NULL),
571 local_storages_child_(NULL),
572 session_storages_child_(NULL),
573 appcaches_child_(NULL),
574 indexed_dbs_child_(NULL),
575 file_systems_child_(NULL),
576 quota_child_(NULL),
577 server_bound_certs_child_(NULL),
578 flash_lso_child_(NULL),
579 url_(url),
580 canonicalized_host_(CanonicalizeHost(url)) {}
581
~CookieTreeHostNode()582 CookieTreeHostNode::~CookieTreeHostNode() {}
583
GetHost() const584 const std::string CookieTreeHostNode::GetHost() const {
585 const std::string file_origin_node_name(
586 std::string(url::kFileScheme) + url::kStandardSchemeSeparator);
587 return url_.SchemeIsFile() ? file_origin_node_name : url_.host();
588 }
589
GetDetailedInfo() const590 CookieTreeNode::DetailedInfo CookieTreeHostNode::GetDetailedInfo() const {
591 return DetailedInfo().InitHost();
592 }
593
GetOrCreateCookiesNode()594 CookieTreeCookiesNode* CookieTreeHostNode::GetOrCreateCookiesNode() {
595 if (cookies_child_)
596 return cookies_child_;
597 cookies_child_ = new CookieTreeCookiesNode;
598 AddChildSortedByTitle(cookies_child_);
599 return cookies_child_;
600 }
601
GetOrCreateDatabasesNode()602 CookieTreeDatabasesNode* CookieTreeHostNode::GetOrCreateDatabasesNode() {
603 if (databases_child_)
604 return databases_child_;
605 databases_child_ = new CookieTreeDatabasesNode;
606 AddChildSortedByTitle(databases_child_);
607 return databases_child_;
608 }
609
610 CookieTreeLocalStoragesNode*
GetOrCreateLocalStoragesNode()611 CookieTreeHostNode::GetOrCreateLocalStoragesNode() {
612 if (local_storages_child_)
613 return local_storages_child_;
614 local_storages_child_ = new CookieTreeLocalStoragesNode;
615 AddChildSortedByTitle(local_storages_child_);
616 return local_storages_child_;
617 }
618
619 CookieTreeSessionStoragesNode*
GetOrCreateSessionStoragesNode()620 CookieTreeHostNode::GetOrCreateSessionStoragesNode() {
621 if (session_storages_child_)
622 return session_storages_child_;
623 session_storages_child_ = new CookieTreeSessionStoragesNode;
624 AddChildSortedByTitle(session_storages_child_);
625 return session_storages_child_;
626 }
627
GetOrCreateAppCachesNode()628 CookieTreeAppCachesNode* CookieTreeHostNode::GetOrCreateAppCachesNode() {
629 if (appcaches_child_)
630 return appcaches_child_;
631 appcaches_child_ = new CookieTreeAppCachesNode;
632 AddChildSortedByTitle(appcaches_child_);
633 return appcaches_child_;
634 }
635
GetOrCreateIndexedDBsNode()636 CookieTreeIndexedDBsNode* CookieTreeHostNode::GetOrCreateIndexedDBsNode() {
637 if (indexed_dbs_child_)
638 return indexed_dbs_child_;
639 indexed_dbs_child_ = new CookieTreeIndexedDBsNode;
640 AddChildSortedByTitle(indexed_dbs_child_);
641 return indexed_dbs_child_;
642 }
643
GetOrCreateFileSystemsNode()644 CookieTreeFileSystemsNode* CookieTreeHostNode::GetOrCreateFileSystemsNode() {
645 if (file_systems_child_)
646 return file_systems_child_;
647 file_systems_child_ = new CookieTreeFileSystemsNode;
648 AddChildSortedByTitle(file_systems_child_);
649 return file_systems_child_;
650 }
651
UpdateOrCreateQuotaNode(std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)652 CookieTreeQuotaNode* CookieTreeHostNode::UpdateOrCreateQuotaNode(
653 std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info) {
654 if (quota_child_)
655 return quota_child_;
656 quota_child_ = new CookieTreeQuotaNode(quota_info);
657 AddChildSortedByTitle(quota_child_);
658 return quota_child_;
659 }
660
661 CookieTreeServerBoundCertsNode*
GetOrCreateServerBoundCertsNode()662 CookieTreeHostNode::GetOrCreateServerBoundCertsNode() {
663 if (server_bound_certs_child_)
664 return server_bound_certs_child_;
665 server_bound_certs_child_ = new CookieTreeServerBoundCertsNode;
666 AddChildSortedByTitle(server_bound_certs_child_);
667 return server_bound_certs_child_;
668 }
669
GetOrCreateFlashLSONode(const std::string & domain)670 CookieTreeFlashLSONode* CookieTreeHostNode::GetOrCreateFlashLSONode(
671 const std::string& domain) {
672 DCHECK_EQ(GetHost(), domain);
673 if (flash_lso_child_)
674 return flash_lso_child_;
675 flash_lso_child_ = new CookieTreeFlashLSONode(domain);
676 AddChildSortedByTitle(flash_lso_child_);
677 return flash_lso_child_;
678 }
679
CreateContentException(CookieSettings * cookie_settings,ContentSetting setting) const680 void CookieTreeHostNode::CreateContentException(
681 CookieSettings* cookie_settings, ContentSetting setting) const {
682 DCHECK(setting == CONTENT_SETTING_ALLOW ||
683 setting == CONTENT_SETTING_BLOCK ||
684 setting == CONTENT_SETTING_SESSION_ONLY);
685 if (CanCreateContentException()) {
686 cookie_settings->ResetCookieSetting(
687 ContentSettingsPattern::FromURLNoWildcard(url_),
688 ContentSettingsPattern::Wildcard());
689 cookie_settings->SetCookieSetting(
690 ContentSettingsPattern::FromURL(url_),
691 ContentSettingsPattern::Wildcard(), setting);
692 }
693 }
694
CanCreateContentException() const695 bool CookieTreeHostNode::CanCreateContentException() const {
696 return !url_.SchemeIsFile();
697 }
698
699 ///////////////////////////////////////////////////////////////////////////////
700 // CookieTreeCookiesNode, public:
701
CookieTreeCookiesNode()702 CookieTreeCookiesNode::CookieTreeCookiesNode()
703 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIES)) {
704 }
705
~CookieTreeCookiesNode()706 CookieTreeCookiesNode::~CookieTreeCookiesNode() {
707 }
708
GetDetailedInfo() const709 CookieTreeNode::DetailedInfo CookieTreeCookiesNode::GetDetailedInfo() const {
710 return DetailedInfo().Init(DetailedInfo::TYPE_COOKIES);
711 }
712
713 ///////////////////////////////////////////////////////////////////////////////
714 // CookieTreeAppCachesNode, public:
715
CookieTreeAppCachesNode()716 CookieTreeAppCachesNode::CookieTreeAppCachesNode()
717 : CookieTreeNode(l10n_util::GetStringUTF16(
718 IDS_COOKIES_APPLICATION_CACHES)) {
719 }
720
~CookieTreeAppCachesNode()721 CookieTreeAppCachesNode::~CookieTreeAppCachesNode() {}
722
GetDetailedInfo() const723 CookieTreeNode::DetailedInfo CookieTreeAppCachesNode::GetDetailedInfo() const {
724 return DetailedInfo().Init(DetailedInfo::TYPE_APPCACHES);
725 }
726
727 ///////////////////////////////////////////////////////////////////////////////
728 // CookieTreeDatabasesNode, public:
729
CookieTreeDatabasesNode()730 CookieTreeDatabasesNode::CookieTreeDatabasesNode()
731 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASES)) {
732 }
733
~CookieTreeDatabasesNode()734 CookieTreeDatabasesNode::~CookieTreeDatabasesNode() {}
735
GetDetailedInfo() const736 CookieTreeNode::DetailedInfo CookieTreeDatabasesNode::GetDetailedInfo() const {
737 return DetailedInfo().Init(DetailedInfo::TYPE_DATABASES);
738 }
739
740 ///////////////////////////////////////////////////////////////////////////////
741 // CookieTreeLocalStoragesNode, public:
742
CookieTreeLocalStoragesNode()743 CookieTreeLocalStoragesNode::CookieTreeLocalStoragesNode()
744 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_LOCAL_STORAGE)) {
745 }
746
~CookieTreeLocalStoragesNode()747 CookieTreeLocalStoragesNode::~CookieTreeLocalStoragesNode() {}
748
749 CookieTreeNode::DetailedInfo
GetDetailedInfo() const750 CookieTreeLocalStoragesNode::GetDetailedInfo() const {
751 return DetailedInfo().Init(DetailedInfo::TYPE_LOCAL_STORAGES);
752 }
753
754 ///////////////////////////////////////////////////////////////////////////////
755 // CookieTreeSessionStoragesNode, public:
756
CookieTreeSessionStoragesNode()757 CookieTreeSessionStoragesNode::CookieTreeSessionStoragesNode()
758 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SESSION_STORAGE)) {
759 }
760
~CookieTreeSessionStoragesNode()761 CookieTreeSessionStoragesNode::~CookieTreeSessionStoragesNode() {}
762
763 CookieTreeNode::DetailedInfo
GetDetailedInfo() const764 CookieTreeSessionStoragesNode::GetDetailedInfo() const {
765 return DetailedInfo().Init(DetailedInfo::TYPE_SESSION_STORAGES);
766 }
767
768 ///////////////////////////////////////////////////////////////////////////////
769 // CookieTreeIndexedDBsNode, public:
770
CookieTreeIndexedDBsNode()771 CookieTreeIndexedDBsNode::CookieTreeIndexedDBsNode()
772 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_INDEXED_DBS)) {
773 }
774
~CookieTreeIndexedDBsNode()775 CookieTreeIndexedDBsNode::~CookieTreeIndexedDBsNode() {}
776
777 CookieTreeNode::DetailedInfo
GetDetailedInfo() const778 CookieTreeIndexedDBsNode::GetDetailedInfo() const {
779 return DetailedInfo().Init(DetailedInfo::TYPE_INDEXED_DBS);
780 }
781
782 ///////////////////////////////////////////////////////////////////////////////
783 // CookieTreeFileSystemsNode, public:
784
CookieTreeFileSystemsNode()785 CookieTreeFileSystemsNode::CookieTreeFileSystemsNode()
786 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_FILE_SYSTEMS)) {
787 }
788
~CookieTreeFileSystemsNode()789 CookieTreeFileSystemsNode::~CookieTreeFileSystemsNode() {}
790
791 CookieTreeNode::DetailedInfo
GetDetailedInfo() const792 CookieTreeFileSystemsNode::GetDetailedInfo() const {
793 return DetailedInfo().Init(DetailedInfo::TYPE_FILE_SYSTEMS);
794 }
795
796 ///////////////////////////////////////////////////////////////////////////////
797 // CookieTreeServerBoundCertsNode, public:
798
CookieTreeServerBoundCertsNode()799 CookieTreeServerBoundCertsNode::CookieTreeServerBoundCertsNode()
800 : CookieTreeNode(
801 l10n_util::GetStringUTF16(IDS_COOKIES_SERVER_BOUND_CERTS)) {
802 }
803
~CookieTreeServerBoundCertsNode()804 CookieTreeServerBoundCertsNode::~CookieTreeServerBoundCertsNode() {}
805
806 CookieTreeNode::DetailedInfo
GetDetailedInfo() const807 CookieTreeServerBoundCertsNode::GetDetailedInfo() const {
808 return DetailedInfo().Init(DetailedInfo::TYPE_SERVER_BOUND_CERTS);
809 }
810
AddChildSortedByTitle(CookieTreeNode * new_child)811 void CookieTreeNode::AddChildSortedByTitle(CookieTreeNode* new_child) {
812 DCHECK(new_child);
813 std::vector<CookieTreeNode*>::iterator iter =
814 std::lower_bound(children().begin(), children().end(), new_child,
815 NodeTitleComparator());
816 GetModel()->Add(this, new_child, iter - children().begin());
817 }
818
819 ///////////////////////////////////////////////////////////////////////////////
820 // CookieTreeFlashLSONode
CookieTreeFlashLSONode(const std::string & domain)821 CookieTreeFlashLSONode::CookieTreeFlashLSONode(
822 const std::string& domain)
823 : domain_(domain) {}
~CookieTreeFlashLSONode()824 CookieTreeFlashLSONode::~CookieTreeFlashLSONode() {}
825
DeleteStoredObjects()826 void CookieTreeFlashLSONode::DeleteStoredObjects() {
827 // We are one level below the host node.
828 CookieTreeHostNode* host = static_cast<CookieTreeHostNode*>(parent());
829 CHECK_EQ(host->GetDetailedInfo().node_type,
830 CookieTreeNode::DetailedInfo::TYPE_HOST);
831 LocalDataContainer* container = GetModel()->data_container();
832 CHECK(container);
833
834 container->flash_lso_helper_->DeleteFlashLSOsForSite(domain_);
835 }
836
GetDetailedInfo() const837 CookieTreeNode::DetailedInfo CookieTreeFlashLSONode::GetDetailedInfo() const {
838 return DetailedInfo().InitFlashLSO(domain_);
839 }
840
841 ///////////////////////////////////////////////////////////////////////////////
842 // ScopedBatchUpdateNotifier
ScopedBatchUpdateNotifier(CookiesTreeModel * model,CookieTreeNode * node)843 CookiesTreeModel::ScopedBatchUpdateNotifier::ScopedBatchUpdateNotifier(
844 CookiesTreeModel* model, CookieTreeNode* node)
845 : model_(model), node_(node), batch_in_progress_(false) {
846 }
847
~ScopedBatchUpdateNotifier()848 CookiesTreeModel::ScopedBatchUpdateNotifier::~ScopedBatchUpdateNotifier() {
849 if (batch_in_progress_) {
850 model_->NotifyObserverTreeNodeChanged(node_);
851 model_->NotifyObserverEndBatch();
852 }
853 }
854
StartBatchUpdate()855 void CookiesTreeModel::ScopedBatchUpdateNotifier::StartBatchUpdate() {
856 if (!batch_in_progress_) {
857 model_->NotifyObserverBeginBatch();
858 batch_in_progress_ = true;
859 }
860 }
861
862 ///////////////////////////////////////////////////////////////////////////////
863 // CookiesTreeModel, public:
CookiesTreeModel(LocalDataContainer * data_container,ExtensionSpecialStoragePolicy * special_storage_policy,bool group_by_cookie_source)864 CookiesTreeModel::CookiesTreeModel(
865 LocalDataContainer* data_container,
866 ExtensionSpecialStoragePolicy* special_storage_policy,
867 bool group_by_cookie_source)
868 : ui::TreeNodeModel<CookieTreeNode>(new CookieTreeRootNode(this)),
869 data_container_(data_container),
870 special_storage_policy_(special_storage_policy),
871 group_by_cookie_source_(group_by_cookie_source),
872 batch_update_(0) {
873 data_container_->Init(this);
874 }
875
~CookiesTreeModel()876 CookiesTreeModel::~CookiesTreeModel() {
877 }
878
879 ///////////////////////////////////////////////////////////////////////////////
880 // CookiesTreeModel, TreeModel methods (public):
881
882 // TreeModel methods:
883 // Returns the set of icons for the nodes in the tree. You only need override
884 // this if you don't want to use the default folder icons.
GetIcons(std::vector<gfx::ImageSkia> * icons)885 void CookiesTreeModel::GetIcons(std::vector<gfx::ImageSkia>* icons) {
886 icons->push_back(*ResourceBundle::GetSharedInstance().GetNativeImageNamed(
887 IDR_DEFAULT_FAVICON).ToImageSkia());
888 icons->push_back(*ResourceBundle::GetSharedInstance().GetNativeImageNamed(
889 IDR_COOKIE_ICON).ToImageSkia());
890 icons->push_back(*ResourceBundle::GetSharedInstance().GetNativeImageNamed(
891 IDR_COOKIE_STORAGE_ICON).ToImageSkia());
892 }
893
894 // Returns the index of the icon to use for |node|. Return -1 to use the
895 // default icon. The index is relative to the list of icons returned from
896 // GetIcons.
GetIconIndex(ui::TreeModelNode * node)897 int CookiesTreeModel::GetIconIndex(ui::TreeModelNode* node) {
898 CookieTreeNode* ct_node = static_cast<CookieTreeNode*>(node);
899 switch (ct_node->GetDetailedInfo().node_type) {
900 case CookieTreeNode::DetailedInfo::TYPE_HOST:
901 return ORIGIN;
902 case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
903 return COOKIE;
904 case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
905 return DATABASE;
906 case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
907 return DATABASE; // close enough
908 case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
909 return DATABASE; // ditto
910 case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
911 return DATABASE; // ditto
912 case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
913 return DATABASE; // ditto
914 case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM:
915 return DATABASE; // ditto
916 case CookieTreeNode::DetailedInfo::TYPE_QUOTA:
917 return -1;
918 case CookieTreeNode::DetailedInfo::TYPE_SERVER_BOUND_CERT:
919 return COOKIE; // It's kinda like a cookie?
920 default:
921 break;
922 }
923 return -1;
924 }
925
DeleteAllStoredObjects()926 void CookiesTreeModel::DeleteAllStoredObjects() {
927 NotifyObserverBeginBatch();
928 CookieTreeNode* root = GetRoot();
929 root->DeleteStoredObjects();
930 int num_children = root->child_count();
931 for (int i = num_children - 1; i >= 0; --i)
932 delete Remove(root, root->GetChild(i));
933 NotifyObserverTreeNodeChanged(root);
934 NotifyObserverEndBatch();
935 }
936
DeleteCookieNode(CookieTreeNode * cookie_node)937 void CookiesTreeModel::DeleteCookieNode(CookieTreeNode* cookie_node) {
938 if (cookie_node == GetRoot())
939 return;
940 cookie_node->DeleteStoredObjects();
941 CookieTreeNode* parent_node = cookie_node->parent();
942 delete Remove(parent_node, cookie_node);
943 if (parent_node->empty())
944 DeleteCookieNode(parent_node);
945 }
946
UpdateSearchResults(const base::string16 & filter)947 void CookiesTreeModel::UpdateSearchResults(const base::string16& filter) {
948 CookieTreeNode* root = GetRoot();
949 ScopedBatchUpdateNotifier notifier(this, root);
950 int num_children = root->child_count();
951 notifier.StartBatchUpdate();
952 for (int i = num_children - 1; i >= 0; --i)
953 delete Remove(root, root->GetChild(i));
954
955 PopulateCookieInfoWithFilter(data_container(), ¬ifier, filter);
956 PopulateDatabaseInfoWithFilter(data_container(), ¬ifier, filter);
957 PopulateLocalStorageInfoWithFilter(data_container(), ¬ifier, filter);
958 PopulateSessionStorageInfoWithFilter(data_container(), ¬ifier, filter);
959 PopulateAppCacheInfoWithFilter(data_container(), ¬ifier, filter);
960 PopulateIndexedDBInfoWithFilter(data_container(), ¬ifier, filter);
961 PopulateFileSystemInfoWithFilter(data_container(), ¬ifier, filter);
962 PopulateQuotaInfoWithFilter(data_container(), ¬ifier, filter);
963 PopulateServerBoundCertInfoWithFilter(data_container(), ¬ifier, filter);
964 }
965
ExtensionsProtectingNode(const CookieTreeNode & cookie_node)966 const extensions::ExtensionSet* CookiesTreeModel::ExtensionsProtectingNode(
967 const CookieTreeNode& cookie_node) {
968 if (!special_storage_policy_.get())
969 return NULL;
970
971 CookieTreeNode::DetailedInfo info = cookie_node.GetDetailedInfo();
972
973 if (!TypeIsProtected(info.node_type))
974 return NULL;
975
976 DCHECK(!info.origin.is_empty());
977 return special_storage_policy_->ExtensionsProtectingOrigin(info.origin);
978 }
979
AddCookiesTreeObserver(Observer * observer)980 void CookiesTreeModel::AddCookiesTreeObserver(Observer* observer) {
981 cookies_observer_list_.AddObserver(observer);
982 // Call super so that TreeNodeModel can notify, too.
983 ui::TreeNodeModel<CookieTreeNode>::AddObserver(observer);
984 }
985
RemoveCookiesTreeObserver(Observer * observer)986 void CookiesTreeModel::RemoveCookiesTreeObserver(Observer* observer) {
987 cookies_observer_list_.RemoveObserver(observer);
988 // Call super so that TreeNodeModel doesn't have dead pointers.
989 ui::TreeNodeModel<CookieTreeNode>::RemoveObserver(observer);
990 }
991
PopulateAppCacheInfo(LocalDataContainer * container)992 void CookiesTreeModel::PopulateAppCacheInfo(LocalDataContainer* container) {
993 ScopedBatchUpdateNotifier notifier(this, GetRoot());
994 PopulateAppCacheInfoWithFilter(container, ¬ifier, base::string16());
995 }
996
PopulateCookieInfo(LocalDataContainer * container)997 void CookiesTreeModel::PopulateCookieInfo(LocalDataContainer* container) {
998 ScopedBatchUpdateNotifier notifier(this, GetRoot());
999 PopulateCookieInfoWithFilter(container, ¬ifier, base::string16());
1000 }
1001
PopulateDatabaseInfo(LocalDataContainer * container)1002 void CookiesTreeModel::PopulateDatabaseInfo(LocalDataContainer* container) {
1003 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1004 PopulateDatabaseInfoWithFilter(container, ¬ifier, base::string16());
1005 }
1006
PopulateLocalStorageInfo(LocalDataContainer * container)1007 void CookiesTreeModel::PopulateLocalStorageInfo(LocalDataContainer* container) {
1008 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1009 PopulateLocalStorageInfoWithFilter(container, ¬ifier, base::string16());
1010 }
1011
PopulateSessionStorageInfo(LocalDataContainer * container)1012 void CookiesTreeModel::PopulateSessionStorageInfo(
1013 LocalDataContainer* container) {
1014 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1015 PopulateSessionStorageInfoWithFilter(container, ¬ifier, base::string16());
1016 }
1017
PopulateIndexedDBInfo(LocalDataContainer * container)1018 void CookiesTreeModel::PopulateIndexedDBInfo(LocalDataContainer* container){
1019 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1020 PopulateIndexedDBInfoWithFilter(container, ¬ifier, base::string16());
1021 }
1022
PopulateFileSystemInfo(LocalDataContainer * container)1023 void CookiesTreeModel::PopulateFileSystemInfo(LocalDataContainer* container) {
1024 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1025 PopulateFileSystemInfoWithFilter(container, ¬ifier, base::string16());
1026 }
1027
PopulateQuotaInfo(LocalDataContainer * container)1028 void CookiesTreeModel::PopulateQuotaInfo(LocalDataContainer* container) {
1029 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1030 PopulateQuotaInfoWithFilter(container, ¬ifier, base::string16());
1031 }
1032
PopulateServerBoundCertInfo(LocalDataContainer * container)1033 void CookiesTreeModel::PopulateServerBoundCertInfo(
1034 LocalDataContainer* container) {
1035 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1036 PopulateServerBoundCertInfoWithFilter(container, ¬ifier, base::string16());
1037 }
1038
PopulateFlashLSOInfo(LocalDataContainer * container)1039 void CookiesTreeModel::PopulateFlashLSOInfo(
1040 LocalDataContainer* container) {
1041 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1042 PopulateFlashLSOInfoWithFilter(container, ¬ifier, base::string16());
1043 }
1044
PopulateAppCacheInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1045 void CookiesTreeModel::PopulateAppCacheInfoWithFilter(
1046 LocalDataContainer* container,
1047 ScopedBatchUpdateNotifier* notifier,
1048 const base::string16& filter) {
1049 using appcache::AppCacheInfo;
1050 typedef std::map<GURL, std::list<AppCacheInfo> > InfoByOrigin;
1051 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1052
1053 if (container->appcache_info_.empty())
1054 return;
1055
1056 notifier->StartBatchUpdate();
1057 for (InfoByOrigin::iterator origin = container->appcache_info_.begin();
1058 origin != container->appcache_info_.end(); ++origin) {
1059 base::string16 host_node_name = base::UTF8ToUTF16(origin->first.host());
1060 if (filter.empty() ||
1061 (host_node_name.find(filter) != base::string16::npos)) {
1062 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin->first);
1063 CookieTreeAppCachesNode* appcaches_node =
1064 host_node->GetOrCreateAppCachesNode();
1065
1066 for (std::list<AppCacheInfo>::iterator info = origin->second.begin();
1067 info != origin->second.end(); ++info) {
1068 appcaches_node->AddAppCacheNode(
1069 new CookieTreeAppCacheNode(origin->first, info));
1070 }
1071 }
1072 }
1073 }
1074
PopulateCookieInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1075 void CookiesTreeModel::PopulateCookieInfoWithFilter(
1076 LocalDataContainer* container,
1077 ScopedBatchUpdateNotifier* notifier,
1078 const base::string16& filter) {
1079 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1080
1081 notifier->StartBatchUpdate();
1082 for (CookieList::iterator it = container->cookie_list_.begin();
1083 it != container->cookie_list_.end(); ++it) {
1084 std::string source_string = it->Source();
1085 if (source_string.empty() || !group_by_cookie_source_) {
1086 std::string domain = it->Domain();
1087 if (domain.length() > 1 && domain[0] == '.')
1088 domain = domain.substr(1);
1089
1090 // We treat secure cookies just the same as normal ones.
1091 source_string = std::string(url::kHttpScheme) +
1092 url::kStandardSchemeSeparator + domain + "/";
1093 }
1094
1095 GURL source(source_string);
1096 if (!filter.size() ||
1097 (CookieTreeHostNode::TitleForUrl(source).find(filter) !=
1098 base::string16::npos)) {
1099 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(source);
1100 CookieTreeCookiesNode* cookies_node =
1101 host_node->GetOrCreateCookiesNode();
1102 CookieTreeCookieNode* new_cookie = new CookieTreeCookieNode(it);
1103 cookies_node->AddCookieNode(new_cookie);
1104 }
1105 }
1106 }
1107
PopulateDatabaseInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1108 void CookiesTreeModel::PopulateDatabaseInfoWithFilter(
1109 LocalDataContainer* container,
1110 ScopedBatchUpdateNotifier* notifier,
1111 const base::string16& filter) {
1112 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1113
1114 if (container->database_info_list_.empty())
1115 return;
1116
1117 notifier->StartBatchUpdate();
1118 for (DatabaseInfoList::iterator database_info =
1119 container->database_info_list_.begin();
1120 database_info != container->database_info_list_.end();
1121 ++database_info) {
1122 GURL origin(database_info->identifier.ToOrigin());
1123
1124 if (!filter.size() ||
1125 (CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
1126 base::string16::npos)) {
1127 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1128 CookieTreeDatabasesNode* databases_node =
1129 host_node->GetOrCreateDatabasesNode();
1130 databases_node->AddDatabaseNode(
1131 new CookieTreeDatabaseNode(database_info));
1132 }
1133 }
1134 }
1135
PopulateLocalStorageInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1136 void CookiesTreeModel::PopulateLocalStorageInfoWithFilter(
1137 LocalDataContainer* container,
1138 ScopedBatchUpdateNotifier* notifier,
1139 const base::string16& filter) {
1140 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1141
1142 if (container->local_storage_info_list_.empty())
1143 return;
1144
1145 notifier->StartBatchUpdate();
1146 for (LocalStorageInfoList::iterator local_storage_info =
1147 container->local_storage_info_list_.begin();
1148 local_storage_info != container->local_storage_info_list_.end();
1149 ++local_storage_info) {
1150 const GURL& origin(local_storage_info->origin_url);
1151
1152 if (!filter.size() ||
1153 (CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
1154 std::string::npos)) {
1155 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1156 CookieTreeLocalStoragesNode* local_storages_node =
1157 host_node->GetOrCreateLocalStoragesNode();
1158 local_storages_node->AddLocalStorageNode(
1159 new CookieTreeLocalStorageNode(local_storage_info));
1160 }
1161 }
1162 }
1163
PopulateSessionStorageInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1164 void CookiesTreeModel::PopulateSessionStorageInfoWithFilter(
1165 LocalDataContainer* container,
1166 ScopedBatchUpdateNotifier* notifier,
1167 const base::string16& filter) {
1168 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1169
1170 if (container->session_storage_info_list_.empty())
1171 return;
1172
1173 notifier->StartBatchUpdate();
1174 for (LocalStorageInfoList::iterator session_storage_info =
1175 container->session_storage_info_list_.begin();
1176 session_storage_info != container->session_storage_info_list_.end();
1177 ++session_storage_info) {
1178 const GURL& origin = session_storage_info->origin_url;
1179
1180 if (!filter.size() ||
1181 (CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
1182 base::string16::npos)) {
1183 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1184 CookieTreeSessionStoragesNode* session_storages_node =
1185 host_node->GetOrCreateSessionStoragesNode();
1186 session_storages_node->AddSessionStorageNode(
1187 new CookieTreeSessionStorageNode(session_storage_info));
1188 }
1189 }
1190 }
1191
PopulateIndexedDBInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1192 void CookiesTreeModel::PopulateIndexedDBInfoWithFilter(
1193 LocalDataContainer* container,
1194 ScopedBatchUpdateNotifier* notifier,
1195 const base::string16& filter) {
1196 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1197
1198 if (container->indexed_db_info_list_.empty())
1199 return;
1200
1201 notifier->StartBatchUpdate();
1202 for (IndexedDBInfoList::iterator indexed_db_info =
1203 container->indexed_db_info_list_.begin();
1204 indexed_db_info != container->indexed_db_info_list_.end();
1205 ++indexed_db_info) {
1206 const GURL& origin = indexed_db_info->origin_;
1207
1208 if (!filter.size() ||
1209 (CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
1210 base::string16::npos)) {
1211 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1212 CookieTreeIndexedDBsNode* indexed_dbs_node =
1213 host_node->GetOrCreateIndexedDBsNode();
1214 indexed_dbs_node->AddIndexedDBNode(
1215 new CookieTreeIndexedDBNode(indexed_db_info));
1216 }
1217 }
1218 }
1219
PopulateServerBoundCertInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1220 void CookiesTreeModel::PopulateServerBoundCertInfoWithFilter(
1221 LocalDataContainer* container,
1222 ScopedBatchUpdateNotifier* notifier,
1223 const base::string16& filter) {
1224 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1225
1226 if (container->server_bound_cert_list_.empty())
1227 return;
1228
1229 notifier->StartBatchUpdate();
1230 for (ServerBoundCertList::iterator cert_info =
1231 container->server_bound_cert_list_.begin();
1232 cert_info != container->server_bound_cert_list_.end();
1233 ++cert_info) {
1234 GURL origin(cert_info->server_identifier());
1235 if (!origin.is_valid()) {
1236 // Domain Bound Cert. Make a valid URL to satisfy the
1237 // CookieTreeRootNode::GetOrCreateHostNode interface.
1238 origin = GURL(std::string(url::kHttpsScheme) +
1239 url::kStandardSchemeSeparator +
1240 cert_info->server_identifier() + "/");
1241 }
1242 base::string16 title = CookieTreeHostNode::TitleForUrl(origin);
1243 if (!filter.size() || title.find(filter) != base::string16::npos) {
1244 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1245 CookieTreeServerBoundCertsNode* server_bound_certs_node =
1246 host_node->GetOrCreateServerBoundCertsNode();
1247 server_bound_certs_node->AddServerBoundCertNode(
1248 new CookieTreeServerBoundCertNode(cert_info));
1249 }
1250 }
1251 }
1252
PopulateFileSystemInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1253 void CookiesTreeModel::PopulateFileSystemInfoWithFilter(
1254 LocalDataContainer* container,
1255 ScopedBatchUpdateNotifier* notifier,
1256 const base::string16& filter) {
1257 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1258
1259 if (container->file_system_info_list_.empty())
1260 return;
1261
1262 notifier->StartBatchUpdate();
1263 for (FileSystemInfoList::iterator file_system_info =
1264 container->file_system_info_list_.begin();
1265 file_system_info != container->file_system_info_list_.end();
1266 ++file_system_info) {
1267 GURL origin(file_system_info->origin);
1268
1269 if (!filter.size() ||
1270 (CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
1271 base::string16::npos)) {
1272 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1273 CookieTreeFileSystemsNode* file_systems_node =
1274 host_node->GetOrCreateFileSystemsNode();
1275 file_systems_node->AddFileSystemNode(
1276 new CookieTreeFileSystemNode(file_system_info));
1277 }
1278 }
1279 }
1280
PopulateQuotaInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1281 void CookiesTreeModel::PopulateQuotaInfoWithFilter(
1282 LocalDataContainer* container,
1283 ScopedBatchUpdateNotifier* notifier,
1284 const base::string16& filter) {
1285 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1286
1287 if (container->quota_info_list_.empty())
1288 return;
1289
1290 notifier->StartBatchUpdate();
1291 for (QuotaInfoList::iterator quota_info = container->quota_info_list_.begin();
1292 quota_info != container->quota_info_list_.end();
1293 ++quota_info) {
1294 if (!filter.size() ||
1295 (base::UTF8ToUTF16(quota_info->host).find(filter) !=
1296 base::string16::npos)) {
1297 CookieTreeHostNode* host_node =
1298 root->GetOrCreateHostNode(GURL("http://" + quota_info->host));
1299 host_node->UpdateOrCreateQuotaNode(quota_info);
1300 }
1301 }
1302 }
1303
PopulateFlashLSOInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1304 void CookiesTreeModel::PopulateFlashLSOInfoWithFilter(
1305 LocalDataContainer* container,
1306 ScopedBatchUpdateNotifier* notifier,
1307 const base::string16& filter) {
1308 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1309
1310 if (container->flash_lso_domain_list_.empty())
1311 return;
1312
1313 std::string filter_utf8 = base::UTF16ToUTF8(filter);
1314 notifier->StartBatchUpdate();
1315 for (std::vector<std::string>::iterator it =
1316 container->flash_lso_domain_list_.begin();
1317 it != container->flash_lso_domain_list_.end(); ++it) {
1318 if (!filter_utf8.size() || it->find(filter_utf8) != std::string::npos) {
1319 // Create a fake origin for GetOrCreateHostNode().
1320 GURL origin("http://" + *it);
1321 CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
1322 host_node->GetOrCreateFlashLSONode(*it);
1323 }
1324 }
1325 }
1326
NotifyObserverBeginBatch()1327 void CookiesTreeModel::NotifyObserverBeginBatch() {
1328 // Only notify the model once if we're batching in a nested manner.
1329 if (batch_update_++ == 0) {
1330 FOR_EACH_OBSERVER(Observer,
1331 cookies_observer_list_,
1332 TreeModelBeginBatch(this));
1333 }
1334 }
1335
NotifyObserverEndBatch()1336 void CookiesTreeModel::NotifyObserverEndBatch() {
1337 // Only notify the observers if this is the outermost call to EndBatch() if
1338 // called in a nested manner.
1339 if (--batch_update_ == 0) {
1340 FOR_EACH_OBSERVER(Observer,
1341 cookies_observer_list_,
1342 TreeModelEndBatch(this));
1343 }
1344 }
1345