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