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