| // Copyright (c) 2011 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/cookies_tree_model.h" |
| |
| #include <algorithm> |
| #include <functional> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/memory/linked_ptr.h" |
| #include "base/string_util.h" |
| #include "base/utf_string_conversions.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "content/browser/in_process_webkit/webkit_context.h" |
| #include "grit/app_resources.h" |
| #include "grit/generated_resources.h" |
| #include "grit/theme_resources.h" |
| #include "net/base/cookie_monster.h" |
| #include "net/base/registry_controlled_domain.h" |
| #include "net/url_request/url_request_context.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/resource/resource_bundle.h" |
| |
| static const char kFileOriginNodeName[] = "file://"; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // 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( |
| net::CookieMonster::CanonicalCookie* cookie) |
| : CookieTreeNode(UTF8ToUTF16(cookie->Name())), |
| cookie_(cookie) { |
| } |
| |
| CookieTreeCookieNode::~CookieTreeCookieNode() {} |
| |
| void CookieTreeCookieNode::DeleteStoredObjects() { |
| // notify CookieMonster that we should delete this cookie |
| // We have stored a copy of all the cookies in the model, and our model is |
| // never re-calculated. Thus, we just need to delete the nodes from our |
| // model, and tell CookieMonster to delete the cookies. We can keep the |
| // vector storing the cookies in-tact and not delete from there (that would |
| // invalidate our pointers), and the fact that it contains semi out-of-date |
| // data is not problematic as we don't re-build the model based on that. |
| GetModel()->cookie_monster_->DeleteCanonicalCookie(*cookie_); |
| } |
| |
| CookieTreeNode::DetailedInfo CookieTreeCookieNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->parent()->GetTitle(), |
| DetailedInfo::TYPE_COOKIE, |
| cookie_, NULL, NULL, NULL, NULL, NULL); |
| } |
| |
| namespace { |
| // comparison functor, for use in CookieTreeRootNode |
| class OriginNodeComparator { |
| public: |
| bool operator() (const CookieTreeNode* lhs, |
| const CookieTreeNode* 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 (CanonicalizeHost(lhs->GetTitle()) < |
| CanonicalizeHost(rhs->GetTitle())); |
| } |
| |
| private: |
| static std::string CanonicalizeHost(const string16& host16) { |
| // 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". |
| |
| std::string host = UTF16ToUTF8(host16); |
| std::string retval = net::RegistryControlledDomainService:: |
| GetDomainAndRegistry(host); |
| 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; |
| } |
| }; |
| |
| } // namespace |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeAppCacheNode, public: |
| |
| CookieTreeAppCacheNode::CookieTreeAppCacheNode( |
| const appcache::AppCacheInfo* appcache_info) |
| : CookieTreeNode(UTF8ToUTF16(appcache_info->manifest_url.spec())), |
| appcache_info_(appcache_info) { |
| } |
| |
| void CookieTreeAppCacheNode::DeleteStoredObjects() { |
| DCHECK(GetModel()->appcache_helper_); |
| GetModel()->appcache_helper_->DeleteAppCacheGroup( |
| appcache_info_->manifest_url); |
| } |
| |
| CookieTreeNode::DetailedInfo CookieTreeAppCacheNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->parent()->GetTitle(), |
| DetailedInfo::TYPE_APPCACHE, |
| NULL, NULL, NULL, NULL, appcache_info_, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeDatabaseNode, public: |
| |
| CookieTreeDatabaseNode::CookieTreeDatabaseNode( |
| BrowsingDataDatabaseHelper::DatabaseInfo* database_info) |
| : CookieTreeNode(database_info->database_name.empty() ? |
| l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME) : |
| UTF8ToUTF16(database_info->database_name)), |
| database_info_(database_info) { |
| } |
| |
| CookieTreeDatabaseNode::~CookieTreeDatabaseNode() {} |
| |
| void CookieTreeDatabaseNode::DeleteStoredObjects() { |
| GetModel()->database_helper_->DeleteDatabase( |
| database_info_->origin_identifier, database_info_->database_name); |
| } |
| |
| CookieTreeNode::DetailedInfo CookieTreeDatabaseNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->parent()->GetTitle(), |
| DetailedInfo::TYPE_DATABASE, |
| NULL, database_info_, NULL, NULL, NULL, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeLocalStorageNode, public: |
| |
| CookieTreeLocalStorageNode::CookieTreeLocalStorageNode( |
| BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info) |
| : CookieTreeNode(UTF8ToUTF16( |
| local_storage_info->origin.empty() ? |
| local_storage_info->database_identifier : |
| local_storage_info->origin)), |
| local_storage_info_(local_storage_info) { |
| } |
| |
| CookieTreeLocalStorageNode::~CookieTreeLocalStorageNode() {} |
| |
| void CookieTreeLocalStorageNode::DeleteStoredObjects() { |
| GetModel()->local_storage_helper_->DeleteLocalStorageFile( |
| local_storage_info_->file_path); |
| } |
| |
| CookieTreeNode::DetailedInfo |
| CookieTreeLocalStorageNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->parent()->GetTitle(), |
| DetailedInfo::TYPE_LOCAL_STORAGE, |
| NULL, NULL, local_storage_info_, NULL, NULL, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeSessionStorageNode, public: |
| |
| CookieTreeSessionStorageNode::CookieTreeSessionStorageNode( |
| BrowsingDataLocalStorageHelper::LocalStorageInfo* session_storage_info) |
| : CookieTreeNode(UTF8ToUTF16( |
| session_storage_info->origin.empty() ? |
| session_storage_info->database_identifier : |
| session_storage_info->origin)), |
| session_storage_info_(session_storage_info) { |
| } |
| |
| CookieTreeSessionStorageNode::~CookieTreeSessionStorageNode() {} |
| |
| CookieTreeNode::DetailedInfo |
| CookieTreeSessionStorageNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->parent()->GetTitle(), |
| DetailedInfo::TYPE_SESSION_STORAGE, |
| NULL, NULL, NULL, session_storage_info_, NULL, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeIndexedDBNode, public: |
| |
| CookieTreeIndexedDBNode::CookieTreeIndexedDBNode( |
| BrowsingDataIndexedDBHelper::IndexedDBInfo* indexed_db_info) |
| : CookieTreeNode(UTF8ToUTF16( |
| indexed_db_info->origin.empty() ? |
| indexed_db_info->database_identifier : |
| indexed_db_info->origin)), |
| indexed_db_info_(indexed_db_info) { |
| } |
| |
| CookieTreeIndexedDBNode::~CookieTreeIndexedDBNode() {} |
| |
| void CookieTreeIndexedDBNode::DeleteStoredObjects() { |
| GetModel()->indexed_db_helper_->DeleteIndexedDBFile( |
| indexed_db_info_->file_path); |
| } |
| |
| CookieTreeNode::DetailedInfo CookieTreeIndexedDBNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->parent()->GetTitle(), |
| DetailedInfo::TYPE_INDEXED_DB, |
| NULL, NULL, NULL, NULL, NULL, indexed_db_info_); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeRootNode, public: |
| |
| CookieTreeRootNode::CookieTreeRootNode(CookiesTreeModel* model) |
| : model_(model) { |
| } |
| |
| CookieTreeRootNode::~CookieTreeRootNode() {} |
| |
| CookieTreeOriginNode* CookieTreeRootNode::GetOrCreateOriginNode( |
| const GURL& url) { |
| CookieTreeOriginNode origin_node(url); |
| |
| // First see if there is an existing match. |
| std::vector<CookieTreeNode*>::iterator origin_node_iterator = |
| lower_bound(children().begin(), |
| children().end(), |
| &origin_node, |
| OriginNodeComparator()); |
| |
| if (origin_node_iterator != children().end() && |
| WideToUTF16Hack(CookieTreeOriginNode::TitleForUrl(url)) == |
| (*origin_node_iterator)->GetTitle()) |
| return static_cast<CookieTreeOriginNode*>(*origin_node_iterator); |
| // Node doesn't exist, create a new one and insert it into the (ordered) |
| // children. |
| CookieTreeOriginNode* retval = new CookieTreeOriginNode(url); |
| DCHECK(model_); |
| model_->Add(this, retval, (origin_node_iterator - children().begin())); |
| return retval; |
| } |
| |
| CookiesTreeModel* CookieTreeRootNode::GetModel() const { |
| return model_; |
| } |
| |
| CookieTreeNode::DetailedInfo CookieTreeRootNode::GetDetailedInfo() const { |
| return DetailedInfo(string16(), |
| DetailedInfo::TYPE_ROOT, |
| NULL, NULL, NULL, NULL, NULL, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeOriginNode, public: |
| |
| // static |
| std::wstring CookieTreeOriginNode::TitleForUrl( |
| const GURL& url) { |
| return UTF8ToWide(url.SchemeIsFile() ? kFileOriginNodeName : url.host()); |
| } |
| |
| CookieTreeOriginNode::CookieTreeOriginNode(const GURL& url) |
| : CookieTreeNode(WideToUTF16Hack(TitleForUrl(url))), |
| cookies_child_(NULL), |
| databases_child_(NULL), |
| local_storages_child_(NULL), |
| session_storages_child_(NULL), |
| appcaches_child_(NULL), |
| indexed_dbs_child_(NULL), |
| url_(url) {} |
| |
| CookieTreeOriginNode::~CookieTreeOriginNode() {} |
| |
| CookieTreeNode::DetailedInfo CookieTreeOriginNode::GetDetailedInfo() const { |
| return DetailedInfo(GetTitle(), |
| DetailedInfo::TYPE_ORIGIN, |
| NULL, NULL, NULL, NULL, NULL, NULL); |
| } |
| |
| CookieTreeCookiesNode* CookieTreeOriginNode::GetOrCreateCookiesNode() { |
| if (cookies_child_) |
| return cookies_child_; |
| cookies_child_ = new CookieTreeCookiesNode; |
| AddChildSortedByTitle(cookies_child_); |
| return cookies_child_; |
| } |
| |
| CookieTreeDatabasesNode* CookieTreeOriginNode::GetOrCreateDatabasesNode() { |
| if (databases_child_) |
| return databases_child_; |
| databases_child_ = new CookieTreeDatabasesNode; |
| AddChildSortedByTitle(databases_child_); |
| return databases_child_; |
| } |
| |
| CookieTreeLocalStoragesNode* |
| CookieTreeOriginNode::GetOrCreateLocalStoragesNode() { |
| if (local_storages_child_) |
| return local_storages_child_; |
| local_storages_child_ = new CookieTreeLocalStoragesNode; |
| AddChildSortedByTitle(local_storages_child_); |
| return local_storages_child_; |
| } |
| |
| CookieTreeSessionStoragesNode* |
| CookieTreeOriginNode::GetOrCreateSessionStoragesNode() { |
| if (session_storages_child_) |
| return session_storages_child_; |
| session_storages_child_ = new CookieTreeSessionStoragesNode; |
| AddChildSortedByTitle(session_storages_child_); |
| return session_storages_child_; |
| } |
| |
| CookieTreeAppCachesNode* CookieTreeOriginNode::GetOrCreateAppCachesNode() { |
| if (appcaches_child_) |
| return appcaches_child_; |
| appcaches_child_ = new CookieTreeAppCachesNode; |
| AddChildSortedByTitle(appcaches_child_); |
| return appcaches_child_; |
| } |
| |
| CookieTreeIndexedDBsNode* CookieTreeOriginNode::GetOrCreateIndexedDBsNode() { |
| if (indexed_dbs_child_) |
| return indexed_dbs_child_; |
| indexed_dbs_child_ = new CookieTreeIndexedDBsNode; |
| AddChildSortedByTitle(indexed_dbs_child_); |
| return indexed_dbs_child_; |
| } |
| |
| void CookieTreeOriginNode::CreateContentException( |
| HostContentSettingsMap* content_settings, ContentSetting setting) const { |
| if (CanCreateContentException()) { |
| content_settings->AddExceptionForURL(url_, |
| CONTENT_SETTINGS_TYPE_COOKIES, |
| "", |
| setting); |
| } |
| } |
| |
| bool CookieTreeOriginNode::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(parent()->GetTitle(), |
| DetailedInfo::TYPE_COOKIES, |
| NULL, NULL, NULL, NULL, NULL, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeAppCachesNode, public: |
| |
| CookieTreeAppCachesNode::CookieTreeAppCachesNode() |
| : CookieTreeNode(l10n_util::GetStringUTF16( |
| IDS_COOKIES_APPLICATION_CACHES)) { |
| } |
| |
| CookieTreeAppCachesNode::~CookieTreeAppCachesNode() {} |
| |
| CookieTreeNode::DetailedInfo CookieTreeAppCachesNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->GetTitle(), |
| DetailedInfo::TYPE_APPCACHES, |
| NULL, NULL, NULL, NULL, NULL, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeDatabasesNode, public: |
| |
| CookieTreeDatabasesNode::CookieTreeDatabasesNode() |
| : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_WEB_DATABASES)) { |
| } |
| |
| CookieTreeDatabasesNode::~CookieTreeDatabasesNode() {} |
| |
| CookieTreeNode::DetailedInfo CookieTreeDatabasesNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->GetTitle(), |
| DetailedInfo::TYPE_DATABASES, |
| NULL, NULL, NULL, NULL, NULL, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeLocalStoragesNode, public: |
| |
| CookieTreeLocalStoragesNode::CookieTreeLocalStoragesNode() |
| : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_LOCAL_STORAGE)) { |
| } |
| |
| CookieTreeLocalStoragesNode::~CookieTreeLocalStoragesNode() {} |
| |
| CookieTreeNode::DetailedInfo |
| CookieTreeLocalStoragesNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->GetTitle(), |
| DetailedInfo::TYPE_LOCAL_STORAGES, |
| NULL, NULL, NULL, NULL, NULL, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeSessionStoragesNode, public: |
| |
| CookieTreeSessionStoragesNode::CookieTreeSessionStoragesNode() |
| : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_SESSION_STORAGE)) { |
| } |
| |
| CookieTreeSessionStoragesNode::~CookieTreeSessionStoragesNode() {} |
| |
| CookieTreeNode::DetailedInfo |
| CookieTreeSessionStoragesNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->GetTitle(), |
| DetailedInfo::TYPE_SESSION_STORAGES, |
| NULL, NULL, NULL, NULL, NULL, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeIndexedDBsNode, public: |
| |
| CookieTreeIndexedDBsNode::CookieTreeIndexedDBsNode() |
| : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_INDEXED_DBS)) { |
| } |
| |
| CookieTreeIndexedDBsNode::~CookieTreeIndexedDBsNode() {} |
| |
| CookieTreeNode::DetailedInfo |
| CookieTreeIndexedDBsNode::GetDetailedInfo() const { |
| return DetailedInfo(parent()->GetTitle(), |
| DetailedInfo::TYPE_INDEXED_DBS, |
| NULL, NULL, NULL, NULL, NULL, NULL); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookieTreeNode, protected |
| |
| bool CookieTreeNode::NodeTitleComparator::operator() ( |
| const CookieTreeNode* lhs, const CookieTreeNode* rhs) { |
| const CookieTreeNode* left = |
| static_cast<const CookieTreeNode*>(lhs); |
| const CookieTreeNode* right = |
| static_cast<const CookieTreeNode*>(rhs); |
| return (left->GetTitle() < right->GetTitle()); |
| } |
| |
| void CookieTreeNode::AddChildSortedByTitle(CookieTreeNode* new_child) { |
| std::vector<CookieTreeNode*>::iterator iter = |
| lower_bound(children().begin(), |
| children().end(), |
| new_child, |
| NodeTitleComparator()); |
| GetModel()->Add(this, new_child, iter - children().begin()); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CookiesTreeModel, public: |
| |
| CookiesTreeModel::CookiesTreeModel( |
| net::CookieMonster* cookie_monster, |
| BrowsingDataDatabaseHelper* database_helper, |
| BrowsingDataLocalStorageHelper* local_storage_helper, |
| BrowsingDataLocalStorageHelper* session_storage_helper, |
| BrowsingDataAppCacheHelper* appcache_helper, |
| BrowsingDataIndexedDBHelper* indexed_db_helper, |
| bool use_cookie_source) |
| : ALLOW_THIS_IN_INITIALIZER_LIST(ui::TreeNodeModel<CookieTreeNode>( |
| new CookieTreeRootNode(this))), |
| cookie_monster_(cookie_monster), |
| appcache_helper_(appcache_helper), |
| database_helper_(database_helper), |
| local_storage_helper_(local_storage_helper), |
| session_storage_helper_(session_storage_helper), |
| indexed_db_helper_(indexed_db_helper), |
| batch_update_(0), |
| use_cookie_source_(use_cookie_source) { |
| LoadCookies(); |
| DCHECK(database_helper_); |
| database_helper_->StartFetching(NewCallback( |
| this, &CookiesTreeModel::OnDatabaseModelInfoLoaded)); |
| DCHECK(local_storage_helper_); |
| local_storage_helper_->StartFetching(NewCallback( |
| this, &CookiesTreeModel::OnLocalStorageModelInfoLoaded)); |
| if (session_storage_helper_) { |
| session_storage_helper_->StartFetching(NewCallback( |
| this, &CookiesTreeModel::OnSessionStorageModelInfoLoaded)); |
| } |
| |
| // TODO(michaeln): when all of the ui impls have been updated, |
| // make this a required parameter. |
| if (appcache_helper_) { |
| appcache_helper_->StartFetching(NewCallback( |
| this, &CookiesTreeModel::OnAppCacheModelInfoLoaded)); |
| } |
| |
| if (indexed_db_helper_) { |
| indexed_db_helper_->StartFetching(NewCallback( |
| this, &CookiesTreeModel::OnIndexedDBModelInfoLoaded)); |
| } |
| } |
| |
| CookiesTreeModel::~CookiesTreeModel() { |
| database_helper_->CancelNotification(); |
| local_storage_helper_->CancelNotification(); |
| if (session_storage_helper_) |
| session_storage_helper_->CancelNotification(); |
| if (appcache_helper_) |
| appcache_helper_->CancelNotification(); |
| if (indexed_db_helper_) |
| indexed_db_helper_->CancelNotification(); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // 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<SkBitmap>* icons) { |
| icons->push_back(*ResourceBundle::GetSharedInstance().GetBitmapNamed( |
| IDR_OMNIBOX_HTTP)); |
| icons->push_back(*ResourceBundle::GetSharedInstance().GetBitmapNamed( |
| IDR_COOKIE_ICON)); |
| icons->push_back(*ResourceBundle::GetSharedInstance().GetBitmapNamed( |
| IDR_COOKIE_STORAGE_ICON)); |
| } |
| |
| // 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_ORIGIN: |
| 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 |
| default: |
| break; |
| } |
| return -1; |
| } |
| |
| void CookiesTreeModel::LoadCookies() { |
| LoadCookiesWithFilter(std::wstring()); |
| } |
| |
| void CookiesTreeModel::LoadCookiesWithFilter(const std::wstring& filter) { |
| // mmargh mmargh mmargh! delicious! |
| |
| all_cookies_ = cookie_monster_->GetAllCookies(); |
| CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot()); |
| for (CookieList::iterator it = all_cookies_.begin(); |
| it != all_cookies_.end(); ++it) { |
| std::string source_string = it->Source(); |
| if (source_string.empty() || !use_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(chrome::kHttpScheme) + |
| chrome::kStandardSchemeSeparator + domain + "/"; |
| } |
| |
| GURL source(source_string); |
| if (!filter.size() || |
| (CookieTreeOriginNode::TitleForUrl(source).find(filter) != |
| std::string::npos)) { |
| CookieTreeOriginNode* origin_node = |
| root->GetOrCreateOriginNode(source); |
| CookieTreeCookiesNode* cookies_node = |
| origin_node->GetOrCreateCookiesNode(); |
| CookieTreeCookieNode* new_cookie = new CookieTreeCookieNode(&*it); |
| cookies_node->AddCookieNode(new_cookie); |
| } |
| } |
| } |
| |
| 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->child_count() == 0) |
| DeleteCookieNode(parent_node); |
| } |
| |
| void CookiesTreeModel::UpdateSearchResults(const std::wstring& filter) { |
| CookieTreeNode* root = GetRoot(); |
| int num_children = root->child_count(); |
| NotifyObserverBeginBatch(); |
| for (int i = num_children - 1; i >= 0; --i) |
| delete Remove(root, root->GetChild(i)); |
| LoadCookiesWithFilter(filter); |
| PopulateDatabaseInfoWithFilter(filter); |
| PopulateLocalStorageInfoWithFilter(filter); |
| PopulateSessionStorageInfoWithFilter(filter); |
| PopulateAppCacheInfoWithFilter(filter); |
| PopulateIndexedDBInfoWithFilter(filter); |
| NotifyObserverTreeNodeChanged(root); |
| NotifyObserverEndBatch(); |
| } |
| |
| 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::OnAppCacheModelInfoLoaded() { |
| appcache_info_ = appcache_helper_->info_collection(); |
| PopulateAppCacheInfoWithFilter(std::wstring()); |
| } |
| |
| void CookiesTreeModel::PopulateAppCacheInfoWithFilter( |
| const std::wstring& filter) { |
| using appcache::AppCacheInfo; |
| using appcache::AppCacheInfoVector; |
| typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin; |
| |
| if (!appcache_info_ || appcache_info_->infos_by_origin.empty()) |
| return; |
| |
| CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot()); |
| NotifyObserverBeginBatch(); |
| for (InfoByOrigin::const_iterator origin = |
| appcache_info_->infos_by_origin.begin(); |
| origin != appcache_info_->infos_by_origin.end(); ++origin) { |
| std::wstring origin_node_name = UTF8ToWide(origin->first.host()); |
| if (filter.empty() || |
| (origin_node_name.find(filter) != std::wstring::npos)) { |
| CookieTreeOriginNode* origin_node = |
| root->GetOrCreateOriginNode(origin->first); |
| CookieTreeAppCachesNode* appcaches_node = |
| origin_node->GetOrCreateAppCachesNode(); |
| |
| for (AppCacheInfoVector::const_iterator info = origin->second.begin(); |
| info != origin->second.end(); ++info) { |
| appcaches_node->AddAppCacheNode( |
| new CookieTreeAppCacheNode(&(*info))); |
| } |
| } |
| } |
| NotifyObserverTreeNodeChanged(root); |
| NotifyObserverEndBatch(); |
| } |
| |
| void CookiesTreeModel::OnDatabaseModelInfoLoaded( |
| const DatabaseInfoList& database_info) { |
| database_info_list_ = database_info; |
| PopulateDatabaseInfoWithFilter(std::wstring()); |
| } |
| |
| void CookiesTreeModel::PopulateDatabaseInfoWithFilter( |
| const std::wstring& filter) { |
| if (database_info_list_.empty()) |
| return; |
| CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot()); |
| NotifyObserverBeginBatch(); |
| for (DatabaseInfoList::iterator database_info = database_info_list_.begin(); |
| database_info != database_info_list_.end(); |
| ++database_info) { |
| GURL origin(database_info->origin); |
| |
| if (!filter.size() || |
| (CookieTreeOriginNode::TitleForUrl(origin).find(filter) != |
| std::wstring::npos)) { |
| CookieTreeOriginNode* origin_node = |
| root->GetOrCreateOriginNode(origin); |
| CookieTreeDatabasesNode* databases_node = |
| origin_node->GetOrCreateDatabasesNode(); |
| databases_node->AddDatabaseNode( |
| new CookieTreeDatabaseNode(&(*database_info))); |
| } |
| } |
| NotifyObserverTreeNodeChanged(root); |
| NotifyObserverEndBatch(); |
| } |
| |
| void CookiesTreeModel::OnLocalStorageModelInfoLoaded( |
| const LocalStorageInfoList& local_storage_info) { |
| local_storage_info_list_ = local_storage_info; |
| PopulateLocalStorageInfoWithFilter(std::wstring()); |
| } |
| |
| void CookiesTreeModel::PopulateLocalStorageInfoWithFilter( |
| const std::wstring& filter) { |
| if (local_storage_info_list_.empty()) |
| return; |
| CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot()); |
| NotifyObserverBeginBatch(); |
| for (LocalStorageInfoList::iterator local_storage_info = |
| local_storage_info_list_.begin(); |
| local_storage_info != local_storage_info_list_.end(); |
| ++local_storage_info) { |
| GURL origin(local_storage_info->origin); |
| |
| if (!filter.size() || |
| (CookieTreeOriginNode::TitleForUrl(origin).find(filter) != |
| std::wstring::npos)) { |
| CookieTreeOriginNode* origin_node = |
| root->GetOrCreateOriginNode(origin); |
| CookieTreeLocalStoragesNode* local_storages_node = |
| origin_node->GetOrCreateLocalStoragesNode(); |
| local_storages_node->AddLocalStorageNode( |
| new CookieTreeLocalStorageNode(&(*local_storage_info))); |
| } |
| } |
| NotifyObserverTreeNodeChanged(root); |
| NotifyObserverEndBatch(); |
| } |
| |
| void CookiesTreeModel::OnSessionStorageModelInfoLoaded( |
| const LocalStorageInfoList& session_storage_info) { |
| session_storage_info_list_ = session_storage_info; |
| PopulateSessionStorageInfoWithFilter(std::wstring()); |
| } |
| |
| void CookiesTreeModel::PopulateSessionStorageInfoWithFilter( |
| const std::wstring& filter) { |
| if (session_storage_info_list_.empty()) |
| return; |
| CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot()); |
| NotifyObserverBeginBatch(); |
| for (LocalStorageInfoList::iterator session_storage_info = |
| session_storage_info_list_.begin(); |
| session_storage_info != session_storage_info_list_.end(); |
| ++session_storage_info) { |
| GURL origin(session_storage_info->origin); |
| |
| if (!filter.size() || |
| (CookieTreeOriginNode::TitleForUrl(origin).find(filter) != |
| std::wstring::npos)) { |
| CookieTreeOriginNode* origin_node = |
| root->GetOrCreateOriginNode(origin); |
| CookieTreeSessionStoragesNode* session_storages_node = |
| origin_node->GetOrCreateSessionStoragesNode(); |
| session_storages_node->AddSessionStorageNode( |
| new CookieTreeSessionStorageNode(&(*session_storage_info))); |
| } |
| } |
| NotifyObserverTreeNodeChanged(root); |
| NotifyObserverEndBatch(); |
| } |
| |
| void CookiesTreeModel::OnIndexedDBModelInfoLoaded( |
| const IndexedDBInfoList& indexed_db_info) { |
| indexed_db_info_list_ = indexed_db_info; |
| PopulateIndexedDBInfoWithFilter(std::wstring()); |
| } |
| |
| void CookiesTreeModel::PopulateIndexedDBInfoWithFilter( |
| const std::wstring& filter) { |
| if (indexed_db_info_list_.empty()) |
| return; |
| CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot()); |
| NotifyObserverBeginBatch(); |
| for (IndexedDBInfoList::iterator indexed_db_info = |
| indexed_db_info_list_.begin(); |
| indexed_db_info != indexed_db_info_list_.end(); |
| ++indexed_db_info) { |
| GURL origin(indexed_db_info->origin); |
| |
| if (!filter.size() || |
| (CookieTreeOriginNode::TitleForUrl(origin).find(filter) != |
| std::wstring::npos)) { |
| CookieTreeOriginNode* origin_node = |
| root->GetOrCreateOriginNode(origin); |
| CookieTreeIndexedDBsNode* indexed_dbs_node = |
| origin_node->GetOrCreateIndexedDBsNode(); |
| indexed_dbs_node->AddIndexedDBNode( |
| new CookieTreeIndexedDBNode(&(*indexed_db_info))); |
| } |
| } |
| NotifyObserverTreeNodeChanged(root); |
| NotifyObserverEndBatch(); |
| } |
| |
| 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)); |
| } |
| } |