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