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 27static const char kFileOriginNodeName[] = "file://"; 28 29/////////////////////////////////////////////////////////////////////////////// 30// CookieTreeNode, public: 31 32void CookieTreeNode::DeleteStoredObjects() { 33 std::for_each(children().begin(), 34 children().end(), 35 std::mem_fun(&CookieTreeNode::DeleteStoredObjects)); 36} 37 38CookiesTreeModel* CookieTreeNode::GetModel() const { 39 if (parent()) 40 return parent()->GetModel(); 41 else 42 return NULL; 43} 44 45/////////////////////////////////////////////////////////////////////////////// 46// CookieTreeCookieNode, public: 47 48CookieTreeCookieNode::CookieTreeCookieNode( 49 net::CookieMonster::CanonicalCookie* cookie) 50 : CookieTreeNode(UTF8ToUTF16(cookie->Name())), 51 cookie_(cookie) { 52} 53 54CookieTreeCookieNode::~CookieTreeCookieNode() {} 55 56void 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 67CookieTreeNode::DetailedInfo CookieTreeCookieNode::GetDetailedInfo() const { 68 return DetailedInfo(parent()->parent()->GetTitle(), 69 DetailedInfo::TYPE_COOKIE, 70 cookie_, NULL, NULL, NULL, NULL, NULL); 71} 72 73namespace { 74// comparison functor, for use in CookieTreeRootNode 75class OriginNodeComparator { 76 public: 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: 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 135CookieTreeAppCacheNode::CookieTreeAppCacheNode( 136 const appcache::AppCacheInfo* appcache_info) 137 : CookieTreeNode(UTF8ToUTF16(appcache_info->manifest_url.spec())), 138 appcache_info_(appcache_info) { 139} 140 141void CookieTreeAppCacheNode::DeleteStoredObjects() { 142 DCHECK(GetModel()->appcache_helper_); 143 GetModel()->appcache_helper_->DeleteAppCacheGroup( 144 appcache_info_->manifest_url); 145} 146 147CookieTreeNode::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 156CookieTreeDatabaseNode::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 164CookieTreeDatabaseNode::~CookieTreeDatabaseNode() {} 165 166void CookieTreeDatabaseNode::DeleteStoredObjects() { 167 GetModel()->database_helper_->DeleteDatabase( 168 database_info_->origin_identifier, database_info_->database_name); 169} 170 171CookieTreeNode::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 180CookieTreeLocalStorageNode::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 189CookieTreeLocalStorageNode::~CookieTreeLocalStorageNode() {} 190 191void CookieTreeLocalStorageNode::DeleteStoredObjects() { 192 GetModel()->local_storage_helper_->DeleteLocalStorageFile( 193 local_storage_info_->file_path); 194} 195 196CookieTreeNode::DetailedInfo 197CookieTreeLocalStorageNode::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 206CookieTreeSessionStorageNode::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 215CookieTreeSessionStorageNode::~CookieTreeSessionStorageNode() {} 216 217CookieTreeNode::DetailedInfo 218CookieTreeSessionStorageNode::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 227CookieTreeIndexedDBNode::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 236CookieTreeIndexedDBNode::~CookieTreeIndexedDBNode() {} 237 238void CookieTreeIndexedDBNode::DeleteStoredObjects() { 239 GetModel()->indexed_db_helper_->DeleteIndexedDBFile( 240 indexed_db_info_->file_path); 241} 242 243CookieTreeNode::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 252CookieTreeRootNode::CookieTreeRootNode(CookiesTreeModel* model) 253 : model_(model) { 254} 255 256CookieTreeRootNode::~CookieTreeRootNode() {} 257 258CookieTreeOriginNode* 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 281CookiesTreeModel* CookieTreeRootNode::GetModel() const { 282 return model_; 283} 284 285CookieTreeNode::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 295std::wstring CookieTreeOriginNode::TitleForUrl( 296 const GURL& url) { 297 return UTF8ToWide(url.SchemeIsFile() ? kFileOriginNodeName : url.host()); 298} 299 300CookieTreeOriginNode::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 310CookieTreeOriginNode::~CookieTreeOriginNode() {} 311 312CookieTreeNode::DetailedInfo CookieTreeOriginNode::GetDetailedInfo() const { 313 return DetailedInfo(GetTitle(), 314 DetailedInfo::TYPE_ORIGIN, 315 NULL, NULL, NULL, NULL, NULL, NULL); 316} 317 318CookieTreeCookiesNode* 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 326CookieTreeDatabasesNode* 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 334CookieTreeLocalStoragesNode* 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 343CookieTreeSessionStoragesNode* 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 352CookieTreeAppCachesNode* 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 360CookieTreeIndexedDBsNode* 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 368void 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 378bool CookieTreeOriginNode::CanCreateContentException() const { 379 return !url_.SchemeIsFile(); 380} 381 382/////////////////////////////////////////////////////////////////////////////// 383// CookieTreeCookiesNode, public: 384 385CookieTreeCookiesNode::CookieTreeCookiesNode() 386 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIES)) { 387} 388 389CookieTreeCookiesNode::~CookieTreeCookiesNode() { 390} 391 392CookieTreeNode::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 401CookieTreeAppCachesNode::CookieTreeAppCachesNode() 402 : CookieTreeNode(l10n_util::GetStringUTF16( 403 IDS_COOKIES_APPLICATION_CACHES)) { 404} 405 406CookieTreeAppCachesNode::~CookieTreeAppCachesNode() {} 407 408CookieTreeNode::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 417CookieTreeDatabasesNode::CookieTreeDatabasesNode() 418 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASES)) { 419} 420 421CookieTreeDatabasesNode::~CookieTreeDatabasesNode() {} 422 423CookieTreeNode::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 432CookieTreeLocalStoragesNode::CookieTreeLocalStoragesNode() 433 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_LOCAL_STORAGE)) { 434} 435 436CookieTreeLocalStoragesNode::~CookieTreeLocalStoragesNode() {} 437 438CookieTreeNode::DetailedInfo 439CookieTreeLocalStoragesNode::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 448CookieTreeSessionStoragesNode::CookieTreeSessionStoragesNode() 449 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SESSION_STORAGE)) { 450} 451 452CookieTreeSessionStoragesNode::~CookieTreeSessionStoragesNode() {} 453 454CookieTreeNode::DetailedInfo 455CookieTreeSessionStoragesNode::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 464CookieTreeIndexedDBsNode::CookieTreeIndexedDBsNode() 465 : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_INDEXED_DBS)) { 466} 467 468CookieTreeIndexedDBsNode::~CookieTreeIndexedDBsNode() {} 469 470CookieTreeNode::DetailedInfo 471CookieTreeIndexedDBsNode::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 480bool 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 489void 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 501CookiesTreeModel::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 544CookiesTreeModel::~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. 561void 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. 573int 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 596void CookiesTreeModel::LoadCookies() { 597 LoadCookiesWithFilter(std::wstring()); 598} 599 600void 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 632void 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 643void 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 653void 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 669void 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 675void 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 681void CookiesTreeModel::OnAppCacheModelInfoLoaded() { 682 appcache_info_ = appcache_helper_->info_collection(); 683 PopulateAppCacheInfoWithFilter(std::wstring()); 684} 685 686void 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 719void CookiesTreeModel::OnDatabaseModelInfoLoaded( 720 const DatabaseInfoList& database_info) { 721 database_info_list_ = database_info; 722 PopulateDatabaseInfoWithFilter(std::wstring()); 723} 724 725void 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 751void CookiesTreeModel::OnLocalStorageModelInfoLoaded( 752 const LocalStorageInfoList& local_storage_info) { 753 local_storage_info_list_ = local_storage_info; 754 PopulateLocalStorageInfoWithFilter(std::wstring()); 755} 756 757void 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 784void CookiesTreeModel::OnSessionStorageModelInfoLoaded( 785 const LocalStorageInfoList& session_storage_info) { 786 session_storage_info_list_ = session_storage_info; 787 PopulateSessionStorageInfoWithFilter(std::wstring()); 788} 789 790void 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 817void CookiesTreeModel::OnIndexedDBModelInfoLoaded( 818 const IndexedDBInfoList& indexed_db_info) { 819 indexed_db_info_list_ = indexed_db_info; 820 PopulateIndexedDBInfoWithFilter(std::wstring()); 821} 822 823void 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 850void 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 859void 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