diff options
Diffstat (limited to 'chrome/browser/bookmark_bar_model.h')
-rw-r--r-- | chrome/browser/bookmark_bar_model.h | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/chrome/browser/bookmark_bar_model.h b/chrome/browser/bookmark_bar_model.h new file mode 100644 index 0000000..edff1c7 --- /dev/null +++ b/chrome/browser/bookmark_bar_model.h @@ -0,0 +1,417 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_BROWSER_BOOKMARK_BAR_H__ +#define CHROME_BROWSER_BOOKMARK_BAR_H__ + +#include "base/observer_list.h" +#include "chrome/browser/cancelable_request.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/history/history_types.h" +#include "chrome/common/notification_service.h" +#include "chrome/views/tree_node_model.h" +#include "googleurl/src/gurl.h" +#include "skia/include/SkBitmap.h" + +class BookmarkBarModel; +class Profile; + +// BookmarkBarNode ------------------------------------------------------------ + +// BookmarkBarNode contains information about a starred entry: title, URL, +// favicon, star id and type. BookmarkBarNodes are returned from a +// BookmarkBarModel. +// +class BookmarkBarNode : public ChromeViews::TreeNode<BookmarkBarNode> { + friend class BookmarkBarModel; + + public: + explicit BookmarkBarNode(BookmarkBarModel* model); + + virtual ~BookmarkBarNode() {} + + // Returns the favicon for the this node. If the favicon has not yet been + // loaded it is loaded and the observer of the model notified when done. + const SkBitmap& GetFavIcon(); + + // Returns the URL. + const GURL& GetURL() const { return url_; } + + // Returns the start ID corresponding to this node. + history::StarID GetStarID() const { return star_id_; } + + // Returns the type of this node. + history::StarredEntry::Type GetType() const { return type_; } + + // Returns a StarredEntry for the node. + history::StarredEntry GetEntry(); + + // Returns the ID of group. + history::UIStarID GetGroupID() { return group_id_; } + + // Called when the favicon becomes invalid. + void InvalidateFavicon() { + loaded_favicon_ = false; + favicon_ = SkBitmap(); + } + + private: + // Resets the properties of the node from the supplied entry. + void Reset(const history::StarredEntry& entry); + + // Resets the URL. Take care to cancel loading before invoking this. + void SetURL(const GURL& url); + + // The model. + BookmarkBarModel* model_; + + // Unique identifier for this node. + history::StarID star_id_; + + // Whether the favicon has been loaded. + bool loaded_favicon_; + + // The favicon. + SkBitmap favicon_; + + // If non-zero, it indicates we're loading the favicon and this is the handle + // from the HistoryService. + HistoryService::Handle favicon_load_handle_; + + // URL. + GURL url_; + + // Type of node. + history::StarredEntry::Type type_; + + // Group ID. + history::UIStarID group_id_; + + // Date we were created. + Time date_added_; + + // Time last modified. Only used for groups. + Time date_group_modified_; + + DISALLOW_EVIL_CONSTRUCTORS(BookmarkBarNode); +}; + + +// BookmarkBarModelObserver --------------------------------------------------- + +// Observer for the BookmarkBarModel. +// +class BookmarkBarModelObserver { + public: + // Invoked when the model has finished loading. + virtual void Loaded(BookmarkBarModel* model) = 0; + + // Invoked when a node has moved. + virtual void BookmarkNodeMoved(BookmarkBarModel* model, + BookmarkBarNode* old_parent, + int old_index, + BookmarkBarNode* new_parent, + int new_index) = 0; + + // Invoked when a node has been added. + virtual void BookmarkNodeAdded(BookmarkBarModel* model, + BookmarkBarNode* parent, + int index) = 0; + + // Invoked when a node has been removed, the item may still be starred though. + virtual void BookmarkNodeRemoved(BookmarkBarModel* model, + BookmarkBarNode* parent, + int index) = 0; + + // Invoked when the title or favicon of a node has changed. + virtual void BookmarkNodeChanged(BookmarkBarModel* model, + BookmarkBarNode* node) = 0; + + // Invoked when a favicon has finished loading. + virtual void BookmarkNodeFavIconLoaded(BookmarkBarModel* model, + BookmarkBarNode* node) = 0; +}; + +// BookmarkBarModel ----------------------------------------------------------- + +// BookmarkBarModel provides a directed acyclic graph of the starred entries +// and groups. Two graphs are provided for the two entry points: those on +// the bookmark bar, and those in the other folder. +// +// The methods of BookmarkBarModel update the internal structure immediately +// and update the backend in the background. +// +// An observer may be attached to observer relevant events. +// +// You should NOT directly create a BookmarkBarModel, instead go through the +// Profile. + +// TODO(sky): rename to BookmarkModel. +class BookmarkBarModel : public NotificationObserver { + friend class BookmarkBarNode; + friend class BookmarkBarModelTest; + + public: + explicit BookmarkBarModel(Profile* profile); + virtual ~BookmarkBarModel(); + + // Returns the root node. The bookmark bar node and other node are children of + // the root node. + BookmarkBarNode* root_node() { return &root_; } + + // Returns the bookmark bar node. + BookmarkBarNode* GetBookmarkBarNode() { return bookmark_bar_node_; } + + // Returns the 'other' node. + BookmarkBarNode* other_node() { return other_node_; } + + // Returns the parent the last node was added to. This never returns NULL + // (as long as the model is loaded). + BookmarkBarNode* GetParentForNewNodes(); + + // Returns a vector containing up to |max_count| of the most recently + // modified groups. This never returns an empty vector. + std::vector<BookmarkBarNode*> GetMostRecentlyModifiedGroups(size_t max_count); + + void AddObserver(BookmarkBarModelObserver* observer) { + observers_.AddObserver(observer); + } + + void RemoveObserver(BookmarkBarModelObserver* observer) { + observers_.RemoveObserver(observer); + } + + // Unstars or deletes the specified entry. Removing a group entry recursively + // unstars all nodes. Observers are notified immediately. + void Remove(BookmarkBarNode* parent, int index); + + // If the specified node is on the bookmark bar it is removed from the + // bookmark bar to be a child of the other node. If the node is not on the + // bookmark bar this does nothing. This is a convenience for invoking + // Move to the other node. + void RemoveFromBookmarkBar(BookmarkBarNode* node); + + // Moves the specified entry to a new location. + void Move(BookmarkBarNode* node, BookmarkBarNode* new_parent, int index); + + // Sets the title of the specified node. + void SetTitle(BookmarkBarNode* node, const std::wstring& title); + + // Returns true if the model finished loading. + bool IsLoaded() { return loaded_; } + + // Returns the node with the specified URL, or NULL if there is no node with + // the specified URL. + BookmarkBarNode* GetNodeByURL(const GURL& url); + + // Returns the node with the specified group id, or NULL if there is no node + // with the specified id. + BookmarkBarNode* GetNodeByGroupID(history::UIStarID group_id); + + // Adds a new group node at the specified position. + BookmarkBarNode* AddGroup(BookmarkBarNode* parent, + int index, + const std::wstring& title); + + // Adds a url at the specified position. If there is already a node with the + // specified URL, it is moved to the new position. + BookmarkBarNode* AddURL(BookmarkBarNode* parent, + int index, + const std::wstring& title, + const GURL& url); + + // Adds a url with a specific creation date. + BookmarkBarNode* AddURLWithCreationTime(BookmarkBarNode* parent, + int index, + const std::wstring& title, + const GURL& url, + const Time& creation_time); + + // This is the convenience that makes sure the url is starred or not + // starred. If the URL is not currently starred, it is added to the + // most recent parent. + void SetURLStarred(const GURL& url, + const std::wstring& title, + bool is_starred); + + // Resets the 'date modified' time of the node to 0. This is used during + // importing to exclude the newly created groups from showing up in the + // combobox of most recently modified groups. + void ResetDateGroupModified(BookmarkBarNode* node); + + private: + // Used to order BookmarkBarNodes by URL. + class NodeURLComparator { + public: + bool operator()(BookmarkBarNode* n1, BookmarkBarNode* n2) const { + return n1->GetURL() < n2->GetURL(); + } + }; + + // Maps from star id of node to actual node. Used during creation of nodes + // from history::StarredEntries. + typedef std::map<history::StarID,BookmarkBarNode*> IDToNodeMap; + + // Overriden to notify the observer the favicon has been loaded. + void FavIconLoaded(BookmarkBarNode* node); + + // NOTE: this does NOT override EntryAdded/EntryChanged as we assume all + // mutation to entries on the bookmark bar occurs through our methods. + + // Removes the node for internal maps. This does NOT delete the node. + void RemoveNode(BookmarkBarNode* node); + + // Callback from the database with the starred entries. Adds the appropriate + // entries to the root node. + void OnGotStarredEntries(HistoryService::Handle, + std::vector<history::StarredEntry>* entries); + + // Invoked from OnGotStarredEntries to create all the BookmarkNodes for + // the specified entries. + void PopulateNodes(std::vector<history::StarredEntry>* entries); + + // Callback from AddFolder/AddURL. + void OnCreatedEntry(HistoryService::Handle handle, history::StarID id); + + // Removes the node from its parent, sends notification, and deletes it. + // type specifies how the node should be removed. + void RemoveAndDeleteNode(BookmarkBarNode* delete_me); + + // Adds the node at the specified position, and sends notification. + BookmarkBarNode* AddNode(BookmarkBarNode* parent, + int index, + BookmarkBarNode* node); + + // Implementation of GetNodeByGrouID. + BookmarkBarNode* GetNodeByGroupID(BookmarkBarNode* node, + history::UIStarID group_id); + + // Adds the bookmark bar and other nodes to the root node. If id_to_node_map + // is non-null, the bookmark bar node and other bookmark nodes are added to + // it. + void AddRootChildren(IDToNodeMap* id_to_node_map); + +#ifndef NDEBUG + void CheckIndex(BookmarkBarNode* parent, int index, bool allow_end) { + DCHECK(parent); + DCHECK(index >= 0 && + (index < parent->GetChildCount() || + allow_end && index == parent->GetChildCount())); + } +#endif + + // Sets the date modified time of the specified node. + void SetDateGroupModified(BookmarkBarNode* parent, const Time time); + + // Creates the bookmark bar/other nodes. This is used during testing (when we + // don't load from the DB), as well as if the db doesn't give us back a + // bookmark bar or other node (which should only happen if there is an error + // in loading the DB). + void CreateBookmarkBarNode(); + void CreateOtherBookmarksNode(); + + // Creates a root node (either the bookmark bar node or other node) from the + // specified starred entry. Only used once when loading. + BookmarkBarNode* CreateRootNodeFromStarredEntry( + const history::StarredEntry& entry); + + // Notification that a favicon has finished loading. If we can decode the + // favicon, FaviconLoaded is invoked. + void OnFavIconDataAvailable( + HistoryService::Handle handle, + bool know_favicon, + scoped_refptr<RefCountedBytes> data, + bool expired, + GURL icon_url); + + // Invoked from the node to load the favicon. Requests the favicon from the + // history service. + void LoadFavIcon(BookmarkBarNode* node); + + // If we're waiting on a favicon for node, the load request is canceled. + void CancelPendingFavIconLoadRequests(BookmarkBarNode* node); + + // Returns true if n1's date modified time is newer than n2s. + static bool MoreRecentlyModified(BookmarkBarNode* n1, BookmarkBarNode* n2); + + // Returns up to count of the most recently modified groups. This may not + // add anything. + void GetMostRecentlyModifiedGroupNodes(BookmarkBarNode* parent, + size_t count, + std::vector<BookmarkBarNode*>* nodes); + + // NotificationObserver. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + Profile* profile_; + + // Whether the initial set of data has been loaded. + bool loaded_; + + // The root node. This contains the bookmark bar node and the 'other' node as + // children. + BookmarkBarNode root_; + + BookmarkBarNode* bookmark_bar_node_; + BookmarkBarNode* other_node_; + + // The observers. + ObserverList<BookmarkBarModelObserver> observers_; + + // Set of nodes ordered by URL. This is not a map to avoid copying the + // urls. + typedef std::set<BookmarkBarNode*,NodeURLComparator> NodesOrderedByURLSet; + NodesOrderedByURLSet nodes_ordered_by_url_set_; + + // Maps from node to request handle. This is used when creating new nodes. + typedef std::map<BookmarkBarNode*,HistoryService::Handle> NodeToHandleMap; + NodeToHandleMap node_to_handle_map_; + + // Used when creating new entries/groups. Maps to the newly created + // node. + CancelableRequestConsumerT<BookmarkBarNode*,NULL> request_consumer_; + + // ID of the next group we create. + // + // After the first load, this is set to the max group_id from the database. + // + // This value is incremented every time a new group is created. It is + // important that the value assigned to a group node remain unique during + // a run of Chrome (BookmarkEditorView for one relies on this). + history::StarID next_group_id_; + + // Used for loading favicons. + CancelableRequestConsumerT<BookmarkBarNode*, NULL> load_consumer_; + + DISALLOW_EVIL_CONSTRUCTORS(BookmarkBarModel); +}; + +#endif // CHROME_BROWSER_BOOKMARK_BAR_H__ |