• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #ifndef COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MODEL_H_
6 #define COMPONENTS_BOOKMARKS_BROWSER_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 "components/bookmarks/browser/bookmark_client.h"
21 #include "components/bookmarks/browser/bookmark_node.h"
22 #include "components/keyed_service/core/keyed_service.h"
23 #include "ui/gfx/image/image.h"
24 #include "url/gurl.h"
25 
26 class BookmarkModelObserver;
27 class PrefService;
28 
29 namespace base {
30 class FilePath;
31 class SequencedTaskRunner;
32 }
33 
34 namespace bookmarks {
35 class BookmarkCodecTest;
36 class BookmarkExpandedStateTracker;
37 class BookmarkIndex;
38 class BookmarkLoadDetails;
39 class BookmarkStorage;
40 class ScopedGroupBookmarkActions;
41 struct BookmarkMatch;
42 }
43 
44 namespace favicon_base {
45 struct FaviconImageResult;
46 }
47 
48 namespace test {
49 class TestBookmarkClient;
50 }
51 
52 // BookmarkModel --------------------------------------------------------------
53 
54 // BookmarkModel provides a directed acyclic graph of URLs and folders.
55 // Three graphs are provided for the three entry points: those on the 'bookmarks
56 // bar', those in the 'other bookmarks' folder and those in the 'mobile' folder.
57 //
58 // An observer may be attached to observe relevant events.
59 //
60 // You should NOT directly create a BookmarkModel, instead go through the
61 // BookmarkModelFactory.
62 class BookmarkModel : public KeyedService {
63  public:
64   struct URLAndTitle {
65     GURL url;
66     base::string16 title;
67   };
68 
69   // |index_urls| says whether URLs should be stored in the BookmarkIndex
70   // in addition to bookmark titles.
71   BookmarkModel(BookmarkClient* client, bool index_urls);
72   virtual ~BookmarkModel();
73 
74   // KeyedService:
75   virtual void Shutdown() OVERRIDE;
76 
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);
86 
87   // Returns true if the model finished loading.
loaded()88   bool loaded() const { return loaded_; }
89 
90   // Returns the root node. The 'bookmark bar' node and 'other' node are
91   // children of the root node.
root_node()92   const BookmarkNode* root_node() const { return &root_; }
93 
94   // Returns the 'bookmark bar' node. This is NULL until loaded.
bookmark_bar_node()95   const BookmarkNode* bookmark_bar_node() const { return bookmark_bar_node_; }
96 
97   // Returns the 'other' node. This is NULL until loaded.
other_node()98   const BookmarkNode* other_node() const { return other_node_; }
99 
100   // Returns the 'mobile' node. This is NULL until loaded.
mobile_node()101   const BookmarkNode* mobile_node() const { return mobile_node_; }
102 
is_root_node(const BookmarkNode * node)103   bool is_root_node(const BookmarkNode* node) const { return node == &root_; }
104 
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_|.
is_permanent_node(const BookmarkNode * node)108   bool is_permanent_node(const BookmarkNode* node) const {
109     return node && (node == &root_ || node->parent() == &root_);
110   }
111 
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();
115 
116   void AddObserver(BookmarkModelObserver* observer);
117   void RemoveObserver(BookmarkModelObserver* observer);
118 
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();
124 
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.
IsDoingExtensiveChanges()129   bool IsDoingExtensiveChanges() const { return extensive_changes_ > 0; }
130 
131   // Removes the node at the given |index| from |parent|. Removing a folder node
132   // recursively removes all nodes. Observers are notified immediately.
133   void Remove(const BookmarkNode* parent, int index);
134 
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();
139 
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);
144 
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);
149 
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);
153 
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);
157 
158   // Sets the title of |node|.
159   void SetTitle(const BookmarkNode* node, const base::string16& title);
160 
161   // Sets the URL of |node|.
162   void SetURL(const BookmarkNode* node, const GURL& url);
163 
164   // Sets the date added time of |node|.
165   void SetDateAdded(const BookmarkNode* node, base::Time date_added);
166 
167   // Returns the set of nodes with the |url|.
168   void GetNodesByURL(const GURL& url, std::vector<const BookmarkNode*>* nodes);
169 
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);
174 
175   // Returns true if there are bookmarks, otherwise returns false.
176   // This method is thread safe.
177   bool HasBookmarks();
178 
179   // Returns true if the specified URL is bookmarked.
180   //
181   // If not on the main thread you *must* invoke BlockTillLoaded first.
182   bool IsBookmarked(const GURL& url);
183 
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.
188   //
189   // If not on the main thread you *must* invoke BlockTillLoaded first.
190   void GetBookmarks(std::vector<BookmarkModel::URLAndTitle>* urls);
191 
192   // Blocks until loaded. This is intended for usage on a thread other than
193   // the main thread.
194   void BlockTillLoaded();
195 
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);
200 
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);
207 
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);
213 
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);
222 
223   // Sorts the children of |parent|, notifying observers by way of the
224   // BookmarkNodeChildrenReordered method.
225   void SortChildren(const BookmarkNode* parent);
226 
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);
233 
234   // Sets the date when the folder was modified.
235   void SetDateFolderModified(const BookmarkNode* node, const base::Time time);
236 
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);
241 
242   // Returns up to |max_count| of bookmarks containing each term from |text|
243   // in either the title or the URL.
244   void GetBookmarksMatching(const base::string16& text,
245                             size_t max_count,
246                             std::vector<bookmarks::BookmarkMatch>* matches);
247 
248   // Sets the store to NULL, making it so the BookmarkModel does not persist
249   // any changes to disk. This is only useful during testing to speed up
250   // testing.
251   void ClearStore();
252 
253   // Returns the next node ID.
next_node_id()254   int64 next_node_id() const { return next_node_id_; }
255 
256   // Returns the object responsible for tracking the set of expanded nodes in
257   // the bookmark editor.
expanded_state_tracker()258   bookmarks::BookmarkExpandedStateTracker* expanded_state_tracker() {
259     return expanded_state_tracker_.get();
260   }
261 
262   // Sets the visibility of one of the permanent nodes (unless the node must
263   // always be visible, see |BookmarkClient::IsPermanentNodeVisible| for more
264   // details). This is set by sync.
265   void SetPermanentNodeVisible(BookmarkNode::Type type, bool value);
266 
267   // Returns the permanent node of type |type|.
268   const BookmarkPermanentNode* PermanentNode(BookmarkNode::Type type);
269 
270   // Sets/deletes meta info of |node|.
271   void SetNodeMetaInfo(const BookmarkNode* node,
272                        const std::string& key,
273                        const std::string& value);
274   void SetNodeMetaInfoMap(const BookmarkNode* node,
275                           const BookmarkNode::MetaInfoMap& meta_info_map);
276   void DeleteNodeMetaInfo(const BookmarkNode* node,
277                           const std::string& key);
278 
279   // Sets the sync transaction version of |node|.
280   void SetNodeSyncTransactionVersion(const BookmarkNode* node,
281                                      int64 sync_transaction_version);
282 
283   // Notify BookmarkModel that the favicons for |urls| have changed and have to
284   // be refetched. This notification is sent by BookmarkClient.
285   void OnFaviconChanged(const std::set<GURL>& urls);
286 
287   // Returns the client used by this BookmarkModel.
client()288   BookmarkClient* client() const { return client_; }
289 
290  private:
291   friend class bookmarks::BookmarkCodecTest;
292   friend class bookmarks::BookmarkStorage;
293   friend class bookmarks::ScopedGroupBookmarkActions;
294   friend class test::TestBookmarkClient;
295 
296   // Used to order BookmarkNodes by URL.
297   class NodeURLComparator {
298    public:
operator()299     bool operator()(const BookmarkNode* n1, const BookmarkNode* n2) const {
300       return n1->url() < n2->url();
301     }
302   };
303 
304   // Implementation of IsBookmarked. Before calling this the caller must obtain
305   // a lock on |url_lock_|.
306   bool IsBookmarkedNoLock(const GURL& url);
307 
308   // Removes the node from internal maps and recurses through all children. If
309   // the node is a url, its url is added to removed_urls.
310   //
311   // This does NOT delete the node.
312   void RemoveNode(BookmarkNode* node, std::set<GURL>* removed_urls);
313 
314   // Invoked when loading is finished. Sets |loaded_| and notifies observers.
315   // BookmarkModel takes ownership of |details|.
316   void DoneLoading(scoped_ptr<bookmarks::BookmarkLoadDetails> details);
317 
318   // Populates |nodes_ordered_by_url_set_| from root.
319   void PopulateNodesByURL(BookmarkNode* node);
320 
321   // Removes the node from its parent, but does not delete it. No notifications
322   // are sent. |removed_urls| is populated with the urls which no longer have
323   // any bookmarks associated with them.
324   // This method should be called after acquiring |url_lock_|.
325   void RemoveNodeAndGetRemovedUrls(BookmarkNode* node,
326                                    std::set<GURL>* removed_urls);
327 
328   // Removes the node from its parent, sends notification, and deletes it.
329   // type specifies how the node should be removed.
330   void RemoveAndDeleteNode(BookmarkNode* delete_me);
331 
332   // Remove |node| from |nodes_ordered_by_url_set_|.
333   void RemoveNodeFromURLSet(BookmarkNode* node);
334 
335   // Adds the |node| at |parent| in the specified |index| and notifies its
336   // observers.
337   BookmarkNode* AddNode(BookmarkNode* parent,
338                         int index,
339                         BookmarkNode* node);
340 
341   // Returns true if the parent and index are valid.
342   bool IsValidIndex(const BookmarkNode* parent, int index, bool allow_end);
343 
344   // Creates one of the possible permanent nodes (bookmark bar node, other node
345   // and mobile node) from |type|.
346   BookmarkPermanentNode* CreatePermanentNode(BookmarkNode::Type type);
347 
348   // Notification that a favicon has finished loading. If we can decode the
349   // favicon, FaviconLoaded is invoked.
350   void OnFaviconDataAvailable(
351       BookmarkNode* node,
352       favicon_base::IconType icon_type,
353       const favicon_base::FaviconImageResult& image_result);
354 
355   // Invoked from the node to load the favicon. Requests the favicon from the
356   // favicon service.
357   void LoadFavicon(BookmarkNode* node, favicon_base::IconType icon_type);
358 
359   // Called to notify the observers that the favicon has been loaded.
360   void FaviconLoaded(const BookmarkNode* node);
361 
362   // If we're waiting on a favicon for node, the load request is canceled.
363   void CancelPendingFaviconLoadRequests(BookmarkNode* node);
364 
365   // Notifies the observers that a set of changes initiated by a single user
366   // action is about to happen and has completed.
367   void BeginGroupedChanges();
368   void EndGroupedChanges();
369 
370   // Generates and returns the next node ID.
371   int64 generate_next_node_id();
372 
373   // Sets the maximum node ID to the given value.
374   // This is used by BookmarkCodec to report the maximum ID after it's done
375   // decoding since during decoding codec assigns node IDs.
set_next_node_id(int64 id)376   void set_next_node_id(int64 id) { next_node_id_ = id; }
377 
378   // Creates and returns a new BookmarkLoadDetails. It's up to the caller to
379   // delete the returned object.
380   scoped_ptr<bookmarks::BookmarkLoadDetails> CreateLoadDetails(
381       const std::string& accept_languages);
382 
383   BookmarkClient* const client_;
384 
385   // Whether the initial set of data has been loaded.
386   bool loaded_;
387 
388   // The root node. This contains the bookmark bar node, the 'other' node and
389   // the mobile node as children.
390   BookmarkNode root_;
391 
392   BookmarkPermanentNode* bookmark_bar_node_;
393   BookmarkPermanentNode* other_node_;
394   BookmarkPermanentNode* mobile_node_;
395 
396   // The maximum ID assigned to the bookmark nodes in the model.
397   int64 next_node_id_;
398 
399   // The observers.
400   ObserverList<BookmarkModelObserver> observers_;
401 
402   // Set of nodes ordered by URL. This is not a map to avoid copying the
403   // urls.
404   // WARNING: |nodes_ordered_by_url_set_| is accessed on multiple threads. As
405   // such, be sure and wrap all usage of it around |url_lock_|.
406   typedef std::multiset<BookmarkNode*, NodeURLComparator> NodesOrderedByURLSet;
407   NodesOrderedByURLSet nodes_ordered_by_url_set_;
408   base::Lock url_lock_;
409 
410   // Used for loading favicons.
411   base::CancelableTaskTracker cancelable_task_tracker_;
412 
413   // Reads/writes bookmarks to disk.
414   scoped_refptr<bookmarks::BookmarkStorage> store_;
415 
416   scoped_ptr<bookmarks::BookmarkIndex> index_;
417 
418   // True if URLs are stored in the BookmarkIndex in addition to bookmark
419   // titles.
420   const bool index_urls_;
421 
422   base::WaitableEvent loaded_signal_;
423 
424   // See description of IsDoingExtensiveChanges above.
425   int extensive_changes_;
426 
427   scoped_ptr<bookmarks::BookmarkExpandedStateTracker> expanded_state_tracker_;
428 
429   DISALLOW_COPY_AND_ASSIGN(BookmarkModel);
430 };
431 
432 #endif  // COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MODEL_H_
433