// Copyright (c) 2010 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. #ifndef CHROME_BROWSER_COOKIES_TREE_MODEL_H_ #define CHROME_BROWSER_COOKIES_TREE_MODEL_H_ #include #include #include "app/tree_node_model.h" #include "base/observer_list.h" #include "base/scoped_ptr.h" #include "chrome/browser/browsing_data_appcache_helper.h" #include "chrome/browser/browsing_data_database_helper.h" #include "chrome/browser/browsing_data_local_storage_helper.h" #include "net/base/cookie_monster.h" class CookiesTreeModel; class CookieTreeAppCacheNode; class CookieTreeAppCachesNode; class CookieTreeCookieNode; class CookieTreeCookiesNode; class CookieTreeDatabaseNode; class CookieTreeDatabasesNode; class CookieTreeLocalStorageNode; class CookieTreeLocalStoragesNode; class CookieTreeOriginNode; class Profile; // CookieTreeNode ------------------------------------------------------------- // The base node type in the Cookies, Databases, and Local Storage options // view, from which all other types are derived. Specialized from TreeNode in // that it has a notion of deleting objects stored in the profile, and being // able to have its children do the same. class CookieTreeNode : public TreeNode { public: // Used to pull out information for the InfoView (the details display below // the tree control.) struct DetailedInfo { // NodeType corresponds to the various CookieTreeNode types. enum NodeType { TYPE_ROOT, // This is used for CookieTreeRootNode nodes. TYPE_ORIGIN, // This is used for CookieTreeOriginNode nodes. TYPE_COOKIES, // This is used for CookieTreeCookiesNode nodes. TYPE_COOKIE, // This is used for CookieTreeCookieNode nodes. TYPE_DATABASES, // This is used for CookieTreeDatabasesNode. TYPE_DATABASE, // This is used for CookieTreeDatabaseNode. TYPE_LOCAL_STORAGES, // This is used for CookieTreeLocalStoragesNode. TYPE_LOCAL_STORAGE, // This is used for CookieTreeLocalStorageNode. TYPE_APPCACHES, // This is used for CookieTreeAppCachesNode. TYPE_APPCACHE, // This is used for CookieTreeAppCacheNode. }; DetailedInfo(const std::wstring& origin, NodeType node_type, const net::CookieMonster::CookieListPair* cookie, const BrowsingDataDatabaseHelper::DatabaseInfo* database_info, const BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info, const appcache::AppCacheInfo* appcache_info) : origin(origin), node_type(node_type), cookie(cookie), database_info(database_info), local_storage_info(local_storage_info), appcache_info(appcache_info) { DCHECK((node_type != TYPE_DATABASE) || database_info); DCHECK((node_type != TYPE_LOCAL_STORAGE) || local_storage_info); DCHECK((node_type != TYPE_APPCACHE) || appcache_info); } std::wstring origin; NodeType node_type; const net::CookieMonster::CookieListPair* cookie; const BrowsingDataDatabaseHelper::DatabaseInfo* database_info; const BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info; const appcache::AppCacheInfo* appcache_info; }; CookieTreeNode() {} explicit CookieTreeNode(const std::wstring& title) : TreeNode(title) {} virtual ~CookieTreeNode() {} // Delete backend storage for this node, and any children nodes. (E.g. delete // the cookie from CookieMonster, clear the database, and so forth.) virtual void DeleteStoredObjects(); // Gets a pointer back to the associated model for the tree we are in. virtual CookiesTreeModel* GetModel() const; // Returns a struct with detailed information used to populate the details // part of the view. virtual DetailedInfo GetDetailedInfo() const = 0; protected: class NodeTitleComparator { public: bool operator() (const CookieTreeNode* lhs, const CookieTreeNode* rhs); }; void AddChildSortedByTitle(CookieTreeNode* new_child); private: DISALLOW_COPY_AND_ASSIGN(CookieTreeNode); }; // CookieTreeRootNode --------------------------------------------------------- // The node at the root of the CookieTree that gets inserted into the view. class CookieTreeRootNode : public CookieTreeNode { public: explicit CookieTreeRootNode(CookiesTreeModel* model) : model_(model) {} virtual ~CookieTreeRootNode() {} CookieTreeOriginNode* GetOrCreateOriginNode(const std::wstring& origin); // CookieTreeNode methods: virtual CookiesTreeModel* GetModel() const { return model_; } virtual DetailedInfo GetDetailedInfo() const { return DetailedInfo(std::wstring(), DetailedInfo::TYPE_ROOT, NULL, NULL, NULL, NULL); } private: CookiesTreeModel* model_; DISALLOW_COPY_AND_ASSIGN(CookieTreeRootNode); }; // CookieTreeOriginNode ------------------------------------------------------- class CookieTreeOriginNode : public CookieTreeNode { public: explicit CookieTreeOriginNode(const std::wstring& origin) : CookieTreeNode(origin), cookies_child_(NULL), databases_child_(NULL), local_storages_child_(NULL), appcaches_child_(NULL) {} virtual ~CookieTreeOriginNode() {} // CookieTreeNode methods: virtual DetailedInfo GetDetailedInfo() const { return DetailedInfo(GetTitle(), DetailedInfo::TYPE_ORIGIN, NULL, NULL, NULL, NULL); } // CookieTreeOriginNode methods: CookieTreeCookiesNode* GetOrCreateCookiesNode(); CookieTreeDatabasesNode* GetOrCreateDatabasesNode(); CookieTreeLocalStoragesNode* GetOrCreateLocalStoragesNode(); CookieTreeAppCachesNode* GetOrCreateAppCachesNode(); private: // A pointer to the COOKIES node. Eventually we will also have database, // appcache, local storage, ..., and when we build up the tree we need to // quickly get a reference to the COOKIES node to add children. Checking each // child and interrogating them to see if they are a COOKIES, APPCACHES, // DATABASES etc node seems less preferable than storing an extra pointer per // origin. CookieTreeCookiesNode* cookies_child_; CookieTreeDatabasesNode* databases_child_; CookieTreeLocalStoragesNode* local_storages_child_; CookieTreeAppCachesNode* appcaches_child_; DISALLOW_COPY_AND_ASSIGN(CookieTreeOriginNode); }; // CookieTreeCookieNode ------------------------------------------------------ class CookieTreeCookieNode : public CookieTreeNode { public: friend class CookieTreeCookiesNode; // Does not take ownership of cookie, and cookie should remain valid at least // as long as the CookieTreeCookieNode is valid. explicit CookieTreeCookieNode(net::CookieMonster::CookieListPair* cookie); virtual ~CookieTreeCookieNode() {} // CookieTreeNode methods: virtual void DeleteStoredObjects(); virtual DetailedInfo GetDetailedInfo() const { return DetailedInfo(GetParent()->GetParent()->GetTitle(), DetailedInfo::TYPE_COOKIE, cookie_, NULL, NULL, NULL); } private: // Cookie_ is not owned by the node, and is expected to remain valid as long // as the CookieTreeCookieNode is valid. net::CookieMonster::CookieListPair* cookie_; DISALLOW_COPY_AND_ASSIGN(CookieTreeCookieNode); }; class CookieTreeCookiesNode : public CookieTreeNode { public: CookieTreeCookiesNode(); virtual ~CookieTreeCookiesNode() {} virtual DetailedInfo GetDetailedInfo() const { return DetailedInfo(GetParent()->GetTitle(), DetailedInfo::TYPE_COOKIES, NULL, NULL, NULL, NULL); } void AddCookieNode(CookieTreeCookieNode* child) { AddChildSortedByTitle(child); } private: DISALLOW_COPY_AND_ASSIGN(CookieTreeCookiesNode); }; // CookieTreeAppCacheNode ----------------------------------------------------- class CookieTreeAppCacheNode : public CookieTreeNode { public: friend class CookieTreeAppCachesNode; // Does not take ownership of appcache_info, and appcache_info should remain // valid at least as long as the CookieTreeAppCacheNode is valid. explicit CookieTreeAppCacheNode( const appcache::AppCacheInfo* appcache_info); virtual ~CookieTreeAppCacheNode() {} virtual void DeleteStoredObjects(); virtual DetailedInfo GetDetailedInfo() const { return DetailedInfo(GetParent()->GetParent()->GetTitle(), DetailedInfo::TYPE_APPCACHE, NULL, NULL, NULL, appcache_info_); } private: const appcache::AppCacheInfo* appcache_info_; DISALLOW_COPY_AND_ASSIGN(CookieTreeAppCacheNode); }; class CookieTreeAppCachesNode : public CookieTreeNode { public: CookieTreeAppCachesNode(); virtual ~CookieTreeAppCachesNode() {} virtual DetailedInfo GetDetailedInfo() const { return DetailedInfo(GetParent()->GetTitle(), DetailedInfo::TYPE_APPCACHES, NULL, NULL, NULL, NULL); } void AddAppCacheNode(CookieTreeAppCacheNode* child) { AddChildSortedByTitle(child); } private: DISALLOW_COPY_AND_ASSIGN(CookieTreeAppCachesNode); }; // CookieTreeDatabaseNode ----------------------------------------------------- class CookieTreeDatabaseNode : public CookieTreeNode { public: friend class CookieTreeDatabasesNode; // Does not take ownership of database_info, and database_info should remain // valid at least as long as the CookieTreeDatabaseNode is valid. explicit CookieTreeDatabaseNode( BrowsingDataDatabaseHelper::DatabaseInfo* database_info); virtual ~CookieTreeDatabaseNode() {} virtual void DeleteStoredObjects(); virtual DetailedInfo GetDetailedInfo() const { return DetailedInfo(GetParent()->GetParent()->GetTitle(), DetailedInfo::TYPE_DATABASE, NULL, database_info_, NULL, NULL); } private: // database_info_ is not owned by the node, and is expected to remain // valid as long as the CookieTreeDatabaseNode is valid. BrowsingDataDatabaseHelper::DatabaseInfo* database_info_; DISALLOW_COPY_AND_ASSIGN(CookieTreeDatabaseNode); }; class CookieTreeDatabasesNode : public CookieTreeNode { public: CookieTreeDatabasesNode(); virtual ~CookieTreeDatabasesNode() {} virtual DetailedInfo GetDetailedInfo() const { return DetailedInfo(GetParent()->GetTitle(), DetailedInfo::TYPE_DATABASES, NULL, NULL, NULL, NULL); } void AddDatabaseNode(CookieTreeDatabaseNode* child) { AddChildSortedByTitle(child); } private: DISALLOW_COPY_AND_ASSIGN(CookieTreeDatabasesNode); }; // CookieTreeLocalStorageNode ------------------------------------------------- class CookieTreeLocalStorageNode : public CookieTreeNode { public: friend class CookieTreeLocalStoragesNode; // Does not take ownership of local_storage_info, and local_storage_info // should remain valid at least as long as the CookieTreeStorageNode is valid. explicit CookieTreeLocalStorageNode( BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info); virtual ~CookieTreeLocalStorageNode() {} // CookieTreeStorageNode methods: virtual void DeleteStoredObjects(); virtual DetailedInfo GetDetailedInfo() const { return DetailedInfo(GetParent()->GetParent()->GetTitle(), DetailedInfo::TYPE_LOCAL_STORAGE, NULL, NULL, local_storage_info_, NULL); } private: // local_storage_info_ is not owned by the node, and is expected to remain // valid as long as the CookieTreeLocalStorageNode is valid. BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info_; DISALLOW_COPY_AND_ASSIGN(CookieTreeLocalStorageNode); }; class CookieTreeLocalStoragesNode : public CookieTreeNode { public: CookieTreeLocalStoragesNode(); virtual ~CookieTreeLocalStoragesNode() {} virtual DetailedInfo GetDetailedInfo() const { return DetailedInfo(GetParent()->GetTitle(), DetailedInfo::TYPE_LOCAL_STORAGES, NULL, NULL, NULL, NULL); } void AddLocalStorageNode(CookieTreeLocalStorageNode* child) { AddChildSortedByTitle(child); } private: DISALLOW_COPY_AND_ASSIGN(CookieTreeLocalStoragesNode); }; class CookiesTreeModel : public TreeNodeModel { public: // Because non-cookie nodes are fetched in a background thread, they are not // present at the time the Model is created. The Model then notifies its // observers for every item added from databases, local storage, and // appcache. We extend the Observer interface to add notifications before and // after these batch inserts. class Observer : public TreeModelObserver { public: virtual void TreeModelBeginBatch(CookiesTreeModel* model) {} virtual void TreeModelEndBatch(CookiesTreeModel* model) {} }; CookiesTreeModel( Profile* profile, BrowsingDataDatabaseHelper* database_helper, BrowsingDataLocalStorageHelper* local_storage_helper, BrowsingDataAppCacheHelper* appcache_helper); virtual ~CookiesTreeModel(); // 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. virtual void GetIcons(std::vector* icons); // 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. virtual int GetIconIndex(TreeModelNode* node); // CookiesTreeModel methods: void DeleteAllStoredObjects(); void DeleteCookieNode(CookieTreeNode* cookie_node); // Filter the origins to only display matched results. void UpdateSearchResults(const std::wstring& filter); // Overload the Add/Remove observer methods so we can notify about // CookiesTreeModel-specific things. Note that this is NOT overriding the // method by the same name in TreeNodeModel because the argument type is // different. Therefore, if this AddObserver(TreeModelObserver*) is called, // the observer will NOT be notified about batching. This is also why we // maintain a separate list of observers that are specifically Observer* // objects. virtual void AddObserver(Observer* observer); virtual void RemoveObserver(Observer* observer); private: enum CookieIconIndex { ORIGIN = 0, COOKIE = 1, DATABASE = 2 }; typedef net::CookieMonster::CookieList CookieList; typedef std::vector CookiePtrList; typedef std::vector DatabaseInfoList; typedef std::vector LocalStorageInfoList; void LoadCookies(); void LoadCookiesWithFilter(const std::wstring& filter); void OnAppCacheModelInfoLoaded(); void OnDatabaseModelInfoLoaded(const DatabaseInfoList& database_info); void OnStorageModelInfoLoaded(const LocalStorageInfoList& local_storage_info); void PopulateAppCacheInfoWithFilter(const std::wstring& filter); void PopulateDatabaseInfoWithFilter(const std::wstring& filter); void PopulateLocalStorageInfoWithFilter(const std::wstring& filter); void NotifyObserverBeginBatch(); void NotifyObserverEndBatch(); // The profile from which this model sources cookies. Profile* profile_; CookieList all_cookies_; scoped_refptr appcache_helper_; scoped_refptr database_helper_; scoped_refptr appcache_info_; DatabaseInfoList database_info_list_; scoped_refptr local_storage_helper_; LocalStorageInfoList local_storage_info_list_; // The CookiesTreeModel maintains a separate list of observers that are // specifically of the type CookiesTreeModel::Observer. ObserverList cookies_observer_list_; // If this is non-zero, then this model is batching updates (there's a lot of // notifications coming down the pipe). This is an integer is used to balance // calls to Begin/EndBatch() if they're called in a nested manner. int batch_update_; friend class CookieTreeAppCacheNode; friend class CookieTreeCookieNode; friend class CookieTreeDatabaseNode; friend class CookieTreeLocalStorageNode; DISALLOW_COPY_AND_ASSIGN(CookiesTreeModel); }; #endif // CHROME_BROWSER_COOKIES_TREE_MODEL_H_