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_STORAGE_H_
6#define COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_STORAGE_H_
7
8#include "base/callback_forward.h"
9#include "base/files/file_path.h"
10#include "base/files/important_file_writer.h"
11#include "base/memory/ref_counted.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/memory/scoped_vector.h"
14#include "base/memory/weak_ptr.h"
15#include "components/bookmarks/browser/bookmark_node.h"
16
17class BookmarkModel;
18
19namespace base {
20class SequencedTaskRunner;
21}
22
23namespace bookmarks {
24
25class BookmarkIndex;
26
27// A list of BookmarkPermanentNodes that owns them.
28typedef ScopedVector<BookmarkPermanentNode> BookmarkPermanentNodeList;
29
30// A callback that generates a BookmarkPermanentNodeList, given a max ID to
31// use. The max ID argument will be updated after any new nodes have been
32// created and assigned IDs.
33typedef base::Callback<BookmarkPermanentNodeList(int64*)> LoadExtraCallback;
34
35// BookmarkLoadDetails is used by BookmarkStorage when loading bookmarks.
36// BookmarkModel creates a BookmarkLoadDetails and passes it (including
37// ownership) to BookmarkStorage. BookmarkStorage loads the bookmarks (and
38// index) in the background thread, then calls back to the BookmarkModel (on
39// the main thread) when loading is done, passing ownership back to the
40// BookmarkModel. While loading BookmarkModel does not maintain references to
41// the contents of the BookmarkLoadDetails, this ensures we don't have any
42// threading problems.
43class BookmarkLoadDetails {
44 public:
45  BookmarkLoadDetails(BookmarkPermanentNode* bb_node,
46                      BookmarkPermanentNode* other_folder_node,
47                      BookmarkPermanentNode* mobile_folder_node,
48                      const LoadExtraCallback& load_extra_callback,
49                      BookmarkIndex* index,
50                      int64 max_id);
51  ~BookmarkLoadDetails();
52
53  void LoadExtraNodes();
54
55  BookmarkPermanentNode* bb_node() { return bb_node_.get(); }
56  BookmarkPermanentNode* release_bb_node() { return bb_node_.release(); }
57  BookmarkPermanentNode* mobile_folder_node() {
58    return mobile_folder_node_.get();
59  }
60  BookmarkPermanentNode* release_mobile_folder_node() {
61    return mobile_folder_node_.release();
62  }
63  BookmarkPermanentNode* other_folder_node() {
64    return other_folder_node_.get();
65  }
66  BookmarkPermanentNode* release_other_folder_node() {
67    return other_folder_node_.release();
68  }
69  const BookmarkPermanentNodeList& extra_nodes() {
70    return extra_nodes_;
71  }
72  void release_extra_nodes(std::vector<BookmarkPermanentNode*>* extra_nodes) {
73    extra_nodes_.release(extra_nodes);
74  }
75  BookmarkIndex* index() { return index_.get(); }
76  BookmarkIndex* release_index() { return index_.release(); }
77
78  const BookmarkNode::MetaInfoMap& model_meta_info_map() const {
79    return model_meta_info_map_;
80  }
81  void set_model_meta_info_map(const BookmarkNode::MetaInfoMap& meta_info_map) {
82    model_meta_info_map_ = meta_info_map;
83  }
84
85  int64 model_sync_transaction_version() const {
86    return model_sync_transaction_version_;
87  }
88  void set_model_sync_transaction_version(int64 sync_transaction_version) {
89    model_sync_transaction_version_ = sync_transaction_version;
90  }
91
92  // Max id of the nodes.
93  void set_max_id(int64 max_id) { max_id_ = max_id; }
94  int64 max_id() const { return max_id_; }
95
96  // Computed checksum.
97  void set_computed_checksum(const std::string& value) {
98    computed_checksum_ = value;
99  }
100  const std::string& computed_checksum() const { return computed_checksum_; }
101
102  // Stored checksum.
103  void set_stored_checksum(const std::string& value) {
104    stored_checksum_ = value;
105  }
106  const std::string& stored_checksum() const { return stored_checksum_; }
107
108  // Whether ids were reassigned. IDs are reassigned during decoding if the
109  // checksum of the file doesn't match, some IDs are missing or not
110  // unique. Basically, if the user modified the bookmarks directly we'll
111  // reassign the ids to ensure they are unique.
112  void set_ids_reassigned(bool value) { ids_reassigned_ = value; }
113  bool ids_reassigned() const { return ids_reassigned_; }
114
115 private:
116  scoped_ptr<BookmarkPermanentNode> bb_node_;
117  scoped_ptr<BookmarkPermanentNode> other_folder_node_;
118  scoped_ptr<BookmarkPermanentNode> mobile_folder_node_;
119  LoadExtraCallback load_extra_callback_;
120  BookmarkPermanentNodeList extra_nodes_;
121  scoped_ptr<BookmarkIndex> index_;
122  BookmarkNode::MetaInfoMap model_meta_info_map_;
123  int64 model_sync_transaction_version_;
124  int64 max_id_;
125  std::string computed_checksum_;
126  std::string stored_checksum_;
127  bool ids_reassigned_;
128
129  DISALLOW_COPY_AND_ASSIGN(BookmarkLoadDetails);
130};
131
132// BookmarkStorage handles reading/write the bookmark bar model. The
133// BookmarkModel uses the BookmarkStorage to load bookmarks from disk, as well
134// as notifying the BookmarkStorage every time the model changes.
135//
136// Internally BookmarkStorage uses BookmarkCodec to do the actual read/write.
137class BookmarkStorage : public base::ImportantFileWriter::DataSerializer {
138 public:
139  // Creates a BookmarkStorage for the specified model. The data will be loaded
140  // from and saved to a location derived from |profile_path|. The IO code will
141  // be executed as a task in |sequenced_task_runner|.
142  BookmarkStorage(BookmarkModel* model,
143                  const base::FilePath& profile_path,
144                  base::SequencedTaskRunner* sequenced_task_runner);
145  virtual ~BookmarkStorage();
146
147  // Loads the bookmarks into the model, notifying the model when done. This
148  // takes ownership of |details| and send the |OnLoadFinished| callback from
149  // a task in |task_runner|. See BookmarkLoadDetails for details.
150  void LoadBookmarks(
151      scoped_ptr<BookmarkLoadDetails> details,
152      const scoped_refptr<base::SequencedTaskRunner>& task_runner);
153
154  // Schedules saving the bookmark bar model to disk.
155  void ScheduleSave();
156
157  // Notification the bookmark bar model is going to be deleted. If there is
158  // a pending save, it is saved immediately.
159  void BookmarkModelDeleted();
160
161  // Callback from backend after loading the bookmark file.
162  void OnLoadFinished(scoped_ptr<BookmarkLoadDetails> details);
163
164  // ImportantFileWriter::DataSerializer implementation.
165  virtual bool SerializeData(std::string* output) OVERRIDE;
166
167 private:
168  // Serializes the data and schedules save using ImportantFileWriter.
169  // Returns true on successful serialization.
170  bool SaveNow();
171
172  // The model. The model is NULL once BookmarkModelDeleted has been invoked.
173  BookmarkModel* model_;
174
175  // Helper to write bookmark data safely.
176  base::ImportantFileWriter writer_;
177
178  // Sequenced task runner where file I/O operations will be performed at.
179  scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
180
181  base::WeakPtrFactory<BookmarkStorage> weak_factory_;
182
183  DISALLOW_COPY_AND_ASSIGN(BookmarkStorage);
184};
185
186}  // namespace bookmarks
187
188#endif  // COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_STORAGE_H_
189