| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "chrome/browser/undo/bookmark_undo_service.h" | |
| 6 | |
| 7 #include "chrome/browser/undo/bookmark_renumber_observer.h" | |
| 8 #include "chrome/browser/undo/undo_operation.h" | |
| 9 #include "components/bookmarks/browser/bookmark_model.h" | |
| 10 #include "components/bookmarks/browser/bookmark_node_data.h" | |
| 11 #include "components/bookmarks/browser/bookmark_utils.h" | |
| 12 #include "components/bookmarks/browser/scoped_group_bookmark_actions.h" | |
| 13 #include "grit/components_strings.h" | |
| 14 | |
| 15 using bookmarks::BookmarkModel; | |
| 16 using bookmarks::BookmarkNode; | |
| 17 using bookmarks::BookmarkNodeData; | |
| 18 | |
| 19 namespace { | |
| 20 | |
| 21 // BookmarkUndoOperation ------------------------------------------------------ | |
| 22 | |
| 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 BookmarkUndoOperation(BookmarkModel* bookmark_model, | |
| 29 BookmarkRenumberObserver* undo_renumber_observer) | |
| 30 : bookmark_model_(bookmark_model), | |
| 31 undo_renumber_observer_(undo_renumber_observer) {} | |
| 32 ~BookmarkUndoOperation() override {} | |
| 33 | |
| 34 BookmarkModel* bookmark_model() { return bookmark_model_; } | |
| 35 | |
| 36 BookmarkRenumberObserver* undo_renumber_observer() { | |
| 37 return undo_renumber_observer_; | |
| 38 } | |
| 39 | |
| 40 private: | |
| 41 BookmarkModel* bookmark_model_; | |
| 42 BookmarkRenumberObserver* undo_renumber_observer_; | |
| 43 }; | |
| 44 | |
| 45 // BookmarkAddOperation ------------------------------------------------------- | |
| 46 | |
| 47 // Handles the undo of the insertion of a bookmark or folder. | |
| 48 class BookmarkAddOperation : public BookmarkUndoOperation { | |
| 49 public: | |
| 50 BookmarkAddOperation(BookmarkModel* bookmark_model, | |
| 51 BookmarkRenumberObserver* undo_renumber_observer, | |
| 52 const BookmarkNode* parent, | |
| 53 int index); | |
| 54 ~BookmarkAddOperation() override {} | |
| 55 | |
| 56 // UndoOperation: | |
| 57 void Undo() override; | |
| 58 int GetUndoLabelId() const override; | |
| 59 int GetRedoLabelId() const override; | |
| 60 | |
| 61 // BookmarkRenumberObserver: | |
| 62 void OnBookmarkRenumbered(int64 old_id, int64 new_id) override; | |
| 63 | |
| 64 private: | |
| 65 int64 parent_id_; | |
| 66 const int index_; | |
| 67 | |
| 68 DISALLOW_COPY_AND_ASSIGN(BookmarkAddOperation); | |
| 69 }; | |
| 70 | |
| 71 BookmarkAddOperation::BookmarkAddOperation( | |
| 72 BookmarkModel* bookmark_model, | |
| 73 BookmarkRenumberObserver* undo_renumber_observer, | |
| 74 const BookmarkNode* parent, | |
| 75 int index) | |
| 76 : BookmarkUndoOperation(bookmark_model, undo_renumber_observer), | |
| 77 parent_id_(parent->id()), | |
| 78 index_(index) { | |
| 79 } | |
| 80 | |
| 81 void BookmarkAddOperation::Undo() { | |
| 82 BookmarkModel* model = bookmark_model(); | |
| 83 const BookmarkNode* parent = | |
| 84 bookmarks::GetBookmarkNodeByID(model, parent_id_); | |
| 85 DCHECK(parent); | |
| 86 | |
| 87 model->Remove(parent, index_); | |
| 88 } | |
| 89 | |
| 90 int BookmarkAddOperation::GetUndoLabelId() const { | |
| 91 return IDS_BOOKMARK_BAR_UNDO_ADD; | |
| 92 } | |
| 93 | |
| 94 int BookmarkAddOperation::GetRedoLabelId() const { | |
| 95 return IDS_BOOKMARK_BAR_REDO_DELETE; | |
| 96 } | |
| 97 | |
| 98 void BookmarkAddOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
| 99 if (parent_id_ == old_id) | |
| 100 parent_id_ = new_id; | |
| 101 } | |
| 102 | |
| 103 // BookmarkRemoveOperation ---------------------------------------------------- | |
| 104 | |
| 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. | |
| 107 // | |
| 108 // The BookmarkModel allows only single bookmark node to be removed. | |
| 109 class BookmarkRemoveOperation : public BookmarkUndoOperation { | |
| 110 public: | |
| 111 BookmarkRemoveOperation(BookmarkModel* bookmark_model, | |
| 112 BookmarkRenumberObserver* undo_renumber_observer, | |
| 113 const BookmarkNode* parent, | |
| 114 int old_index, | |
| 115 const BookmarkNode* node); | |
| 116 ~BookmarkRemoveOperation() override {} | |
| 117 | |
| 118 // UndoOperation: | |
| 119 void Undo() override; | |
| 120 int GetUndoLabelId() const override; | |
| 121 int GetRedoLabelId() const override; | |
| 122 | |
| 123 // BookmarkRenumberObserver: | |
| 124 void OnBookmarkRenumbered(int64 old_id, int64 new_id) override; | |
| 125 | |
| 126 private: | |
| 127 void UpdateBookmarkIds(const BookmarkNodeData::Element& element, | |
| 128 const BookmarkNode* parent, | |
| 129 int index_added_at); | |
| 130 | |
| 131 int64 parent_id_; | |
| 132 const int old_index_; | |
| 133 BookmarkNodeData removed_node_; | |
| 134 | |
| 135 DISALLOW_COPY_AND_ASSIGN(BookmarkRemoveOperation); | |
| 136 }; | |
| 137 | |
| 138 BookmarkRemoveOperation::BookmarkRemoveOperation( | |
| 139 BookmarkModel* bookmark_model, | |
| 140 BookmarkRenumberObserver* undo_renumber_observer, | |
| 141 const BookmarkNode* parent, | |
| 142 int old_index, | |
| 143 const BookmarkNode* node) | |
| 144 : BookmarkUndoOperation(bookmark_model, undo_renumber_observer), | |
| 145 parent_id_(parent->id()), | |
| 146 old_index_(old_index), | |
| 147 removed_node_(node) { | |
| 148 } | |
| 149 | |
| 150 void BookmarkRemoveOperation::Undo() { | |
| 151 DCHECK(removed_node_.is_valid()); | |
| 152 BookmarkModel* model = bookmark_model(); | |
| 153 const BookmarkNode* parent = | |
| 154 bookmarks::GetBookmarkNodeByID(model, parent_id_); | |
| 155 DCHECK(parent); | |
| 156 | |
| 157 bookmarks::CloneBookmarkNode( | |
| 158 model, removed_node_.elements, parent, old_index_, false); | |
| 159 UpdateBookmarkIds(removed_node_.elements[0], parent, old_index_); | |
| 160 } | |
| 161 | |
| 162 int BookmarkRemoveOperation::GetUndoLabelId() const { | |
| 163 return IDS_BOOKMARK_BAR_UNDO_DELETE; | |
| 164 } | |
| 165 | |
| 166 int BookmarkRemoveOperation::GetRedoLabelId() const { | |
| 167 return IDS_BOOKMARK_BAR_REDO_ADD; | |
| 168 } | |
| 169 | |
| 170 void BookmarkRemoveOperation::UpdateBookmarkIds( | |
| 171 const BookmarkNodeData::Element& element, | |
| 172 const BookmarkNode* parent, | |
| 173 int index_added_at) { | |
| 174 const BookmarkNode* node = parent->GetChild(index_added_at); | |
| 175 if (element.id() != node->id()) | |
| 176 undo_renumber_observer()->OnBookmarkRenumbered(element.id(), node->id()); | |
| 177 if (!element.is_url) { | |
| 178 for (int i = 0; i < static_cast<int>(element.children.size()); ++i) | |
| 179 UpdateBookmarkIds(element.children[i], node, 0); | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 void BookmarkRemoveOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
| 184 if (parent_id_ == old_id) | |
| 185 parent_id_ = new_id; | |
| 186 } | |
| 187 | |
| 188 // BookmarkEditOperation ------------------------------------------------------ | |
| 189 | |
| 190 // Handles the undo of the modification of a bookmark node. | |
| 191 class BookmarkEditOperation : public BookmarkUndoOperation { | |
| 192 public: | |
| 193 BookmarkEditOperation(BookmarkModel* bookmark_model, | |
| 194 BookmarkRenumberObserver* undo_renumber_observer, | |
| 195 const BookmarkNode* node); | |
| 196 ~BookmarkEditOperation() override {} | |
| 197 | |
| 198 // UndoOperation: | |
| 199 void Undo() override; | |
| 200 int GetUndoLabelId() const override; | |
| 201 int GetRedoLabelId() const override; | |
| 202 | |
| 203 // BookmarkRenumberObserver: | |
| 204 void OnBookmarkRenumbered(int64 old_id, int64 new_id) override; | |
| 205 | |
| 206 private: | |
| 207 int64 node_id_; | |
| 208 BookmarkNodeData original_bookmark_; | |
| 209 | |
| 210 DISALLOW_COPY_AND_ASSIGN(BookmarkEditOperation); | |
| 211 }; | |
| 212 | |
| 213 BookmarkEditOperation::BookmarkEditOperation( | |
| 214 BookmarkModel* bookmark_model, | |
| 215 BookmarkRenumberObserver* undo_renumber_observer, | |
| 216 const BookmarkNode* node) | |
| 217 : BookmarkUndoOperation(bookmark_model, undo_renumber_observer), | |
| 218 node_id_(node->id()), | |
| 219 original_bookmark_(node) { | |
| 220 } | |
| 221 | |
| 222 void BookmarkEditOperation::Undo() { | |
| 223 DCHECK(original_bookmark_.is_valid()); | |
| 224 BookmarkModel* model = bookmark_model(); | |
| 225 const BookmarkNode* node = bookmarks::GetBookmarkNodeByID(model, node_id_); | |
| 226 DCHECK(node); | |
| 227 | |
| 228 model->SetTitle(node, original_bookmark_.elements[0].title); | |
| 229 if (original_bookmark_.elements[0].is_url) | |
| 230 model->SetURL(node, original_bookmark_.elements[0].url); | |
| 231 } | |
| 232 | |
| 233 int BookmarkEditOperation::GetUndoLabelId() const { | |
| 234 return IDS_BOOKMARK_BAR_UNDO_EDIT; | |
| 235 } | |
| 236 | |
| 237 int BookmarkEditOperation::GetRedoLabelId() const { | |
| 238 return IDS_BOOKMARK_BAR_REDO_EDIT; | |
| 239 } | |
| 240 | |
| 241 void BookmarkEditOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
| 242 if (node_id_ == old_id) | |
| 243 node_id_ = new_id; | |
| 244 } | |
| 245 | |
| 246 // BookmarkMoveOperation ------------------------------------------------------ | |
| 247 | |
| 248 // Handles the undo of a bookmark being moved to a new location. | |
| 249 class BookmarkMoveOperation : public BookmarkUndoOperation { | |
| 250 public: | |
| 251 BookmarkMoveOperation(BookmarkModel* bookmark_model, | |
| 252 BookmarkRenumberObserver* undo_renumber_observer, | |
| 253 const BookmarkNode* old_parent, | |
| 254 int old_index, | |
| 255 const BookmarkNode* new_parent, | |
| 256 int new_index); | |
| 257 ~BookmarkMoveOperation() override {} | |
| 258 int GetUndoLabelId() const override; | |
| 259 int GetRedoLabelId() const override; | |
| 260 | |
| 261 // UndoOperation: | |
| 262 void Undo() override; | |
| 263 | |
| 264 // BookmarkRenumberObserver: | |
| 265 void OnBookmarkRenumbered(int64 old_id, int64 new_id) override; | |
| 266 | |
| 267 private: | |
| 268 int64 old_parent_id_; | |
| 269 int64 new_parent_id_; | |
| 270 int old_index_; | |
| 271 int new_index_; | |
| 272 | |
| 273 DISALLOW_COPY_AND_ASSIGN(BookmarkMoveOperation); | |
| 274 }; | |
| 275 | |
| 276 BookmarkMoveOperation::BookmarkMoveOperation( | |
| 277 BookmarkModel* bookmark_model, | |
| 278 BookmarkRenumberObserver* undo_renumber_observer, | |
| 279 const BookmarkNode* old_parent, | |
| 280 int old_index, | |
| 281 const BookmarkNode* new_parent, | |
| 282 int new_index) | |
| 283 : BookmarkUndoOperation(bookmark_model, undo_renumber_observer), | |
| 284 old_parent_id_(old_parent->id()), | |
| 285 new_parent_id_(new_parent->id()), | |
| 286 old_index_(old_index), | |
| 287 new_index_(new_index) { | |
| 288 } | |
| 289 | |
| 290 void BookmarkMoveOperation::Undo() { | |
| 291 BookmarkModel* model = bookmark_model(); | |
| 292 const BookmarkNode* old_parent = | |
| 293 bookmarks::GetBookmarkNodeByID(model, old_parent_id_); | |
| 294 const BookmarkNode* new_parent = | |
| 295 bookmarks::GetBookmarkNodeByID(model, new_parent_id_); | |
| 296 DCHECK(old_parent); | |
| 297 DCHECK(new_parent); | |
| 298 | |
| 299 const BookmarkNode* node = new_parent->GetChild(new_index_); | |
| 300 int destination_index = old_index_; | |
| 301 | |
| 302 // If the bookmark was moved up within the same parent then the destination | |
| 303 // index needs to be incremented since the old index did not account for the | |
| 304 // moved bookmark. | |
| 305 if (old_parent == new_parent && new_index_ < old_index_) | |
| 306 ++destination_index; | |
| 307 | |
| 308 model->Move(node, old_parent, destination_index); | |
| 309 } | |
| 310 | |
| 311 int BookmarkMoveOperation::GetUndoLabelId() const { | |
| 312 return IDS_BOOKMARK_BAR_UNDO_MOVE; | |
| 313 } | |
| 314 | |
| 315 int BookmarkMoveOperation::GetRedoLabelId() const { | |
| 316 return IDS_BOOKMARK_BAR_REDO_MOVE; | |
| 317 } | |
| 318 | |
| 319 void BookmarkMoveOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
| 320 if (old_parent_id_ == old_id) | |
| 321 old_parent_id_ = new_id; | |
| 322 if (new_parent_id_ == old_id) | |
| 323 new_parent_id_ = new_id; | |
| 324 } | |
| 325 | |
| 326 // BookmarkReorderOperation --------------------------------------------------- | |
| 327 | |
| 328 // Handle the undo of reordering of bookmarks that can happen as a result of | |
| 329 // sorting a bookmark folder by name or the undo of that operation. The change | |
| 330 // of order is not recursive so only the order of the immediate children of the | |
| 331 // folder need to be restored. | |
| 332 class BookmarkReorderOperation : public BookmarkUndoOperation { | |
| 333 public: | |
| 334 BookmarkReorderOperation(BookmarkModel* bookmark_model, | |
| 335 BookmarkRenumberObserver* undo_renumber_observer, | |
| 336 const BookmarkNode* parent); | |
| 337 ~BookmarkReorderOperation() override; | |
| 338 | |
| 339 // UndoOperation: | |
| 340 void Undo() override; | |
| 341 int GetUndoLabelId() const override; | |
| 342 int GetRedoLabelId() const override; | |
| 343 | |
| 344 // BookmarkRenumberObserver: | |
| 345 void OnBookmarkRenumbered(int64 old_id, int64 new_id) override; | |
| 346 | |
| 347 private: | |
| 348 int64 parent_id_; | |
| 349 std::vector<int64> ordered_bookmarks_; | |
| 350 | |
| 351 DISALLOW_COPY_AND_ASSIGN(BookmarkReorderOperation); | |
| 352 }; | |
| 353 | |
| 354 BookmarkReorderOperation::BookmarkReorderOperation( | |
| 355 BookmarkModel* bookmark_model, | |
| 356 BookmarkRenumberObserver* undo_renumber_observer, | |
| 357 const BookmarkNode* parent) | |
| 358 : BookmarkUndoOperation(bookmark_model, undo_renumber_observer), | |
| 359 parent_id_(parent->id()) { | |
| 360 ordered_bookmarks_.resize(parent->child_count()); | |
| 361 for (int i = 0; i < parent->child_count(); ++i) | |
| 362 ordered_bookmarks_[i] = parent->GetChild(i)->id(); | |
| 363 } | |
| 364 | |
| 365 BookmarkReorderOperation::~BookmarkReorderOperation() { | |
| 366 } | |
| 367 | |
| 368 void BookmarkReorderOperation::Undo() { | |
| 369 BookmarkModel* model = bookmark_model(); | |
| 370 const BookmarkNode* parent = | |
| 371 bookmarks::GetBookmarkNodeByID(model, parent_id_); | |
| 372 DCHECK(parent); | |
| 373 | |
| 374 std::vector<const BookmarkNode*> ordered_nodes; | |
| 375 for (size_t i = 0; i < ordered_bookmarks_.size(); ++i) { | |
| 376 ordered_nodes.push_back( | |
| 377 bookmarks::GetBookmarkNodeByID(model, ordered_bookmarks_[i])); | |
| 378 } | |
| 379 | |
| 380 model->ReorderChildren(parent, ordered_nodes); | |
| 381 } | |
| 382 | |
| 383 int BookmarkReorderOperation::GetUndoLabelId() const { | |
| 384 return IDS_BOOKMARK_BAR_UNDO_REORDER; | |
| 385 } | |
| 386 | |
| 387 int BookmarkReorderOperation::GetRedoLabelId() const { | |
| 388 return IDS_BOOKMARK_BAR_REDO_REORDER; | |
| 389 } | |
| 390 | |
| 391 void BookmarkReorderOperation::OnBookmarkRenumbered(int64 old_id, | |
| 392 int64 new_id) { | |
| 393 if (parent_id_ == old_id) | |
| 394 parent_id_ = new_id; | |
| 395 for (size_t i = 0; i < ordered_bookmarks_.size(); ++i) { | |
| 396 if (ordered_bookmarks_[i] == old_id) | |
| 397 ordered_bookmarks_[i] = new_id; | |
| 398 } | |
| 399 } | |
| 400 | |
| 401 } // namespace | |
| 402 | |
| 403 // BookmarkUndoService -------------------------------------------------------- | |
| 404 | |
| 405 BookmarkUndoService::BookmarkUndoService() : scoped_observer_(this) { | |
| 406 } | |
| 407 | |
| 408 BookmarkUndoService::~BookmarkUndoService() { | |
| 409 } | |
| 410 | |
| 411 void BookmarkUndoService::Start(BookmarkModel* model) { | |
| 412 scoped_observer_.Add(model); | |
| 413 } | |
| 414 | |
| 415 void BookmarkUndoService::Shutdown() { | |
| 416 scoped_observer_.RemoveAll(); | |
| 417 } | |
| 418 | |
| 419 void BookmarkUndoService::BookmarkModelLoaded(BookmarkModel* model, | |
| 420 bool ids_reassigned) { | |
| 421 undo_manager_.RemoveAllOperations(); | |
| 422 } | |
| 423 | |
| 424 void BookmarkUndoService::BookmarkModelBeingDeleted(BookmarkModel* model) { | |
| 425 undo_manager_.RemoveAllOperations(); | |
| 426 } | |
| 427 | |
| 428 void BookmarkUndoService::BookmarkNodeMoved(BookmarkModel* model, | |
| 429 const BookmarkNode* old_parent, | |
| 430 int old_index, | |
| 431 const BookmarkNode* new_parent, | |
| 432 int new_index) { | |
| 433 scoped_ptr<UndoOperation> op(new BookmarkMoveOperation( | |
| 434 model, this, old_parent, old_index, new_parent, new_index)); | |
| 435 undo_manager()->AddUndoOperation(op.Pass()); | |
| 436 } | |
| 437 | |
| 438 void BookmarkUndoService::BookmarkNodeAdded(BookmarkModel* model, | |
| 439 const BookmarkNode* parent, | |
| 440 int index) { | |
| 441 scoped_ptr<UndoOperation> op( | |
| 442 new BookmarkAddOperation(model, this, parent, index)); | |
| 443 undo_manager()->AddUndoOperation(op.Pass()); | |
| 444 } | |
| 445 | |
| 446 void BookmarkUndoService::OnWillRemoveBookmarks(BookmarkModel* model, | |
| 447 const BookmarkNode* parent, | |
| 448 int old_index, | |
| 449 const BookmarkNode* node) { | |
| 450 scoped_ptr<UndoOperation> op( | |
| 451 new BookmarkRemoveOperation(model, this, parent, old_index, node)); | |
| 452 undo_manager()->AddUndoOperation(op.Pass()); | |
| 453 } | |
| 454 | |
| 455 void BookmarkUndoService::OnWillRemoveAllUserBookmarks(BookmarkModel* model) { | |
| 456 bookmarks::ScopedGroupBookmarkActions merge_removes(model); | |
| 457 for (int i = 0; i < model->root_node()->child_count(); ++i) { | |
| 458 const BookmarkNode* permanent_node = model->root_node()->GetChild(i); | |
| 459 for (int j = permanent_node->child_count() - 1; j >= 0; --j) { | |
| 460 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation( | |
| 461 model, this, permanent_node, j, permanent_node->GetChild(j))); | |
| 462 undo_manager()->AddUndoOperation(op.Pass()); | |
| 463 } | |
| 464 } | |
| 465 } | |
| 466 | |
| 467 void BookmarkUndoService::OnWillChangeBookmarkNode(BookmarkModel* model, | |
| 468 const BookmarkNode* node) { | |
| 469 scoped_ptr<UndoOperation> op(new BookmarkEditOperation(model, this, node)); | |
| 470 undo_manager()->AddUndoOperation(op.Pass()); | |
| 471 } | |
| 472 | |
| 473 void BookmarkUndoService::OnWillReorderBookmarkNode(BookmarkModel* model, | |
| 474 const BookmarkNode* node) { | |
| 475 scoped_ptr<UndoOperation> op(new BookmarkReorderOperation(model, this, node)); | |
| 476 undo_manager()->AddUndoOperation(op.Pass()); | |
| 477 } | |
| 478 | |
| 479 void BookmarkUndoService::GroupedBookmarkChangesBeginning( | |
| 480 BookmarkModel* model) { | |
| 481 undo_manager()->StartGroupingActions(); | |
| 482 } | |
| 483 | |
| 484 void BookmarkUndoService::GroupedBookmarkChangesEnded(BookmarkModel* model) { | |
| 485 undo_manager()->EndGroupingActions(); | |
| 486 } | |
| 487 | |
| 488 void BookmarkUndoService::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
| 489 std::vector<UndoOperation*> all_operations = | |
| 490 undo_manager()->GetAllUndoOperations(); | |
| 491 for (UndoOperation* op : all_operations) { | |
| 492 static_cast<BookmarkUndoOperation*>(op) | |
| 493 ->OnBookmarkRenumbered(old_id, new_id); | |
| 494 } | |
| 495 } | |
| OLD | NEW |