Index: components/bookmarks/browser/bookmark_model.cc |
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc |
index 5709533dba2d0be60f7f29ded432599ba10be75a..8799ec2e21dbadaac403a6de7f6ea5d557de3358 100644 |
--- a/components/bookmarks/browser/bookmark_model.cc |
+++ b/components/bookmarks/browser/bookmark_model.cc |
@@ -15,12 +15,14 @@ |
#include "base/metrics/histogram_macros.h" |
#include "base/profiler/scoped_tracker.h" |
#include "base/strings/string_util.h" |
+#include "base/tuple.h" |
#include "components/bookmarks/browser/bookmark_expanded_state_tracker.h" |
#include "components/bookmarks/browser/bookmark_index.h" |
#include "components/bookmarks/browser/bookmark_match.h" |
#include "components/bookmarks/browser/bookmark_model_observer.h" |
#include "components/bookmarks/browser/bookmark_node_data.h" |
#include "components/bookmarks/browser/bookmark_storage.h" |
+#include "components/bookmarks/browser/bookmark_undo_delegate.h" |
#include "components/bookmarks/browser/bookmark_utils.h" |
#include "components/favicon_base/favicon_types.h" |
#include "grit/components_strings.h" |
@@ -89,6 +91,23 @@ class SortComparator : public std::binary_function<const BookmarkNode*, |
icu::Collator* collator_; |
}; |
+// Delegate that does nothing. |
+class EmptyUndoDelegate : public BookmarkUndoDelegate { |
+ public: |
+ EmptyUndoDelegate() {} |
+ ~EmptyUndoDelegate() override {} |
+ |
+ private: |
+ // BookmarkUndoDelegate: |
+ void SetUndoProvider(BookmarkUndoProvider* provider) override {} |
+ void OnBookmarkNodeRemoved(BookmarkModel* model, |
+ const BookmarkNode* parent, |
+ int index, |
+ scoped_ptr<BookmarkNode> node) override {} |
+ |
+ DISALLOW_COPY_AND_ASSIGN(EmptyUndoDelegate); |
+}; |
+ |
} // namespace |
// BookmarkModel -------------------------------------------------------------- |
@@ -104,7 +123,9 @@ BookmarkModel::BookmarkModel(BookmarkClient* client) |
observers_( |
base::ObserverList<BookmarkModelObserver>::NOTIFY_EXISTING_ONLY), |
loaded_signal_(true, false), |
- extensive_changes_(0) { |
+ extensive_changes_(0), |
+ undo_delegate_(nullptr), |
+ empty_undo_delegate_(new EmptyUndoDelegate) { |
DCHECK(client_); |
} |
@@ -199,7 +220,8 @@ void BookmarkModel::Remove(const BookmarkNode* node) { |
void BookmarkModel::RemoveAllUserBookmarks() { |
std::set<GURL> removed_urls; |
- ScopedVector<BookmarkNode> removed_nodes; |
+ std::vector<base::Tuple<const BookmarkNode*, int, BookmarkNode*>> |
sky
2015/10/09 16:01:19
Using a tuple certainly works, but it's not partic
jianli
2015/10/09 21:51:16
Done.
|
+ removed_node_data; |
FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
OnWillRemoveAllUserBookmarks(this)); |
@@ -211,15 +233,16 @@ void BookmarkModel::RemoveAllUserBookmarks() { |
{ |
base::AutoLock url_lock(url_lock_); |
for (int i = 0; i < root_.child_count(); ++i) { |
- BookmarkNode* permanent_node = root_.GetChild(i); |
+ const BookmarkNode* permanent_node = root_.GetChild(i); |
if (!client_->CanBeEditedByUser(permanent_node)) |
continue; |
for (int j = permanent_node->child_count() - 1; j >= 0; --j) { |
- BookmarkNode* child_node = permanent_node->GetChild(j); |
- removed_nodes.push_back(child_node); |
+ BookmarkNode* child_node = AsMutable(permanent_node->GetChild(j)); |
RemoveNodeAndGetRemovedUrls(child_node, &removed_urls); |
+ removed_node_data.push_back( |
+ base::MakeTuple(permanent_node, j, child_node)); |
} |
} |
} |
@@ -229,6 +252,16 @@ void BookmarkModel::RemoveAllUserBookmarks() { |
FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
BookmarkAllUserNodesRemoved(this, removed_urls)); |
+ |
+ BeginGroupedChanges(); |
+ for (const auto& tuple : removed_node_data) { |
+ undo_delegate()->OnBookmarkNodeRemoved( |
+ this, |
+ base::get<0>(tuple), |
+ base::get<1>(tuple), |
+ scoped_ptr<BookmarkNode>(base::get<2>(tuple))); |
+ } |
+ EndGroupedChanges(); |
} |
void BookmarkModel::Move(const BookmarkNode* node, |
@@ -718,6 +751,25 @@ const BookmarkPermanentNode* BookmarkModel::PermanentNode( |
} |
} |
+void BookmarkModel::RestoreRemovedNode(const BookmarkNode* parent, |
+ int index, |
+ scoped_ptr<BookmarkNode> scoped_node) { |
+ BookmarkNode* node = scoped_node.release(); |
+ AddNode(AsMutable(parent), index, node); |
+ |
+ // We might be restoring a folder node that have already contained a set of |
+ // child nodes. We need to notify all of them. |
+ NotifyNodeAddedForAllDescendents(node); |
+} |
+ |
+void BookmarkModel::NotifyNodeAddedForAllDescendents(const BookmarkNode* node) { |
+ for (int i = 0; i < node->child_count(); ++i) { |
+ FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
+ BookmarkNodeAdded(this, node, i)); |
+ NotifyNodeAddedForAllDescendents(node->GetChild(i)); |
+ } |
+} |
+ |
bool BookmarkModel::IsBookmarkedNoLock(const GURL& url) { |
BookmarkNode tmp_node(url); |
return (nodes_ordered_by_url_set_.find(&tmp_node) != |
@@ -859,6 +911,8 @@ void BookmarkModel::RemoveAndDeleteNode(BookmarkNode* delete_me) { |
BookmarkModelObserver, |
observers_, |
BookmarkNodeRemoved(this, parent, index, node.get(), removed_urls)); |
+ |
+ undo_delegate()->OnBookmarkNodeRemoved(this, parent, index, node.Pass()); |
} |
void BookmarkModel::RemoveNodeFromInternalMaps(BookmarkNode* node) { |
@@ -909,11 +963,9 @@ BookmarkNode* BookmarkModel::AddNode(BookmarkNode* parent, |
if (store_.get()) |
store_->ScheduleSave(); |
- if (node->type() == BookmarkNode::URL) { |
+ { |
base::AutoLock url_lock(url_lock_); |
AddNodeToInternalMaps(node); |
- } else { |
- index_->Add(node); |
} |
FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, |
@@ -923,9 +975,13 @@ BookmarkNode* BookmarkModel::AddNode(BookmarkNode* parent, |
} |
void BookmarkModel::AddNodeToInternalMaps(BookmarkNode* node) { |
- index_->Add(node); |
url_lock_.AssertAcquired(); |
- nodes_ordered_by_url_set_.insert(node); |
+ if (node->is_url()) { |
+ index_->Add(node); |
+ nodes_ordered_by_url_set_.insert(node); |
+ } |
+ for (int i = 0; i < node->child_count(); ++i) |
+ AddNodeToInternalMaps(node->GetChild(i)); |
} |
bool BookmarkModel::IsValidIndex(const BookmarkNode* parent, |
@@ -1048,4 +1104,14 @@ scoped_ptr<BookmarkLoadDetails> BookmarkModel::CreateLoadDetails( |
next_node_id_)); |
} |
+void BookmarkModel::set_undo_delegate(BookmarkUndoDelegate* undo_delegate) { |
+ undo_delegate_ = undo_delegate; |
+ if (undo_delegate_) |
+ undo_delegate_->SetUndoProvider(this); |
+} |
+ |
+BookmarkUndoDelegate* BookmarkModel::undo_delegate() const { |
+ return undo_delegate_ ? undo_delegate_ : empty_undo_delegate_.get(); |
+} |
+ |
} // namespace bookmarks |