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