OLD | NEW |
| (Empty) |
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 "components/bookmarks/core/browser/bookmark_client.h" | |
21 #include "components/bookmarks/core/browser/bookmark_node.h" | |
22 #include "components/bookmarks/core/browser/bookmark_service.h" | |
23 #include "ui/gfx/image/image.h" | |
24 #include "url/gurl.h" | |
25 | |
26 class BookmarkExpandedStateTracker; | |
27 class BookmarkIndex; | |
28 class BookmarkLoadDetails; | |
29 class BookmarkModelObserver; | |
30 class BookmarkStorage; | |
31 struct BookmarkMatch; | |
32 class PrefService; | |
33 class ScopedGroupBookmarkActions; | |
34 | |
35 namespace base { | |
36 class FilePath; | |
37 class SequencedTaskRunner; | |
38 } | |
39 | |
40 namespace favicon_base { | |
41 struct FaviconImageResult; | |
42 } | |
43 | |
44 namespace test { | |
45 class TestBookmarkClient; | |
46 } | |
47 | |
48 // BookmarkModel -------------------------------------------------------------- | |
49 | |
50 // BookmarkModel provides a directed acyclic graph of URLs and folders. | |
51 // Three graphs are provided for the three entry points: those on the 'bookmarks | |
52 // bar', those in the 'other bookmarks' folder and those in the 'mobile' folder. | |
53 // | |
54 // An observer may be attached to observe relevant events. | |
55 // | |
56 // You should NOT directly create a BookmarkModel, instead go through the | |
57 // BookmarkModelFactory. | |
58 class BookmarkModel : public BookmarkService { | |
59 public: | |
60 // |index_urls| says whether URLs should be stored in the BookmarkIndex | |
61 // in addition to bookmark titles. | |
62 BookmarkModel(BookmarkClient* client, bool index_urls); | |
63 virtual ~BookmarkModel(); | |
64 | |
65 // Invoked prior to destruction to release any necessary resources. | |
66 void Shutdown(); | |
67 | |
68 // Loads the bookmarks. This is called upon creation of the | |
69 // BookmarkModel. You need not invoke this directly. | |
70 // All load operations will be executed on |io_task_runner| and the completion | |
71 // callback will be called from |ui_task_runner|. | |
72 void Load(PrefService* pref_service, | |
73 const std::string& accept_languages, | |
74 const base::FilePath& profile_path, | |
75 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner, | |
76 const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner); | |
77 | |
78 // Returns true if the model finished loading. | |
79 bool loaded() const { return loaded_; } | |
80 | |
81 // Returns the root node. The 'bookmark bar' node and 'other' node are | |
82 // children of the root node. | |
83 const BookmarkNode* root_node() const { return &root_; } | |
84 | |
85 // Returns the 'bookmark bar' node. This is NULL until loaded. | |
86 const BookmarkNode* bookmark_bar_node() const { return bookmark_bar_node_; } | |
87 | |
88 // Returns the 'other' node. This is NULL until loaded. | |
89 const BookmarkNode* other_node() const { return other_node_; } | |
90 | |
91 // Returns the 'mobile' node. This is NULL until loaded. | |
92 const BookmarkNode* mobile_node() const { return mobile_node_; } | |
93 | |
94 bool is_root_node(const BookmarkNode* node) const { return node == &root_; } | |
95 | |
96 // Returns whether the given |node| is one of the permanent nodes - root node, | |
97 // 'bookmark bar' node, 'other' node or 'mobile' node. | |
98 bool is_permanent_node(const BookmarkNode* node) const { | |
99 return node == &root_ || | |
100 node == bookmark_bar_node_ || | |
101 node == other_node_ || | |
102 node == mobile_node_; | |
103 } | |
104 | |
105 // Returns the parent the last node was added to. This never returns NULL | |
106 // (as long as the model is loaded). | |
107 const BookmarkNode* GetParentForNewNodes(); | |
108 | |
109 void AddObserver(BookmarkModelObserver* observer); | |
110 void RemoveObserver(BookmarkModelObserver* observer); | |
111 | |
112 // Notifies the observers that an extensive set of changes is about to happen, | |
113 // such as during import or sync, so they can delay any expensive UI updates | |
114 // until it's finished. | |
115 void BeginExtensiveChanges(); | |
116 void EndExtensiveChanges(); | |
117 | |
118 // Returns true if this bookmark model is currently in a mode where extensive | |
119 // changes might happen, such as for import and sync. This is helpful for | |
120 // observers that are created after the mode has started, and want to check | |
121 // state during their own initializer, such as the NTP. | |
122 bool IsDoingExtensiveChanges() const { return extensive_changes_ > 0; } | |
123 | |
124 // Removes the node at the given |index| from |parent|. Removing a folder node | |
125 // recursively removes all nodes. Observers are notified immediately. | |
126 void Remove(const BookmarkNode* parent, int index); | |
127 | |
128 // Removes all the non-permanent bookmark nodes. Observers are only notified | |
129 // when all nodes have been removed. There is no notification for individual | |
130 // node removals. | |
131 void RemoveAll(); | |
132 | |
133 // Moves |node| to |new_parent| and inserts it at the given |index|. | |
134 void Move(const BookmarkNode* node, | |
135 const BookmarkNode* new_parent, | |
136 int index); | |
137 | |
138 // Inserts a copy of |node| into |new_parent| at |index|. | |
139 void Copy(const BookmarkNode* node, | |
140 const BookmarkNode* new_parent, | |
141 int index); | |
142 | |
143 // Returns the favicon for |node|. If the favicon has not yet been | |
144 // loaded it is loaded and the observer of the model notified when done. | |
145 const gfx::Image& GetFavicon(const BookmarkNode* node); | |
146 | |
147 // Sets the title of |node|. | |
148 void SetTitle(const BookmarkNode* node, const base::string16& title); | |
149 | |
150 // Sets the URL of |node|. | |
151 void SetURL(const BookmarkNode* node, const GURL& url); | |
152 | |
153 // Sets the date added time of |node|. | |
154 void SetDateAdded(const BookmarkNode* node, base::Time date_added); | |
155 | |
156 // Returns the set of nodes with the |url|. | |
157 void GetNodesByURL(const GURL& url, std::vector<const BookmarkNode*>* nodes); | |
158 | |
159 // Returns the most recently added node for the |url|. Returns NULL if |url| | |
160 // is not bookmarked. | |
161 const BookmarkNode* GetMostRecentlyAddedNodeForURL(const GURL& url); | |
162 | |
163 // Returns true if there are bookmarks, otherwise returns false. | |
164 // This method is thread safe. | |
165 bool HasBookmarks(); | |
166 | |
167 // Returns true if there is a bookmark with the |url|. | |
168 // This method is thread safe. | |
169 // See BookmarkService for more details on this. | |
170 virtual bool IsBookmarked(const GURL& url) OVERRIDE; | |
171 | |
172 // Returns all the bookmarked urls and their titles. | |
173 // This method is thread safe. | |
174 // See BookmarkService for more details on this. | |
175 virtual void GetBookmarks( | |
176 std::vector<BookmarkService::URLAndTitle>* urls) OVERRIDE; | |
177 | |
178 // Blocks until loaded; this is NOT invoked on the main thread. | |
179 // See BookmarkService for more details on this. | |
180 virtual void BlockTillLoaded() OVERRIDE; | |
181 | |
182 // Adds a new folder node at the specified position. | |
183 const BookmarkNode* AddFolder(const BookmarkNode* parent, | |
184 int index, | |
185 const base::string16& title); | |
186 | |
187 // Adds a new folder with meta info. | |
188 const BookmarkNode* AddFolderWithMetaInfo( | |
189 const BookmarkNode* parent, | |
190 int index, | |
191 const base::string16& title, | |
192 const BookmarkNode::MetaInfoMap* meta_info); | |
193 | |
194 // Adds a url at the specified position. | |
195 const BookmarkNode* AddURL(const BookmarkNode* parent, | |
196 int index, | |
197 const base::string16& title, | |
198 const GURL& url); | |
199 | |
200 // Adds a url with a specific creation date and meta info. | |
201 const BookmarkNode* AddURLWithCreationTimeAndMetaInfo( | |
202 const BookmarkNode* parent, | |
203 int index, | |
204 const base::string16& title, | |
205 const GURL& url, | |
206 const base::Time& creation_time, | |
207 const BookmarkNode::MetaInfoMap* meta_info); | |
208 | |
209 // Sorts the children of |parent|, notifying observers by way of the | |
210 // BookmarkNodeChildrenReordered method. | |
211 void SortChildren(const BookmarkNode* parent); | |
212 | |
213 // Order the children of |parent| as specified in |ordered_nodes|. This | |
214 // function should only be used to reorder the child nodes of |parent| and | |
215 // is not meant to move nodes between different parent. Notifies observers | |
216 // using the BookmarkNodeChildrenReordered method. | |
217 void ReorderChildren(const BookmarkNode* parent, | |
218 const std::vector<const BookmarkNode*>& ordered_nodes); | |
219 | |
220 // Sets the date when the folder was modified. | |
221 void SetDateFolderModified(const BookmarkNode* node, const base::Time time); | |
222 | |
223 // Resets the 'date modified' time of the node to 0. This is used during | |
224 // importing to exclude the newly created folders from showing up in the | |
225 // combobox of most recently modified folders. | |
226 void ResetDateFolderModified(const BookmarkNode* node); | |
227 | |
228 // Returns up to |max_count| of bookmarks containing each term from |text| | |
229 // in either the title or the URL. | |
230 void GetBookmarksMatching( | |
231 const base::string16& text, | |
232 size_t max_count, | |
233 std::vector<BookmarkMatch>* matches); | |
234 | |
235 // Sets the store to NULL, making it so the BookmarkModel does not persist | |
236 // any changes to disk. This is only useful during testing to speed up | |
237 // testing. | |
238 void ClearStore(); | |
239 | |
240 // Returns the next node ID. | |
241 int64 next_node_id() const { return next_node_id_; } | |
242 | |
243 // Returns the object responsible for tracking the set of expanded nodes in | |
244 // the bookmark editor. | |
245 BookmarkExpandedStateTracker* expanded_state_tracker() { | |
246 return expanded_state_tracker_.get(); | |
247 } | |
248 | |
249 // Sets the visibility of one of the permanent nodes. This is set by sync. | |
250 void SetPermanentNodeVisible(BookmarkNode::Type type, bool value); | |
251 | |
252 // Sets/deletes meta info of |node|. | |
253 void SetNodeMetaInfo(const BookmarkNode* node, | |
254 const std::string& key, | |
255 const std::string& value); | |
256 void SetNodeMetaInfoMap(const BookmarkNode* node, | |
257 const BookmarkNode::MetaInfoMap& meta_info_map); | |
258 void DeleteNodeMetaInfo(const BookmarkNode* node, | |
259 const std::string& key); | |
260 | |
261 // Sets the sync transaction version of |node|. | |
262 void SetNodeSyncTransactionVersion(const BookmarkNode* node, | |
263 int64 sync_transaction_version); | |
264 | |
265 // Notify BookmarkModel that the favicons for |urls| have changed and have to | |
266 // be refetched. This notification is sent by BookmarkClient. | |
267 void OnFaviconChanged(const std::set<GURL>& urls); | |
268 | |
269 // Returns the client used by this BookmarkModel. | |
270 BookmarkClient* client() const { return client_; } | |
271 | |
272 private: | |
273 friend class BookmarkCodecTest; | |
274 friend class BookmarkModelTest; | |
275 friend class BookmarkStorage; | |
276 friend class ScopedGroupBookmarkActions; | |
277 friend class test::TestBookmarkClient; | |
278 | |
279 // Used to order BookmarkNodes by URL. | |
280 class NodeURLComparator { | |
281 public: | |
282 bool operator()(const BookmarkNode* n1, const BookmarkNode* n2) const { | |
283 return n1->url() < n2->url(); | |
284 } | |
285 }; | |
286 | |
287 // Implementation of IsBookmarked. Before calling this the caller must obtain | |
288 // a lock on |url_lock_|. | |
289 bool IsBookmarkedNoLock(const GURL& url); | |
290 | |
291 // Removes the node from internal maps and recurses through all children. If | |
292 // the node is a url, its url is added to removed_urls. | |
293 // | |
294 // This does NOT delete the node. | |
295 void RemoveNode(BookmarkNode* node, std::set<GURL>* removed_urls); | |
296 | |
297 // Invoked when loading is finished. Sets |loaded_| and notifies observers. | |
298 // BookmarkModel takes ownership of |details|. | |
299 void DoneLoading(scoped_ptr<BookmarkLoadDetails> details); | |
300 | |
301 // Populates |nodes_ordered_by_url_set_| from root. | |
302 void PopulateNodesByURL(BookmarkNode* node); | |
303 | |
304 // Removes the node from its parent, but does not delete it. No notifications | |
305 // are sent. |removed_urls| is populated with the urls which no longer have | |
306 // any bookmarks associated with them. | |
307 // This method should be called after acquiring |url_lock_|. | |
308 void RemoveNodeAndGetRemovedUrls(BookmarkNode* node, | |
309 std::set<GURL>* removed_urls); | |
310 | |
311 // Removes the node from its parent, sends notification, and deletes it. | |
312 // type specifies how the node should be removed. | |
313 void RemoveAndDeleteNode(BookmarkNode* delete_me); | |
314 | |
315 // Remove |node| from |nodes_ordered_by_url_set_|. | |
316 void RemoveNodeFromURLSet(BookmarkNode* node); | |
317 | |
318 // Adds the |node| at |parent| in the specified |index| and notifies its | |
319 // observers. | |
320 BookmarkNode* AddNode(BookmarkNode* parent, | |
321 int index, | |
322 BookmarkNode* node); | |
323 | |
324 // Returns true if the parent and index are valid. | |
325 bool IsValidIndex(const BookmarkNode* parent, int index, bool allow_end); | |
326 | |
327 // Creates one of the possible permanent nodes (bookmark bar node, other node | |
328 // and mobile node) from |type|. | |
329 BookmarkPermanentNode* CreatePermanentNode(BookmarkNode::Type type); | |
330 | |
331 // Notification that a favicon has finished loading. If we can decode the | |
332 // favicon, FaviconLoaded is invoked. | |
333 void OnFaviconDataAvailable( | |
334 BookmarkNode* node, | |
335 const favicon_base::FaviconImageResult& image_result); | |
336 | |
337 // Invoked from the node to load the favicon. Requests the favicon from the | |
338 // favicon service. | |
339 void LoadFavicon(BookmarkNode* node); | |
340 | |
341 // Called to notify the observers that the favicon has been loaded. | |
342 void FaviconLoaded(const BookmarkNode* node); | |
343 | |
344 // If we're waiting on a favicon for node, the load request is canceled. | |
345 void CancelPendingFaviconLoadRequests(BookmarkNode* node); | |
346 | |
347 // Notifies the observers that a set of changes initiated by a single user | |
348 // action is about to happen and has completed. | |
349 void BeginGroupedChanges(); | |
350 void EndGroupedChanges(); | |
351 | |
352 // Generates and returns the next node ID. | |
353 int64 generate_next_node_id(); | |
354 | |
355 // Sets the maximum node ID to the given value. | |
356 // This is used by BookmarkCodec to report the maximum ID after it's done | |
357 // decoding since during decoding codec assigns node IDs. | |
358 void set_next_node_id(int64 id) { next_node_id_ = id; } | |
359 | |
360 // Creates and returns a new BookmarkLoadDetails. It's up to the caller to | |
361 // delete the returned object. | |
362 scoped_ptr<BookmarkLoadDetails> CreateLoadDetails( | |
363 const std::string& accept_languages); | |
364 | |
365 BookmarkClient* const client_; | |
366 | |
367 // Whether the initial set of data has been loaded. | |
368 bool loaded_; | |
369 | |
370 // The root node. This contains the bookmark bar node and the 'other' node as | |
371 // children. | |
372 BookmarkNode root_; | |
373 | |
374 BookmarkPermanentNode* bookmark_bar_node_; | |
375 BookmarkPermanentNode* other_node_; | |
376 BookmarkPermanentNode* mobile_node_; | |
377 | |
378 // The maximum ID assigned to the bookmark nodes in the model. | |
379 int64 next_node_id_; | |
380 | |
381 // The observers. | |
382 ObserverList<BookmarkModelObserver> observers_; | |
383 | |
384 // Set of nodes ordered by URL. This is not a map to avoid copying the | |
385 // urls. | |
386 // WARNING: |nodes_ordered_by_url_set_| is accessed on multiple threads. As | |
387 // such, be sure and wrap all usage of it around |url_lock_|. | |
388 typedef std::multiset<BookmarkNode*, NodeURLComparator> NodesOrderedByURLSet; | |
389 NodesOrderedByURLSet nodes_ordered_by_url_set_; | |
390 base::Lock url_lock_; | |
391 | |
392 // Used for loading favicons. | |
393 base::CancelableTaskTracker cancelable_task_tracker_; | |
394 | |
395 // Reads/writes bookmarks to disk. | |
396 scoped_refptr<BookmarkStorage> store_; | |
397 | |
398 scoped_ptr<BookmarkIndex> index_; | |
399 | |
400 // True if URLs are stored in the BookmarkIndex in addition to bookmark | |
401 // titles. | |
402 const bool index_urls_; | |
403 | |
404 base::WaitableEvent loaded_signal_; | |
405 | |
406 // See description of IsDoingExtensiveChanges above. | |
407 int extensive_changes_; | |
408 | |
409 scoped_ptr<BookmarkExpandedStateTracker> expanded_state_tracker_; | |
410 | |
411 DISALLOW_COPY_AND_ASSIGN(BookmarkModel); | |
412 }; | |
413 | |
414 #endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_MODEL_H_ | |
OLD | NEW |