bookmark_model.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  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. #ifndef COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MODEL_H_
  5. #define COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MODEL_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <map>
  9. #include <memory>
  10. #include <set>
  11. #include <string>
  12. #include <vector>
  13. #include "base/check_op.h"
  14. #include "base/compiler_specific.h"
  15. #include "base/memory/raw_ptr.h"
  16. #include "base/memory/scoped_refptr.h"
  17. #include "base/memory/weak_ptr.h"
  18. #include "base/observer_list.h"
  19. #include "base/sequence_checker.h"
  20. #include "components/bookmarks/browser/bookmark_client.h"
  21. #include "components/bookmarks/browser/bookmark_node.h"
  22. #include "components/bookmarks/browser/bookmark_undo_provider.h"
  23. #include "components/keyed_service/core/keyed_service.h"
  24. #include "third_party/abseil-cpp/absl/types/optional.h"
  25. #include "ui/gfx/image/image.h"
  26. #include "url/gurl.h"
  27. class PrefService;
  28. namespace base {
  29. class FilePath;
  30. class GUID;
  31. }
  32. namespace favicon_base {
  33. struct FaviconImageResult;
  34. }
  35. namespace query_parser {
  36. enum class MatchingAlgorithm;
  37. }
  38. namespace bookmarks {
  39. class BookmarkCodecTest;
  40. class BookmarkExpandedStateTracker;
  41. class BookmarkLoadDetails;
  42. class BookmarkModelObserver;
  43. class BookmarkStorage;
  44. class BookmarkUndoDelegate;
  45. class ModelLoader;
  46. class ScopedGroupBookmarkActions;
  47. class TestBookmarkClient;
  48. class TitledUrlIndex;
  49. class UrlIndex;
  50. struct UrlAndTitle;
  51. struct TitledUrlMatch;
  52. // BookmarkModel --------------------------------------------------------------
  53. // BookmarkModel provides a directed acyclic graph of URLs and folders.
  54. // Three graphs are provided for the three entry points: those on the 'bookmarks
  55. // bar', those in the 'other bookmarks' folder and those in the 'mobile' folder.
  56. //
  57. // An observer may be attached to observe relevant events.
  58. //
  59. // You should NOT directly create a BookmarkModel, instead go through the
  60. // BookmarkModelFactory.
  61. class BookmarkModel : public BookmarkUndoProvider,
  62. public KeyedService {
  63. public:
  64. explicit BookmarkModel(std::unique_ptr<BookmarkClient> client);
  65. BookmarkModel(const BookmarkModel&) = delete;
  66. BookmarkModel& operator=(const BookmarkModel&) = delete;
  67. ~BookmarkModel() override;
  68. // Triggers the loading of bookmarks, which is an asynchronous operation with
  69. // most heavy-lifting taking place in a background sequence. Upon completion,
  70. // loaded() will return true and observers will be notified via
  71. // BookmarkModelLoaded().
  72. void Load(PrefService* pref_service, const base::FilePath& profile_path);
  73. // Returns true if the model finished loading.
  74. bool loaded() const {
  75. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  76. return loaded_;
  77. }
  78. // Returns the object responsible for tracking loading.
  79. scoped_refptr<ModelLoader> model_loader();
  80. // Returns the root node. The 'bookmark bar' node and 'other' node are
  81. // children of the root node.
  82. const BookmarkNode* root_node() const {
  83. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  84. return root_;
  85. }
  86. // Returns the 'bookmark bar' node. This is NULL until loaded.
  87. const BookmarkNode* bookmark_bar_node() const {
  88. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  89. return bookmark_bar_node_;
  90. }
  91. // Returns the 'other' node. This is NULL until loaded.
  92. const BookmarkNode* other_node() const {
  93. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  94. return other_node_;
  95. }
  96. // Returns the 'mobile' node. This is NULL until loaded.
  97. const BookmarkNode* mobile_node() const {
  98. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  99. return mobile_node_;
  100. }
  101. bool is_root_node(const BookmarkNode* node) const {
  102. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  103. 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_|.
  108. bool is_permanent_node(const BookmarkNode* node) const {
  109. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  110. return node && (node == root_ || node->parent() == root_);
  111. }
  112. void AddObserver(BookmarkModelObserver* observer);
  113. void RemoveObserver(BookmarkModelObserver* observer);
  114. // Notifies the observers that an extensive set of changes is about to happen,
  115. // such as during import or sync, so they can delay any expensive UI updates
  116. // until it's finished.
  117. void BeginExtensiveChanges();
  118. void EndExtensiveChanges();
  119. // Returns true if this bookmark model is currently in a mode where extensive
  120. // changes might happen, such as for import and sync. This is helpful for
  121. // observers that are created after the mode has started, and want to check
  122. // state during their own initializer, such as the NTP.
  123. bool IsDoingExtensiveChanges() const { return extensive_changes_ > 0; }
  124. // Removes |node| from the model and deletes it. Removing a folder node
  125. // recursively removes all nodes. Observers are notified immediately. |node|
  126. // must not be a permanent node.
  127. void Remove(const BookmarkNode* node);
  128. // Removes all the non-permanent bookmark nodes that are editable by the user.
  129. // Observers are only notified when all nodes have been removed. There is no
  130. // notification for individual node removals.
  131. void RemoveAllUserBookmarks();
  132. // Moves |node| to |new_parent| and inserts it at the given |index|.
  133. void Move(const BookmarkNode* node,
  134. const BookmarkNode* new_parent,
  135. size_t index);
  136. // Inserts a copy of |node| into |new_parent| at |index|.
  137. void Copy(const BookmarkNode* node,
  138. const BookmarkNode* new_parent,
  139. size_t index);
  140. // Returns the favicon for |node|. If the favicon has not yet been loaded,
  141. // a load will be triggered and the observer of the model notified when done.
  142. // This also means that, on return, the node's state is guaranteed to be
  143. // either LOADED_FAVICON (if it was already loaded prior to the call) or
  144. // LOADING_FAVICON (with the exception of folders, where the call is a no-op).
  145. const gfx::Image& GetFavicon(const BookmarkNode* node);
  146. // Sets the title of |node|.
  147. void SetTitle(const BookmarkNode* node, const std::u16string& title);
  148. // Sets the URL of |node|.
  149. void SetURL(const BookmarkNode* node, const GURL& url);
  150. // Sets the date added time of |node|.
  151. void SetDateAdded(const BookmarkNode* node, base::Time date_added);
  152. // Returns the set of nodes with the |url|.
  153. void GetNodesByURL(const GURL& url, std::vector<const BookmarkNode*>* nodes);
  154. // Returns the most recently added user node for the |url|; urls from any
  155. // nodes that are not editable by the user are never returned by this call.
  156. // Returns NULL if |url| is not bookmarked.
  157. const BookmarkNode* GetMostRecentlyAddedUserNodeForURL(const GURL& url);
  158. // Returns true if there are bookmarks, otherwise returns false.
  159. bool HasBookmarks();
  160. // Returns true is there is no user created bookmarks or folders.
  161. bool HasNoUserCreatedBookmarksOrFolders();
  162. // Returns true if the specified URL is bookmarked.
  163. bool IsBookmarked(const GURL& url);
  164. // Returns, by reference in |bookmarks|, the set of bookmarked urls and their
  165. // titles. This returns the unique set of URLs. For example, if two bookmarks
  166. // reference the same URL only one entry is added not matter the titles are
  167. // same or not.
  168. void GetBookmarks(std::vector<UrlAndTitle>* urls);
  169. // Adds a new folder node at the specified position with the given
  170. // |creation_time|, |guid| and |meta_info|. If no GUID is provided (i.e.
  171. // nullopt), then a random one will be generated. If a GUID is provided, it
  172. // must be valid.
  173. const BookmarkNode* AddFolder(
  174. const BookmarkNode* parent,
  175. size_t index,
  176. const std::u16string& title,
  177. const BookmarkNode::MetaInfoMap* meta_info = nullptr,
  178. absl::optional<base::Time> creation_time = absl::nullopt,
  179. absl::optional<base::GUID> guid = absl::nullopt);
  180. // Adds a new bookmark for the given `url` at the specified position with the
  181. // given `meta_info`. Used for bookmarks being added through some direct user
  182. // action (e.g. the bookmark star).
  183. const BookmarkNode* AddNewURL(
  184. const BookmarkNode* parent,
  185. size_t index,
  186. const std::u16string& title,
  187. const GURL& url,
  188. const BookmarkNode::MetaInfoMap* meta_info = nullptr);
  189. // Adds a url at the specified position with the given `creation_time`,
  190. // `meta_info`, `guid`, and `last_used_time`. If no GUID is provided
  191. // (i.e. nullopt), then a random one will be generated. If a GUID is
  192. // provided, it must be valid. Used for bookmarks not being added from
  193. // direct user actions (e.g. created via sync, locally modified bookmark
  194. // or pre-existing bookmark).
  195. const BookmarkNode* AddURL(
  196. const BookmarkNode* parent,
  197. size_t index,
  198. const std::u16string& title,
  199. const GURL& url,
  200. const BookmarkNode::MetaInfoMap* meta_info = nullptr,
  201. absl::optional<base::Time> creation_time = absl::nullopt,
  202. absl::optional<base::GUID> guid = absl::nullopt);
  203. // Sorts the children of |parent|, notifying observers by way of the
  204. // BookmarkNodeChildrenReordered method.
  205. void SortChildren(const BookmarkNode* parent);
  206. // Order the children of |parent| as specified in |ordered_nodes|. This
  207. // function should only be used to reorder the child nodes of |parent| and
  208. // is not meant to move nodes between different parent. Notifies observers
  209. // using the BookmarkNodeChildrenReordered method.
  210. void ReorderChildren(const BookmarkNode* parent,
  211. const std::vector<const BookmarkNode*>& ordered_nodes);
  212. // Sets the date when the folder was modified.
  213. void SetDateFolderModified(const BookmarkNode* node, const base::Time time);
  214. // Resets the 'date modified' time of the node to 0. This is used during
  215. // importing to exclude the newly created folders from showing up in the
  216. // combobox of most recently modified folders.
  217. void ResetDateFolderModified(const BookmarkNode* node);
  218. // Updates the last used `time` for the given `id` / `url`.
  219. void UpdateLastUsedTime(const BookmarkNode* node, const base::Time time);
  220. // Clears the last used time for the given time range. Called when the user
  221. // clears their history. Time() and Time::Max() are used for min/max values.
  222. void ClearLastUsedTimeInRange(const base::Time delete_begin,
  223. const base::Time delete_end);
  224. // Returns up to |max_count| bookmarks containing each term from |query| in
  225. // either the title, URL, or, if |match_ancestor_titles| is true, the titles
  226. // of ancestors. |matching_algorithm| determines the algorithm used by
  227. // QueryParser internally to parse |query|.
  228. std::vector<TitledUrlMatch> GetBookmarksMatching(
  229. const std::u16string& query,
  230. size_t max_count,
  231. query_parser::MatchingAlgorithm matching_algorithm,
  232. bool match_ancestor_titles = false);
  233. // Sets the store to NULL, making it so the BookmarkModel does not persist
  234. // any changes to disk. This is only useful during testing to speed up
  235. // testing.
  236. void ClearStore();
  237. // Returns the next node ID.
  238. int64_t next_node_id() const { return next_node_id_; }
  239. // Returns the object responsible for tracking the set of expanded nodes in
  240. // the bookmark editor.
  241. BookmarkExpandedStateTracker* expanded_state_tracker() {
  242. return expanded_state_tracker_.get();
  243. }
  244. // Sets/deletes meta info of |node|.
  245. void SetNodeMetaInfo(const BookmarkNode* node,
  246. const std::string& key,
  247. const std::string& value);
  248. void SetNodeMetaInfoMap(const BookmarkNode* node,
  249. const BookmarkNode::MetaInfoMap& meta_info_map);
  250. void DeleteNodeMetaInfo(const BookmarkNode* node,
  251. const std::string& key);
  252. // Adds |key| to the set of meta info keys that are not copied when a node is
  253. // cloned.
  254. void AddNonClonedKey(const std::string& key);
  255. // Returns the set of meta info keys that should not be copied when a node is
  256. // cloned.
  257. const std::set<std::string>& non_cloned_keys() const {
  258. return non_cloned_keys_;
  259. }
  260. // Notify BookmarkModel that the favicons for the given page URLs (e.g.
  261. // http://www.google.com) and the given icon URL (e.g.
  262. // http://www.google.com/favicon.ico) have changed. It is valid to call
  263. // OnFaviconsChanged() with non-empty |page_urls| and an empty |icon_url| and
  264. // vice versa.
  265. void OnFaviconsChanged(const std::set<GURL>& page_urls,
  266. const GURL& icon_url);
  267. // Returns the client used by this BookmarkModel.
  268. BookmarkClient* client() const { return client_.get(); }
  269. void SetUndoDelegate(BookmarkUndoDelegate* undo_delegate);
  270. base::WeakPtr<BookmarkModel> AsWeakPtr() {
  271. return weak_factory_.GetWeakPtr();
  272. }
  273. private:
  274. friend class BookmarkCodecTest;
  275. friend class BookmarkModelFaviconTest;
  276. friend class BookmarkStorage;
  277. friend class ScopedGroupBookmarkActions;
  278. friend class TestBookmarkClient;
  279. // BookmarkUndoProvider:
  280. void RestoreRemovedNode(const BookmarkNode* parent,
  281. size_t index,
  282. std::unique_ptr<BookmarkNode> node) override;
  283. // Notifies the observers for adding every descendant of |node|.
  284. void NotifyNodeAddedForAllDescendants(const BookmarkNode* node);
  285. // Removes the node from internal maps and recurses through all children. If
  286. // the node is a url, its url is added to removed_urls.
  287. //
  288. // This does NOT delete the node.
  289. void RemoveNodeFromIndexRecursive(BookmarkNode* node);
  290. // Called when done loading. Updates internal state and notifies observers.
  291. void DoneLoading(std::unique_ptr<BookmarkLoadDetails> details);
  292. // Adds the |node| at |parent| in the specified |index| and notifies its
  293. // observers.
  294. BookmarkNode* AddNode(BookmarkNode* parent,
  295. size_t index,
  296. std::unique_ptr<BookmarkNode> node);
  297. // Adds |node| to |index_| and recursively invokes this for all children.
  298. void AddNodeToIndexRecursive(const BookmarkNode* node);
  299. // Returns true if the parent and index are valid.
  300. bool IsValidIndex(const BookmarkNode* parent, size_t index, bool allow_end);
  301. // Notification that a favicon has finished loading. If we can decode the
  302. // favicon, FaviconLoaded is invoked.
  303. void OnFaviconDataAvailable(
  304. BookmarkNode* node,
  305. const favicon_base::FaviconImageResult& image_result);
  306. // Invoked from the node to load the favicon. Requests the favicon from the
  307. // favicon service.
  308. void LoadFavicon(BookmarkNode* node);
  309. // Called to notify the observers that the favicon has been loaded.
  310. void FaviconLoaded(const BookmarkNode* node);
  311. // If we're waiting on a favicon for node, the load request is canceled.
  312. void CancelPendingFaviconLoadRequests(BookmarkNode* node);
  313. // Notifies the observers that a set of changes initiated by a single user
  314. // action is about to happen and has completed.
  315. void BeginGroupedChanges();
  316. void EndGroupedChanges();
  317. // Generates and returns the next node ID.
  318. int64_t generate_next_node_id();
  319. // Sets the maximum node ID to the given value.
  320. // This is used by BookmarkCodec to report the maximum ID after it's done
  321. // decoding since during decoding codec assigns node IDs.
  322. void set_next_node_id(int64_t id) { next_node_id_ = id; }
  323. BookmarkUndoDelegate* undo_delegate() const;
  324. // Implementation of `UpdateLastUsedTime` which gives the option to skip
  325. // saving the change to `BookmarkStorage. Used to efficiently make changes
  326. // to multiple bookmarks.
  327. void UpdateLastUsedTimeImpl(const BookmarkNode* node, base::Time time);
  328. void ClearLastUsedTimeInRangeRecursive(BookmarkNode* node,
  329. const base::Time delete_begin,
  330. const base::Time delete_end);
  331. std::unique_ptr<BookmarkClient> client_;
  332. // Whether the initial set of data has been loaded.
  333. bool loaded_ = false;
  334. // See |root_| for details.
  335. std::unique_ptr<BookmarkNode> owned_root_;
  336. // The root node. This contains the bookmark bar node, the 'other' node and
  337. // the mobile node as children. The value of |root_| is initially that of
  338. // |owned_root_|. Once loading has completed, |owned_root_| is destroyed and
  339. // this is set to url_index_->root(). |owned_root_| is done as lots of
  340. // existing code assumes the root is non-null while loading.
  341. raw_ptr<BookmarkNode> root_ = nullptr;
  342. raw_ptr<BookmarkPermanentNode> bookmark_bar_node_ = nullptr;
  343. raw_ptr<BookmarkPermanentNode> other_node_ = nullptr;
  344. raw_ptr<BookmarkPermanentNode> mobile_node_ = nullptr;
  345. // The maximum ID assigned to the bookmark nodes in the model.
  346. int64_t next_node_id_ = 1;
  347. // The observers.
  348. base::ObserverList<BookmarkModelObserver>::Unchecked observers_;
  349. // Used for loading favicons.
  350. base::CancelableTaskTracker cancelable_task_tracker_;
  351. // Writes bookmarks to disk.
  352. std::unique_ptr<BookmarkStorage> store_;
  353. std::unique_ptr<TitledUrlIndex> titled_url_index_;
  354. // Owned by |model_loader_|.
  355. // WARNING: in some tests this does *not* refer to
  356. // |ModelLoader::history_bookmark_model_|. This is because some tests
  357. // directly call DoneLoading().
  358. // TODO: this is confusing, fix tests not to circumvent ModelLoader.
  359. scoped_refptr<UrlIndex> url_index_;
  360. // See description of IsDoingExtensiveChanges above.
  361. int extensive_changes_ = 0;
  362. std::unique_ptr<BookmarkExpandedStateTracker> expanded_state_tracker_;
  363. std::set<std::string> non_cloned_keys_;
  364. raw_ptr<BookmarkUndoDelegate> undo_delegate_ = nullptr;
  365. std::unique_ptr<BookmarkUndoDelegate> empty_undo_delegate_;
  366. scoped_refptr<ModelLoader> model_loader_;
  367. SEQUENCE_CHECKER(sequence_checker_);
  368. base::WeakPtrFactory<BookmarkModel> weak_factory_{this};
  369. };
  370. } // namespace bookmarks
  371. #endif // COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MODEL_H_