blob: 5663eb08e4c68073190507e3061ad637c03b1964 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/browsing_data/cookies_tree_model.h"
#include <algorithm>
#include <functional>
#include <vector>
#include "base/bind.h"
#include "base/memory/linked_ptr.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
#include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h"
#include "chrome/browser/browsing_data/browsing_data_server_bound_cert_helper.h"
#include "chrome/browser/content_settings/cookie_settings.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_special_storage_policy.h"
#include "content/public/common/url_constants.h"
#include "extensions/common/extension_set.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "grit/ui_resources.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/cookies/canonical_cookie.h"
#include "net/url_request/url_request_context.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image_skia.h"
namespace {
struct NodeTitleComparator {
bool operator()(const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
return lhs->GetTitle() < rhs->GetTitle();
}
};
// Comparison functor, for use in CookieTreeRootNode.
struct HostNodeComparator {
bool operator()(const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
// This comparator is only meant to compare CookieTreeHostNode types. Make
// sure we check this, as the static cast below is dangerous if we get the
// wrong object type.
CHECK_EQ(CookieTreeNode::DetailedInfo::TYPE_HOST,
lhs->GetDetailedInfo().node_type);
CHECK_EQ(CookieTreeNode::DetailedInfo::TYPE_HOST,
rhs->GetDetailedInfo().node_type);
const CookieTreeHostNode* ltn =
static_cast<const CookieTreeHostNode*>(lhs);
const CookieTreeHostNode* rtn =
static_cast<const CookieTreeHostNode*>(rhs);
// We want to order by registry controlled domain, so we would get
// google.com, ad.google.com, www.google.com,
// microsoft.com, ad.microsoft.com. CanonicalizeHost transforms the origins
// into a form like google.com.www so that string comparisons work.
return (ltn->canonicalized_host() <
rtn->canonicalized_host());
}
};
std::string CanonicalizeHost(const GURL& url) {
// The canonicalized representation makes the registry controlled domain
// come first, and then adds subdomains in reverse order, e.g.
// 1.mail.google.com would become google.com.mail.1, and then a standard
// string comparison works to order hosts by registry controlled domain
// first. Leading dots are ignored, ".google.com" is the same as
// "google.com".
if (url.SchemeIsFile()) {
return std::string(url::kFileScheme) +
url::kStandardSchemeSeparator;
}
std::string host = url.host();
std::string retval =
net::registry_controlled_domains::GetDomainAndRegistry(
host,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
if (!retval.length()) // Is an IP address or other special origin.
return host;
std::string::size_type position = host.rfind(retval);
// The host may be the registry controlled domain, in which case fail fast.
if (position == 0 || position == std::string::npos)
return host;
// If host is www.google.com, retval will contain google.com at this point.
// Start operating to the left of the registry controlled domain, e.g. in
// the www.google.com example, start at index 3.
--position;
// If position == 0, that means it's a dot; this will be ignored to treat
// ".google.com" the same as "google.com".
while (position > 0) {
retval += std::string(".");
// Copy up to the next dot. host[position] is a dot so start after it.
std::string::size_type next_dot = host.rfind(".", position - 1);
if (next_dot == std::string::npos) {
retval += host.substr(0, position);
break;
}
retval += host.substr(next_dot + 1, position - (next_dot + 1));
position = next_dot;
}
return retval;
}
bool TypeIsProtected(CookieTreeNode::DetailedInfo::NodeType type) {
switch (type) {
case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
return false;
case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
return true;
case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
return true;
case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
return true;
case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
return true;
case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
return true;
case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM:
return true;
case CookieTreeNode::DetailedInfo::TYPE_QUOTA:
return false;
case CookieTreeNode::DetailedInfo::TYPE_SERVER_BOUND_CERT:
return false;
case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO:
return false;
default:
break;
}
return false;
}
// This function returns the local data container associated with a leaf tree
// node. The app node is assumed to be 3 levels above the leaf because of the
// following structure:
// root -> origin -> storage type -> leaf node
LocalDataContainer* GetLocalDataContainerForNode(CookieTreeNode* node) {
CookieTreeHostNode* host = static_cast<CookieTreeHostNode*>(
node->parent()->parent());
CHECK_EQ(host->GetDetailedInfo().node_type,
CookieTreeNode::DetailedInfo::TYPE_HOST);
return node->GetModel()->data_container();
}
} // namespace
CookieTreeNode::DetailedInfo::DetailedInfo()
: node_type(TYPE_NONE),
cookie(NULL),
database_info(NULL),
local_storage_info(NULL),
session_storage_info(NULL),
appcache_info(NULL),
indexed_db_info(NULL),
file_system_info(NULL),
quota_info(NULL),
server_bound_cert(NULL) {}
CookieTreeNode::DetailedInfo::~DetailedInfo() {}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::Init(
NodeType type) {
DCHECK_EQ(TYPE_NONE, node_type);
node_type = type;
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitHost() {
Init(TYPE_HOST);
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitCookie(
const net::CanonicalCookie* cookie) {
Init(TYPE_COOKIE);
this->cookie = cookie;
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitDatabase(
const BrowsingDataDatabaseHelper::DatabaseInfo* database_info) {
Init(TYPE_DATABASE);
this->database_info = database_info;
origin = database_info->identifier.ToOrigin();
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitLocalStorage(
const BrowsingDataLocalStorageHelper::LocalStorageInfo*
local_storage_info) {
Init(TYPE_LOCAL_STORAGE);
this->local_storage_info = local_storage_info;
origin = local_storage_info->origin_url;
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitSessionStorage(
const BrowsingDataLocalStorageHelper::LocalStorageInfo*
session_storage_info) {
Init(TYPE_SESSION_STORAGE);
this->session_storage_info = session_storage_info;
origin = session_storage_info->origin_url;
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitAppCache(
const GURL& origin,
const appcache::AppCacheInfo* appcache_info) {
Init(TYPE_APPCACHE);
this->appcache_info = appcache_info;
this->origin = origin;
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitIndexedDB(
const content::IndexedDBInfo* indexed_db_info) {
Init(TYPE_INDEXED_DB);
this->indexed_db_info = indexed_db_info;
this->origin = indexed_db_info->origin_;
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitFileSystem(
const BrowsingDataFileSystemHelper::FileSystemInfo* file_system_info) {
Init(TYPE_FILE_SYSTEM);
this->file_system_info = file_system_info;
this->origin = file_system_info->origin;
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitQuota(
const BrowsingDataQuotaHelper::QuotaInfo* quota_info) {
Init(TYPE_QUOTA);
this->quota_info = quota_info;
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitServerBoundCert(
const net::ServerBoundCertStore::ServerBoundCert* server_bound_cert) {
Init(TYPE_SERVER_BOUND_CERT);
this->server_bound_cert = server_bound_cert;
return *this;
}
CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitFlashLSO(
const std::string& flash_lso_domain) {
Init(TYPE_FLASH_LSO);
this->flash_lso_domain = flash_lso_domain;
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeNode, public:
void CookieTreeNode::DeleteStoredObjects() {
std::for_each(children().begin(),
children().end(),
std::mem_fun(&CookieTreeNode::DeleteStoredObjects));
}
CookiesTreeModel* CookieTreeNode::GetModel() const {
if (parent())
return parent()->GetModel();
else
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeCookieNode, public:
CookieTreeCookieNode::CookieTreeCookieNode(
std::list<net::CanonicalCookie>::iterator cookie)
: CookieTreeNode(base::UTF8ToUTF16(cookie->Name())),
cookie_(cookie) {
}
CookieTreeCookieNode::~CookieTreeCookieNode() {}
void CookieTreeCookieNode::DeleteStoredObjects() {
LocalDataContainer* container = GetLocalDataContainerForNode(this);
CHECK(container);
container->cookie_helper_->DeleteCookie(*cookie_);
container->cookie_list_.erase(cookie_);
}
CookieTreeNode::DetailedInfo CookieTreeCookieNode::GetDetailedInfo() const {
return DetailedInfo().InitCookie(&*cookie_);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeAppCacheNode, public:
CookieTreeAppCacheNode::CookieTreeAppCacheNode(
const GURL& origin_url,
std::list<appcache::AppCacheInfo>::iterator appcache_info)
: CookieTreeNode(base::UTF8ToUTF16(appcache_info->manifest_url.spec())),
origin_url_(origin_url),
appcache_info_(appcache_info) {
}
CookieTreeAppCacheNode::~CookieTreeAppCacheNode() {
}
void CookieTreeAppCacheNode::DeleteStoredObjects() {
LocalDataContainer* container = GetLocalDataContainerForNode(this);
if (container) {
DCHECK(container->appcache_helper_.get());
container->appcache_helper_
->DeleteAppCacheGroup(appcache_info_->manifest_url);
container->appcache_info_[origin_url_].erase(appcache_info_);
}
}
CookieTreeNode::DetailedInfo CookieTreeAppCacheNode::GetDetailedInfo() const {
return DetailedInfo().InitAppCache(origin_url_, &*appcache_info_);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeDatabaseNode, public:
CookieTreeDatabaseNode::CookieTreeDatabaseNode(
std::list<BrowsingDataDatabaseHelper::DatabaseInfo>::iterator database_info)
: CookieTreeNode(database_info->database_name.empty() ?
l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME) :
base::UTF8ToUTF16(database_info->database_name)),
database_info_(database_info) {
}
CookieTreeDatabaseNode::~CookieTreeDatabaseNode() {}
void CookieTreeDatabaseNode::DeleteStoredObjects() {
LocalDataContainer* container = GetLocalDataContainerForNode(this);
if (container) {
container->database_helper_->DeleteDatabase(
database_info_->identifier.ToString(), database_info_->database_name);
container->database_info_list_.erase(database_info_);
}
}
CookieTreeNode::DetailedInfo CookieTreeDatabaseNode::GetDetailedInfo() const {
return DetailedInfo().InitDatabase(&*database_info_);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeLocalStorageNode, public:
CookieTreeLocalStorageNode::CookieTreeLocalStorageNode(
std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::iterator
local_storage_info)
: CookieTreeNode(base::UTF8ToUTF16(local_storage_info->origin_url.spec())),
local_storage_info_(local_storage_info) {
}
CookieTreeLocalStorageNode::~CookieTreeLocalStorageNode() {}
void CookieTreeLocalStorageNode::DeleteStoredObjects() {
LocalDataContainer* container = GetLocalDataContainerForNode(this);
if (container) {
container->local_storage_helper_->DeleteOrigin(
local_storage_info_->origin_url);
container->local_storage_info_list_.erase(local_storage_info_);
}
}
CookieTreeNode::DetailedInfo
CookieTreeLocalStorageNode::GetDetailedInfo() const {
return DetailedInfo().InitLocalStorage(
&*local_storage_info_);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeSessionStorageNode, public:
CookieTreeSessionStorageNode::CookieTreeSessionStorageNode(
std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>::iterator
session_storage_info)
: CookieTreeNode(
base::UTF8ToUTF16(session_storage_info->origin_url.spec())),
session_storage_info_(session_storage_info) {
}
CookieTreeSessionStorageNode::~CookieTreeSessionStorageNode() {}
void CookieTreeSessionStorageNode::DeleteStoredObjects() {
LocalDataContainer* container = GetLocalDataContainerForNode(this);
if (container) {
// TODO(rsesek): There's no easy way to get the namespace_id for a session
// storage, nor is there an easy way to clear session storage just by
// origin. This is probably okay since session storage is not persistent.
// http://crbug.com/168996
container->session_storage_info_list_.erase(session_storage_info_);
}
}
CookieTreeNode::DetailedInfo
CookieTreeSessionStorageNode::GetDetailedInfo() const {
return DetailedInfo().InitSessionStorage(&*session_storage_info_);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeIndexedDBNode, public:
CookieTreeIndexedDBNode::CookieTreeIndexedDBNode(
std::list<content::IndexedDBInfo>::iterator
indexed_db_info)
: CookieTreeNode(base::UTF8ToUTF16(
indexed_db_info->origin_.spec())),
indexed_db_info_(indexed_db_info) {
}
CookieTreeIndexedDBNode::~CookieTreeIndexedDBNode() {}
void CookieTreeIndexedDBNode::DeleteStoredObjects() {
LocalDataContainer* container = GetLocalDataContainerForNode(this);
if (container) {
container->indexed_db_helper_->DeleteIndexedDB(
indexed_db_info_->origin_);
container->indexed_db_info_list_.erase(indexed_db_info_);
}
}
CookieTreeNode::DetailedInfo CookieTreeIndexedDBNode::GetDetailedInfo() const {
return DetailedInfo().InitIndexedDB(&*indexed_db_info_);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeFileSystemNode, public:
CookieTreeFileSystemNode::CookieTreeFileSystemNode(
std::list<BrowsingDataFileSystemHelper::FileSystemInfo>::iterator
file_system_info)
: CookieTreeNode(base::UTF8ToUTF16(
file_system_info->origin.spec())),
file_system_info_(file_system_info) {
}
CookieTreeFileSystemNode::~CookieTreeFileSystemNode() {}
void CookieTreeFileSystemNode::DeleteStoredObjects() {
LocalDataContainer* container = GetLocalDataContainerForNode(this);
if (container) {
container->file_system_helper_->DeleteFileSystemOrigin(
file_system_info_->origin);
container->file_system_info_list_.erase(file_system_info_);
}
}
CookieTreeNode::DetailedInfo CookieTreeFileSystemNode::GetDetailedInfo() const {
return DetailedInfo().InitFileSystem(&*file_system_info_);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeQuotaNode, public:
CookieTreeQuotaNode::CookieTreeQuotaNode(
std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info)
: CookieTreeNode(base::UTF8ToUTF16(quota_info->host)),
quota_info_(quota_info) {
}
CookieTreeQuotaNode::~CookieTreeQuotaNode() {}
void CookieTreeQuotaNode::DeleteStoredObjects() {
// Calling this function may cause unexpected over-quota state of origin.
// However, it'll caused no problem, just prevent usage growth of the origin.
LocalDataContainer* container = GetModel()->data_container();
if (container) {
container->quota_helper_->RevokeHostQuota(quota_info_->host);
container->quota_info_list_.erase(quota_info_);
}
}
CookieTreeNode::DetailedInfo CookieTreeQuotaNode::GetDetailedInfo() const {
return DetailedInfo().InitQuota(&*quota_info_);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeServerBoundCertNode, public:
CookieTreeServerBoundCertNode::CookieTreeServerBoundCertNode(
net::ServerBoundCertStore::ServerBoundCertList::iterator cert)
: CookieTreeNode(base::ASCIIToUTF16(cert->server_identifier())),
server_bound_cert_(cert) {
}
CookieTreeServerBoundCertNode::~CookieTreeServerBoundCertNode() {}
void CookieTreeServerBoundCertNode::DeleteStoredObjects() {
LocalDataContainer* container = GetLocalDataContainerForNode(this);
if (container) {
container->server_bound_cert_helper_->DeleteServerBoundCert(
server_bound_cert_->server_identifier());
container->server_bound_cert_list_.erase(server_bound_cert_);
}
}
CookieTreeNode::DetailedInfo
CookieTreeServerBoundCertNode::GetDetailedInfo() const {
return DetailedInfo().InitServerBoundCert(&*server_bound_cert_);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeRootNode, public:
CookieTreeRootNode::CookieTreeRootNode(CookiesTreeModel* model)
: model_(model) {
}
CookieTreeRootNode::~CookieTreeRootNode() {}
CookieTreeHostNode* CookieTreeRootNode::GetOrCreateHostNode(
const GURL& url) {
scoped_ptr<CookieTreeHostNode> host_node(
new CookieTreeHostNode(url));
// First see if there is an existing match.
std::vector<CookieTreeNode*>::iterator host_node_iterator =
std::lower_bound(children().begin(), children().end(), host_node.get(),
HostNodeComparator());
if (host_node_iterator != children().end() &&
CookieTreeHostNode::TitleForUrl(url) ==
(*host_node_iterator)->GetTitle())
return static_cast<CookieTreeHostNode*>(*host_node_iterator);
// Node doesn't exist, insert the new one into the (ordered) children.
DCHECK(model_);
model_->Add(this, host_node.get(),
(host_node_iterator - children().begin()));
return host_node.release();
}
CookiesTreeModel* CookieTreeRootNode::GetModel() const {
return model_;
}
CookieTreeNode::DetailedInfo CookieTreeRootNode::GetDetailedInfo() const {
return DetailedInfo().Init(DetailedInfo::TYPE_ROOT);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeHostNode, public:
// static
base::string16 CookieTreeHostNode::TitleForUrl(const GURL& url) {
const std::string file_origin_node_name(
std::string(url::kFileScheme) + url::kStandardSchemeSeparator);
return base::UTF8ToUTF16(url.SchemeIsFile() ? file_origin_node_name
: url.host());
}
CookieTreeHostNode::CookieTreeHostNode(const GURL& url)
: CookieTreeNode(TitleForUrl(url)),
cookies_child_(NULL),
databases_child_(NULL),
local_storages_child_(NULL),
session_storages_child_(NULL),
appcaches_child_(NULL),
indexed_dbs_child_(NULL),
file_systems_child_(NULL),
quota_child_(NULL),
server_bound_certs_child_(NULL),
flash_lso_child_(NULL),
url_(url),
canonicalized_host_(CanonicalizeHost(url)) {}
CookieTreeHostNode::~CookieTreeHostNode() {}
const std::string CookieTreeHostNode::GetHost() const {
const std::string file_origin_node_name(
std::string(url::kFileScheme) + url::kStandardSchemeSeparator);
return url_.SchemeIsFile() ? file_origin_node_name : url_.host();
}
CookieTreeNode::DetailedInfo CookieTreeHostNode::GetDetailedInfo() const {
return DetailedInfo().InitHost();
}
CookieTreeCookiesNode* CookieTreeHostNode::GetOrCreateCookiesNode() {
if (cookies_child_)
return cookies_child_;
cookies_child_ = new CookieTreeCookiesNode;
AddChildSortedByTitle(cookies_child_);
return cookies_child_;
}
CookieTreeDatabasesNode* CookieTreeHostNode::GetOrCreateDatabasesNode() {
if (databases_child_)
return databases_child_;
databases_child_ = new CookieTreeDatabasesNode;
AddChildSortedByTitle(databases_child_);
return databases_child_;
}
CookieTreeLocalStoragesNode*
CookieTreeHostNode::GetOrCreateLocalStoragesNode() {
if (local_storages_child_)
return local_storages_child_;
local_storages_child_ = new CookieTreeLocalStoragesNode;
AddChildSortedByTitle(local_storages_child_);
return local_storages_child_;
}
CookieTreeSessionStoragesNode*
CookieTreeHostNode::GetOrCreateSessionStoragesNode() {
if (session_storages_child_)
return session_storages_child_;
session_storages_child_ = new CookieTreeSessionStoragesNode;
AddChildSortedByTitle(session_storages_child_);
return session_storages_child_;
}
CookieTreeAppCachesNode* CookieTreeHostNode::GetOrCreateAppCachesNode() {
if (appcaches_child_)
return appcaches_child_;
appcaches_child_ = new CookieTreeAppCachesNode;
AddChildSortedByTitle(appcaches_child_);
return appcaches_child_;
}
CookieTreeIndexedDBsNode* CookieTreeHostNode::GetOrCreateIndexedDBsNode() {
if (indexed_dbs_child_)
return indexed_dbs_child_;
indexed_dbs_child_ = new CookieTreeIndexedDBsNode;
AddChildSortedByTitle(indexed_dbs_child_);
return indexed_dbs_child_;
}
CookieTreeFileSystemsNode* CookieTreeHostNode::GetOrCreateFileSystemsNode() {
if (file_systems_child_)
return file_systems_child_;
file_systems_child_ = new CookieTreeFileSystemsNode;
AddChildSortedByTitle(file_systems_child_);
return file_systems_child_;
}
CookieTreeQuotaNode* CookieTreeHostNode::UpdateOrCreateQuotaNode(
std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info) {
if (quota_child_)
return quota_child_;
quota_child_ = new CookieTreeQuotaNode(quota_info);
AddChildSortedByTitle(quota_child_);
return quota_child_;
}
CookieTreeServerBoundCertsNode*
CookieTreeHostNode::GetOrCreateServerBoundCertsNode() {
if (server_bound_certs_child_)
return server_bound_certs_child_;
server_bound_certs_child_ = new CookieTreeServerBoundCertsNode;
AddChildSortedByTitle(server_bound_certs_child_);
return server_bound_certs_child_;
}
CookieTreeFlashLSONode* CookieTreeHostNode::GetOrCreateFlashLSONode(
const std::string& domain) {
DCHECK_EQ(GetHost(), domain);
if (flash_lso_child_)
return flash_lso_child_;
flash_lso_child_ = new CookieTreeFlashLSONode(domain);
AddChildSortedByTitle(flash_lso_child_);
return flash_lso_child_;
}
void CookieTreeHostNode::CreateContentException(
CookieSettings* cookie_settings, ContentSetting setting) const {
DCHECK(setting == CONTENT_SETTING_ALLOW ||
setting == CONTENT_SETTING_BLOCK ||
setting == CONTENT_SETTING_SESSION_ONLY);
if (CanCreateContentException()) {
cookie_settings->ResetCookieSetting(
ContentSettingsPattern::FromURLNoWildcard(url_),
ContentSettingsPattern::Wildcard());
cookie_settings->SetCookieSetting(
ContentSettingsPattern::FromURL(url_),
ContentSettingsPattern::Wildcard(), setting);
}
}
bool CookieTreeHostNode::CanCreateContentException() const {
return !url_.SchemeIsFile();
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeCookiesNode, public:
CookieTreeCookiesNode::CookieTreeCookiesNode()
: CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_COOKIES)) {
}
CookieTreeCookiesNode::~CookieTreeCookiesNode() {
}
CookieTreeNode::DetailedInfo CookieTreeCookiesNode::GetDetailedInfo() const {
return DetailedInfo().Init(DetailedInfo::TYPE_COOKIES);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeAppCachesNode, public:
CookieTreeAppCachesNode::CookieTreeAppCachesNode()
: CookieTreeNode(l10n_util::GetStringUTF16(
IDS_COOKIES_APPLICATION_CACHES)) {
}
CookieTreeAppCachesNode::~CookieTreeAppCachesNode() {}
CookieTreeNode::DetailedInfo CookieTreeAppCachesNode::GetDetailedInfo() const {
return DetailedInfo().Init(DetailedInfo::TYPE_APPCACHES);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeDatabasesNode, public:
CookieTreeDatabasesNode::CookieTreeDatabasesNode()
: CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASES)) {
}
CookieTreeDatabasesNode::~CookieTreeDatabasesNode() {}
CookieTreeNode::DetailedInfo CookieTreeDatabasesNode::GetDetailedInfo() const {
return DetailedInfo().Init(DetailedInfo::TYPE_DATABASES);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeLocalStoragesNode, public:
CookieTreeLocalStoragesNode::CookieTreeLocalStoragesNode()
: CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_LOCAL_STORAGE)) {
}
CookieTreeLocalStoragesNode::~CookieTreeLocalStoragesNode() {}
CookieTreeNode::DetailedInfo
CookieTreeLocalStoragesNode::GetDetailedInfo() const {
return DetailedInfo().Init(DetailedInfo::TYPE_LOCAL_STORAGES);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeSessionStoragesNode, public:
CookieTreeSessionStoragesNode::CookieTreeSessionStoragesNode()
: CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SESSION_STORAGE)) {
}
CookieTreeSessionStoragesNode::~CookieTreeSessionStoragesNode() {}
CookieTreeNode::DetailedInfo
CookieTreeSessionStoragesNode::GetDetailedInfo() const {
return DetailedInfo().Init(DetailedInfo::TYPE_SESSION_STORAGES);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeIndexedDBsNode, public:
CookieTreeIndexedDBsNode::CookieTreeIndexedDBsNode()
: CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_INDEXED_DBS)) {
}
CookieTreeIndexedDBsNode::~CookieTreeIndexedDBsNode() {}
CookieTreeNode::DetailedInfo
CookieTreeIndexedDBsNode::GetDetailedInfo() const {
return DetailedInfo().Init(DetailedInfo::TYPE_INDEXED_DBS);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeFileSystemsNode, public:
CookieTreeFileSystemsNode::CookieTreeFileSystemsNode()
: CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_FILE_SYSTEMS)) {
}
CookieTreeFileSystemsNode::~CookieTreeFileSystemsNode() {}
CookieTreeNode::DetailedInfo
CookieTreeFileSystemsNode::GetDetailedInfo() const {
return DetailedInfo().Init(DetailedInfo::TYPE_FILE_SYSTEMS);
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeServerBoundCertsNode, public:
CookieTreeServerBoundCertsNode::CookieTreeServerBoundCertsNode()
: CookieTreeNode(
l10n_util::GetStringUTF16(IDS_COOKIES_SERVER_BOUND_CERTS)) {
}
CookieTreeServerBoundCertsNode::~CookieTreeServerBoundCertsNode() {}
CookieTreeNode::DetailedInfo
CookieTreeServerBoundCertsNode::GetDetailedInfo() const {
return DetailedInfo().Init(DetailedInfo::TYPE_SERVER_BOUND_CERTS);
}
void CookieTreeNode::AddChildSortedByTitle(CookieTreeNode* new_child) {
DCHECK(new_child);
std::vector<CookieTreeNode*>::iterator iter =
std::lower_bound(children().begin(), children().end(), new_child,
NodeTitleComparator());
GetModel()->Add(this, new_child, iter - children().begin());
}
///////////////////////////////////////////////////////////////////////////////
// CookieTreeFlashLSONode
CookieTreeFlashLSONode::CookieTreeFlashLSONode(
const std::string& domain)
: domain_(domain) {}
CookieTreeFlashLSONode::~CookieTreeFlashLSONode() {}
void CookieTreeFlashLSONode::DeleteStoredObjects() {
// We are one level below the host node.
CookieTreeHostNode* host = static_cast<CookieTreeHostNode*>(parent());
CHECK_EQ(host->GetDetailedInfo().node_type,
CookieTreeNode::DetailedInfo::TYPE_HOST);
LocalDataContainer* container = GetModel()->data_container();
CHECK(container);
container->flash_lso_helper_->DeleteFlashLSOsForSite(domain_);
}
CookieTreeNode::DetailedInfo CookieTreeFlashLSONode::GetDetailedInfo() const {
return DetailedInfo().InitFlashLSO(domain_);
}
///////////////////////////////////////////////////////////////////////////////
// ScopedBatchUpdateNotifier
CookiesTreeModel::ScopedBatchUpdateNotifier::ScopedBatchUpdateNotifier(
CookiesTreeModel* model, CookieTreeNode* node)
: model_(model), node_(node), batch_in_progress_(false) {
}
CookiesTreeModel::ScopedBatchUpdateNotifier::~ScopedBatchUpdateNotifier() {
if (batch_in_progress_) {
model_->NotifyObserverTreeNodeChanged(node_);
model_->NotifyObserverEndBatch();
}
}
void CookiesTreeModel::ScopedBatchUpdateNotifier::StartBatchUpdate() {
if (!batch_in_progress_) {
model_->NotifyObserverBeginBatch();
batch_in_progress_ = true;
}
}
///////////////////////////////////////////////////////////////////////////////
// CookiesTreeModel, public:
CookiesTreeModel::CookiesTreeModel(
LocalDataContainer* data_container,
ExtensionSpecialStoragePolicy* special_storage_policy,
bool group_by_cookie_source)
: ui::TreeNodeModel<CookieTreeNode>(new CookieTreeRootNode(this)),
data_container_(data_container),
special_storage_policy_(special_storage_policy),
group_by_cookie_source_(group_by_cookie_source),
batch_update_(0) {
data_container_->Init(this);
}
CookiesTreeModel::~CookiesTreeModel() {
}
///////////////////////////////////////////////////////////////////////////////
// CookiesTreeModel, TreeModel methods (public):
// TreeModel methods:
// Returns the set of icons for the nodes in the tree. You only need override
// this if you don't want to use the default folder icons.
void CookiesTreeModel::GetIcons(std::vector<gfx::ImageSkia>* icons) {
icons->push_back(*ResourceBundle::GetSharedInstance().GetNativeImageNamed(
IDR_DEFAULT_FAVICON).ToImageSkia());
icons->push_back(*ResourceBundle::GetSharedInstance().GetNativeImageNamed(
IDR_COOKIE_ICON).ToImageSkia());
icons->push_back(*ResourceBundle::GetSharedInstance().GetNativeImageNamed(
IDR_COOKIE_STORAGE_ICON).ToImageSkia());
}
// Returns the index of the icon to use for |node|. Return -1 to use the
// default icon. The index is relative to the list of icons returned from
// GetIcons.
int CookiesTreeModel::GetIconIndex(ui::TreeModelNode* node) {
CookieTreeNode* ct_node = static_cast<CookieTreeNode*>(node);
switch (ct_node->GetDetailedInfo().node_type) {
case CookieTreeNode::DetailedInfo::TYPE_HOST:
return ORIGIN;
case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
return COOKIE;
case CookieTreeNode::DetailedInfo::TYPE_DATABASE:
return DATABASE;
case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE:
return DATABASE; // close enough
case CookieTreeNode::DetailedInfo::TYPE_SESSION_STORAGE:
return DATABASE; // ditto
case CookieTreeNode::DetailedInfo::TYPE_APPCACHE:
return DATABASE; // ditto
case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB:
return DATABASE; // ditto
case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM:
return DATABASE; // ditto
case CookieTreeNode::DetailedInfo::TYPE_QUOTA:
return -1;
case CookieTreeNode::DetailedInfo::TYPE_SERVER_BOUND_CERT:
return COOKIE; // It's kinda like a cookie?
default:
break;
}
return -1;
}
void CookiesTreeModel::DeleteAllStoredObjects() {
NotifyObserverBeginBatch();
CookieTreeNode* root = GetRoot();
root->DeleteStoredObjects();
int num_children = root->child_count();
for (int i = num_children - 1; i >= 0; --i)
delete Remove(root, root->GetChild(i));
NotifyObserverTreeNodeChanged(root);
NotifyObserverEndBatch();
}
void CookiesTreeModel::DeleteCookieNode(CookieTreeNode* cookie_node) {
if (cookie_node == GetRoot())
return;
cookie_node->DeleteStoredObjects();
CookieTreeNode* parent_node = cookie_node->parent();
delete Remove(parent_node, cookie_node);
if (parent_node->empty())
DeleteCookieNode(parent_node);
}
void CookiesTreeModel::UpdateSearchResults(const base::string16& filter) {
CookieTreeNode* root = GetRoot();
ScopedBatchUpdateNotifier notifier(this, root);
int num_children = root->child_count();
notifier.StartBatchUpdate();
for (int i = num_children - 1; i >= 0; --i)
delete Remove(root, root->GetChild(i));
PopulateCookieInfoWithFilter(data_container(), &notifier, filter);
PopulateDatabaseInfoWithFilter(data_container(), &notifier, filter);
PopulateLocalStorageInfoWithFilter(data_container(), &notifier, filter);
PopulateSessionStorageInfoWithFilter(data_container(), &notifier, filter);
PopulateAppCacheInfoWithFilter(data_container(), &notifier, filter);
PopulateIndexedDBInfoWithFilter(data_container(), &notifier, filter);
PopulateFileSystemInfoWithFilter(data_container(), &notifier, filter);
PopulateQuotaInfoWithFilter(data_container(), &notifier, filter);
PopulateServerBoundCertInfoWithFilter(data_container(), &notifier, filter);
}
const extensions::ExtensionSet* CookiesTreeModel::ExtensionsProtectingNode(
const CookieTreeNode& cookie_node) {
if (!special_storage_policy_.get())
return NULL;
CookieTreeNode::DetailedInfo info = cookie_node.GetDetailedInfo();
if (!TypeIsProtected(info.node_type))
return NULL;
DCHECK(!info.origin.is_empty());
return special_storage_policy_->ExtensionsProtectingOrigin(info.origin);
}
void CookiesTreeModel::AddCookiesTreeObserver(Observer* observer) {
cookies_observer_list_.AddObserver(observer);
// Call super so that TreeNodeModel can notify, too.
ui::TreeNodeModel<CookieTreeNode>::AddObserver(observer);
}
void CookiesTreeModel::RemoveCookiesTreeObserver(Observer* observer) {
cookies_observer_list_.RemoveObserver(observer);
// Call super so that TreeNodeModel doesn't have dead pointers.
ui::TreeNodeModel<CookieTreeNode>::RemoveObserver(observer);
}
void CookiesTreeModel::PopulateAppCacheInfo(LocalDataContainer* container) {
ScopedBatchUpdateNotifier notifier(this, GetRoot());
PopulateAppCacheInfoWithFilter(container, &notifier, base::string16());
}
void CookiesTreeModel::PopulateCookieInfo(LocalDataContainer* container) {
ScopedBatchUpdateNotifier notifier(this, GetRoot());
PopulateCookieInfoWithFilter(container, &notifier, base::string16());
}
void CookiesTreeModel::PopulateDatabaseInfo(LocalDataContainer* container) {
ScopedBatchUpdateNotifier notifier(this, GetRoot());
PopulateDatabaseInfoWithFilter(container, &notifier, base::string16());
}
void CookiesTreeModel::PopulateLocalStorageInfo(LocalDataContainer* container) {
ScopedBatchUpdateNotifier notifier(this, GetRoot());
PopulateLocalStorageInfoWithFilter(container, &notifier, base::string16());
}
void CookiesTreeModel::PopulateSessionStorageInfo(
LocalDataContainer* container) {
ScopedBatchUpdateNotifier notifier(this, GetRoot());
PopulateSessionStorageInfoWithFilter(container, &notifier, base::string16());
}
void CookiesTreeModel::PopulateIndexedDBInfo(LocalDataContainer* container){
ScopedBatchUpdateNotifier notifier(this, GetRoot());
PopulateIndexedDBInfoWithFilter(container, &notifier, base::string16());
}
void CookiesTreeModel::PopulateFileSystemInfo(LocalDataContainer* container) {
ScopedBatchUpdateNotifier notifier(this, GetRoot());
PopulateFileSystemInfoWithFilter(container, &notifier, base::string16());
}
void CookiesTreeModel::PopulateQuotaInfo(LocalDataContainer* container) {
ScopedBatchUpdateNotifier notifier(this, GetRoot());
PopulateQuotaInfoWithFilter(container, &notifier, base::string16());
}
void CookiesTreeModel::PopulateServerBoundCertInfo(
LocalDataContainer* container) {
ScopedBatchUpdateNotifier notifier(this, GetRoot());
PopulateServerBoundCertInfoWithFilter(container, &notifier, base::string16());
}
void CookiesTreeModel::PopulateFlashLSOInfo(
LocalDataContainer* container) {
ScopedBatchUpdateNotifier notifier(this, GetRoot());
PopulateFlashLSOInfoWithFilter(container, &notifier, base::string16());
}
void CookiesTreeModel::PopulateAppCacheInfoWithFilter(
LocalDataContainer* container,
ScopedBatchUpdateNotifier* notifier,
const base::string16& filter) {
using appcache::AppCacheInfo;
typedef std::map<GURL, std::list<AppCacheInfo> > InfoByOrigin;
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
if (container->appcache_info_.empty())
return;
notifier->StartBatchUpdate();
for (InfoByOrigin::iterator origin = container->appcache_info_.begin();
origin != container->appcache_info_.end(); ++origin) {
base::string16 host_node_name = base::UTF8ToUTF16(origin->first.host());
if (filter.empty() ||
(host_node_name.find(filter) != base::string16::npos)) {
CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin->first);
CookieTreeAppCachesNode* appcaches_node =
host_node->GetOrCreateAppCachesNode();
for (std::list<AppCacheInfo>::iterator info = origin->second.begin();
info != origin->second.end(); ++info) {
appcaches_node->AddAppCacheNode(
new CookieTreeAppCacheNode(origin->first, info));
}
}
}
}
void CookiesTreeModel::PopulateCookieInfoWithFilter(
LocalDataContainer* container,
ScopedBatchUpdateNotifier* notifier,
const base::string16& filter) {
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
notifier->StartBatchUpdate();
for (CookieList::iterator it = container->cookie_list_.begin();
it != container->cookie_list_.end(); ++it) {
std::string source_string = it->Source();
if (source_string.empty() || !group_by_cookie_source_) {
std::string domain = it->Domain();
if (domain.length() > 1 && domain[0] == '.')
domain = domain.substr(1);
// We treat secure cookies just the same as normal ones.
source_string = std::string(url::kHttpScheme) +
url::kStandardSchemeSeparator + domain + "/";
}
GURL source(source_string);
if (!filter.size() ||
(CookieTreeHostNode::TitleForUrl(source).find(filter) !=
base::string16::npos)) {
CookieTreeHostNode* host_node = root->GetOrCreateHostNode(source);
CookieTreeCookiesNode* cookies_node =
host_node->GetOrCreateCookiesNode();
CookieTreeCookieNode* new_cookie = new CookieTreeCookieNode(it);
cookies_node->AddCookieNode(new_cookie);
}
}
}
void CookiesTreeModel::PopulateDatabaseInfoWithFilter(
LocalDataContainer* container,
ScopedBatchUpdateNotifier* notifier,
const base::string16& filter) {
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
if (container->database_info_list_.empty())
return;
notifier->StartBatchUpdate();
for (DatabaseInfoList::iterator database_info =
container->database_info_list_.begin();
database_info != container->database_info_list_.end();
++database_info) {
GURL origin(database_info->identifier.ToOrigin());
if (!filter.size() ||
(CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
base::string16::npos)) {
CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
CookieTreeDatabasesNode* databases_node =
host_node->GetOrCreateDatabasesNode();
databases_node->AddDatabaseNode(
new CookieTreeDatabaseNode(database_info));
}
}
}
void CookiesTreeModel::PopulateLocalStorageInfoWithFilter(
LocalDataContainer* container,
ScopedBatchUpdateNotifier* notifier,
const base::string16& filter) {
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
if (container->local_storage_info_list_.empty())
return;
notifier->StartBatchUpdate();
for (LocalStorageInfoList::iterator local_storage_info =
container->local_storage_info_list_.begin();
local_storage_info != container->local_storage_info_list_.end();
++local_storage_info) {
const GURL& origin(local_storage_info->origin_url);
if (!filter.size() ||
(CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
std::string::npos)) {
CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
CookieTreeLocalStoragesNode* local_storages_node =
host_node->GetOrCreateLocalStoragesNode();
local_storages_node->AddLocalStorageNode(
new CookieTreeLocalStorageNode(local_storage_info));
}
}
}
void CookiesTreeModel::PopulateSessionStorageInfoWithFilter(
LocalDataContainer* container,
ScopedBatchUpdateNotifier* notifier,
const base::string16& filter) {
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
if (container->session_storage_info_list_.empty())
return;
notifier->StartBatchUpdate();
for (LocalStorageInfoList::iterator session_storage_info =
container->session_storage_info_list_.begin();
session_storage_info != container->session_storage_info_list_.end();
++session_storage_info) {
const GURL& origin = session_storage_info->origin_url;
if (!filter.size() ||
(CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
base::string16::npos)) {
CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
CookieTreeSessionStoragesNode* session_storages_node =
host_node->GetOrCreateSessionStoragesNode();
session_storages_node->AddSessionStorageNode(
new CookieTreeSessionStorageNode(session_storage_info));
}
}
}
void CookiesTreeModel::PopulateIndexedDBInfoWithFilter(
LocalDataContainer* container,
ScopedBatchUpdateNotifier* notifier,
const base::string16& filter) {
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
if (container->indexed_db_info_list_.empty())
return;
notifier->StartBatchUpdate();
for (IndexedDBInfoList::iterator indexed_db_info =
container->indexed_db_info_list_.begin();
indexed_db_info != container->indexed_db_info_list_.end();
++indexed_db_info) {
const GURL& origin = indexed_db_info->origin_;
if (!filter.size() ||
(CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
base::string16::npos)) {
CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
CookieTreeIndexedDBsNode* indexed_dbs_node =
host_node->GetOrCreateIndexedDBsNode();
indexed_dbs_node->AddIndexedDBNode(
new CookieTreeIndexedDBNode(indexed_db_info));
}
}
}
void CookiesTreeModel::PopulateServerBoundCertInfoWithFilter(
LocalDataContainer* container,
ScopedBatchUpdateNotifier* notifier,
const base::string16& filter) {
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
if (container->server_bound_cert_list_.empty())
return;
notifier->StartBatchUpdate();
for (ServerBoundCertList::iterator cert_info =
container->server_bound_cert_list_.begin();
cert_info != container->server_bound_cert_list_.end();
++cert_info) {
GURL origin(cert_info->server_identifier());
if (!origin.is_valid()) {
// Domain Bound Cert. Make a valid URL to satisfy the
// CookieTreeRootNode::GetOrCreateHostNode interface.
origin = GURL(std::string(url::kHttpsScheme) +
url::kStandardSchemeSeparator +
cert_info->server_identifier() + "/");
}
base::string16 title = CookieTreeHostNode::TitleForUrl(origin);
if (!filter.size() || title.find(filter) != base::string16::npos) {
CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
CookieTreeServerBoundCertsNode* server_bound_certs_node =
host_node->GetOrCreateServerBoundCertsNode();
server_bound_certs_node->AddServerBoundCertNode(
new CookieTreeServerBoundCertNode(cert_info));
}
}
}
void CookiesTreeModel::PopulateFileSystemInfoWithFilter(
LocalDataContainer* container,
ScopedBatchUpdateNotifier* notifier,
const base::string16& filter) {
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
if (container->file_system_info_list_.empty())
return;
notifier->StartBatchUpdate();
for (FileSystemInfoList::iterator file_system_info =
container->file_system_info_list_.begin();
file_system_info != container->file_system_info_list_.end();
++file_system_info) {
GURL origin(file_system_info->origin);
if (!filter.size() ||
(CookieTreeHostNode::TitleForUrl(origin).find(filter) !=
base::string16::npos)) {
CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
CookieTreeFileSystemsNode* file_systems_node =
host_node->GetOrCreateFileSystemsNode();
file_systems_node->AddFileSystemNode(
new CookieTreeFileSystemNode(file_system_info));
}
}
}
void CookiesTreeModel::PopulateQuotaInfoWithFilter(
LocalDataContainer* container,
ScopedBatchUpdateNotifier* notifier,
const base::string16& filter) {
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
if (container->quota_info_list_.empty())
return;
notifier->StartBatchUpdate();
for (QuotaInfoList::iterator quota_info = container->quota_info_list_.begin();
quota_info != container->quota_info_list_.end();
++quota_info) {
if (!filter.size() ||
(base::UTF8ToUTF16(quota_info->host).find(filter) !=
base::string16::npos)) {
CookieTreeHostNode* host_node =
root->GetOrCreateHostNode(GURL("http://" + quota_info->host));
host_node->UpdateOrCreateQuotaNode(quota_info);
}
}
}
void CookiesTreeModel::PopulateFlashLSOInfoWithFilter(
LocalDataContainer* container,
ScopedBatchUpdateNotifier* notifier,
const base::string16& filter) {
CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
if (container->flash_lso_domain_list_.empty())
return;
std::string filter_utf8 = base::UTF16ToUTF8(filter);
notifier->StartBatchUpdate();
for (std::vector<std::string>::iterator it =
container->flash_lso_domain_list_.begin();
it != container->flash_lso_domain_list_.end(); ++it) {
if (!filter_utf8.size() || it->find(filter_utf8) != std::string::npos) {
// Create a fake origin for GetOrCreateHostNode().
GURL origin("http://" + *it);
CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin);
host_node->GetOrCreateFlashLSONode(*it);
}
}
}
void CookiesTreeModel::NotifyObserverBeginBatch() {
// Only notify the model once if we're batching in a nested manner.
if (batch_update_++ == 0) {
FOR_EACH_OBSERVER(Observer,
cookies_observer_list_,
TreeModelBeginBatch(this));
}
}
void CookiesTreeModel::NotifyObserverEndBatch() {
// Only notify the observers if this is the outermost call to EndBatch() if
// called in a nested manner.
if (--batch_update_ == 0) {
FOR_EACH_OBSERVER(Observer,
cookies_observer_list_,
TreeModelEndBatch(this));
}
}