Index: ui/message_center/views/message_list_view.cc |
diff --git a/ui/message_center/views/message_list_view.cc b/ui/message_center/views/message_list_view.cc |
index bd731b70ee0047419d31b7e9bcce308a5658cc07..06cce39c28a3b0defe6e473284cfcea9da3e3661 100644 |
--- a/ui/message_center/views/message_list_view.cc |
+++ b/ui/message_center/views/message_list_view.cc |
@@ -2,6 +2,8 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include <algorithm> |
+ |
#include "base/command_line.h" |
#include "base/location.h" |
#include "base/single_thread_task_runner.h" |
@@ -100,6 +102,20 @@ void MessageListView::AddNotificationAt(MessageView* view, int index) { |
void MessageListView::RemoveNotification(MessageView* view) { |
DCHECK_EQ(view->parent(), this); |
+ // TODO(yhananda): We should consider consolidating clearing_all_views_, |
+ // deleting_views_ and deleted_when_done_. |
+ if (std::find(clearing_all_views_.begin(), clearing_all_views_.end(), view) != |
+ clearing_all_views_.end() || |
+ deleting_views_.find(view) != deleting_views_.end() || |
+ deleted_when_done_.find(view) != deleted_when_done_.end()) { |
+ // Let's skip deleting the view if it's already scheduled for deleting. |
+ // Even if we check clearing_all_views_ here, we actualy have no idea |
+ // whether the view is due to be removed or not because it could be in its |
+ // animation before removal. |
+ // In short, we could delete the view twice even if we check these three |
+ // lists. |
+ return; |
+ } |
if (GetContentsBounds().IsEmpty()) { |
delete view; |
@@ -120,6 +136,11 @@ void MessageListView::RemoveNotification(MessageView* view) { |
void MessageListView::UpdateNotification(MessageView* view, |
const Notification& notification) { |
+ // Skip updating the notification being cleared |
+ if (std::find(clearing_all_views_.begin(), clearing_all_views_.end(), view) != |
+ clearing_all_views_.end()) |
+ return; |
+ |
int index = GetIndexOf(view); |
DCHECK_LE(0, index); // GetIndexOf is negative if not a child. |
@@ -242,6 +263,15 @@ void MessageListView::ClearAllClosableNotifications( |
continue; |
if (child->IsPinned()) |
continue; |
+ if (deleting_views_.find(child) != deleting_views_.end() || |
+ deleted_when_done_.find(child) != deleted_when_done_.end()) { |
+ // We don't check clearing_all_views_ here, so this can lead to a |
+ // notification being deleted twice. Even if we do check it, there is a |
+ // problem similar to the problem in RemoveNotification(), it could be |
+ // currently in its animation before removal, and we could similarly |
+ // delete it twice. This is a bug. |
+ continue; |
+ } |
clearing_all_views_.push_back(child); |
} |
if (clearing_all_views_.empty()) { |
@@ -298,7 +328,9 @@ bool MessageListView::IsValidChild(const views::View* child) const { |
deleting_views_.find(const_cast<views::View*>(child)) == |
deleting_views_.end() && |
deleted_when_done_.find(const_cast<views::View*>(child)) == |
- deleted_when_done_.end(); |
+ deleted_when_done_.end() && |
+ std::find(clearing_all_views_.begin(), clearing_all_views_.end(), |
+ child) == clearing_all_views_.end(); |
} |
void MessageListView::DoUpdateIfPossible() { |