NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / undo / bookmark_undo_service.cc
blob63de7e7285f92c248eb0d75d87a3a93c53d36f4e
1 // Copyright 2013 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.
5 #include "chrome/browser/undo/bookmark_undo_service.h"
7 #include "chrome/browser/bookmarks/bookmark_model.h"
8 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
9 #include "chrome/browser/bookmarks/bookmark_node_data.h"
10 #include "chrome/browser/bookmarks/bookmark_utils.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/undo/bookmark_renumber_observer.h"
13 #include "chrome/browser/undo/bookmark_undo_service_factory.h"
14 #include "chrome/browser/undo/bookmark_undo_utils.h"
15 #include "chrome/browser/undo/undo_operation.h"
16 #include "grit/generated_resources.h"
17 #include "ui/base/l10n/l10n_util.h"
19 namespace {
21 // BookmarkUndoOperation ------------------------------------------------------
23 // Base class for all bookmark related UndoOperations that facilitates access to
24 // the BookmarkUndoService.
25 class BookmarkUndoOperation : public UndoOperation,
26 public BookmarkRenumberObserver {
27 public:
28 explicit BookmarkUndoOperation(Profile* profile);
29 virtual ~BookmarkUndoOperation() {}
31 BookmarkModel* GetBookmarkModel() const;
32 BookmarkRenumberObserver* GetUndoRenumberObserver() const;
34 private:
35 Profile* profile_;
38 BookmarkUndoOperation::BookmarkUndoOperation(Profile* profile)
39 : profile_(profile) {
42 BookmarkModel* BookmarkUndoOperation::GetBookmarkModel() const {
43 return BookmarkModelFactory::GetForProfile(profile_);
46 BookmarkRenumberObserver* BookmarkUndoOperation::GetUndoRenumberObserver()
47 const {
48 return BookmarkUndoServiceFactory::GetForProfile(profile_);
51 // BookmarkAddOperation -------------------------------------------------------
53 // Handles the undo of the insertion of a bookmark or folder.
54 class BookmarkAddOperation : public BookmarkUndoOperation {
55 public:
56 BookmarkAddOperation(Profile* profile, const BookmarkNode* parent, int index);
57 virtual ~BookmarkAddOperation() {}
59 // UndoOperation:
60 virtual void Undo() OVERRIDE;
61 virtual int GetUndoLabelId() const OVERRIDE;
62 virtual int GetRedoLabelId() const OVERRIDE;
64 // BookmarkRenumberObserver:
65 virtual void OnBookmarkRenumbered(int64 old_id, int64 new_id) OVERRIDE;
67 private:
68 int64 parent_id_;
69 const int index_;
71 DISALLOW_COPY_AND_ASSIGN(BookmarkAddOperation);
74 BookmarkAddOperation::BookmarkAddOperation(Profile* profile,
75 const BookmarkNode* parent,
76 int index)
77 : BookmarkUndoOperation(profile),
78 parent_id_(parent->id()),
79 index_(index) {
82 void BookmarkAddOperation::Undo() {
83 BookmarkModel* model = GetBookmarkModel();
84 const BookmarkNode* parent = model->GetNodeByID(parent_id_);
85 DCHECK(parent);
87 model->Remove(parent, index_);
90 int BookmarkAddOperation::GetUndoLabelId() const {
91 return IDS_BOOKMARK_BAR_UNDO_ADD;
94 int BookmarkAddOperation::GetRedoLabelId() const {
95 return IDS_BOOKMARK_BAR_REDO_DELETE;
98 void BookmarkAddOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
99 if (parent_id_ == old_id)
100 parent_id_ = new_id;
103 // BookmarkRemoveOperation ----------------------------------------------------
105 // Handles the undo of the deletion of a bookmark node. For a bookmark folder,
106 // the information for all descendant bookmark nodes is maintained.
108 // The BookmarkModel allows only single bookmark node to be removed.
109 class BookmarkRemoveOperation : public BookmarkUndoOperation {
110 public:
111 BookmarkRemoveOperation(Profile* profile,
112 const BookmarkNode* parent,
113 int old_index,
114 const BookmarkNode* node);
115 virtual ~BookmarkRemoveOperation() {}
117 // UndoOperation:
118 virtual void Undo() OVERRIDE;
119 virtual int GetUndoLabelId() const OVERRIDE;
120 virtual int GetRedoLabelId() const OVERRIDE;
122 // BookmarkRenumberObserver:
123 virtual void OnBookmarkRenumbered(int64 old_id, int64 new_id) OVERRIDE;
125 private:
126 void UpdateBookmarkIds(const BookmarkNodeData::Element& element,
127 const BookmarkNode* parent,
128 int index_added_at) const;
130 int64 parent_id_;
131 const int old_index_;
132 BookmarkNodeData removed_node_;
134 DISALLOW_COPY_AND_ASSIGN(BookmarkRemoveOperation);
137 BookmarkRemoveOperation::BookmarkRemoveOperation(Profile* profile,
138 const BookmarkNode* parent,
139 int old_index,
140 const BookmarkNode* node)
141 : BookmarkUndoOperation(profile),
142 parent_id_(parent->id()),
143 old_index_(old_index),
144 removed_node_(node) {
147 void BookmarkRemoveOperation::Undo() {
148 DCHECK(removed_node_.is_valid());
149 BookmarkModel* model = GetBookmarkModel();
150 const BookmarkNode* parent = model->GetNodeByID(parent_id_);
151 DCHECK(parent);
153 bookmark_utils::CloneBookmarkNode(model, removed_node_.elements, parent,
154 old_index_, false);
155 UpdateBookmarkIds(removed_node_.elements[0], parent, old_index_);
158 int BookmarkRemoveOperation::GetUndoLabelId() const {
159 return IDS_BOOKMARK_BAR_UNDO_DELETE;
162 int BookmarkRemoveOperation::GetRedoLabelId() const {
163 return IDS_BOOKMARK_BAR_REDO_ADD;
166 void BookmarkRemoveOperation::UpdateBookmarkIds(
167 const BookmarkNodeData::Element& element,
168 const BookmarkNode* parent,
169 int index_added_at) const {
170 const BookmarkNode* node = parent->GetChild(index_added_at);
171 if (element.id() != node->id())
172 GetUndoRenumberObserver()->OnBookmarkRenumbered(element.id(), node->id());
173 if (!element.is_url) {
174 for (int i = 0; i < static_cast<int>(element.children.size()); ++i)
175 UpdateBookmarkIds(element.children[i], node, 0);
179 void BookmarkRemoveOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
180 if (parent_id_ == old_id)
181 parent_id_ = new_id;
184 // BookmarkEditOperation ------------------------------------------------------
186 // Handles the undo of the modification of a bookmark node.
187 class BookmarkEditOperation : public BookmarkUndoOperation {
188 public:
189 BookmarkEditOperation(Profile* profile,
190 const BookmarkNode* node);
191 virtual ~BookmarkEditOperation() {}
193 // UndoOperation:
194 virtual void Undo() OVERRIDE;
195 virtual int GetUndoLabelId() const OVERRIDE;
196 virtual int GetRedoLabelId() const OVERRIDE;
198 // BookmarkRenumberObserver:
199 virtual void OnBookmarkRenumbered(int64 old_id, int64 new_id) OVERRIDE;
201 private:
202 int64 node_id_;
203 BookmarkNodeData original_bookmark_;
205 DISALLOW_COPY_AND_ASSIGN(BookmarkEditOperation);
208 BookmarkEditOperation::BookmarkEditOperation(Profile* profile,
209 const BookmarkNode* node)
210 : BookmarkUndoOperation(profile),
211 node_id_(node->id()),
212 original_bookmark_(node) {
215 void BookmarkEditOperation::Undo() {
216 DCHECK(original_bookmark_.is_valid());
217 BookmarkModel* model = GetBookmarkModel();
218 const BookmarkNode* node = model->GetNodeByID(node_id_);
219 DCHECK(node);
221 model->SetTitle(node, original_bookmark_.elements[0].title);
222 if (original_bookmark_.elements[0].is_url)
223 model->SetURL(node, original_bookmark_.elements[0].url);
226 int BookmarkEditOperation::GetUndoLabelId() const {
227 return IDS_BOOKMARK_BAR_UNDO_EDIT;
230 int BookmarkEditOperation::GetRedoLabelId() const {
231 return IDS_BOOKMARK_BAR_REDO_EDIT;
234 void BookmarkEditOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
235 if (node_id_ == old_id)
236 node_id_ = new_id;
239 // BookmarkMoveOperation ------------------------------------------------------
241 // Handles the undo of a bookmark being moved to a new location.
242 class BookmarkMoveOperation : public BookmarkUndoOperation {
243 public:
244 BookmarkMoveOperation(Profile* profile,
245 const BookmarkNode* old_parent,
246 int old_index,
247 const BookmarkNode* new_parent,
248 int new_index);
249 virtual ~BookmarkMoveOperation() {}
250 virtual int GetUndoLabelId() const OVERRIDE;
251 virtual int GetRedoLabelId() const OVERRIDE;
253 // UndoOperation:
254 virtual void Undo() OVERRIDE;
256 // BookmarkRenumberObserver:
257 virtual void OnBookmarkRenumbered(int64 old_id, int64 new_id) OVERRIDE;
259 private:
260 int64 old_parent_id_;
261 int64 new_parent_id_;
262 int old_index_;
263 int new_index_;
265 DISALLOW_COPY_AND_ASSIGN(BookmarkMoveOperation);
268 BookmarkMoveOperation::BookmarkMoveOperation(Profile* profile,
269 const BookmarkNode* old_parent,
270 int old_index,
271 const BookmarkNode* new_parent,
272 int new_index)
273 : BookmarkUndoOperation(profile),
274 old_parent_id_(old_parent->id()),
275 new_parent_id_(new_parent->id()),
276 old_index_(old_index),
277 new_index_(new_index) {
280 void BookmarkMoveOperation::Undo() {
281 BookmarkModel* model = GetBookmarkModel();
282 const BookmarkNode* old_parent = model->GetNodeByID(old_parent_id_);
283 const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id_);
284 DCHECK(old_parent);
285 DCHECK(new_parent);
287 const BookmarkNode* node = new_parent->GetChild(new_index_);
288 int destination_index = old_index_;
290 // If the bookmark was moved up within the same parent then the destination
291 // index needs to be incremented since the old index did not account for the
292 // moved bookmark.
293 if (old_parent == new_parent && new_index_ < old_index_)
294 ++destination_index;
296 model->Move(node, old_parent, destination_index);
299 int BookmarkMoveOperation::GetUndoLabelId() const {
300 return IDS_BOOKMARK_BAR_UNDO_MOVE;
303 int BookmarkMoveOperation::GetRedoLabelId() const {
304 return IDS_BOOKMARK_BAR_REDO_MOVE;
307 void BookmarkMoveOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
308 if (old_parent_id_ == old_id)
309 old_parent_id_ = new_id;
310 if (new_parent_id_ == old_id)
311 new_parent_id_ = new_id;
314 // BookmarkReorderOperation ---------------------------------------------------
316 // Handle the undo of reordering of bookmarks that can happen as a result of
317 // sorting a bookmark folder by name or the undo of that operation. The change
318 // of order is not recursive so only the order of the immediate children of the
319 // folder need to be restored.
320 class BookmarkReorderOperation : public BookmarkUndoOperation {
321 public:
322 BookmarkReorderOperation(Profile* profile,
323 const BookmarkNode* parent);
324 virtual ~BookmarkReorderOperation();
326 // UndoOperation:
327 virtual void Undo() OVERRIDE;
328 virtual int GetUndoLabelId() const OVERRIDE;
329 virtual int GetRedoLabelId() const OVERRIDE;
331 // BookmarkRenumberObserver:
332 virtual void OnBookmarkRenumbered(int64 old_id, int64 new_id) OVERRIDE;
334 private:
335 int64 parent_id_;
336 std::vector<int64> ordered_bookmarks_;
338 DISALLOW_COPY_AND_ASSIGN(BookmarkReorderOperation);
341 BookmarkReorderOperation::BookmarkReorderOperation(Profile* profile,
342 const BookmarkNode* parent)
343 : BookmarkUndoOperation(profile),
344 parent_id_(parent->id()) {
345 ordered_bookmarks_.resize(parent->child_count());
346 for (int i = 0; i < parent->child_count(); ++i)
347 ordered_bookmarks_[i] = parent->GetChild(i)->id();
350 BookmarkReorderOperation::~BookmarkReorderOperation() {
353 void BookmarkReorderOperation::Undo() {
354 BookmarkModel* model = GetBookmarkModel();
355 const BookmarkNode* parent = model->GetNodeByID(parent_id_);
356 DCHECK(parent);
358 std::vector<const BookmarkNode*> ordered_nodes;
359 for (size_t i = 0; i < ordered_bookmarks_.size(); ++i)
360 ordered_nodes.push_back(model->GetNodeByID(ordered_bookmarks_[i]));
362 model->ReorderChildren(parent, ordered_nodes);
365 int BookmarkReorderOperation::GetUndoLabelId() const {
366 return IDS_BOOKMARK_BAR_UNDO_REORDER;
369 int BookmarkReorderOperation::GetRedoLabelId() const {
370 return IDS_BOOKMARK_BAR_REDO_REORDER;
373 void BookmarkReorderOperation::OnBookmarkRenumbered(int64 old_id,
374 int64 new_id) {
375 if (parent_id_ == old_id)
376 parent_id_ = new_id;
377 for (size_t i = 0; i < ordered_bookmarks_.size(); ++i) {
378 if (ordered_bookmarks_[i] == old_id)
379 ordered_bookmarks_[i] = new_id;
383 } // namespace
385 // BookmarkUndoService --------------------------------------------------------
387 BookmarkUndoService::BookmarkUndoService(Profile* profile) : profile_(profile) {
390 BookmarkUndoService::~BookmarkUndoService() {
391 BookmarkModelFactory::GetForProfile(profile_)->RemoveObserver(this);
394 void BookmarkUndoService::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
395 std::vector<UndoOperation*> all_operations =
396 undo_manager()->GetAllUndoOperations();
397 for (std::vector<UndoOperation*>::iterator it = all_operations.begin();
398 it != all_operations.end(); ++it) {
399 static_cast<BookmarkUndoOperation*>(*it)->OnBookmarkRenumbered(old_id,
400 new_id);
404 void BookmarkUndoService::BookmarkModelLoaded(BookmarkModel* model,
405 bool ids_reassigned) {
406 undo_manager_.RemoveAllOperations();
409 void BookmarkUndoService::BookmarkModelBeingDeleted(BookmarkModel* model) {
410 undo_manager_.RemoveAllOperations();
413 void BookmarkUndoService::BookmarkNodeMoved(BookmarkModel* model,
414 const BookmarkNode* old_parent,
415 int old_index,
416 const BookmarkNode* new_parent,
417 int new_index) {
418 scoped_ptr<UndoOperation> op(new BookmarkMoveOperation(profile_,
419 old_parent,
420 old_index,
421 new_parent,
422 new_index));
423 undo_manager()->AddUndoOperation(op.Pass());
426 void BookmarkUndoService::BookmarkNodeAdded(BookmarkModel* model,
427 const BookmarkNode* parent,
428 int index) {
429 scoped_ptr<UndoOperation> op(new BookmarkAddOperation(profile_,
430 parent,
431 index));
432 undo_manager()->AddUndoOperation(op.Pass());
435 void BookmarkUndoService::OnWillRemoveBookmarks(BookmarkModel* model,
436 const BookmarkNode* parent,
437 int old_index,
438 const BookmarkNode* node) {
439 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(profile_,
440 parent,
441 old_index,
442 node));
443 undo_manager()->AddUndoOperation(op.Pass());
446 void BookmarkUndoService::OnWillRemoveAllBookmarks(BookmarkModel* model) {
447 ScopedGroupBookmarkActions merge_removes(profile_);
448 for (int i = 0; i < model->root_node()->child_count(); ++i) {
449 const BookmarkNode* permanent_node = model->root_node()->GetChild(i);
450 for (int j = permanent_node->child_count() - 1; j >= 0; --j) {
451 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(profile_,
452 permanent_node, j, permanent_node->GetChild(j)));
453 undo_manager()->AddUndoOperation(op.Pass());
458 void BookmarkUndoService::OnWillChangeBookmarkNode(BookmarkModel* model,
459 const BookmarkNode* node) {
460 scoped_ptr<UndoOperation> op(new BookmarkEditOperation(profile_, node));
461 undo_manager()->AddUndoOperation(op.Pass());
464 void BookmarkUndoService::OnWillReorderBookmarkNode(BookmarkModel* model,
465 const BookmarkNode* node) {
466 scoped_ptr<UndoOperation> op(new BookmarkReorderOperation(profile_, node));
467 undo_manager()->AddUndoOperation(op.Pass());