| // 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. |
| |
| #ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_MODEL_H_ |
| #define CHROME_BROWSER_BOOKMARKS_BOOKMARK_MODEL_H_ |
| #pragma once |
| |
| #include "build/build_config.h" |
| |
| #include <set> |
| #include <vector> |
| |
| #include "base/observer_list.h" |
| #include "base/string16.h" |
| #include "base/synchronization/lock.h" |
| #include "base/synchronization/waitable_event.h" |
| #include "chrome/browser/bookmarks/bookmark_model_observer.h" |
| #include "chrome/browser/bookmarks/bookmark_service.h" |
| #include "chrome/browser/favicon_service.h" |
| #include "chrome/browser/history/history.h" |
| #include "chrome/browser/history/history_types.h" |
| #include "content/browser/cancelable_request.h" |
| #include "content/common/notification_registrar.h" |
| #include "googleurl/src/gurl.h" |
| #include "testing/gtest/include/gtest/gtest_prod.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "ui/base/models/tree_node_model.h" |
| |
| class BookmarkIndex; |
| class BookmarkLoadDetails; |
| class BookmarkModel; |
| class BookmarkStorage; |
| class Profile; |
| |
| namespace bookmark_utils { |
| struct TitleMatch; |
| } |
| |
| // BookmarkNode --------------------------------------------------------------- |
| |
| // BookmarkNode contains information about a starred entry: title, URL, favicon, |
| // star id and type. BookmarkNodes are returned from a BookmarkModel. |
| // |
| class BookmarkNode : public ui::TreeNode<BookmarkNode> { |
| friend class BookmarkModel; |
| |
| public: |
| enum Type { |
| URL, |
| FOLDER, |
| BOOKMARK_BAR, |
| OTHER_NODE |
| }; |
| // Creates a new node with the specified url and id of 0 |
| explicit BookmarkNode(const GURL& url); |
| // Creates a new node with the specified url and id. |
| BookmarkNode(int64 id, const GURL& url); |
| virtual ~BookmarkNode(); |
| |
| // Returns the URL. |
| const GURL& GetURL() const { return url_; } |
| // Sets the URL to the given value. |
| void SetURL(const GURL& url) { url_ = url; } |
| |
| // Returns a unique id for this node. |
| // For bookmark nodes that are managed by the bookmark model, the IDs are |
| // persisted across sessions. |
| int64 id() const { return id_; } |
| // Sets the id to the given value. |
| void set_id(int64 id) { id_ = id; } |
| |
| // Returns the type of this node. |
| BookmarkNode::Type type() const { return type_; } |
| void set_type(BookmarkNode::Type type) { type_ = type; } |
| |
| // Returns the time the bookmark/folder was added. |
| const base::Time& date_added() const { return date_added_; } |
| // Sets the time the bookmark/folder was added. |
| void set_date_added(const base::Time& date) { date_added_ = date; } |
| |
| // Returns the last time the folder was modified. This is only maintained |
| // for folders (including the bookmark and other folder). |
| const base::Time& date_folder_modified() const { |
| return date_folder_modified_; |
| } |
| // Sets the last time the folder was modified. |
| void set_date_folder_modified(const base::Time& date) { |
| date_folder_modified_ = date; |
| } |
| |
| // Convenience for testing if this nodes represents a folder. A folder is a |
| // node whose type is not URL. |
| bool is_folder() const { return type_ != URL; } |
| |
| // Is this a URL? |
| bool is_url() const { return type_ == URL; } |
| |
| // Returns the favicon. In nearly all cases you should use the method |
| // BookmarkModel::GetFavicon rather than this. BookmarkModel::GetFavicon |
| // takes care of loading the favicon if it isn't already loaded, where as |
| // this does not. |
| const SkBitmap& favicon() const { return favicon_; } |
| void set_favicon(const SkBitmap& icon) { favicon_ = icon; } |
| |
| // The following methods are used by the bookmark model, and are not |
| // really useful outside of it. |
| |
| bool is_favicon_loaded() const { return loaded_favicon_; } |
| void set_favicon_loaded(bool value) { loaded_favicon_ = value; } |
| |
| HistoryService::Handle favicon_load_handle() const { |
| return favicon_load_handle_; |
| } |
| void set_favicon_load_handle(HistoryService::Handle handle) { |
| favicon_load_handle_ = handle; |
| } |
| |
| // Called when the favicon becomes invalid. |
| void InvalidateFavicon(); |
| |
| // Resets the properties of the node from the supplied entry. |
| // This is used by the bookmark model and not really useful outside of it. |
| void Reset(const history::StarredEntry& entry); |
| |
| // TODO(sky): Consider adding last visit time here, it'll greatly simplify |
| // HistoryContentsProvider. |
| |
| private: |
| // helper to initialize various fields during construction. |
| void Initialize(int64 id); |
| |
| // Unique identifier for this node. |
| int64 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_; |
| |
| // The URL. BookmarkModel maintains maps off this URL, it is important that |
| // changes to the URL is done through the bookmark model. |
| GURL url_; |
| |
| // Type of node. |
| BookmarkNode::Type type_; |
| |
| // Date we were created. |
| base::Time date_added_; |
| |
| // Time last modified. Only used for folders. |
| base::Time date_folder_modified_; |
| |
| DISALLOW_COPY_AND_ASSIGN(BookmarkNode); |
| }; |
| |
| // BookmarkModel -------------------------------------------------------------- |
| |
| // BookmarkModel provides a directed acyclic graph of the starred entries |
| // and folders. Two graphs are provided for the two entry points: those on |
| // the bookmark bar, and those in the other folder. |
| // |
| // An observer may be attached to observer relevant events. |
| // |
| // You should NOT directly create a BookmarkModel, instead go through the |
| // Profile. |
| |
| class BookmarkModel : public NotificationObserver, public BookmarkService { |
| friend class BookmarkCodecTest; |
| friend class BookmarkModelTest; |
| friend class BookmarkStorage; |
| |
| public: |
| explicit BookmarkModel(Profile* profile); |
| virtual ~BookmarkModel(); |
| |
| // Loads the bookmarks. This is called by Profile upon creation of the |
| // BookmarkModel. You need not invoke this directly. |
| void Load(); |
| |
| // Returns the root node. The bookmark bar node and other node are children of |
| // the root node. |
| const BookmarkNode* root_node() { return &root_; } |
| |
| // Returns the bookmark bar node. This is NULL until loaded. |
| const BookmarkNode* GetBookmarkBarNode() { return bookmark_bar_node_; } |
| |
| // Returns the 'other' node. This is NULL until loaded. |
| const BookmarkNode* 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). |
| const BookmarkNode* GetParentForNewNodes(); |
| |
| void AddObserver(BookmarkModelObserver* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void RemoveObserver(BookmarkModelObserver* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| // Notify the observes that an import is about to happen, so they can |
| // delay any expensive UI updates until it is finished. |
| void BeginImportMode(); |
| void EndImportMode(); |
| |
| // Unstars or deletes the specified entry. Removing a folder entry recursively |
| // unstars all nodes. Observers are notified immediately. |
| void Remove(const BookmarkNode* parent, int index); |
| |
| // Moves the specified entry to a new location. |
| void Move(const BookmarkNode* node, |
| const BookmarkNode* new_parent, |
| int index); |
| |
| // Duplicates a bookmark node and inserts it at a new location. |
| void Copy(const BookmarkNode* node, |
| const BookmarkNode* new_parent, |
| int index); |
| |
| // Returns the favicon for |node|. If the favicon has not yet been |
| // loaded it is loaded and the observer of the model notified when done. |
| const SkBitmap& GetFavicon(const BookmarkNode* node); |
| |
| // Sets the title of the specified node. |
| void SetTitle(const BookmarkNode* node, const string16& title); |
| |
| // Sets the URL of the specified bookmark node. |
| void SetURL(const BookmarkNode* node, const GURL& url); |
| |
| // Returns true if the model finished loading. |
| virtual bool IsLoaded(); |
| |
| // Returns the set of nodes with the specified URL. |
| void GetNodesByURL(const GURL& url, std::vector<const BookmarkNode*>* nodes); |
| |
| // Returns the most recently added node for the url. Returns NULL if url is |
| // not bookmarked. |
| const BookmarkNode* GetMostRecentlyAddedNodeForURL(const GURL& url); |
| |
| // Returns all the bookmarked urls. This method is thread safe. |
| virtual void GetBookmarks(std::vector<GURL>* urls); |
| |
| // Returns true if there are bookmarks, otherwise returns false. This method |
| // is thread safe. |
| bool HasBookmarks(); |
| |
| // Returns true if there is a bookmark for the specified URL. This method is |
| // thread safe. See BookmarkService for more details on this. |
| virtual bool IsBookmarked(const GURL& url); |
| |
| // Blocks until loaded; this is NOT invoked on the main thread. See |
| // BookmarkService for more details on this. |
| virtual void BlockTillLoaded(); |
| |
| // Returns the node with the specified id, or NULL if there is no node with |
| // the specified id. |
| const BookmarkNode* GetNodeByID(int64 id); |
| |
| // Adds a new folder node at the specified position. |
| const BookmarkNode* AddFolder(const BookmarkNode* parent, |
| int index, |
| const string16& title); |
| |
| // Adds a url at the specified position. |
| const BookmarkNode* AddURL(const BookmarkNode* parent, |
| int index, |
| const string16& title, |
| const GURL& url); |
| |
| // Adds a url with a specific creation date. |
| const BookmarkNode* AddURLWithCreationTime(const BookmarkNode* parent, |
| int index, |
| const string16& title, |
| const GURL& url, |
| const base::Time& creation_time); |
| |
| // Sorts the children of |parent|, notifying observers by way of the |
| // BookmarkNodeChildrenReordered method. |
| void SortChildren(const BookmarkNode* parent); |
| |
| // This is the convenience that makes sure the url is starred or not starred. |
| // If is_starred is false, all bookmarks for URL are removed. If is_starred is |
| // true and there are no bookmarks for url, a bookmark is created. |
| void SetURLStarred(const GURL& url, |
| const string16& title, |
| bool is_starred); |
| |
| // Sets the date modified time of the specified node. |
| void SetDateFolderModified(const BookmarkNode* parent, const base::Time time); |
| |
| // Resets the 'date modified' time of the node to 0. This is used during |
| // importing to exclude the newly created folders from showing up in the |
| // combobox of most recently modified folders. |
| void ResetDateFolderModified(const BookmarkNode* node); |
| |
| void GetBookmarksWithTitlesMatching( |
| const string16& text, |
| size_t max_count, |
| std::vector<bookmark_utils::TitleMatch>* matches); |
| |
| Profile* profile() const { return profile_; } |
| |
| bool is_root(const BookmarkNode* node) const { return node == &root_; } |
| bool is_bookmark_bar_node(const BookmarkNode* node) const { |
| return node == bookmark_bar_node_; |
| } |
| bool is_other_bookmarks_node(const BookmarkNode* node) const { |
| return node == other_node_; |
| } |
| // Returns whether the given node is one of the permanent nodes - root node, |
| // bookmark bar node or other bookmarks node. |
| bool is_permanent_node(const BookmarkNode* node) const { |
| return is_root(node) || |
| is_bookmark_bar_node(node) || |
| is_other_bookmarks_node(node); |
| } |
| |
| // Sets the store to NULL, making it so the BookmarkModel does not persist |
| // any changes to disk. This is only useful during testing to speed up |
| // testing. |
| void ClearStore(); |
| |
| // Returns whether the bookmarks file changed externally. |
| bool file_changed() const { return file_changed_; } |
| |
| // Returns the next node ID. |
| int64 next_node_id() const { return next_node_id_; } |
| |
| private: |
| // Used to order BookmarkNodes by URL. |
| class NodeURLComparator { |
| public: |
| bool operator()(const BookmarkNode* n1, const BookmarkNode* n2) const { |
| return n1->GetURL() < n2->GetURL(); |
| } |
| }; |
| |
| // Implementation of IsBookmarked. Before calling this the caller must |
| // obtain a lock on url_lock_. |
| bool IsBookmarkedNoLock(const GURL& url); |
| |
| // Overriden to notify the observer the favicon has been loaded. |
| void FaviconLoaded(const BookmarkNode* node); |
| |
| // Removes the node from internal maps and recurses through all children. If |
| // the node is a url, its url is added to removed_urls. |
| // |
| // This does NOT delete the node. |
| void RemoveNode(BookmarkNode* node, std::set<GURL>* removed_urls); |
| |
| // Invoked when loading is finished. Sets loaded_ and notifies observers. |
| // BookmarkModel takes ownership of |details|. |
| void DoneLoading(BookmarkLoadDetails* details); |
| |
| // Populates nodes_ordered_by_url_set_ from root. |
| void PopulateNodesByURL(BookmarkNode* node); |
| |
| // Removes the node from its parent, sends notification, and deletes it. |
| // type specifies how the node should be removed. |
| void RemoveAndDeleteNode(BookmarkNode* delete_me); |
| |
| // Adds the node at the specified position and sends notification. If |
| // was_bookmarked is true, it indicates a bookmark already existed for the |
| // URL. |
| BookmarkNode* AddNode(BookmarkNode* parent, |
| int index, |
| BookmarkNode* node, |
| bool was_bookmarked); |
| |
| // Implementation of GetNodeByID. |
| const BookmarkNode* GetNodeByID(const BookmarkNode* node, int64 id); |
| |
| // Returns true if the parent and index are valid. |
| bool IsValidIndex(const BookmarkNode* parent, int index, bool allow_end); |
| |
| // Creates the bookmark bar/other nodes. These call into |
| // CreateRootNodeFromStarredEntry. |
| BookmarkNode* CreateBookmarkNode(); |
| BookmarkNode* CreateOtherBookmarksNode(); |
| |
| // Creates a root node (either the bookmark bar node or other node) from the |
| // specified starred entry. |
| BookmarkNode* CreateRootNodeFromStarredEntry( |
| const history::StarredEntry& entry); |
| |
| // Notification that a favicon has finished loading. If we can decode the |
| // favicon, FaviconLoaded is invoked. |
| void OnFaviconDataAvailable(FaviconService::Handle handle, |
| history::FaviconData favicon); |
| |
| // Invoked from the node to load the favicon. Requests the favicon from the |
| // favicon service. |
| void LoadFavicon(BookmarkNode* node); |
| |
| // If we're waiting on a favicon for node, the load request is canceled. |
| void CancelPendingFaviconLoadRequests(BookmarkNode* node); |
| |
| // NotificationObserver. |
| virtual void Observe(NotificationType type, |
| const NotificationSource& source, |
| const NotificationDetails& details); |
| |
| // Generates and returns the next node ID. |
| int64 generate_next_node_id(); |
| |
| // Sets the maximum node ID to the given value. |
| // This is used by BookmarkCodec to report the maximum ID after it's done |
| // decoding since during decoding codec assigns node IDs. |
| void set_next_node_id(int64 id) { next_node_id_ = id; } |
| |
| // Records that the bookmarks file was changed externally. |
| void SetFileChanged(); |
| |
| // Creates and returns a new BookmarkLoadDetails. It's up to the caller to |
| // delete the returned object. |
| BookmarkLoadDetails* CreateLoadDetails(); |
| |
| NotificationRegistrar registrar_; |
| |
| Profile* profile_; |
| |
| // Whether the initial set of data has been loaded. |
| bool loaded_; |
| |
| // Whether the bookmarks file was changed externally. This is set after |
| // loading is complete and once set the value never changes. |
| bool file_changed_; |
| |
| // The root node. This contains the bookmark bar node and the 'other' node as |
| // children. |
| BookmarkNode root_; |
| |
| BookmarkNode* bookmark_bar_node_; |
| BookmarkNode* other_node_; |
| |
| // The maximum ID assigned to the bookmark nodes in the model. |
| int64 next_node_id_; |
| |
| // The observers. |
| ObserverList<BookmarkModelObserver> observers_; |
| |
| // Set of nodes ordered by URL. This is not a map to avoid copying the |
| // urls. |
| // WARNING: nodes_ordered_by_url_set_ is accessed on multiple threads. As |
| // such, be sure and wrap all usage of it around url_lock_. |
| typedef std::multiset<BookmarkNode*, NodeURLComparator> NodesOrderedByURLSet; |
| NodesOrderedByURLSet nodes_ordered_by_url_set_; |
| base::Lock url_lock_; |
| |
| // Used for loading favicons and the empty history request. |
| CancelableRequestConsumerTSimple<BookmarkNode*> load_consumer_; |
| |
| // Reads/writes bookmarks to disk. |
| scoped_refptr<BookmarkStorage> store_; |
| |
| scoped_ptr<BookmarkIndex> index_; |
| |
| base::WaitableEvent loaded_signal_; |
| |
| DISALLOW_COPY_AND_ASSIGN(BookmarkModel); |
| }; |
| |
| #endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_MODEL_H_ |