NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / bookmarks / bookmark_model.h
blob5578bc1825f4e5acc16b393f6a253a9cbda75838
1 // Copyright (c) 2012 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 CHROME_BROWSER_BOOKMARKS_BOOKMARK_MODEL_H_
6 #define CHROME_BROWSER_BOOKMARKS_BOOKMARK_MODEL_H_
8 #include <map>
9 #include <set>
10 #include <vector>
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/observer_list.h"
17 #include "base/strings/string16.h"
18 #include "base/synchronization/lock.h"
19 #include "base/synchronization/waitable_event.h"
20 #include "base/task/cancelable_task_tracker.h"
21 #include "chrome/browser/bookmarks/bookmark_service.h"
22 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
23 #include "content/public/browser/notification_observer.h"
24 #include "content/public/browser/notification_registrar.h"
25 #include "ui/base/models/tree_node_model.h"
26 #include "ui/gfx/image/image.h"
27 #include "url/gurl.h"
29 class BookmarkExpandedStateTracker;
30 class BookmarkIndex;
31 class BookmarkLoadDetails;
32 class BookmarkModel;
33 class BookmarkModelObserver;
34 class BookmarkStorage;
35 struct BookmarkTitleMatch;
36 class Profile;
38 namespace base {
39 class SequencedTaskRunner;
42 namespace chrome {
43 struct FaviconImageResult;
46 // BookmarkNode ---------------------------------------------------------------
48 // BookmarkNode contains information about a starred entry: title, URL, favicon,
49 // id and type. BookmarkNodes are returned from BookmarkModel.
50 class BookmarkNode : public ui::TreeNode<BookmarkNode> {
51 public:
52 enum Type {
53 URL,
54 FOLDER,
55 BOOKMARK_BAR,
56 OTHER_NODE,
57 MOBILE
60 enum FaviconState {
61 INVALID_FAVICON,
62 LOADING_FAVICON,
63 LOADED_FAVICON,
66 typedef std::map<std::string, std::string> MetaInfoMap;
68 static const int64 kInvalidSyncTransactionVersion;
70 // Creates a new node with an id of 0 and |url|.
71 explicit BookmarkNode(const GURL& url);
72 // Creates a new node with |id| and |url|.
73 BookmarkNode(int64 id, const GURL& url);
75 virtual ~BookmarkNode();
77 // Set the node's internal title. Note that this neither invokes observers
78 // nor updates any bookmark model this node may be in. For that functionality,
79 // BookmarkModel::SetTitle(..) should be used instead.
80 virtual void SetTitle(const base::string16& title) OVERRIDE;
82 // Returns an unique id for this node.
83 // For bookmark nodes that are managed by the bookmark model, the IDs are
84 // persisted across sessions.
85 int64 id() const { return id_; }
86 void set_id(int64 id) { id_ = id; }
88 const GURL& url() const { return url_; }
89 void set_url(const GURL& url) { url_ = url; }
91 // Returns the favicon's URL. Returns an empty URL if there is no favicon
92 // associated with this bookmark.
93 const GURL& icon_url() const { return icon_url_; }
95 Type type() const { return type_; }
96 void set_type(Type type) { type_ = type; }
98 // Returns the time the node was added.
99 const base::Time& date_added() const { return date_added_; }
100 void set_date_added(const base::Time& date) { date_added_ = date; }
102 // Returns the last time the folder was modified. This is only maintained
103 // for folders (including the bookmark bar and other folder).
104 const base::Time& date_folder_modified() const {
105 return date_folder_modified_;
107 void set_date_folder_modified(const base::Time& date) {
108 date_folder_modified_ = date;
111 // Convenience for testing if this node represents a folder. A folder is a
112 // node whose type is not URL.
113 bool is_folder() const { return type_ != URL; }
114 bool is_url() const { return type_ == URL; }
116 bool is_favicon_loaded() const { return favicon_state_ == LOADED_FAVICON; }
118 // Accessor method for controlling the visibility of a bookmark node/sub-tree.
119 // Note that visibility is not propagated down the tree hierarchy so if a
120 // parent node is marked as invisible, a child node may return "Visible". This
121 // function is primarily useful when traversing the model to generate a UI
122 // representation but we may want to suppress some nodes.
123 virtual bool IsVisible() const;
125 // Gets/sets/deletes value of |key| in the meta info represented by
126 // |meta_info_str_|. Return true if key is found in meta info for gets or
127 // meta info is changed indeed for sets/deletes.
128 bool GetMetaInfo(const std::string& key, std::string* value) const;
129 bool SetMetaInfo(const std::string& key, const std::string& value);
130 bool DeleteMetaInfo(const std::string& key);
131 void SetMetaInfoMap(const MetaInfoMap& meta_info_map);
132 // Returns NULL if there are no values in the map.
133 const MetaInfoMap* GetMetaInfoMap() const;
135 void set_sync_transaction_version(int64 sync_transaction_version) {
136 sync_transaction_version_ = sync_transaction_version;
138 int64 sync_transaction_version() const {
139 return sync_transaction_version_;
142 // TODO(sky): Consider adding last visit time here, it'll greatly simplify
143 // HistoryContentsProvider.
145 private:
146 friend class BookmarkModel;
148 // A helper function to initialize various fields during construction.
149 void Initialize(int64 id);
151 // Called when the favicon becomes invalid.
152 void InvalidateFavicon();
154 // Sets the favicon's URL.
155 void set_icon_url(const GURL& icon_url) {
156 icon_url_ = icon_url;
159 const gfx::Image& favicon() const { return favicon_; }
160 void set_favicon(const gfx::Image& icon) { favicon_ = icon; }
162 FaviconState favicon_state() const { return favicon_state_; }
163 void set_favicon_state(FaviconState state) { favicon_state_ = state; }
165 base::CancelableTaskTracker::TaskId favicon_load_task_id() const {
166 return favicon_load_task_id_;
168 void set_favicon_load_task_id(base::CancelableTaskTracker::TaskId id) {
169 favicon_load_task_id_ = id;
172 // The unique identifier for this node.
173 int64 id_;
175 // The URL of this node. BookmarkModel maintains maps off this URL, so changes
176 // to the URL must be done through the BookmarkModel.
177 GURL url_;
179 // The type of this node. See enum above.
180 Type type_;
182 // Date of when this node was created.
183 base::Time date_added_;
185 // Date of the last modification. Only used for folders.
186 base::Time date_folder_modified_;
188 // The favicon of this node.
189 gfx::Image favicon_;
191 // The URL of the node's favicon.
192 GURL icon_url_;
194 // The loading state of the favicon.
195 FaviconState favicon_state_;
197 // If not base::CancelableTaskTracker::kBadTaskId, it indicates
198 // we're loading the
199 // favicon and the task is tracked by CancelabelTaskTracker.
200 base::CancelableTaskTracker::TaskId favicon_load_task_id_;
202 // A map that stores arbitrary meta information about the node.
203 scoped_ptr<MetaInfoMap> meta_info_map_;
205 // The sync transaction version. Defaults to kInvalidSyncTransactionVersion.
206 int64 sync_transaction_version_;
208 DISALLOW_COPY_AND_ASSIGN(BookmarkNode);
211 // BookmarkPermanentNode -------------------------------------------------------
213 // Node used for the permanent folders (excluding the root).
214 class BookmarkPermanentNode : public BookmarkNode {
215 public:
216 explicit BookmarkPermanentNode(int64 id);
217 virtual ~BookmarkPermanentNode();
219 // WARNING: this code is used for other projects. Contact noyau@ for details.
220 void set_visible(bool value) { visible_ = value; }
222 // BookmarkNode overrides:
223 virtual bool IsVisible() const OVERRIDE;
225 private:
226 bool visible_;
228 DISALLOW_COPY_AND_ASSIGN(BookmarkPermanentNode);
231 // BookmarkModel --------------------------------------------------------------
233 // BookmarkModel provides a directed acyclic graph of URLs and folders.
234 // Three graphs are provided for the three entry points: those on the 'bookmarks
235 // bar', those in the 'other bookmarks' folder and those in the 'mobile' folder.
237 // An observer may be attached to observe relevant events.
239 // You should NOT directly create a BookmarkModel, instead go through the
240 // BookmarkModelFactory.
241 class BookmarkModel : public content::NotificationObserver,
242 public BookmarkService,
243 public BrowserContextKeyedService {
244 public:
245 explicit BookmarkModel(Profile* profile);
246 virtual ~BookmarkModel();
248 // Invoked prior to destruction to release any necessary resources.
249 virtual void Shutdown() OVERRIDE;
251 // Loads the bookmarks. This is called upon creation of the
252 // BookmarkModel. You need not invoke this directly.
253 // All load operations will be executed on |task_runner|.
254 void Load(const scoped_refptr<base::SequencedTaskRunner>& task_runner);
256 // Returns true if the model finished loading.
257 bool loaded() const { return loaded_; }
259 // Returns the root node. The 'bookmark bar' node and 'other' node are
260 // children of the root node.
261 const BookmarkNode* root_node() { return &root_; }
263 // Returns the 'bookmark bar' node. This is NULL until loaded.
264 const BookmarkNode* bookmark_bar_node() { return bookmark_bar_node_; }
266 // Returns the 'other' node. This is NULL until loaded.
267 const BookmarkNode* other_node() { return other_node_; }
269 // Returns the 'mobile' node. This is NULL until loaded.
270 const BookmarkNode* mobile_node() { return mobile_node_; }
272 bool is_root_node(const BookmarkNode* node) const { return node == &root_; }
274 // Returns whether the given |node| is one of the permanent nodes - root node,
275 // 'bookmark bar' node, 'other' node or 'mobile' node.
276 bool is_permanent_node(const BookmarkNode* node) const {
277 return node == &root_ ||
278 node == bookmark_bar_node_ ||
279 node == other_node_ ||
280 node == mobile_node_;
283 // Returns the parent the last node was added to. This never returns NULL
284 // (as long as the model is loaded).
285 const BookmarkNode* GetParentForNewNodes();
287 void AddObserver(BookmarkModelObserver* observer);
288 void RemoveObserver(BookmarkModelObserver* observer);
290 // Notifies the observers that an extensive set of changes is about to happen,
291 // such as during import or sync, so they can delay any expensive UI updates
292 // until it's finished.
293 void BeginExtensiveChanges();
294 void EndExtensiveChanges();
296 // Returns true if this bookmark model is currently in a mode where extensive
297 // changes might happen, such as for import and sync. This is helpful for
298 // observers that are created after the mode has started, and want to check
299 // state during their own initializer, such as the NTP.
300 bool IsDoingExtensiveChanges() const { return extensive_changes_ > 0; }
302 // Removes the node at the given |index| from |parent|. Removing a folder node
303 // recursively removes all nodes. Observers are notified immediately.
304 void Remove(const BookmarkNode* parent, int index);
306 // Removes all the non-permanent bookmark nodes. Observers are only notified
307 // when all nodes have been removed. There is no notification for individual
308 // node removals.
309 void RemoveAll();
311 // Moves |node| to |new_parent| and inserts it at the given |index|.
312 void Move(const BookmarkNode* node,
313 const BookmarkNode* new_parent,
314 int index);
316 // Inserts a copy of |node| into |new_parent| at |index|.
317 void Copy(const BookmarkNode* node,
318 const BookmarkNode* new_parent,
319 int index);
321 // Returns the favicon for |node|. If the favicon has not yet been
322 // loaded it is loaded and the observer of the model notified when done.
323 const gfx::Image& GetFavicon(const BookmarkNode* node);
325 // Sets the title of |node|.
326 void SetTitle(const BookmarkNode* node, const base::string16& title);
328 // Sets the URL of |node|.
329 void SetURL(const BookmarkNode* node, const GURL& url);
331 // Sets the date added time of |node|.
332 void SetDateAdded(const BookmarkNode* node, base::Time date_added);
334 // Returns the set of nodes with the |url|.
335 void GetNodesByURL(const GURL& url, std::vector<const BookmarkNode*>* nodes);
337 // Returns the most recently added node for the |url|. Returns NULL if |url|
338 // is not bookmarked.
339 const BookmarkNode* GetMostRecentlyAddedNodeForURL(const GURL& url);
341 // Returns true if there are bookmarks, otherwise returns false.
342 // This method is thread safe.
343 bool HasBookmarks();
345 // Returns true if there is a bookmark with the |url|.
346 // This method is thread safe.
347 // See BookmarkService for more details on this.
348 virtual bool IsBookmarked(const GURL& url) OVERRIDE;
350 // Returns all the bookmarked urls and their titles.
351 // This method is thread safe.
352 // See BookmarkService for more details on this.
353 virtual void GetBookmarks(
354 std::vector<BookmarkService::URLAndTitle>* urls) OVERRIDE;
356 // Blocks until loaded; this is NOT invoked on the main thread.
357 // See BookmarkService for more details on this.
358 virtual void BlockTillLoaded() OVERRIDE;
360 // Returns the node with |id|, or NULL if there is no node with |id|.
361 const BookmarkNode* GetNodeByID(int64 id) const;
363 // Adds a new folder node at the specified position.
364 const BookmarkNode* AddFolder(const BookmarkNode* parent,
365 int index,
366 const base::string16& title);
368 // Adds a url at the specified position.
369 const BookmarkNode* AddURL(const BookmarkNode* parent,
370 int index,
371 const base::string16& title,
372 const GURL& url);
374 // Adds a url with a specific creation date.
375 const BookmarkNode* AddURLWithCreationTime(const BookmarkNode* parent,
376 int index,
377 const base::string16& title,
378 const GURL& url,
379 const base::Time& creation_time);
381 // Sorts the children of |parent|, notifying observers by way of the
382 // BookmarkNodeChildrenReordered method.
383 void SortChildren(const BookmarkNode* parent);
385 // Order the children of |parent| as specified in |ordered_nodes|. This
386 // function should only be used to reorder the child nodes of |parent| and
387 // is not meant to move nodes between different parent. Notifies observers
388 // using the BookmarkNodeChildrenReordered method.
389 void ReorderChildren(const BookmarkNode* parent,
390 const std::vector<const BookmarkNode*>& ordered_nodes);
392 // Sets the date when the folder was modified.
393 void SetDateFolderModified(const BookmarkNode* node, const base::Time time);
395 // Resets the 'date modified' time of the node to 0. This is used during
396 // importing to exclude the newly created folders from showing up in the
397 // combobox of most recently modified folders.
398 void ResetDateFolderModified(const BookmarkNode* node);
400 void GetBookmarksWithTitlesMatching(
401 const base::string16& text,
402 size_t max_count,
403 std::vector<BookmarkTitleMatch>* matches);
405 // Sets the store to NULL, making it so the BookmarkModel does not persist
406 // any changes to disk. This is only useful during testing to speed up
407 // testing.
408 void ClearStore();
410 // Returns the next node ID.
411 int64 next_node_id() const { return next_node_id_; }
413 // Returns the object responsible for tracking the set of expanded nodes in
414 // the bookmark editor.
415 BookmarkExpandedStateTracker* expanded_state_tracker() {
416 return expanded_state_tracker_.get();
419 // Sets the visibility of one of the permanent nodes. This is set by sync.
420 void SetPermanentNodeVisible(BookmarkNode::Type type, bool value);
422 // Sets/deletes meta info of |node|.
423 void SetNodeMetaInfo(const BookmarkNode* node,
424 const std::string& key,
425 const std::string& value);
426 void SetNodeMetaInfoMap(const BookmarkNode* node,
427 const BookmarkNode::MetaInfoMap& meta_info_map);
428 void DeleteNodeMetaInfo(const BookmarkNode* node,
429 const std::string& key);
431 // Sets the sync transaction version of |node|.
432 void SetNodeSyncTransactionVersion(const BookmarkNode* node,
433 int64 sync_transaction_version);
435 // Returns the profile that corresponds to this BookmarkModel.
436 Profile* profile() { return profile_; }
438 private:
439 friend class BookmarkCodecTest;
440 friend class BookmarkModelTest;
441 friend class BookmarkStorage;
443 // Used to order BookmarkNodes by URL.
444 class NodeURLComparator {
445 public:
446 bool operator()(const BookmarkNode* n1, const BookmarkNode* n2) const {
447 return n1->url() < n2->url();
451 // Implementation of IsBookmarked. Before calling this the caller must obtain
452 // a lock on |url_lock_|.
453 bool IsBookmarkedNoLock(const GURL& url);
455 // Removes the node from internal maps and recurses through all children. If
456 // the node is a url, its url is added to removed_urls.
458 // This does NOT delete the node.
459 void RemoveNode(BookmarkNode* node, std::set<GURL>* removed_urls);
461 // Invoked when loading is finished. Sets |loaded_| and notifies observers.
462 // BookmarkModel takes ownership of |details|.
463 void DoneLoading(BookmarkLoadDetails* details);
465 // Populates |nodes_ordered_by_url_set_| from root.
466 void PopulateNodesByURL(BookmarkNode* node);
468 // Removes the node from its parent, but does not delete it. No notifications
469 // are sent. |removed_urls| is populated with the urls which no longer have
470 // any bookmarks associated with them.
471 // This method should be called after acquiring |url_lock_|.
472 void RemoveNodeAndGetRemovedUrls(BookmarkNode* node,
473 std::set<GURL>* removed_urls);
475 // Removes the node from its parent, sends notification, and deletes it.
476 // type specifies how the node should be removed.
477 void RemoveAndDeleteNode(BookmarkNode* delete_me);
479 // Remove |node| from |nodes_ordered_by_url_set_|.
480 void RemoveNodeFromURLSet(BookmarkNode* node);
482 // Notifies the history backend about urls of removed bookmarks.
483 void NotifyHistoryAboutRemovedBookmarks(
484 const std::set<GURL>& removed_bookmark_urls) const;
486 // Adds the |node| at |parent| in the specified |index| and notifies its
487 // observers.
488 BookmarkNode* AddNode(BookmarkNode* parent,
489 int index,
490 BookmarkNode* node);
492 // Implementation of GetNodeByID.
493 const BookmarkNode* GetNodeByID(const BookmarkNode* node, int64 id) const;
495 // Returns true if the parent and index are valid.
496 bool IsValidIndex(const BookmarkNode* parent, int index, bool allow_end);
498 // Creates one of the possible permanent nodes (bookmark bar node, other node
499 // and mobile node) from |type|.
500 BookmarkPermanentNode* CreatePermanentNode(BookmarkNode::Type type);
502 // Notification that a favicon has finished loading. If we can decode the
503 // favicon, FaviconLoaded is invoked.
504 void OnFaviconDataAvailable(BookmarkNode* node,
505 const chrome::FaviconImageResult& image_result);
507 // Invoked from the node to load the favicon. Requests the favicon from the
508 // favicon service.
509 void LoadFavicon(BookmarkNode* node);
511 // Called to notify the observers that the favicon has been loaded.
512 void FaviconLoaded(const BookmarkNode* node);
514 // If we're waiting on a favicon for node, the load request is canceled.
515 void CancelPendingFaviconLoadRequests(BookmarkNode* node);
517 // content::NotificationObserver:
518 virtual void Observe(int type,
519 const content::NotificationSource& source,
520 const content::NotificationDetails& details) OVERRIDE;
522 // Generates and returns the next node ID.
523 int64 generate_next_node_id();
525 // Sets the maximum node ID to the given value.
526 // This is used by BookmarkCodec to report the maximum ID after it's done
527 // decoding since during decoding codec assigns node IDs.
528 void set_next_node_id(int64 id) { next_node_id_ = id; }
530 // Creates and returns a new BookmarkLoadDetails. It's up to the caller to
531 // delete the returned object.
532 BookmarkLoadDetails* CreateLoadDetails();
534 content::NotificationRegistrar registrar_;
536 Profile* profile_;
538 // Whether the initial set of data has been loaded.
539 bool loaded_;
541 // The root node. This contains the bookmark bar node and the 'other' node as
542 // children.
543 BookmarkNode root_;
545 BookmarkPermanentNode* bookmark_bar_node_;
546 BookmarkPermanentNode* other_node_;
547 BookmarkPermanentNode* mobile_node_;
549 // The maximum ID assigned to the bookmark nodes in the model.
550 int64 next_node_id_;
552 // The observers.
553 ObserverList<BookmarkModelObserver> observers_;
555 // Set of nodes ordered by URL. This is not a map to avoid copying the
556 // urls.
557 // WARNING: |nodes_ordered_by_url_set_| is accessed on multiple threads. As
558 // such, be sure and wrap all usage of it around |url_lock_|.
559 typedef std::multiset<BookmarkNode*, NodeURLComparator> NodesOrderedByURLSet;
560 NodesOrderedByURLSet nodes_ordered_by_url_set_;
561 base::Lock url_lock_;
563 // Used for loading favicons.
564 base::CancelableTaskTracker cancelable_task_tracker_;
566 // Reads/writes bookmarks to disk.
567 scoped_refptr<BookmarkStorage> store_;
569 scoped_ptr<BookmarkIndex> index_;
571 base::WaitableEvent loaded_signal_;
573 // See description of IsDoingExtensiveChanges above.
574 int extensive_changes_;
576 scoped_ptr<BookmarkExpandedStateTracker> expanded_state_tracker_;
578 DISALLOW_COPY_AND_ASSIGN(BookmarkModel);
581 #endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_MODEL_H_