Home | History | Annotate | Download | only in browser
      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.
     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.
     92   const BookmarkNode* root_node() const { return &root_; }
     93 
     94   // Returns the 'bookmark bar' node. This is NULL until loaded.
     95   const BookmarkNode* bookmark_bar_node() const { return bookmark_bar_node_; }
     96 
     97   // Returns the 'other' node. This is NULL until loaded.
     98   const BookmarkNode* other_node() const { return other_node_; }
     99 
    100   // Returns the 'mobile' node. This is NULL until loaded.
    101   const BookmarkNode* mobile_node() const { return mobile_node_; }
    102 
    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_|.
    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.
    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.
    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.
    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.
    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:
    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.
    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