Popular sites on the NTP: Try to keep the ordering constant
[chromium-blink-merge.git] / components / bookmarks / browser / bookmark_model.h
blob27837703d0adc6719ef330fb483cd6afe1d1bcb7
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MODEL_H_
6 #define COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MODEL_H_
8 #include <stdint.h>
9 #include <map>
10 #include <set>
11 #include <vector>
13 #include "base/compiler_specific.h"
14 #include "base/macros.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/observer_list.h"
18 #include "base/strings/string16.h"
19 #include "base/synchronization/lock.h"
20 #include "base/synchronization/waitable_event.h"
21 #include "components/bookmarks/browser/bookmark_client.h"
22 #include "components/bookmarks/browser/bookmark_node.h"
23 #include "components/keyed_service/core/keyed_service.h"
24 #include "ui/gfx/image/image.h"
25 #include "url/gurl.h"
27 class PrefService;
29 namespace base {
30 class FilePath;
31 class SequencedTaskRunner;
34 namespace favicon_base {
35 struct FaviconImageResult;
38 namespace query_parser {
39 enum class MatchingAlgorithm;
42 namespace bookmarks {
44 class BookmarkCodecTest;
45 class BookmarkExpandedStateTracker;
46 class BookmarkIndex;
47 class BookmarkLoadDetails;
48 class BookmarkModelObserver;
49 class BookmarkStorage;
50 class ScopedGroupBookmarkActions;
51 class TestBookmarkClient;
52 struct BookmarkMatch;
54 // BookmarkModel --------------------------------------------------------------
56 // BookmarkModel provides a directed acyclic graph of URLs and folders.
57 // Three graphs are provided for the three entry points: those on the 'bookmarks
58 // bar', those in the 'other bookmarks' folder and those in the 'mobile' folder.
60 // An observer may be attached to observe relevant events.
62 // You should NOT directly create a BookmarkModel, instead go through the
63 // BookmarkModelFactory.
64 class BookmarkModel : public KeyedService {
65 public:
66 struct URLAndTitle {
67 GURL url;
68 base::string16 title;
71 explicit BookmarkModel(BookmarkClient* client);
72 ~BookmarkModel() override;
74 // KeyedService:
75 void Shutdown() override;
77 // Loads the bookmarks. This is called upon creation of the
78 // BookmarkModel. You need not invoke this directly.
79 // All load operations will be executed on |io_task_runner| and the completion
80 // callback will be called from |ui_task_runner|.
81 void Load(PrefService* pref_service,
82 const std::string& accept_languages,
83 const base::FilePath& profile_path,
84 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
85 const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner);
87 // Returns true if the model finished loading.
88 bool loaded() const { return loaded_; }
90 // Returns the root node. The 'bookmark bar' node and 'other' node are
91 // children of the root node.
92 const BookmarkNode* root_node() const { return &root_; }
94 // Returns the 'bookmark bar' node. This is NULL until loaded.
95 const BookmarkNode* bookmark_bar_node() const { return bookmark_bar_node_; }
97 // Returns the 'other' node. This is NULL until loaded.
98 const BookmarkNode* other_node() const { return other_node_; }
100 // Returns the 'mobile' node. This is NULL until loaded.
101 const BookmarkNode* mobile_node() const { return mobile_node_; }
103 bool is_root_node(const BookmarkNode* node) const { return node == &root_; }
105 // Returns whether the given |node| is one of the permanent nodes - root node,
106 // 'bookmark bar' node, 'other' node or 'mobile' node, or one of the root
107 // nodes supplied by the |client_|.
108 bool is_permanent_node(const BookmarkNode* node) const {
109 return node && (node == &root_ || node->parent() == &root_);
112 // Returns the parent the last node was added to. This never returns NULL
113 // (as long as the model is loaded).
114 const BookmarkNode* GetParentForNewNodes();
116 void AddObserver(BookmarkModelObserver* observer);
117 void RemoveObserver(BookmarkModelObserver* observer);
119 // Notifies the observers that an extensive set of changes is about to happen,
120 // such as during import or sync, so they can delay any expensive UI updates
121 // until it's finished.
122 void BeginExtensiveChanges();
123 void EndExtensiveChanges();
125 // Returns true if this bookmark model is currently in a mode where extensive
126 // changes might happen, such as for import and sync. This is helpful for
127 // observers that are created after the mode has started, and want to check
128 // state during their own initializer, such as the NTP.
129 bool IsDoingExtensiveChanges() const { return extensive_changes_ > 0; }
131 // Removes |node| from the model and deletes it. Removing a folder node
132 // recursively removes all nodes. Observers are notified immediately.
133 void Remove(const BookmarkNode* node);
135 // Removes all the non-permanent bookmark nodes that are editable by the user.
136 // Observers are only notified when all nodes have been removed. There is no
137 // notification for individual node removals.
138 void RemoveAllUserBookmarks();
140 // Moves |node| to |new_parent| and inserts it at the given |index|.
141 void Move(const BookmarkNode* node,
142 const BookmarkNode* new_parent,
143 int index);
145 // Inserts a copy of |node| into |new_parent| at |index|.
146 void Copy(const BookmarkNode* node,
147 const BookmarkNode* new_parent,
148 int index);
150 // Returns the favicon for |node|. If the favicon has not yet been
151 // loaded it is loaded and the observer of the model notified when done.
152 const gfx::Image& GetFavicon(const BookmarkNode* node);
154 // Returns the type of the favicon for |node|. If the favicon has not yet
155 // been loaded, it returns |favicon_base::INVALID_ICON|.
156 favicon_base::IconType GetFaviconType(const BookmarkNode* node);
158 // Sets the title of |node|.
159 void SetTitle(const BookmarkNode* node, const base::string16& title);
161 // Sets the URL of |node|.
162 void SetURL(const BookmarkNode* node, const GURL& url);
164 // Sets the date added time of |node|.
165 void SetDateAdded(const BookmarkNode* node, base::Time date_added);
167 // Returns the set of nodes with the |url|.
168 void GetNodesByURL(const GURL& url, std::vector<const BookmarkNode*>* nodes);
170 // Returns the most recently added user node for the |url|; urls from any
171 // nodes that are not editable by the user are never returned by this call.
172 // Returns NULL if |url| is not bookmarked.
173 const BookmarkNode* GetMostRecentlyAddedUserNodeForURL(const GURL& url);
175 // Returns true if there are bookmarks, otherwise returns false.
176 // This method is thread safe.
177 bool HasBookmarks();
179 // Returns true if the specified URL is bookmarked.
181 // If not on the main thread you *must* invoke BlockTillLoaded first.
182 bool IsBookmarked(const GURL& url);
184 // Returns, by reference in |bookmarks|, the set of bookmarked urls and their
185 // titles. This returns the unique set of URLs. For example, if two bookmarks
186 // reference the same URL only one entry is added not matter the titles are
187 // same or not.
189 // If not on the main thread you *must* invoke BlockTillLoaded first.
190 void GetBookmarks(std::vector<BookmarkModel::URLAndTitle>* urls);
192 // Blocks until loaded. This is intended for usage on a thread other than
193 // the main thread.
194 void BlockTillLoaded();
196 // Adds a new folder node at the specified position.
197 const BookmarkNode* AddFolder(const BookmarkNode* parent,
198 int index,
199 const base::string16& title);
201 // Adds a new folder with meta info.
202 const BookmarkNode* AddFolderWithMetaInfo(
203 const BookmarkNode* parent,
204 int index,
205 const base::string16& title,
206 const BookmarkNode::MetaInfoMap* meta_info);
208 // Adds a url at the specified position.
209 const BookmarkNode* AddURL(const BookmarkNode* parent,
210 int index,
211 const base::string16& title,
212 const GURL& url);
214 // Adds a url with a specific creation date and meta info.
215 const BookmarkNode* AddURLWithCreationTimeAndMetaInfo(
216 const BookmarkNode* parent,
217 int index,
218 const base::string16& title,
219 const GURL& url,
220 const base::Time& creation_time,
221 const BookmarkNode::MetaInfoMap* meta_info);
223 // Sorts the children of |parent|, notifying observers by way of the
224 // BookmarkNodeChildrenReordered method.
225 void SortChildren(const BookmarkNode* parent);
227 // Order the children of |parent| as specified in |ordered_nodes|. This
228 // function should only be used to reorder the child nodes of |parent| and
229 // is not meant to move nodes between different parent. Notifies observers
230 // using the BookmarkNodeChildrenReordered method.
231 void ReorderChildren(const BookmarkNode* parent,
232 const std::vector<const BookmarkNode*>& ordered_nodes);
234 // Sets the date when the folder was modified.
235 void SetDateFolderModified(const BookmarkNode* node, const base::Time time);
237 // Resets the 'date modified' time of the node to 0. This is used during
238 // importing to exclude the newly created folders from showing up in the
239 // combobox of most recently modified folders.
240 void ResetDateFolderModified(const BookmarkNode* node);
242 // Returns up to |max_count| of bookmarks containing each term from |text|
243 // in either the title or the URL. It uses default matching algorithm.
244 void GetBookmarksMatching(const base::string16& text,
245 size_t max_count,
246 std::vector<BookmarkMatch>* matches);
248 // Returns up to |max_count| of bookmarks containing each term from |text|
249 // in either the title or the URL.
250 void GetBookmarksMatching(const base::string16& text,
251 size_t max_count,
252 query_parser::MatchingAlgorithm matching_algorithm,
253 std::vector<BookmarkMatch>* matches);
255 // Sets the store to NULL, making it so the BookmarkModel does not persist
256 // any changes to disk. This is only useful during testing to speed up
257 // testing.
258 void ClearStore();
260 // Returns the next node ID.
261 int64_t next_node_id() const { return next_node_id_; }
263 // Returns the object responsible for tracking the set of expanded nodes in
264 // the bookmark editor.
265 BookmarkExpandedStateTracker* expanded_state_tracker() {
266 return expanded_state_tracker_.get();
269 // Sets the visibility of one of the permanent nodes (unless the node must
270 // always be visible, see |BookmarkClient::IsPermanentNodeVisible| for more
271 // details). This is set by sync.
272 void SetPermanentNodeVisible(BookmarkNode::Type type, bool value);
274 // Returns the permanent node of type |type|.
275 const BookmarkPermanentNode* PermanentNode(BookmarkNode::Type type);
277 // Sets/deletes meta info of |node|.
278 void SetNodeMetaInfo(const BookmarkNode* node,
279 const std::string& key,
280 const std::string& value);
281 void SetNodeMetaInfoMap(const BookmarkNode* node,
282 const BookmarkNode::MetaInfoMap& meta_info_map);
283 void DeleteNodeMetaInfo(const BookmarkNode* node,
284 const std::string& key);
286 // Adds |key| to the set of meta info keys that are not copied when a node is
287 // cloned.
288 void AddNonClonedKey(const std::string& key);
290 // Returns the set of meta info keys that should not be copied when a node is
291 // cloned.
292 const std::set<std::string>& non_cloned_keys() const {
293 return non_cloned_keys_;
296 // Sets the sync transaction version of |node|.
297 void SetNodeSyncTransactionVersion(const BookmarkNode* node,
298 int64_t sync_transaction_version);
300 // Notify BookmarkModel that the favicons for the given page URLs (e.g.
301 // http://www.google.com) and the given icon URL (e.g.
302 // http://www.google.com/favicon.ico) have changed. It is valid to call
303 // OnFaviconsChanged() with non-empty |page_urls| and an empty |icon_url| and
304 // vice versa.
305 void OnFaviconsChanged(const std::set<GURL>& page_urls,
306 const GURL& icon_url);
308 // Returns the client used by this BookmarkModel.
309 BookmarkClient* client() const { return client_; }
311 private:
312 friend class BookmarkCodecTest;
313 friend class BookmarkModelFaviconTest;
314 friend class BookmarkStorage;
315 friend class ScopedGroupBookmarkActions;
316 friend class TestBookmarkClient;
318 // Used to order BookmarkNodes by URL.
319 class NodeURLComparator {
320 public:
321 bool operator()(const BookmarkNode* n1, const BookmarkNode* n2) const {
322 return n1->url() < n2->url();
326 // Implementation of IsBookmarked. Before calling this the caller must obtain
327 // a lock on |url_lock_|.
328 bool IsBookmarkedNoLock(const GURL& url);
330 // Removes the node from internal maps and recurses through all children. If
331 // the node is a url, its url is added to removed_urls.
333 // This does NOT delete the node.
334 void RemoveNode(BookmarkNode* node, std::set<GURL>* removed_urls);
336 // Invoked when loading is finished. Sets |loaded_| and notifies observers.
337 // BookmarkModel takes ownership of |details|.
338 void DoneLoading(scoped_ptr<BookmarkLoadDetails> details);
340 // Populates |nodes_ordered_by_url_set_| from root.
341 void PopulateNodesByURL(BookmarkNode* node);
343 // Removes the node from its parent, but does not delete it. No notifications
344 // are sent. |removed_urls| is populated with the urls which no longer have
345 // any bookmarks associated with them.
346 // This method should be called after acquiring |url_lock_|.
347 void RemoveNodeAndGetRemovedUrls(BookmarkNode* node,
348 std::set<GURL>* removed_urls);
350 // Removes the node from its parent, sends notification, and deletes it.
351 // type specifies how the node should be removed.
352 void RemoveAndDeleteNode(BookmarkNode* delete_me);
354 // Remove |node| from |nodes_ordered_by_url_set_| and |index_|.
355 void RemoveNodeFromInternalMaps(BookmarkNode* node);
357 // Adds the |node| at |parent| in the specified |index| and notifies its
358 // observers.
359 BookmarkNode* AddNode(BookmarkNode* parent,
360 int index,
361 BookmarkNode* node);
363 // Adds the |node| to |nodes_ordered_by_url_set_| and |index_|.
364 void AddNodeToInternalMaps(BookmarkNode* node);
366 // Returns true if the parent and index are valid.
367 bool IsValidIndex(const BookmarkNode* parent, int index, bool allow_end);
369 // Creates one of the possible permanent nodes (bookmark bar node, other node
370 // and mobile node) from |type|.
371 BookmarkPermanentNode* CreatePermanentNode(BookmarkNode::Type type);
373 // Notification that a favicon has finished loading. If we can decode the
374 // favicon, FaviconLoaded is invoked.
375 void OnFaviconDataAvailable(
376 BookmarkNode* node,
377 favicon_base::IconType icon_type,
378 const favicon_base::FaviconImageResult& image_result);
380 // Invoked from the node to load the favicon. Requests the favicon from the
381 // favicon service.
382 void LoadFavicon(BookmarkNode* node, favicon_base::IconType icon_type);
384 // Called to notify the observers that the favicon has been loaded.
385 void FaviconLoaded(const BookmarkNode* node);
387 // If we're waiting on a favicon for node, the load request is canceled.
388 void CancelPendingFaviconLoadRequests(BookmarkNode* node);
390 // Notifies the observers that a set of changes initiated by a single user
391 // action is about to happen and has completed.
392 void BeginGroupedChanges();
393 void EndGroupedChanges();
395 // Generates and returns the next node ID.
396 int64_t generate_next_node_id();
398 // Sets the maximum node ID to the given value.
399 // This is used by BookmarkCodec to report the maximum ID after it's done
400 // decoding since during decoding codec assigns node IDs.
401 void set_next_node_id(int64_t id) { next_node_id_ = id; }
403 // Creates and returns a new BookmarkLoadDetails. It's up to the caller to
404 // delete the returned object.
405 scoped_ptr<BookmarkLoadDetails> CreateLoadDetails(
406 const std::string& accept_languages);
408 BookmarkClient* const client_;
410 // Whether the initial set of data has been loaded.
411 bool loaded_;
413 // The root node. This contains the bookmark bar node, the 'other' node and
414 // the mobile node as children.
415 BookmarkNode root_;
417 BookmarkPermanentNode* bookmark_bar_node_;
418 BookmarkPermanentNode* other_node_;
419 BookmarkPermanentNode* mobile_node_;
421 // The maximum ID assigned to the bookmark nodes in the model.
422 int64_t next_node_id_;
424 // The observers.
425 base::ObserverList<BookmarkModelObserver> observers_;
427 // Set of nodes ordered by URL. This is not a map to avoid copying the
428 // urls.
429 // WARNING: |nodes_ordered_by_url_set_| is accessed on multiple threads. As
430 // such, be sure and wrap all usage of it around |url_lock_|.
431 typedef std::multiset<BookmarkNode*, NodeURLComparator> NodesOrderedByURLSet;
432 NodesOrderedByURLSet nodes_ordered_by_url_set_;
433 base::Lock url_lock_;
435 // Used for loading favicons.
436 base::CancelableTaskTracker cancelable_task_tracker_;
438 // Reads/writes bookmarks to disk.
439 scoped_ptr<BookmarkStorage> store_;
441 scoped_ptr<BookmarkIndex> index_;
443 base::WaitableEvent loaded_signal_;
445 // See description of IsDoingExtensiveChanges above.
446 int extensive_changes_;
448 scoped_ptr<BookmarkExpandedStateTracker> expanded_state_tracker_;
450 std::set<std::string> non_cloned_keys_;
452 DISALLOW_COPY_AND_ASSIGN(BookmarkModel);
455 } // namespace bookmarks
457 #endif // COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MODEL_H_