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