Chromium Code Reviews| 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/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/undo_manager_utils.h" | |
| 15 #include "chrome/browser/undo/undo_operation.h" | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 // BookmarkUndoOperation ------------------------------------------------------ | |
| 20 | |
| 21 // Base class for all bookmark related UndoOperations that facilitates access to | |
| 22 // the BookmarkUndoService. | |
| 23 class BookmarkUndoOperation : public UndoOperation, | |
| 24 public BookmarkRenumberObserver { | |
| 25 public: | |
| 26 explicit BookmarkUndoOperation(Profile* profile); | |
| 27 virtual ~BookmarkUndoOperation() {} | |
| 28 | |
| 29 BookmarkModel* GetBookmarkModel() const; | |
| 30 BookmarkRenumberObserver* GetUndoRenumberObserver() const; | |
| 31 | |
| 32 private: | |
| 33 Profile* profile_; | |
| 34 }; | |
| 35 | |
| 36 BookmarkUndoOperation::BookmarkUndoOperation(Profile* profile) | |
| 37 : profile_(profile) { | |
| 38 } | |
| 39 | |
| 40 BookmarkModel* BookmarkUndoOperation::GetBookmarkModel() const { | |
| 41 return BookmarkModelFactory::GetForProfile(profile_); | |
| 42 } | |
| 43 | |
| 44 BookmarkRenumberObserver* BookmarkUndoOperation::GetUndoRenumberObserver( | |
| 45 ) const { | |
|
Tom Cassiotis
2013/09/04 13:44:43
I spent a non-trivial amount of time to figure out
sky
2013/09/04 21:52:18
HA! For the record the style guide is here: http:/
Tom Cassiotis
2013/09/05 12:51:58
I did look at the style guide to figure out the fo
| |
| 46 return BookmarkUndoServiceFactory::GetForProfile(profile_); | |
| 47 } | |
| 48 | |
| 49 // BookmarkAddOperation ------------------------------------------------------- | |
| 50 | |
| 51 // Handles the undo of the insertion of a bookmark or folder. | |
| 52 class BookmarkAddOperation : public BookmarkUndoOperation { | |
| 53 public: | |
| 54 BookmarkAddOperation(Profile* profile, const BookmarkNode* parent, int index); | |
| 55 virtual ~BookmarkAddOperation() {} | |
| 56 | |
| 57 // UndoOperation: | |
| 58 virtual void Undo() OVERRIDE; | |
| 59 | |
| 60 // BookmarkRenumberObserver: | |
| 61 virtual void OnBookmarkRenumbered(int64 old_id, int64 new_id) OVERRIDE; | |
| 62 | |
| 63 private: | |
| 64 int64 parent_id_; | |
| 65 const int index_; | |
| 66 | |
| 67 DISALLOW_COPY_AND_ASSIGN(BookmarkAddOperation); | |
| 68 }; | |
| 69 | |
| 70 BookmarkAddOperation::BookmarkAddOperation(Profile* profile, | |
| 71 const BookmarkNode* parent, | |
| 72 int index) | |
| 73 : BookmarkUndoOperation(profile), | |
| 74 parent_id_(parent->id()), | |
| 75 index_(index) { | |
| 76 } | |
| 77 | |
| 78 void BookmarkAddOperation::Undo() { | |
| 79 BookmarkModel* model = GetBookmarkModel(); | |
| 80 const BookmarkNode* parent = model->GetNodeByID(parent_id_); | |
| 81 DCHECK(parent); | |
| 82 | |
| 83 model->Remove(parent, index_); | |
| 84 } | |
| 85 | |
| 86 void BookmarkAddOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
| 87 if (parent_id_ == old_id) | |
| 88 parent_id_ = new_id; | |
| 89 } | |
| 90 | |
| 91 // BookmarkRemoveOperation ---------------------------------------------------- | |
| 92 | |
| 93 // Handles the undo of the deletion of a bookmark node. For a bookmark folder, | |
| 94 // the information for all descendant bookmark nodes is maintained. | |
| 95 // | |
| 96 // The BookmarkModel allows only single bookmark node to be removed. | |
| 97 class BookmarkRemoveOperation : public BookmarkUndoOperation { | |
| 98 public: | |
| 99 BookmarkRemoveOperation(Profile* profile, | |
| 100 const BookmarkNode* parent, | |
| 101 int old_index, | |
| 102 const BookmarkNode* node); | |
| 103 virtual ~BookmarkRemoveOperation() {} | |
| 104 | |
| 105 // UndoOperation: | |
| 106 virtual void Undo() OVERRIDE; | |
| 107 | |
| 108 // BookmarkRenumberObserver: | |
| 109 virtual void OnBookmarkRenumbered(int64 old_id, int64 new_id) OVERRIDE; | |
| 110 | |
| 111 private: | |
| 112 void UpdateBookmarkIds(const BookmarkNodeData::Element& element, | |
| 113 const BookmarkNode* parent, | |
| 114 int index_added_at) const; | |
| 115 | |
| 116 int64 parent_id_; | |
| 117 const int old_index_; | |
| 118 BookmarkNodeData removed_node_; | |
| 119 | |
| 120 DISALLOW_COPY_AND_ASSIGN(BookmarkRemoveOperation); | |
| 121 }; | |
| 122 | |
| 123 BookmarkRemoveOperation::BookmarkRemoveOperation(Profile* profile, | |
| 124 const BookmarkNode* parent, | |
| 125 int old_index, | |
| 126 const BookmarkNode* node) | |
| 127 : BookmarkUndoOperation(profile), | |
| 128 parent_id_(parent->id()), | |
| 129 old_index_(old_index), | |
| 130 removed_node_(node) { | |
| 131 } | |
| 132 | |
| 133 void BookmarkRemoveOperation::Undo() { | |
| 134 DCHECK(removed_node_.is_valid()); | |
| 135 BookmarkModel* model = GetBookmarkModel(); | |
| 136 const BookmarkNode* parent = model->GetNodeByID(parent_id_); | |
| 137 DCHECK(parent); | |
| 138 | |
| 139 bookmark_utils::CloneBookmarkNode(model, removed_node_.elements, parent, | |
| 140 old_index_, false); | |
| 141 UpdateBookmarkIds(removed_node_.elements[0], parent, old_index_); | |
| 142 } | |
| 143 | |
| 144 void BookmarkRemoveOperation::UpdateBookmarkIds( | |
| 145 const BookmarkNodeData::Element& element, | |
| 146 const BookmarkNode* parent, | |
| 147 int index_added_at) const { | |
| 148 BookmarkModel* model = GetBookmarkModel(); | |
| 149 | |
| 150 const BookmarkNode* node = parent->GetChild(index_added_at); | |
| 151 if (element.id() != node->id()) | |
| 152 GetUndoRenumberObserver()->OnBookmarkRenumbered(element.id(), node->id()); | |
| 153 if (!element.is_url) { | |
| 154 for (int i = 0; i < static_cast<int>(element.children.size()); ++i) | |
| 155 UpdateBookmarkIds(element.children[i], node, 0); | |
| 156 } | |
| 157 } | |
| 158 | |
| 159 void BookmarkRemoveOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
| 160 if (parent_id_ == old_id) | |
| 161 parent_id_ = new_id; | |
| 162 } | |
| 163 | |
| 164 // BookmarkEditOperation ------------------------------------------------------ | |
| 165 | |
| 166 // Handles the undo of the modification of a bookmark node. | |
| 167 class BookmarkEditOperation : public BookmarkUndoOperation { | |
| 168 public: | |
| 169 BookmarkEditOperation(Profile* profile, | |
| 170 const BookmarkNode* node); | |
| 171 virtual ~BookmarkEditOperation() {} | |
| 172 | |
| 173 // UndoOperation: | |
| 174 virtual void Undo() OVERRIDE; | |
| 175 | |
| 176 // BookmarkRenumberObserver: | |
| 177 virtual void OnBookmarkRenumbered(int64 old_id, int64 new_id) OVERRIDE; | |
| 178 | |
| 179 private: | |
| 180 int64 node_id_; | |
| 181 BookmarkNodeData original_bookmark_; | |
| 182 | |
| 183 DISALLOW_COPY_AND_ASSIGN(BookmarkEditOperation); | |
| 184 }; | |
| 185 | |
| 186 BookmarkEditOperation::BookmarkEditOperation(Profile* profile, | |
| 187 const BookmarkNode* node) | |
| 188 : BookmarkUndoOperation(profile), | |
| 189 node_id_(node->id()), | |
| 190 original_bookmark_(node) { | |
| 191 } | |
| 192 | |
| 193 void BookmarkEditOperation::Undo() { | |
| 194 DCHECK(original_bookmark_.is_valid()); | |
| 195 BookmarkModel* model = GetBookmarkModel(); | |
| 196 const BookmarkNode* node = model->GetNodeByID(node_id_); | |
| 197 DCHECK(node); | |
| 198 | |
| 199 model->SetTitle(node, original_bookmark_.elements[0].title); | |
| 200 if (original_bookmark_.elements[0].is_url) | |
| 201 model->SetURL(node, original_bookmark_.elements[0].url); | |
| 202 } | |
| 203 | |
| 204 void BookmarkEditOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
| 205 if (node_id_ == old_id) | |
| 206 node_id_ = new_id; | |
| 207 } | |
| 208 | |
| 209 // BookmarkMoveOperation ------------------------------------------------------ | |
| 210 | |
| 211 // Handles the undo of a bookmark being moved to a new location. | |
| 212 class BookmarkMoveOperation : public BookmarkUndoOperation { | |
| 213 public: | |
| 214 BookmarkMoveOperation(Profile* profile, | |
| 215 const BookmarkNode* old_parent, | |
| 216 int old_index, | |
| 217 const BookmarkNode* new_parent, | |
| 218 int new_index); | |
| 219 virtual ~BookmarkMoveOperation() {} | |
| 220 | |
| 221 // UndoOperation: | |
| 222 virtual void Undo() OVERRIDE; | |
| 223 | |
| 224 // BookmarkRenumberObserver: | |
| 225 virtual void OnBookmarkRenumbered(int64 old_id, int64 new_id) OVERRIDE; | |
| 226 | |
| 227 private: | |
| 228 int64 old_parent_id_; | |
| 229 int64 new_parent_id_; | |
| 230 int old_index_; | |
| 231 int new_index_; | |
| 232 | |
| 233 DISALLOW_COPY_AND_ASSIGN(BookmarkMoveOperation); | |
| 234 }; | |
| 235 | |
| 236 BookmarkMoveOperation::BookmarkMoveOperation(Profile* profile, | |
| 237 const BookmarkNode* old_parent, | |
| 238 int old_index, | |
| 239 const BookmarkNode* new_parent, | |
| 240 int new_index) | |
| 241 : BookmarkUndoOperation(profile), | |
| 242 old_parent_id_(old_parent->id()), | |
| 243 old_index_(old_index), | |
| 244 new_parent_id_(new_parent->id()), | |
| 245 new_index_(new_index) { | |
| 246 } | |
| 247 | |
| 248 void BookmarkMoveOperation::Undo() { | |
| 249 BookmarkModel* model = GetBookmarkModel(); | |
| 250 const BookmarkNode* old_parent = model->GetNodeByID(old_parent_id_); | |
| 251 const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id_); | |
| 252 DCHECK(old_parent); | |
| 253 DCHECK(new_parent); | |
| 254 | |
| 255 const BookmarkNode* node = new_parent->GetChild(new_index_); | |
| 256 int destination_index = old_index_; | |
| 257 | |
| 258 // If the bookmark was moved up within the same parent then the destination | |
| 259 // index needs to be incremented since the old index did not account for the | |
| 260 // moved bookmark. | |
| 261 if (old_parent == new_parent && new_index_ < old_index_) | |
| 262 ++destination_index; | |
| 263 | |
| 264 model->Move(node, old_parent, destination_index); | |
| 265 } | |
| 266 | |
| 267 void BookmarkMoveOperation::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
| 268 if (old_parent_id_ == old_id) | |
| 269 old_parent_id_ = new_id; | |
| 270 if (new_parent_id_ == old_id) | |
| 271 new_parent_id_ = new_id; | |
| 272 } | |
| 273 | |
| 274 // BookmarkReorderOperation --------------------------------------------------- | |
| 275 | |
| 276 // Handle the undo of reordering of bookmarks that can happen as a result of | |
| 277 // sorting a bookmark folder by name or the undo of that operation. The change | |
| 278 // of order is not recursive so only the order of the immediate children of the | |
| 279 // folder need to be restored. | |
| 280 class BookmarkReorderOperation : public BookmarkUndoOperation { | |
| 281 public: | |
| 282 BookmarkReorderOperation(Profile* profile, | |
| 283 const BookmarkNode* parent); | |
| 284 virtual ~BookmarkReorderOperation(); | |
| 285 | |
| 286 // UndoOperation: | |
| 287 virtual void Undo() OVERRIDE; | |
| 288 | |
| 289 // BookmarkRenumberObserver: | |
| 290 virtual void OnBookmarkRenumbered(int64 old_id, int64 new_id) OVERRIDE; | |
| 291 | |
| 292 private: | |
| 293 int64 parent_id_; | |
| 294 std::vector<int64> ordered_bookmarks_; | |
| 295 | |
| 296 DISALLOW_COPY_AND_ASSIGN(BookmarkReorderOperation); | |
| 297 }; | |
| 298 | |
| 299 BookmarkReorderOperation::BookmarkReorderOperation(Profile* profile, | |
| 300 const BookmarkNode* parent) | |
| 301 : BookmarkUndoOperation(profile), | |
| 302 parent_id_(parent->id()) { | |
| 303 ordered_bookmarks_.resize(parent->child_count()); | |
| 304 for (int i = 0; i < parent->child_count(); ++i) | |
| 305 ordered_bookmarks_[i] = parent->GetChild(i)->id(); | |
| 306 } | |
| 307 | |
| 308 BookmarkReorderOperation::~BookmarkReorderOperation() { | |
| 309 } | |
| 310 | |
| 311 void BookmarkReorderOperation::Undo() { | |
| 312 BookmarkModel* model = GetBookmarkModel(); | |
| 313 const BookmarkNode* parent = model->GetNodeByID(parent_id_); | |
| 314 DCHECK(parent); | |
| 315 | |
| 316 std::vector<const BookmarkNode*> ordered_nodes; | |
| 317 for (size_t i = 0; i < ordered_bookmarks_.size(); ++i) | |
| 318 ordered_nodes.push_back(model->GetNodeByID(ordered_bookmarks_[i])); | |
| 319 | |
| 320 model->ReorderChildren(parent, ordered_nodes); | |
| 321 } | |
| 322 | |
| 323 void BookmarkReorderOperation::OnBookmarkRenumbered(int64 old_id, | |
| 324 int64 new_id) { | |
| 325 if (parent_id_ == old_id) | |
| 326 parent_id_ = new_id; | |
| 327 for (size_t i = 0; i < ordered_bookmarks_.size(); ++i) { | |
| 328 if (ordered_bookmarks_[i] == old_id) | |
| 329 ordered_bookmarks_[i] = new_id; | |
| 330 } | |
| 331 } | |
| 332 | |
| 333 } // namespace | |
| 334 | |
| 335 // BookmarkUndoService -------------------------------------------------------- | |
| 336 | |
| 337 BookmarkUndoService::BookmarkUndoService(Profile* profile) : profile_(profile) { | |
| 338 BookmarkModelFactory::GetForProfile(profile_)->AddObserver(this); | |
| 339 } | |
| 340 | |
| 341 BookmarkUndoService::~BookmarkUndoService() { | |
| 342 BookmarkModelFactory::GetForProfile(profile_)->RemoveObserver(this); | |
| 343 } | |
| 344 | |
| 345 void BookmarkUndoService::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
| 346 std::vector<UndoOperation*> all_operations = | |
| 347 undo_manager()->GetAllUndoOperations(); | |
| 348 for (std::vector<UndoOperation*>::iterator it = all_operations.begin(); | |
| 349 it != all_operations.end(); ++it) { | |
| 350 static_cast<BookmarkUndoOperation*>(*it)->OnBookmarkRenumbered(old_id, | |
| 351 new_id); | |
| 352 } | |
| 353 } | |
| 354 | |
| 355 void BookmarkUndoService::Loaded(BookmarkModel* model, bool ids_reassigned) { | |
| 356 undo_manager_.RemoveAllOperations(); | |
| 357 } | |
| 358 | |
| 359 void BookmarkUndoService::BookmarkModelBeingDeleted(BookmarkModel* model) { | |
| 360 undo_manager_.RemoveAllOperations(); | |
| 361 } | |
| 362 | |
| 363 void BookmarkUndoService::BookmarkNodeMoved(BookmarkModel* model, | |
| 364 const BookmarkNode* old_parent, | |
| 365 int old_index, | |
| 366 const BookmarkNode* new_parent, | |
| 367 int new_index) { | |
| 368 scoped_ptr<UndoOperation> op(new BookmarkMoveOperation(profile_, | |
| 369 old_parent, | |
| 370 old_index, | |
| 371 new_parent, | |
| 372 new_index)); | |
| 373 undo_manager()->AddUndoOperation(op.Pass()); | |
| 374 } | |
| 375 | |
| 376 void BookmarkUndoService::BookmarkNodeAdded(BookmarkModel* model, | |
| 377 const BookmarkNode* parent, | |
| 378 int index) { | |
| 379 scoped_ptr<UndoOperation> op(new BookmarkAddOperation(profile_, | |
| 380 parent, | |
| 381 index)); | |
| 382 undo_manager()->AddUndoOperation(op.Pass()); | |
| 383 } | |
| 384 | |
| 385 void BookmarkUndoService::OnWillRemoveBookmarks(BookmarkModel* model, | |
| 386 const BookmarkNode* parent, | |
| 387 int old_index, | |
| 388 const BookmarkNode* node) { | |
| 389 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(profile_, | |
| 390 parent, | |
| 391 old_index, | |
| 392 node)); | |
| 393 undo_manager()->AddUndoOperation(op.Pass()); | |
| 394 } | |
| 395 | |
| 396 void BookmarkUndoService::OnWillRemoveAllBookmarks(BookmarkModel* model) { | |
| 397 ScopedGroupingAction merge_removes(undo_manager()); | |
| 398 for (int i = 0; i < model->root_node()->child_count(); ++i) { | |
| 399 const BookmarkNode* permanent_node = model->root_node()->GetChild(i); | |
| 400 for (int j = permanent_node->child_count() - 1; j >= 0; --j) { | |
| 401 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(profile_, | |
| 402 permanent_node, j, permanent_node->GetChild(j))); | |
| 403 undo_manager()->AddUndoOperation(op.Pass()); | |
| 404 } | |
| 405 } | |
| 406 } | |
| 407 | |
| 408 void BookmarkUndoService::OnWillChangeBookmarkNode(BookmarkModel* model, | |
| 409 const BookmarkNode* node) { | |
| 410 scoped_ptr<UndoOperation> op(new BookmarkEditOperation(profile_, node)); | |
| 411 undo_manager()->AddUndoOperation(op.Pass()); | |
| 412 } | |
| 413 | |
| 414 void BookmarkUndoService::OnWillReorderBookmarkNode(BookmarkModel* model, | |
| 415 const BookmarkNode* node) { | |
| 416 scoped_ptr<UndoOperation> op(new BookmarkReorderOperation(profile_, node)); | |
| 417 undo_manager()->AddUndoOperation(op.Pass()); | |
| 418 } | |
| OLD | NEW |