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