• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/cookies_tree_model.h"
6 
7 #include <algorithm>
8 #include <functional>
9 #include <vector>
10 
11 #include "base/callback.h"
12 #include "base/memory/linked_ptr.h"
13 #include "base/string_util.h"
14 #include "base/utf_string_conversions.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "content/browser/in_process_webkit/webkit_context.h"
17 #include "grit/app_resources.h"
18 #include "grit/generated_resources.h"
19 #include "grit/theme_resources.h"
20 #include "net/base/cookie_monster.h"
21 #include "net/base/registry_controlled_domain.h"
22 #include "net/url_request/url_request_context.h"
23 #include "third_party/skia/include/core/SkBitmap.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/base/resource/resource_bundle.h"
26 
27 static const char kFileOriginNodeName[] = "file://";
28 
29 ///////////////////////////////////////////////////////////////////////////////
30 // CookieTreeNode, public:
31 
DeleteStoredObjects()32 void CookieTreeNode::DeleteStoredObjects() {
33   std::for_each(children().begin(),
34                 children().end(),
35                 std::mem_fun(&CookieTreeNode::DeleteStoredObjects));
36 }
37 
GetModel() const38 CookiesTreeModel* CookieTreeNode::GetModel() const {
39   if (parent())
40     return parent()->GetModel();
41   else
42     return NULL;
43 }
44 
45 ///////////////////////////////////////////////////////////////////////////////
46 // CookieTreeCookieNode, public:
47 
CookieTreeCookieNode(net::CookieMonster::CanonicalCookie * cookie)48 CookieTreeCookieNode::CookieTreeCookieNode(
49     net::CookieMonster::CanonicalCookie* cookie)
50     : CookieTreeNode(UTF8ToUTF16(cookie->Name())),
51       cookie_(cookie) {
52 }
53 
~CookieTreeCookieNode()54 CookieTreeCookieNode::~CookieTreeCookieNode() {}
55 
DeleteStoredObjects()56 void CookieTreeCookieNode::DeleteStoredObjects() {
57   // notify CookieMonster that we should delete this cookie
58   // We have stored a copy of all the cookies in the model, and our model is
59   // never re-calculated. Thus, we just need to delete the nodes from our
60   // model, and tell CookieMonster to delete the cookies. We can keep the
61   // vector storing the cookies in-tact and not delete from there (that would
62   // invalidate our pointers), and the fact that it contains semi out-of-date
63   // data is not problematic as we don't re-build the model based on that.
64   GetModel()->cookie_monster_->DeleteCanonicalCookie(*cookie_);
65 }
66 
GetDetailedInfo() const67 CookieTreeNode::DetailedInfo CookieTreeCookieNode::GetDetailedInfo() const {
68   return DetailedInfo(parent()->parent()->GetTitle(),
69                       DetailedInfo::TYPE_COOKIE,
70                       cookie_, NULL, NULL, NULL, NULL, NULL);
71 }
72 
73 namespace {
74 // comparison functor, for use in CookieTreeRootNode
75 class OriginNodeComparator {
76  public:
operator ()(const CookieTreeNode * lhs,const CookieTreeNode * rhs)77   bool operator() (const CookieTreeNode* lhs,
78                    const CookieTreeNode* rhs) {
79     // We want to order by registry controlled domain, so we would get
80     // google.com, ad.google.com, www.google.com,
81     // microsoft.com, ad.microsoft.com. CanonicalizeHost transforms the origins
82     // into a form like google.com.www so that string comparisons work.
83     return (CanonicalizeHost(lhs->GetTitle()) <
84             CanonicalizeHost(rhs->GetTitle()));
85   }
86 
87  private:
CanonicalizeHost(const string16 & host16)88   static std::string CanonicalizeHost(const string16& host16) {
89     // The canonicalized representation makes the registry controlled domain
90     // come first, and then adds subdomains in reverse order, e.g.
91     // 1.mail.google.com would become google.com.mail.1, and then a standard
92     // string comparison works to order hosts by registry controlled domain
93     // first. Leading dots are ignored, ".google.com" is the same as
94     // "google.com".
95 
96     std::string host = UTF16ToUTF8(host16);
97     std::string retval = net::RegistryControlledDomainService::
98         GetDomainAndRegistry(host);
99     if (!retval.length())  // Is an IP address or other special origin.
100       return host;
101 
102     std::string::size_type position = host.rfind(retval);
103 
104     // The host may be the registry controlled domain, in which case fail fast.
105     if (position == 0 || position == std::string::npos)
106       return host;
107 
108     // If host is www.google.com, retval will contain google.com at this point.
109     // Start operating to the left of the registry controlled domain, e.g. in
110     // the www.google.com example, start at index 3.
111     --position;
112 
113     // If position == 0, that means it's a dot; this will be ignored to treat
114     // ".google.com" the same as "google.com".
115     while (position > 0) {
116       retval += std::string(".");
117       // Copy up to the next dot. host[position] is a dot so start after it.
118       std::string::size_type next_dot = host.rfind(".", position - 1);
119       if (next_dot == std::string::npos) {
120         retval += host.substr(0, position);
121         break;
122       }
123       retval += host.substr(next_dot + 1, position - (next_dot + 1));
124       position = next_dot;
125     }
126     return retval;
127   }
128 };
129 
130 }  // namespace
131 
132 ///////////////////////////////////////////////////////////////////////////////
133 // CookieTreeAppCacheNode, public:
134 
CookieTreeAppCacheNode(const appcache::AppCacheInfo * appcache_info)135 CookieTreeAppCacheNode::CookieTreeAppCacheNode(
136     const appcache::AppCacheInfo* appcache_info)
137     : CookieTreeNode(UTF8ToUTF16(appcache_info->manifest_url.spec())),
138       appcache_info_(appcache_info) {
139 }
140 
DeleteStoredObjects()141 void CookieTreeAppCacheNode::DeleteStoredObjects() {
142   DCHECK(GetModel()->appcache_helper_);
143   GetModel()->appcache_helper_->DeleteAppCacheGroup(
144       appcache_info_->manifest_url);
145 }
146 
GetDetailedInfo() const147 CookieTreeNode::DetailedInfo CookieTreeAppCacheNode::GetDetailedInfo() const {
148   return DetailedInfo(parent()->parent()->GetTitle(),
149                       DetailedInfo::TYPE_APPCACHE,
150                       NULL, NULL, NULL, NULL, appcache_info_, NULL);
151 }
152 
153 ///////////////////////////////////////////////////////////////////////////////
154 // CookieTreeDatabaseNode, public:
155 
CookieTreeDatabaseNode(BrowsingDataDatabaseHelper::DatabaseInfo * database_info)156 CookieTreeDatabaseNode::CookieTreeDatabaseNode(
157     BrowsingDataDatabaseHelper::DatabaseInfo* database_info)
158     : CookieTreeNode(database_info->database_name.empty() ?
159           l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME) :
160           UTF8ToUTF16(database_info->database_name)),
161       database_info_(database_info) {
162 }
163 
~CookieTreeDatabaseNode()164 CookieTreeDatabaseNode::~CookieTreeDatabaseNode() {}
165 
DeleteStoredObjects()166 void CookieTreeDatabaseNode::DeleteStoredObjects() {
167   GetModel()->database_helper_->DeleteDatabase(
168       database_info_->origin_identifier, database_info_->database_name);
169 }
170 
GetDetailedInfo() const171 CookieTreeNode::DetailedInfo CookieTreeDatabaseNode::GetDetailedInfo() const {
172   return DetailedInfo(parent()->parent()->GetTitle(),
173                       DetailedInfo::TYPE_DATABASE,
174                       NULL, database_info_, NULL, NULL, NULL, NULL);
175 }
176 
177 ///////////////////////////////////////////////////////////////////////////////
178 // CookieTreeLocalStorageNode, public:
179 
CookieTreeLocalStorageNode(BrowsingDataLocalStorageHelper::LocalStorageInfo * local_storage_info)180 CookieTreeLocalStorageNode::CookieTreeLocalStorageNode(
181     BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info)
182     : CookieTreeNode(UTF8ToUTF16(
183           local_storage_info->origin.empty() ?
184               local_storage_info->database_identifier :
185               local_storage_info->origin)),
186       local_storage_info_(local_storage_info) {
187 }
188 
~CookieTreeLocalStorageNode()189 CookieTreeLocalStorageNode::~CookieTreeLocalStorageNode() {}
190 
DeleteStoredObjects()191 void CookieTreeLocalStorageNode::DeleteStoredObjects() {
192   GetModel()->local_storage_helper_->DeleteLocalStorageFile(
193       local_storage_info_->file_path);
194 }
195 
196 CookieTreeNode::DetailedInfo
GetDetailedInfo() const197 CookieTreeLocalStorageNode::GetDetailedInfo() const {
198   return DetailedInfo(parent()->parent()->GetTitle(),
199                       DetailedInfo::TYPE_LOCAL_STORAGE,
200                       NULL, NULL, local_storage_info_, NULL, NULL, NULL);
201 }
202 
203 ///////////////////////////////////////////////////////////////////////////////
204 // CookieTreeSessionStorageNode, public:
205 
CookieTreeSessionStorageNode(BrowsingDataLocalStorageHelper::LocalStorageInfo * session_storage_info)206 CookieTreeSessionStorageNode::CookieTreeSessionStorageNode(
207     BrowsingDataLocalStorageHelper::LocalStorageInfo* session_storage_info)
208     : CookieTreeNode(UTF8ToUTF16(
209           session_storage_info->origin.empty() ?
210               session_storage_info->database_identifier :
211               session_storage_info->origin)),
212       session_storage_info_(session_storage_info) {
213 }
214 
~CookieTreeSessionStorageNode()215 CookieTreeSessionStorageNode::~CookieTreeSessionStorageNode() {}
216 
217 CookieTreeNode::DetailedInfo
GetDetailedInfo() const218 CookieTreeSessionStorageNode::GetDetailedInfo() const {
219   return DetailedInfo(parent()->parent()->GetTitle(),
220                       DetailedInfo::TYPE_SESSION_STORAGE,
221                       NULL, NULL, NULL, session_storage_info_, NULL, NULL);
222 }
223 
224 ///////////////////////////////////////////////////////////////////////////////
225 // CookieTreeIndexedDBNode, public:
226 
CookieTreeIndexedDBNode(BrowsingDataIndexedDBHelper::IndexedDBInfo * indexed_db_info)227 CookieTreeIndexedDBNode::CookieTreeIndexedDBNode(
228     BrowsingDataIndexedDBHelper::IndexedDBInfo* indexed_db_info)
229     : CookieTreeNode(UTF8ToUTF16(
230           indexed_db_info->origin.empty() ?
231               indexed_db_info->database_identifier :
232               indexed_db_info->origin)),
233       indexed_db_info_(indexed_db_info) {
234 }
235 
~CookieTreeIndexedDBNode()236 CookieTreeIndexedDBNode::~CookieTreeIndexedDBNode() {}
237 
DeleteStoredObjects()238 void CookieTreeIndexedDBNode::DeleteStoredObjects() {
239   GetModel()->indexed_db_helper_->DeleteIndexedDBFile(
240       indexed_db_info_->file_path);
241 }
242 
GetDetailedInfo() const243 CookieTreeNode::DetailedInfo CookieTreeIndexedDBNode::GetDetailedInfo() const {
244   return DetailedInfo(parent()->parent()->GetTitle(),
245                       DetailedInfo::TYPE_INDEXED_DB,
246                       NULL, NULL, NULL, NULL, NULL, indexed_db_info_);
247 }
248 
249 ///////////////////////////////////////////////////////////////////////////////
250 // CookieTreeRootNode, public:
251 
CookieTreeRootNode(CookiesTreeModel * model)252 CookieTreeRootNode::CookieTreeRootNode(CookiesTreeModel* model)
253     : model_(model) {
254 }
255 
~CookieTreeRootNode()256 CookieTreeRootNode::~CookieTreeRootNode() {}
257 
GetOrCreateOriginNode(const GURL & url)258 CookieTreeOriginNode* CookieTreeRootNode::GetOrCreateOriginNode(
259     const GURL& url) {
260   CookieTreeOriginNode origin_node(url);
261 
262   // First see if there is an existing match.
263   std::vector<CookieTreeNode*>::iterator origin_node_iterator =
264       lower_bound(children().begin(),
265                   children().end(),
266                   &origin_node,
267                   OriginNodeComparator());
268 
269   if (origin_node_iterator != children().end() &&
270       WideToUTF16Hack(CookieTreeOriginNode::TitleForUrl(url)) ==
271       (*origin_node_iterator)->GetTitle())
272     return static_cast<CookieTreeOriginNode*>(*origin_node_iterator);
273   // Node doesn't exist, create a new one and insert it into the (ordered)
274   // children.
275   CookieTreeOriginNode* retval = new CookieTreeOriginNode(url);
276   DCHECK(model_);
277   model_->Add(this, retval, (origin_node_iterator - children().begin()));
278   return retval;
279 }
280 
GetModel() const281 CookiesTreeModel* CookieTreeRootNode::GetModel() const {
282   return model_;
283 }
284 
GetDetailedInfo() const285 CookieTreeNode::DetailedInfo CookieTreeRootNode::GetDetailedInfo() const {
286   return DetailedInfo(string16(),
287                       DetailedInfo::TYPE_ROOT,
288                       NULL, NULL, NULL, NULL, NULL, NULL);
289 }
290 
291 ///////////////////////////////////////////////////////////////////////////////
292 // CookieTreeOriginNode, public:
293 
294 // static
TitleForUrl(const GURL & url)295 std::wstring CookieTreeOriginNode::TitleForUrl(
296     const GURL& url) {
297   return UTF8ToWide(url.SchemeIsFile() ? kFileOriginNodeName : url.host());
298 }
299 
CookieTreeOriginNode(const GURL & url)300 CookieTreeOriginNode::CookieTreeOriginNode(const GURL& url)
301     : CookieTreeNode(WideToUTF16Hack(TitleForUrl(url))),
302       cookies_child_(NULL),
303       databases_child_(NULL),
304       local_storages_child_(NULL),
305       session_storages_child_(NULL),
306       appcaches_child_(NULL),
307       indexed_dbs_child_(NULL),
308       url_(url) {}
309 
~CookieTreeOriginNode()310 CookieTreeOriginNode::~CookieTreeOriginNode() {}
311 
GetDetailedInfo() const312 CookieTreeNode::DetailedInfo CookieTreeOriginNode::GetDetailedInfo() const {
313   return DetailedInfo(GetTitle(),
314                       DetailedInfo::TYPE_ORIGIN,
315                       NULL, NULL, NULL, NULL, NULL, NULL);
316 }
317 
GetOrCreateCookiesNode()318 CookieTreeCookiesNode* CookieTreeOriginNode::GetOrCreateCookiesNode() {
319   if (cookies_child_)
320     return cookies_child_;
321   cookies_child_ = new CookieTreeCookiesNode;
322   AddChildSortedByTitle(cookies_child_);
323   return cookies_child_;
324 }
325 
GetOrCreateDatabasesNode()326 CookieTreeDatabasesNode* CookieTreeOriginNode::GetOrCreateDatabasesNode() {
327   if (databases_child_)
328     return databases_child_;
329   databases_child_ = new CookieTreeDatabasesNode;
330   AddChildSortedByTitle(databases_child_);
331   return databases_child_;
332 }
333 
334 CookieTreeLocalStoragesNode*
GetOrCreateLocalStoragesNode()335     CookieTreeOriginNode::GetOrCreateLocalStoragesNode() {
336   if (local_storages_child_)
337     return local_storages_child_;
338   local_storages_child_ = new CookieTreeLocalStoragesNode;
339   AddChildSortedByTitle(local_storages_child_);
340   return local_storages_child_;
341 }
342 
343 CookieTreeSessionStoragesNode*
GetOrCreateSessionStoragesNode()344     CookieTreeOriginNode::GetOrCreateSessionStoragesNode() {
345   if (session_storages_child_)
346     return session_storages_child_;
347   session_storages_child_ = new CookieTreeSessionStoragesNode;
348   AddChildSortedByTitle(session_storages_child_);
349   return session_storages_child_;
350 }
351 
GetOrCreateAppCachesNode()352 CookieTreeAppCachesNode* CookieTreeOriginNode::GetOrCreateAppCachesNode() {
353   if (appcaches_child_)
354     return appcaches_child_;
355   appcaches_child_ = new CookieTreeAppCachesNode;
356   AddChildSortedByTitle(appcaches_child_);
357   return appcaches_child_;
358 }
359 
GetOrCreateIndexedDBsNode()360 CookieTreeIndexedDBsNode* CookieTreeOriginNode::GetOrCreateIndexedDBsNode() {
361   if (indexed_dbs_child_)
362     return indexed_dbs_child_;
363   indexed_dbs_child_ = new CookieTreeIndexedDBsNode;
364   AddChildSortedByTitle(indexed_dbs_child_);
365   return indexed_dbs_child_;
366 }
367 
CreateContentException(HostContentSettingsMap * content_settings,ContentSetting setting) const368 void CookieTreeOriginNode::CreateContentException(
369     HostContentSettingsMap* content_settings, ContentSetting setting) const {
370   if (CanCreateContentException()) {
371     content_settings->AddExceptionForURL(url_,
372                                          CONTENT_SETTINGS_TYPE_COOKIES,
373                                          "",
374                                          setting);
375   }
376 }
377 
CanCreateContentException() const378 bool CookieTreeOriginNode::CanCreateContentException() const {
379   return !url_.SchemeIsFile();
380 }
381 
382 ///////////////////////////////////////////////////////////////////////////////
383 // CookieTreeCookiesNode, public:
384 
CookieTreeCookiesNode()385 CookieTreeCookiesNode::CookieTreeCookiesNode()
386     : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIES)) {
387 }
388 
~CookieTreeCookiesNode()389 CookieTreeCookiesNode::~CookieTreeCookiesNode() {
390 }
391 
GetDetailedInfo() const392 CookieTreeNode::DetailedInfo CookieTreeCookiesNode::GetDetailedInfo() const {
393   return DetailedInfo(parent()->GetTitle(),
394                       DetailedInfo::TYPE_COOKIES,
395                       NULL, NULL, NULL, NULL, NULL, NULL);
396 }
397 
398 ///////////////////////////////////////////////////////////////////////////////
399 // CookieTreeAppCachesNode, public:
400 
CookieTreeAppCachesNode()401 CookieTreeAppCachesNode::CookieTreeAppCachesNode()
402     : CookieTreeNode(l10n_util::GetStringUTF16(
403                          IDS_COOKIES_APPLICATION_CACHES)) {
404 }
405 
~CookieTreeAppCachesNode()406 CookieTreeAppCachesNode::~CookieTreeAppCachesNode() {}
407 
GetDetailedInfo() const408 CookieTreeNode::DetailedInfo CookieTreeAppCachesNode::GetDetailedInfo() const {
409   return DetailedInfo(parent()->GetTitle(),
410                       DetailedInfo::TYPE_APPCACHES,
411                       NULL, NULL, NULL, NULL, NULL, NULL);
412 }
413 
414 ///////////////////////////////////////////////////////////////////////////////
415 // CookieTreeDatabasesNode, public:
416 
CookieTreeDatabasesNode()417 CookieTreeDatabasesNode::CookieTreeDatabasesNode()
418     : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASES)) {
419 }
420 
~CookieTreeDatabasesNode()421 CookieTreeDatabasesNode::~CookieTreeDatabasesNode() {}
422 
GetDetailedInfo() const423 CookieTreeNode::DetailedInfo CookieTreeDatabasesNode::GetDetailedInfo() const {
424   return DetailedInfo(parent()->GetTitle(),
425                       DetailedInfo::TYPE_DATABASES,
426                       NULL, NULL, NULL, NULL, NULL, NULL);
427 }
428 
429 ///////////////////////////////////////////////////////////////////////////////
430 // CookieTreeLocalStoragesNode, public:
431 
CookieTreeLocalStoragesNode()432 CookieTreeLocalStoragesNode::CookieTreeLocalStoragesNode()
433     : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_LOCAL_STORAGE)) {
434 }
435 
~CookieTreeLocalStoragesNode()436 CookieTreeLocalStoragesNode::~CookieTreeLocalStoragesNode() {}
437 
438 CookieTreeNode::DetailedInfo
GetDetailedInfo() const439 CookieTreeLocalStoragesNode::GetDetailedInfo() const {
440   return DetailedInfo(parent()->GetTitle(),
441                       DetailedInfo::TYPE_LOCAL_STORAGES,
442                       NULL, NULL, NULL, NULL, NULL, NULL);
443 }
444 
445 ///////////////////////////////////////////////////////////////////////////////
446 // CookieTreeSessionStoragesNode, public:
447 
CookieTreeSessionStoragesNode()448 CookieTreeSessionStoragesNode::CookieTreeSessionStoragesNode()
449     : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SESSION_STORAGE)) {
450 }
451 
~CookieTreeSessionStoragesNode()452 CookieTreeSessionStoragesNode::~CookieTreeSessionStoragesNode() {}
453 
454 CookieTreeNode::DetailedInfo
GetDetailedInfo() const455 CookieTreeSessionStoragesNode::GetDetailedInfo() const {
456   return DetailedInfo(parent()->GetTitle(),
457                       DetailedInfo::TYPE_SESSION_STORAGES,
458                       NULL, NULL, NULL, NULL, NULL, NULL);
459 }
460 
461 ///////////////////////////////////////////////////////////////////////////////
462 // CookieTreeIndexedDBsNode, public:
463 
CookieTreeIndexedDBsNode()464 CookieTreeIndexedDBsNode::CookieTreeIndexedDBsNode()
465     : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_INDEXED_DBS)) {
466 }
467 
~CookieTreeIndexedDBsNode()468 CookieTreeIndexedDBsNode::~CookieTreeIndexedDBsNode() {}
469 
470 CookieTreeNode::DetailedInfo
GetDetailedInfo() const471 CookieTreeIndexedDBsNode::GetDetailedInfo() const {
472   return DetailedInfo(parent()->GetTitle(),
473                       DetailedInfo::TYPE_INDEXED_DBS,
474                       NULL, NULL, NULL, NULL, NULL, NULL);
475 }
476 
477 ///////////////////////////////////////////////////////////////////////////////
478 // CookieTreeNode, protected
479 
operator ()(const CookieTreeNode * lhs,const CookieTreeNode * rhs)480 bool CookieTreeNode::NodeTitleComparator::operator() (
481     const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
482   const CookieTreeNode* left =
483       static_cast<const CookieTreeNode*>(lhs);
484   const CookieTreeNode* right =
485       static_cast<const CookieTreeNode*>(rhs);
486   return (left->GetTitle() < right->GetTitle());
487 }
488 
AddChildSortedByTitle(CookieTreeNode * new_child)489 void CookieTreeNode::AddChildSortedByTitle(CookieTreeNode* new_child) {
490   std::vector<CookieTreeNode*>::iterator iter =
491       lower_bound(children().begin(),
492                   children().end(),
493                   new_child,
494                   NodeTitleComparator());
495   GetModel()->Add(this, new_child, iter - children().begin());
496 }
497 
498 ///////////////////////////////////////////////////////////////////////////////
499 // CookiesTreeModel, public:
500 
CookiesTreeModel(net::CookieMonster * cookie_monster,BrowsingDataDatabaseHelper * database_helper,BrowsingDataLocalStorageHelper * local_storage_helper,BrowsingDataLocalStorageHelper * session_storage_helper,BrowsingDataAppCacheHelper * appcache_helper,BrowsingDataIndexedDBHelper * indexed_db_helper,bool use_cookie_source)501 CookiesTreeModel::CookiesTreeModel(
502     net::CookieMonster* cookie_monster,
503     BrowsingDataDatabaseHelper* database_helper,
504     BrowsingDataLocalStorageHelper* local_storage_helper,
505     BrowsingDataLocalStorageHelper* session_storage_helper,
506     BrowsingDataAppCacheHelper* appcache_helper,
507     BrowsingDataIndexedDBHelper* indexed_db_helper,
508     bool use_cookie_source)
509     : ALLOW_THIS_IN_INITIALIZER_LIST(ui::TreeNodeModel<CookieTreeNode>(
510           new CookieTreeRootNode(this))),
511       cookie_monster_(cookie_monster),
512       appcache_helper_(appcache_helper),
513       database_helper_(database_helper),
514       local_storage_helper_(local_storage_helper),
515       session_storage_helper_(session_storage_helper),
516       indexed_db_helper_(indexed_db_helper),
517       batch_update_(0),
518       use_cookie_source_(use_cookie_source) {
519   LoadCookies();
520   DCHECK(database_helper_);
521   database_helper_->StartFetching(NewCallback(
522       this, &CookiesTreeModel::OnDatabaseModelInfoLoaded));
523   DCHECK(local_storage_helper_);
524   local_storage_helper_->StartFetching(NewCallback(
525       this, &CookiesTreeModel::OnLocalStorageModelInfoLoaded));
526   if (session_storage_helper_) {
527     session_storage_helper_->StartFetching(NewCallback(
528         this, &CookiesTreeModel::OnSessionStorageModelInfoLoaded));
529   }
530 
531   // TODO(michaeln): when all of the ui impls have been updated,
532   // make this a required parameter.
533   if (appcache_helper_) {
534     appcache_helper_->StartFetching(NewCallback(
535         this, &CookiesTreeModel::OnAppCacheModelInfoLoaded));
536   }
537 
538   if (indexed_db_helper_) {
539     indexed_db_helper_->StartFetching(NewCallback(
540         this, &CookiesTreeModel::OnIndexedDBModelInfoLoaded));
541   }
542 }
543 
~CookiesTreeModel()544 CookiesTreeModel::~CookiesTreeModel() {
545   database_helper_->CancelNotification();
546   local_storage_helper_->CancelNotification();
547   if (session_storage_helper_)
548     session_storage_helper_->CancelNotification();
549   if (appcache_helper_)
550     appcache_helper_->CancelNotification();
551   if (indexed_db_helper_)
552     indexed_db_helper_->CancelNotification();
553 }
554 
555 ///////////////////////////////////////////////////////////////////////////////
556 // CookiesTreeModel, TreeModel methods (public):
557 
558 // TreeModel methods:
559 // Returns the set of icons for the nodes in the tree. You only need override
560 // this if you don't want to use the default folder icons.
GetIcons(std::vector<SkBitmap> * icons)561 void CookiesTreeModel::GetIcons(std::vector<SkBitmap>* icons) {
562   icons->push_back(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
563       IDR_OMNIBOX_HTTP));
564   icons->push_back(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
565       IDR_COOKIE_ICON));
566   icons->push_back(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
567       IDR_COOKIE_STORAGE_ICON));
568 }
569 
570 // Returns the index of the icon to use for |node|. Return -1 to use the
571 // default icon. The index is relative to the list of icons returned from
572 // GetIcons.
GetIconIndex(ui::TreeModelNode * node)573 int CookiesTreeModel::GetIconIndex(ui::TreeModelNode* node) {
574   CookieTreeNode* ct_node = static_cast<CookieTreeNode*>(node);
575   switch (ct_node->GetDetailedInfo().node_type) {
576     case CookieTreeNode::DetailedInfo::TYPE_ORIGIN:
577       return ORIGIN;
578     case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
579       return COOKIE;
580     case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
581       return DATABASE;
582     case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
583       return DATABASE;  // close enough
584     case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
585       return DATABASE;  // ditto
586     case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
587       return DATABASE;  // ditto
588     case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
589       return DATABASE;  // ditto
590     default:
591       break;
592   }
593   return -1;
594 }
595 
LoadCookies()596 void CookiesTreeModel::LoadCookies() {
597   LoadCookiesWithFilter(std::wstring());
598 }
599 
LoadCookiesWithFilter(const std::wstring & filter)600 void CookiesTreeModel::LoadCookiesWithFilter(const std::wstring& filter) {
601   // mmargh mmargh mmargh! delicious!
602 
603   all_cookies_ = cookie_monster_->GetAllCookies();
604   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
605   for (CookieList::iterator it = all_cookies_.begin();
606        it != all_cookies_.end(); ++it) {
607     std::string source_string = it->Source();
608     if (source_string.empty() || !use_cookie_source_) {
609       std::string domain = it->Domain();
610       if (domain.length() > 1 && domain[0] == '.')
611         domain = domain.substr(1);
612 
613       // We treat secure cookies just the same as normal ones.
614       source_string = std::string(chrome::kHttpScheme) +
615           chrome::kStandardSchemeSeparator + domain + "/";
616     }
617 
618     GURL source(source_string);
619     if (!filter.size() ||
620         (CookieTreeOriginNode::TitleForUrl(source).find(filter) !=
621          std::string::npos)) {
622       CookieTreeOriginNode* origin_node =
623           root->GetOrCreateOriginNode(source);
624       CookieTreeCookiesNode* cookies_node =
625           origin_node->GetOrCreateCookiesNode();
626       CookieTreeCookieNode* new_cookie = new CookieTreeCookieNode(&*it);
627       cookies_node->AddCookieNode(new_cookie);
628     }
629   }
630 }
631 
DeleteAllStoredObjects()632 void CookiesTreeModel::DeleteAllStoredObjects() {
633   NotifyObserverBeginBatch();
634   CookieTreeNode* root = GetRoot();
635   root->DeleteStoredObjects();
636   int num_children = root->child_count();
637   for (int i = num_children - 1; i >= 0; --i)
638     delete Remove(root, root->GetChild(i));
639   NotifyObserverTreeNodeChanged(root);
640   NotifyObserverEndBatch();
641 }
642 
DeleteCookieNode(CookieTreeNode * cookie_node)643 void CookiesTreeModel::DeleteCookieNode(CookieTreeNode* cookie_node) {
644   if (cookie_node == GetRoot())
645     return;
646   cookie_node->DeleteStoredObjects();
647   CookieTreeNode* parent_node = cookie_node->parent();
648   delete Remove(parent_node, cookie_node);
649   if (parent_node->child_count() == 0)
650     DeleteCookieNode(parent_node);
651 }
652 
UpdateSearchResults(const std::wstring & filter)653 void CookiesTreeModel::UpdateSearchResults(const std::wstring& filter) {
654   CookieTreeNode* root = GetRoot();
655   int num_children = root->child_count();
656   NotifyObserverBeginBatch();
657   for (int i = num_children - 1; i >= 0; --i)
658     delete Remove(root, root->GetChild(i));
659   LoadCookiesWithFilter(filter);
660   PopulateDatabaseInfoWithFilter(filter);
661   PopulateLocalStorageInfoWithFilter(filter);
662   PopulateSessionStorageInfoWithFilter(filter);
663   PopulateAppCacheInfoWithFilter(filter);
664   PopulateIndexedDBInfoWithFilter(filter);
665   NotifyObserverTreeNodeChanged(root);
666   NotifyObserverEndBatch();
667 }
668 
AddCookiesTreeObserver(Observer * observer)669 void CookiesTreeModel::AddCookiesTreeObserver(Observer* observer) {
670   cookies_observer_list_.AddObserver(observer);
671   // Call super so that TreeNodeModel can notify, too.
672   ui::TreeNodeModel<CookieTreeNode>::AddObserver(observer);
673 }
674 
RemoveCookiesTreeObserver(Observer * observer)675 void CookiesTreeModel::RemoveCookiesTreeObserver(Observer* observer) {
676   cookies_observer_list_.RemoveObserver(observer);
677   // Call super so that TreeNodeModel doesn't have dead pointers.
678   ui::TreeNodeModel<CookieTreeNode>::RemoveObserver(observer);
679 }
680 
OnAppCacheModelInfoLoaded()681 void CookiesTreeModel::OnAppCacheModelInfoLoaded() {
682   appcache_info_ = appcache_helper_->info_collection();
683   PopulateAppCacheInfoWithFilter(std::wstring());
684 }
685 
PopulateAppCacheInfoWithFilter(const std::wstring & filter)686 void CookiesTreeModel::PopulateAppCacheInfoWithFilter(
687     const std::wstring& filter) {
688   using appcache::AppCacheInfo;
689   using appcache::AppCacheInfoVector;
690   typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin;
691 
692   if (!appcache_info_ || appcache_info_->infos_by_origin.empty())
693     return;
694 
695   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
696   NotifyObserverBeginBatch();
697   for (InfoByOrigin::const_iterator origin =
698            appcache_info_->infos_by_origin.begin();
699        origin != appcache_info_->infos_by_origin.end(); ++origin) {
700     std::wstring origin_node_name = UTF8ToWide(origin->first.host());
701     if (filter.empty() ||
702         (origin_node_name.find(filter) != std::wstring::npos)) {
703       CookieTreeOriginNode* origin_node =
704           root->GetOrCreateOriginNode(origin->first);
705       CookieTreeAppCachesNode* appcaches_node =
706           origin_node->GetOrCreateAppCachesNode();
707 
708       for (AppCacheInfoVector::const_iterator info = origin->second.begin();
709            info != origin->second.end(); ++info) {
710         appcaches_node->AddAppCacheNode(
711             new CookieTreeAppCacheNode(&(*info)));
712       }
713     }
714   }
715   NotifyObserverTreeNodeChanged(root);
716   NotifyObserverEndBatch();
717 }
718 
OnDatabaseModelInfoLoaded(const DatabaseInfoList & database_info)719 void CookiesTreeModel::OnDatabaseModelInfoLoaded(
720     const DatabaseInfoList& database_info) {
721   database_info_list_ = database_info;
722   PopulateDatabaseInfoWithFilter(std::wstring());
723 }
724 
PopulateDatabaseInfoWithFilter(const std::wstring & filter)725 void CookiesTreeModel::PopulateDatabaseInfoWithFilter(
726     const std::wstring& filter) {
727   if (database_info_list_.empty())
728     return;
729   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
730   NotifyObserverBeginBatch();
731   for (DatabaseInfoList::iterator database_info = database_info_list_.begin();
732        database_info != database_info_list_.end();
733        ++database_info) {
734     GURL origin(database_info->origin);
735 
736     if (!filter.size() ||
737         (CookieTreeOriginNode::TitleForUrl(origin).find(filter) !=
738          std::wstring::npos)) {
739       CookieTreeOriginNode* origin_node =
740           root->GetOrCreateOriginNode(origin);
741       CookieTreeDatabasesNode* databases_node =
742           origin_node->GetOrCreateDatabasesNode();
743       databases_node->AddDatabaseNode(
744           new CookieTreeDatabaseNode(&(*database_info)));
745     }
746   }
747   NotifyObserverTreeNodeChanged(root);
748   NotifyObserverEndBatch();
749 }
750 
OnLocalStorageModelInfoLoaded(const LocalStorageInfoList & local_storage_info)751 void CookiesTreeModel::OnLocalStorageModelInfoLoaded(
752     const LocalStorageInfoList& local_storage_info) {
753   local_storage_info_list_ = local_storage_info;
754   PopulateLocalStorageInfoWithFilter(std::wstring());
755 }
756 
PopulateLocalStorageInfoWithFilter(const std::wstring & filter)757 void CookiesTreeModel::PopulateLocalStorageInfoWithFilter(
758     const std::wstring& filter) {
759   if (local_storage_info_list_.empty())
760     return;
761   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
762   NotifyObserverBeginBatch();
763   for (LocalStorageInfoList::iterator local_storage_info =
764        local_storage_info_list_.begin();
765        local_storage_info != local_storage_info_list_.end();
766        ++local_storage_info) {
767     GURL origin(local_storage_info->origin);
768 
769     if (!filter.size() ||
770         (CookieTreeOriginNode::TitleForUrl(origin).find(filter) !=
771          std::wstring::npos)) {
772       CookieTreeOriginNode* origin_node =
773           root->GetOrCreateOriginNode(origin);
774       CookieTreeLocalStoragesNode* local_storages_node =
775           origin_node->GetOrCreateLocalStoragesNode();
776       local_storages_node->AddLocalStorageNode(
777           new CookieTreeLocalStorageNode(&(*local_storage_info)));
778     }
779   }
780   NotifyObserverTreeNodeChanged(root);
781   NotifyObserverEndBatch();
782 }
783 
OnSessionStorageModelInfoLoaded(const LocalStorageInfoList & session_storage_info)784 void CookiesTreeModel::OnSessionStorageModelInfoLoaded(
785     const LocalStorageInfoList& session_storage_info) {
786   session_storage_info_list_ = session_storage_info;
787   PopulateSessionStorageInfoWithFilter(std::wstring());
788 }
789 
PopulateSessionStorageInfoWithFilter(const std::wstring & filter)790 void CookiesTreeModel::PopulateSessionStorageInfoWithFilter(
791     const std::wstring& filter) {
792   if (session_storage_info_list_.empty())
793     return;
794   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
795   NotifyObserverBeginBatch();
796   for (LocalStorageInfoList::iterator session_storage_info =
797        session_storage_info_list_.begin();
798        session_storage_info != session_storage_info_list_.end();
799        ++session_storage_info) {
800     GURL origin(session_storage_info->origin);
801 
802     if (!filter.size() ||
803         (CookieTreeOriginNode::TitleForUrl(origin).find(filter) !=
804          std::wstring::npos)) {
805       CookieTreeOriginNode* origin_node =
806           root->GetOrCreateOriginNode(origin);
807       CookieTreeSessionStoragesNode* session_storages_node =
808           origin_node->GetOrCreateSessionStoragesNode();
809       session_storages_node->AddSessionStorageNode(
810           new CookieTreeSessionStorageNode(&(*session_storage_info)));
811     }
812   }
813   NotifyObserverTreeNodeChanged(root);
814   NotifyObserverEndBatch();
815 }
816 
OnIndexedDBModelInfoLoaded(const IndexedDBInfoList & indexed_db_info)817 void CookiesTreeModel::OnIndexedDBModelInfoLoaded(
818     const IndexedDBInfoList& indexed_db_info) {
819   indexed_db_info_list_ = indexed_db_info;
820   PopulateIndexedDBInfoWithFilter(std::wstring());
821 }
822 
PopulateIndexedDBInfoWithFilter(const std::wstring & filter)823 void CookiesTreeModel::PopulateIndexedDBInfoWithFilter(
824     const std::wstring& filter) {
825   if (indexed_db_info_list_.empty())
826     return;
827   CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
828   NotifyObserverBeginBatch();
829   for (IndexedDBInfoList::iterator indexed_db_info =
830        indexed_db_info_list_.begin();
831        indexed_db_info != indexed_db_info_list_.end();
832        ++indexed_db_info) {
833     GURL origin(indexed_db_info->origin);
834 
835     if (!filter.size() ||
836         (CookieTreeOriginNode::TitleForUrl(origin).find(filter) !=
837          std::wstring::npos)) {
838       CookieTreeOriginNode* origin_node =
839           root->GetOrCreateOriginNode(origin);
840       CookieTreeIndexedDBsNode* indexed_dbs_node =
841           origin_node->GetOrCreateIndexedDBsNode();
842       indexed_dbs_node->AddIndexedDBNode(
843           new CookieTreeIndexedDBNode(&(*indexed_db_info)));
844     }
845   }
846   NotifyObserverTreeNodeChanged(root);
847   NotifyObserverEndBatch();
848 }
849 
NotifyObserverBeginBatch()850 void CookiesTreeModel::NotifyObserverBeginBatch() {
851   // Only notify the model once if we're batching in a nested manner.
852   if (batch_update_++ == 0) {
853     FOR_EACH_OBSERVER(Observer,
854                       cookies_observer_list_,
855                       TreeModelBeginBatch(this));
856   }
857 }
858 
NotifyObserverEndBatch()859 void CookiesTreeModel::NotifyObserverEndBatch() {
860   // Only notify the observers if this is the outermost call to EndBatch() if
861   // called in a nested manner.
862   if (--batch_update_ == 0) {
863     FOR_EACH_OBSERVER(Observer,
864                       cookies_observer_list_,
865                       TreeModelEndBatch(this));
866   }
867 }
868