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 <map>
10 #include <vector>
11
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"
30
31 #if defined(ENABLE_EXTENSIONS)
32 #include "chrome/browser/extensions/extension_special_storage_policy.h"
33 #include "extensions/common/extension_set.h"
34 #endif
35
36 namespace {
37
38 struct NodeTitleComparator {
operator ()__anon0151e1d50111::NodeTitleComparator39 bool operator()(const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
40 return lhs->GetTitle() < rhs->GetTitle();
41 }
42 };
43
44 // Comparison functor, for use in CookieTreeRootNode.
45 struct HostNodeComparator {
operator ()__anon0151e1d50111::HostNodeComparator46 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);
54
55 const CookieTreeHostNode* ltn =
56 static_cast<const CookieTreeHostNode*>(lhs);
57 const CookieTreeHostNode* rtn =
58 static_cast<const CookieTreeHostNode*>(rhs);
59
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());
66 }
67 };
68
CanonicalizeHost(const GURL & url)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".
76
77 if (url.SchemeIsFile()) {
78 return std::string(url::kFileScheme) +
79 url::kStandardSchemeSeparator;
80 }
81
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;
89
90 std::string::size_type position = host.rfind(retval);
91
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;
95
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;
100
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;
110 }
111 retval += host.substr(next_dot + 1, position - (next_dot + 1));
112 position = next_dot;
113 }
114 return retval;
115 }
116
117 #if defined(ENABLE_EXTENSIONS)
TypeIsProtected(CookieTreeNode::DetailedInfo::NodeType type)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;
144 }
145 return false;
146 }
147 #endif
148
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
GetLocalDataContainerForNode(CookieTreeNode * 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();
159 }
160
161 } // namespace
162
DetailedInfo()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) {
175 }
176
~DetailedInfo()177 CookieTreeNode::DetailedInfo::~DetailedInfo() {}
178
Init(NodeType type)179 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::Init(
180 NodeType type) {
181 DCHECK_EQ(TYPE_NONE, node_type);
182 node_type = type;
183 return *this;
184 }
185
InitHost()186 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitHost() {
187 Init(TYPE_HOST);
188 return *this;
189 }
190
InitCookie(const net::CanonicalCookie * cookie)191 CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitCookie(
192 const net::CanonicalCookie* cookie) {
193 Init(TYPE_COOKIE);
194 this->cookie = cookie;
195 return *this;
196 }
197
InitDatabase(const BrowsingDataDatabaseHelper::DatabaseInfo * database_info)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;
204 }
205
InitLocalStorage(const BrowsingDataLocalStorageHelper::LocalStorageInfo * local_storage_info)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;
213 }
214
InitSessionStorage(const BrowsingDataLocalStorageHelper::LocalStorageInfo * session_storage_info)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;
222 }
223
InitAppCache(const GURL & origin,const content::AppCacheInfo * appcache_info)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;
231 }
232
InitIndexedDB(const content::IndexedDBInfo * indexed_db_info)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;
239 }
240
InitFileSystem(const BrowsingDataFileSystemHelper::FileSystemInfo * file_system_info)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;
247 }
248
InitQuota(const BrowsingDataQuotaHelper::QuotaInfo * quota_info)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;
254 }
255
InitChannelID(const net::ChannelIDStore::ChannelID * channel_id)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;
261 }
262
InitServiceWorker(const content::ServiceWorkerUsageInfo * service_worker_info)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;
269 }
270
InitFlashLSO(const std::string & flash_lso_domain)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;
276 }
277
278 ///////////////////////////////////////////////////////////////////////////////
279 // CookieTreeNode, public:
280
DeleteStoredObjects()281 void CookieTreeNode::DeleteStoredObjects() {
282 std::for_each(children().begin(),
283 children().end(),
284 std::mem_fun(&CookieTreeNode::DeleteStoredObjects));
285 }
286
GetModel() const287 CookiesTreeModel* CookieTreeNode::GetModel() const {
288 if (parent())
289 return parent()->GetModel();
290 else
291 return NULL;
292 }
293
294 ///////////////////////////////////////////////////////////////////////////////
295 // CookieTreeCookieNode, public:
296
CookieTreeCookieNode(std::list<net::CanonicalCookie>::iterator cookie)297 CookieTreeCookieNode::CookieTreeCookieNode(
298 std::list<net::CanonicalCookie>::iterator cookie)
299 : CookieTreeNode(base::UTF8ToUTF16(cookie->Name())),
300 cookie_(cookie) {
301 }
302
~CookieTreeCookieNode()303 CookieTreeCookieNode::~CookieTreeCookieNode() {}
304
DeleteStoredObjects()305 void CookieTreeCookieNode::DeleteStoredObjects() {
306 LocalDataContainer* container = GetLocalDataContainerForNode(this);
307 container->cookie_helper_->DeleteCookie(*cookie_);
308 container->cookie_list_.erase(cookie_);
309 }
310
GetDetailedInfo() const311 CookieTreeNode::DetailedInfo CookieTreeCookieNode::GetDetailedInfo() const {
312 return DetailedInfo().InitCookie(&*cookie_);
313 }
314
315 ///////////////////////////////////////////////////////////////////////////////
316 // CookieTreeAppCacheNode, public:
317
CookieTreeAppCacheNode(const GURL & origin_url,std::list<content::AppCacheInfo>::iterator appcache_info)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) {
324 }
325
~CookieTreeAppCacheNode()326 CookieTreeAppCacheNode::~CookieTreeAppCacheNode() {
327 }
328
DeleteStoredObjects()329 void CookieTreeAppCacheNode::DeleteStoredObjects() {
330 LocalDataContainer* container = GetLocalDataContainerForNode(this);
331
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_);
337 }
338 }
339
GetDetailedInfo() const340 CookieTreeNode::DetailedInfo CookieTreeAppCacheNode::GetDetailedInfo() const {
341 return DetailedInfo().InitAppCache(origin_url_, &*appcache_info_);
342 }
343
344 ///////////////////////////////////////////////////////////////////////////////
345 // CookieTreeDatabaseNode, public:
346
CookieTreeDatabaseNode(std::list<BrowsingDataDatabaseHelper::DatabaseInfo>::iterator database_info)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) {
353 }
354
~CookieTreeDatabaseNode()355 CookieTreeDatabaseNode::~CookieTreeDatabaseNode() {}
356
DeleteStoredObjects()357 void CookieTreeDatabaseNode::DeleteStoredObjects() {
358 LocalDataContainer* container = GetLocalDataContainerForNode(this);
359
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_);
364 }
365 }
366
GetDetailedInfo() const367 CookieTreeNode::DetailedInfo CookieTreeDatabaseNode::GetDetailedInfo() const {
368 return DetailedInfo().InitDatabase(&*database_info_);
369 }
370
371 ///////////////////////////////////////////////////////////////////////////////
372 // CookieTreeLocalStorageNode, public:
373
CookieTreeLocalStorageNode(std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::iterator local_storage_info)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) {
379 }
380
~CookieTreeLocalStorageNode()381 CookieTreeLocalStorageNode::~CookieTreeLocalStorageNode() {}
382
DeleteStoredObjects()383 void CookieTreeLocalStorageNode::DeleteStoredObjects() {
384 LocalDataContainer* container = GetLocalDataContainerForNode(this);
385
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_);
390 }
391 }
392
393 CookieTreeNode::DetailedInfo
GetDetailedInfo() const394 CookieTreeLocalStorageNode::GetDetailedInfo() const {
395 return DetailedInfo().InitLocalStorage(
396 &*local_storage_info_);
397 }
398
399 ///////////////////////////////////////////////////////////////////////////////
400 // CookieTreeSessionStorageNode, public:
401
CookieTreeSessionStorageNode(std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::iterator session_storage_info)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) {
408 }
409
~CookieTreeSessionStorageNode()410 CookieTreeSessionStorageNode::~CookieTreeSessionStorageNode() {}
411
DeleteStoredObjects()412 void CookieTreeSessionStorageNode::DeleteStoredObjects() {
413 LocalDataContainer* container = GetLocalDataContainerForNode(this);
414
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_);
421 }
422 }
423
424 CookieTreeNode::DetailedInfo
GetDetailedInfo() const425 CookieTreeSessionStorageNode::GetDetailedInfo() const {
426 return DetailedInfo().InitSessionStorage(&*session_storage_info_);
427 }
428
429 ///////////////////////////////////////////////////////////////////////////////
430 // CookieTreeIndexedDBNode, public:
431
CookieTreeIndexedDBNode(std::list<content::IndexedDBInfo>::iterator indexed_db_info)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) {
438 }
439
~CookieTreeIndexedDBNode()440 CookieTreeIndexedDBNode::~CookieTreeIndexedDBNode() {}
441
DeleteStoredObjects()442 void CookieTreeIndexedDBNode::DeleteStoredObjects() {
443 LocalDataContainer* container = GetLocalDataContainerForNode(this);
444
445 if (container) {
446 container->indexed_db_helper_->DeleteIndexedDB(
447 indexed_db_info_->origin_);
448 container->indexed_db_info_list_.erase(indexed_db_info_);
449 }
450 }
451
GetDetailedInfo() const452 CookieTreeNode::DetailedInfo CookieTreeIndexedDBNode::GetDetailedInfo() const {
453 return DetailedInfo().InitIndexedDB(&*indexed_db_info_);
454 }
455
456 ///////////////////////////////////////////////////////////////////////////////
457 // CookieTreeFileSystemNode, public:
458
CookieTreeFileSystemNode(std::list<BrowsingDataFileSystemHelper::FileSystemInfo>::iterator file_system_info)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) {
465 }
466
~CookieTreeFileSystemNode()467 CookieTreeFileSystemNode::~CookieTreeFileSystemNode() {}
468
DeleteStoredObjects()469 void CookieTreeFileSystemNode::DeleteStoredObjects() {
470 LocalDataContainer* container = GetLocalDataContainerForNode(this);
471
472 if (container) {
473 container->file_system_helper_->DeleteFileSystemOrigin(
474 file_system_info_->origin);
475 container->file_system_info_list_.erase(file_system_info_);
476 }
477 }
478
GetDetailedInfo() const479 CookieTreeNode::DetailedInfo CookieTreeFileSystemNode::GetDetailedInfo() const {
480 return DetailedInfo().InitFileSystem(&*file_system_info_);
481 }
482
483 ///////////////////////////////////////////////////////////////////////////////
484 // CookieTreeQuotaNode, public:
485
CookieTreeQuotaNode(std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)486 CookieTreeQuotaNode::CookieTreeQuotaNode(
487 std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)
488 : CookieTreeNode(base::UTF8ToUTF16(quota_info->host)),
489 quota_info_(quota_info) {
490 }
491
~CookieTreeQuotaNode()492 CookieTreeQuotaNode::~CookieTreeQuotaNode() {}
493
DeleteStoredObjects()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();
498
499 if (container) {
500 container->quota_helper_->RevokeHostQuota(quota_info_->host);
501 container->quota_info_list_.erase(quota_info_);
502 }
503 }
504
GetDetailedInfo() const505 CookieTreeNode::DetailedInfo CookieTreeQuotaNode::GetDetailedInfo() const {
506 return DetailedInfo().InitQuota(&*quota_info_);
507 }
508
509 ///////////////////////////////////////////////////////////////////////////////
510 // CookieTreeChannelIDNode, public:
511
CookieTreeChannelIDNode(net::ChannelIDStore::ChannelIDList::iterator channel_id)512 CookieTreeChannelIDNode::CookieTreeChannelIDNode(
513 net::ChannelIDStore::ChannelIDList::iterator channel_id)
514 : CookieTreeNode(base::ASCIIToUTF16(channel_id->server_identifier())),
515 channel_id_(channel_id) {
516 }
517
~CookieTreeChannelIDNode()518 CookieTreeChannelIDNode::~CookieTreeChannelIDNode() {}
519
DeleteStoredObjects()520 void CookieTreeChannelIDNode::DeleteStoredObjects() {
521 LocalDataContainer* container = GetLocalDataContainerForNode(this);
522
523 if (container) {
524 container->channel_id_helper_->DeleteChannelID(
525 channel_id_->server_identifier());
526 container->channel_id_list_.erase(channel_id_);
527 }
528 }
529
530 CookieTreeNode::DetailedInfo
GetDetailedInfo() const531 CookieTreeChannelIDNode::GetDetailedInfo() const {
532 return DetailedInfo().InitChannelID(&*channel_id_);
533 }
534
535 ///////////////////////////////////////////////////////////////////////////////
536 // CookieTreeServiceWorkerNode, public:
537
CookieTreeServiceWorkerNode(std::list<content::ServiceWorkerUsageInfo>::iterator service_worker_info)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) {
542 }
543
~CookieTreeServiceWorkerNode()544 CookieTreeServiceWorkerNode::~CookieTreeServiceWorkerNode() {
545 }
546
DeleteStoredObjects()547 void CookieTreeServiceWorkerNode::DeleteStoredObjects() {
548 LocalDataContainer* container = GetLocalDataContainerForNode(this);
549
550 if (container) {
551 container->service_worker_helper_->DeleteServiceWorkers(
552 service_worker_info_->origin);
553 container->service_worker_info_list_.erase(service_worker_info_);
554 }
555 }
556
GetDetailedInfo() const557 CookieTreeNode::DetailedInfo CookieTreeServiceWorkerNode::GetDetailedInfo()
558 const {
559 return DetailedInfo().InitServiceWorker(&*service_worker_info_);
560 }
561
562 ///////////////////////////////////////////////////////////////////////////////
563 // CookieTreeRootNode, public:
564
CookieTreeRootNode(CookiesTreeModel * model)565 CookieTreeRootNode::CookieTreeRootNode(CookiesTreeModel* model)
566 : model_(model) {
567 }
568
~CookieTreeRootNode()569 CookieTreeRootNode::~CookieTreeRootNode() {}
570
GetOrCreateHostNode(const GURL & url)571 CookieTreeHostNode* CookieTreeRootNode::GetOrCreateHostNode(
572 const GURL& url) {
573 scoped_ptr<CookieTreeHostNode> host_node(
574 new CookieTreeHostNode(url));
575
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();
589 }
590
GetModel() const591 CookiesTreeModel* CookieTreeRootNode::GetModel() const {
592 return model_;
593 }
594
GetDetailedInfo() const595 CookieTreeNode::DetailedInfo CookieTreeRootNode::GetDetailedInfo() const {
596 return DetailedInfo().Init(DetailedInfo::TYPE_ROOT);
597 }
598
599 ///////////////////////////////////////////////////////////////////////////////
600 // CookieTreeHostNode, public:
601
602 // static
TitleForUrl(const GURL & url)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());
608 }
609
CookieTreeHostNode(const GURL & url)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)) {
625 }
626
~CookieTreeHostNode()627 CookieTreeHostNode::~CookieTreeHostNode() {}
628
GetHost() const629 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();
633 }
634
GetDetailedInfo() const635 CookieTreeNode::DetailedInfo CookieTreeHostNode::GetDetailedInfo() const {
636 return DetailedInfo().InitHost();
637 }
638
GetOrCreateCookiesNode()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_;
645 }
646
GetOrCreateDatabasesNode()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_;
653 }
654
655 CookieTreeLocalStoragesNode*
GetOrCreateLocalStoragesNode()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_;
662 }
663
664 CookieTreeSessionStoragesNode*
GetOrCreateSessionStoragesNode()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_;
671 }
672
GetOrCreateAppCachesNode()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_;
679 }
680
GetOrCreateIndexedDBsNode()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_;
687 }
688
GetOrCreateFileSystemsNode()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_;
695 }
696
UpdateOrCreateQuotaNode(std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)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_;
704 }
705
706 CookieTreeChannelIDsNode*
GetOrCreateChannelIDsNode()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_;
713 }
714
715 CookieTreeServiceWorkersNode*
GetOrCreateServiceWorkersNode()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_;
722 }
723
GetOrCreateFlashLSONode(const std::string & domain)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_;
732 }
733
CreateContentException(CookieSettings * cookie_settings,ContentSetting setting) const734 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);
746 }
747 }
748
CanCreateContentException() const749 bool CookieTreeHostNode::CanCreateContentException() const {
750 return !url_.SchemeIsFile();
751 }
752
753 ///////////////////////////////////////////////////////////////////////////////
754 // CookieTreeCookiesNode, public:
755
CookieTreeCookiesNode()756 CookieTreeCookiesNode::CookieTreeCookiesNode()
757 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIES)) {
758 }
759
~CookieTreeCookiesNode()760 CookieTreeCookiesNode::~CookieTreeCookiesNode() {
761 }
762
GetDetailedInfo() const763 CookieTreeNode::DetailedInfo CookieTreeCookiesNode::GetDetailedInfo() const {
764 return DetailedInfo().Init(DetailedInfo::TYPE_COOKIES);
765 }
766
767 ///////////////////////////////////////////////////////////////////////////////
768 // CookieTreeAppCachesNode, public:
769
CookieTreeAppCachesNode()770 CookieTreeAppCachesNode::CookieTreeAppCachesNode()
771 : CookieTreeNode(l10n_util::GetStringUTF16(
772 IDS_COOKIES_APPLICATION_CACHES)) {
773 }
774
~CookieTreeAppCachesNode()775 CookieTreeAppCachesNode::~CookieTreeAppCachesNode() {}
776
GetDetailedInfo() const777 CookieTreeNode::DetailedInfo CookieTreeAppCachesNode::GetDetailedInfo() const {
778 return DetailedInfo().Init(DetailedInfo::TYPE_APPCACHES);
779 }
780
781 ///////////////////////////////////////////////////////////////////////////////
782 // CookieTreeDatabasesNode, public:
783
CookieTreeDatabasesNode()784 CookieTreeDatabasesNode::CookieTreeDatabasesNode()
785 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASES)) {
786 }
787
~CookieTreeDatabasesNode()788 CookieTreeDatabasesNode::~CookieTreeDatabasesNode() {}
789
GetDetailedInfo() const790 CookieTreeNode::DetailedInfo CookieTreeDatabasesNode::GetDetailedInfo() const {
791 return DetailedInfo().Init(DetailedInfo::TYPE_DATABASES);
792 }
793
794 ///////////////////////////////////////////////////////////////////////////////
795 // CookieTreeLocalStoragesNode, public:
796
CookieTreeLocalStoragesNode()797 CookieTreeLocalStoragesNode::CookieTreeLocalStoragesNode()
798 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_LOCAL_STORAGE)) {
799 }
800
~CookieTreeLocalStoragesNode()801 CookieTreeLocalStoragesNode::~CookieTreeLocalStoragesNode() {}
802
803 CookieTreeNode::DetailedInfo
GetDetailedInfo() const804 CookieTreeLocalStoragesNode::GetDetailedInfo() const {
805 return DetailedInfo().Init(DetailedInfo::TYPE_LOCAL_STORAGES);
806 }
807
808 ///////////////////////////////////////////////////////////////////////////////
809 // CookieTreeSessionStoragesNode, public:
810
CookieTreeSessionStoragesNode()811 CookieTreeSessionStoragesNode::CookieTreeSessionStoragesNode()
812 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SESSION_STORAGE)) {
813 }
814
~CookieTreeSessionStoragesNode()815 CookieTreeSessionStoragesNode::~CookieTreeSessionStoragesNode() {}
816
817 CookieTreeNode::DetailedInfo
GetDetailedInfo() const818 CookieTreeSessionStoragesNode::GetDetailedInfo() const {
819 return DetailedInfo().Init(DetailedInfo::TYPE_SESSION_STORAGES);
820 }
821
822 ///////////////////////////////////////////////////////////////////////////////
823 // CookieTreeIndexedDBsNode, public:
824
CookieTreeIndexedDBsNode()825 CookieTreeIndexedDBsNode::CookieTreeIndexedDBsNode()
826 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_INDEXED_DBS)) {
827 }
828
~CookieTreeIndexedDBsNode()829 CookieTreeIndexedDBsNode::~CookieTreeIndexedDBsNode() {}
830
831 CookieTreeNode::DetailedInfo
GetDetailedInfo() const832 CookieTreeIndexedDBsNode::GetDetailedInfo() const {
833 return DetailedInfo().Init(DetailedInfo::TYPE_INDEXED_DBS);
834 }
835
836 ///////////////////////////////////////////////////////////////////////////////
837 // CookieTreeFileSystemsNode, public:
838
CookieTreeFileSystemsNode()839 CookieTreeFileSystemsNode::CookieTreeFileSystemsNode()
840 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_FILE_SYSTEMS)) {
841 }
842
~CookieTreeFileSystemsNode()843 CookieTreeFileSystemsNode::~CookieTreeFileSystemsNode() {}
844
845 CookieTreeNode::DetailedInfo
GetDetailedInfo() const846 CookieTreeFileSystemsNode::GetDetailedInfo() const {
847 return DetailedInfo().Init(DetailedInfo::TYPE_FILE_SYSTEMS);
848 }
849
850 ///////////////////////////////////////////////////////////////////////////////
851 // CookieTreeChannelIDsNode, public:
852
CookieTreeChannelIDsNode()853 CookieTreeChannelIDsNode::CookieTreeChannelIDsNode()
854 : CookieTreeNode(
855 l10n_util::GetStringUTF16(IDS_COOKIES_CHANNEL_IDS)) {
856 }
857
~CookieTreeChannelIDsNode()858 CookieTreeChannelIDsNode::~CookieTreeChannelIDsNode() {}
859
860 CookieTreeNode::DetailedInfo
GetDetailedInfo() const861 CookieTreeChannelIDsNode::GetDetailedInfo() const {
862 return DetailedInfo().Init(DetailedInfo::TYPE_CHANNEL_IDS);
863 }
864
AddChildSortedByTitle(CookieTreeNode * new_child)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());
871 }
872
873 ///////////////////////////////////////////////////////////////////////////////
874 // CookieTreeServiceWorkersNode, public:
875
CookieTreeServiceWorkersNode()876 CookieTreeServiceWorkersNode::CookieTreeServiceWorkersNode()
877 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SERVICE_WORKERS)) {
878 }
879
~CookieTreeServiceWorkersNode()880 CookieTreeServiceWorkersNode::~CookieTreeServiceWorkersNode() {
881 }
882
GetDetailedInfo() const883 CookieTreeNode::DetailedInfo CookieTreeServiceWorkersNode::GetDetailedInfo()
884 const {
885 return DetailedInfo().Init(DetailedInfo::TYPE_SERVICE_WORKERS);
886 }
887
888 ///////////////////////////////////////////////////////////////////////////////
889 // CookieTreeFlashLSONode
CookieTreeFlashLSONode(const std::string & domain)890 CookieTreeFlashLSONode::CookieTreeFlashLSONode(
891 const std::string& domain)
892 : domain_(domain) {}
~CookieTreeFlashLSONode()893 CookieTreeFlashLSONode::~CookieTreeFlashLSONode() {}
894
DeleteStoredObjects()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_);
902 }
903
GetDetailedInfo() const904 CookieTreeNode::DetailedInfo CookieTreeFlashLSONode::GetDetailedInfo() const {
905 return DetailedInfo().InitFlashLSO(domain_);
906 }
907
908 ///////////////////////////////////////////////////////////////////////////////
909 // ScopedBatchUpdateNotifier
ScopedBatchUpdateNotifier(CookiesTreeModel * model,CookieTreeNode * node)910 CookiesTreeModel::ScopedBatchUpdateNotifier::ScopedBatchUpdateNotifier(
911 CookiesTreeModel* model, CookieTreeNode* node)
912 : model_(model), node_(node), batch_in_progress_(false) {
913 }
914
~ScopedBatchUpdateNotifier()915 CookiesTreeModel::ScopedBatchUpdateNotifier::~ScopedBatchUpdateNotifier() {
916 if (batch_in_progress_) {
917 model_->NotifyObserverTreeNodeChanged(node_);
918 model_->NotifyObserverEndBatch();
919 }
920 }
921
StartBatchUpdate()922 void CookiesTreeModel::ScopedBatchUpdateNotifier::StartBatchUpdate() {
923 if (!batch_in_progress_) {
924 model_->NotifyObserverBeginBatch();
925 batch_in_progress_ = true;
926 }
927 }
928
929 ///////////////////////////////////////////////////////////////////////////////
930 // CookiesTreeModel, public:
CookiesTreeModel(LocalDataContainer * data_container,ExtensionSpecialStoragePolicy * special_storage_policy,bool group_by_cookie_source)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);
943 }
944
~CookiesTreeModel()945 CookiesTreeModel::~CookiesTreeModel() {
946 }
947
948 ///////////////////////////////////////////////////////////////////////////////
949 // CookiesTreeModel, TreeModel methods (public):
950
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.
GetIcons(std::vector<gfx::ImageSkia> * 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());
961 }
962
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.
GetIconIndex(ui::TreeModelNode * node)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;
993 }
994 return -1;
995 }
996
DeleteAllStoredObjects()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();
1006 }
1007
DeleteCookieNode(CookieTreeNode * cookie_node)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);
1016 }
1017
UpdateSearchResults(const base::string16 & filter)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));
1025
1026 PopulateCookieInfoWithFilter(data_container(), ¬ifier, filter);
1027 PopulateDatabaseInfoWithFilter(data_container(), ¬ifier, filter);
1028 PopulateLocalStorageInfoWithFilter(data_container(), ¬ifier, filter);
1029 PopulateSessionStorageInfoWithFilter(data_container(), ¬ifier, filter);
1030 PopulateAppCacheInfoWithFilter(data_container(), ¬ifier, filter);
1031 PopulateIndexedDBInfoWithFilter(data_container(), ¬ifier, filter);
1032 PopulateFileSystemInfoWithFilter(data_container(), ¬ifier, filter);
1033 PopulateQuotaInfoWithFilter(data_container(), ¬ifier, filter);
1034 PopulateChannelIDInfoWithFilter(data_container(), ¬ifier, filter);
1035 PopulateServiceWorkerUsageInfoWithFilter(data_container(), ¬ifier, filter);
1036 }
1037
1038 #if defined(ENABLE_EXTENSIONS)
ExtensionsProtectingNode(const CookieTreeNode & cookie_node)1039 const extensions::ExtensionSet* CookiesTreeModel::ExtensionsProtectingNode(
1040 const CookieTreeNode& cookie_node) {
1041 if (!special_storage_policy_.get())
1042 return NULL;
1043
1044 CookieTreeNode::DetailedInfo info = cookie_node.GetDetailedInfo();
1045
1046 if (!TypeIsProtected(info.node_type))
1047 return NULL;
1048
1049 DCHECK(!info.origin.is_empty());
1050 return special_storage_policy_->ExtensionsProtectingOrigin(info.origin);
1051 }
1052 #endif
1053
AddCookiesTreeObserver(Observer * observer)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);
1058 }
1059
RemoveCookiesTreeObserver(Observer * 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);
1064 }
1065
PopulateAppCacheInfo(LocalDataContainer * container)1066 void CookiesTreeModel::PopulateAppCacheInfo(LocalDataContainer* container) {
1067 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1068 PopulateAppCacheInfoWithFilter(container, ¬ifier, base::string16());
1069 }
1070
PopulateCookieInfo(LocalDataContainer * container)1071 void CookiesTreeModel::PopulateCookieInfo(LocalDataContainer* container) {
1072 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1073 PopulateCookieInfoWithFilter(container, ¬ifier, base::string16());
1074 }
1075
PopulateDatabaseInfo(LocalDataContainer * container)1076 void CookiesTreeModel::PopulateDatabaseInfo(LocalDataContainer* container) {
1077 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1078 PopulateDatabaseInfoWithFilter(container, ¬ifier, base::string16());
1079 }
1080
PopulateLocalStorageInfo(LocalDataContainer * container)1081 void CookiesTreeModel::PopulateLocalStorageInfo(LocalDataContainer* container) {
1082 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1083 PopulateLocalStorageInfoWithFilter(container, ¬ifier, base::string16());
1084 }
1085
PopulateSessionStorageInfo(LocalDataContainer * container)1086 void CookiesTreeModel::PopulateSessionStorageInfo(
1087 LocalDataContainer* container) {
1088 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1089 PopulateSessionStorageInfoWithFilter(container, ¬ifier, base::string16());
1090 }
1091
PopulateIndexedDBInfo(LocalDataContainer * container)1092 void CookiesTreeModel::PopulateIndexedDBInfo(LocalDataContainer* container) {
1093 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1094 PopulateIndexedDBInfoWithFilter(container, ¬ifier, base::string16());
1095 }
1096
PopulateFileSystemInfo(LocalDataContainer * container)1097 void CookiesTreeModel::PopulateFileSystemInfo(LocalDataContainer* container) {
1098 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1099 PopulateFileSystemInfoWithFilter(container, ¬ifier, base::string16());
1100 }
1101
PopulateQuotaInfo(LocalDataContainer * container)1102 void CookiesTreeModel::PopulateQuotaInfo(LocalDataContainer* container) {
1103 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1104 PopulateQuotaInfoWithFilter(container, ¬ifier, base::string16());
1105 }
1106
PopulateChannelIDInfo(LocalDataContainer * container)1107 void CookiesTreeModel::PopulateChannelIDInfo(
1108 LocalDataContainer* container) {
1109 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1110 PopulateChannelIDInfoWithFilter(container, ¬ifier, base::string16());
1111 }
1112
PopulateServiceWorkerUsageInfo(LocalDataContainer * container)1113 void CookiesTreeModel::PopulateServiceWorkerUsageInfo(
1114 LocalDataContainer* container) {
1115 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1116 PopulateServiceWorkerUsageInfoWithFilter(
1117 container, ¬ifier, base::string16());
1118 }
1119
PopulateFlashLSOInfo(LocalDataContainer * container)1120 void CookiesTreeModel::PopulateFlashLSOInfo(
1121 LocalDataContainer* container) {
1122 ScopedBatchUpdateNotifier notifier(this, GetRoot());
1123 PopulateFlashLSOInfoWithFilter(container, ¬ifier, base::string16());
1124 }
1125
PopulateAppCacheInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)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());
1133
1134 if (container->appcache_info_.empty())
1135 return;
1136
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();
1146
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));
1151 }
1152 }
1153 }
1154 }
1155
PopulateCookieInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1156 void CookiesTreeModel::PopulateCookieInfoWithFilter(
1157 LocalDataContainer* container,
1158 ScopedBatchUpdateNotifier* notifier,
1159 const base::string16& filter) {
1160 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1161
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);
1170
1171 // We treat secure cookies just the same as normal ones.
1172 source_string = std::string(url::kHttpScheme) +
1173 url::kStandardSchemeSeparator + domain + "/";
1174 }
1175
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);
1184 }
1185 }
1186 }
1187
PopulateDatabaseInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1188 void CookiesTreeModel::PopulateDatabaseInfoWithFilter(
1189 LocalDataContainer* container,
1190 ScopedBatchUpdateNotifier* notifier,
1191 const base::string16& filter) {
1192 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1193
1194 if (container->database_info_list_.empty())
1195 return;
1196
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());
1203
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));
1211 }
1212 }
1213 }
1214
PopulateLocalStorageInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1215 void CookiesTreeModel::PopulateLocalStorageInfoWithFilter(
1216 LocalDataContainer* container,
1217 ScopedBatchUpdateNotifier* notifier,
1218 const base::string16& filter) {
1219 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1220
1221 if (container->local_storage_info_list_.empty())
1222 return;
1223
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);
1230
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));
1238 }
1239 }
1240 }
1241
PopulateSessionStorageInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1242 void CookiesTreeModel::PopulateSessionStorageInfoWithFilter(
1243 LocalDataContainer* container,
1244 ScopedBatchUpdateNotifier* notifier,
1245 const base::string16& filter) {
1246 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1247
1248 if (container->session_storage_info_list_.empty())
1249 return;
1250
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;
1257
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));
1265 }
1266 }
1267 }
1268
PopulateIndexedDBInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1269 void CookiesTreeModel::PopulateIndexedDBInfoWithFilter(
1270 LocalDataContainer* container,
1271 ScopedBatchUpdateNotifier* notifier,
1272 const base::string16& filter) {
1273 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1274
1275 if (container->indexed_db_info_list_.empty())
1276 return;
1277
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_;
1284
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));
1292 }
1293 }
1294 }
1295
PopulateChannelIDInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1296 void CookiesTreeModel::PopulateChannelIDInfoWithFilter(
1297 LocalDataContainer* container,
1298 ScopedBatchUpdateNotifier* notifier,
1299 const base::string16& filter) {
1300 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1301
1302 if (container->channel_id_list_.empty())
1303 return;
1304
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() + "/");
1317 }
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));
1325 }
1326 }
1327 }
1328
PopulateServiceWorkerUsageInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1329 void CookiesTreeModel::PopulateServiceWorkerUsageInfoWithFilter(
1330 LocalDataContainer* container,
1331 ScopedBatchUpdateNotifier* notifier,
1332 const base::string16& filter) {
1333 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1334
1335 if (container->service_worker_info_list_.empty())
1336 return;
1337
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;
1344
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));
1352 }
1353 }
1354 }
1355
PopulateFileSystemInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1356 void CookiesTreeModel::PopulateFileSystemInfoWithFilter(
1357 LocalDataContainer* container,
1358 ScopedBatchUpdateNotifier* notifier,
1359 const base::string16& filter) {
1360 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1361
1362 if (container->file_system_info_list_.empty())
1363 return;
1364
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);
1371
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));
1379 }
1380 }
1381 }
1382
PopulateQuotaInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1383 void CookiesTreeModel::PopulateQuotaInfoWithFilter(
1384 LocalDataContainer* container,
1385 ScopedBatchUpdateNotifier* notifier,
1386 const base::string16& filter) {
1387 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1388
1389 if (container->quota_info_list_.empty())
1390 return;
1391
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);
1401 }
1402 }
1403 }
1404
PopulateFlashLSOInfoWithFilter(LocalDataContainer * container,ScopedBatchUpdateNotifier * notifier,const base::string16 & filter)1405 void CookiesTreeModel::PopulateFlashLSOInfoWithFilter(
1406 LocalDataContainer* container,
1407 ScopedBatchUpdateNotifier* notifier,
1408 const base::string16& filter) {
1409 CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
1410
1411 if (container->flash_lso_domain_list_.empty())
1412 return;
1413
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);
1424 }
1425 }
1426 }
1427
NotifyObserverBeginBatch()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));
1434 }
1435 }
1436
NotifyObserverEndBatch()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));
1444 }
1445 }
1446