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