Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: ui/message_center/views/message_list_view.cc

Issue 2836023002: Fix use-after-free in MessageListView. (Closed)
Patch Set: rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/message_center/views/message_center_view.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm>
6
5 #include "base/command_line.h" 7 #include "base/command_line.h"
6 #include "base/location.h" 8 #include "base/location.h"
7 #include "base/single_thread_task_runner.h" 9 #include "base/single_thread_task_runner.h"
8 #include "base/threading/thread_task_runner_handle.h" 10 #include "base/threading/thread_task_runner_handle.h"
9 #include "ui/gfx/animation/slide_animation.h" 11 #include "ui/gfx/animation/slide_animation.h"
10 #include "ui/message_center/message_center_style.h" 12 #include "ui/message_center/message_center_style.h"
11 #include "ui/message_center/message_center_switches.h" 13 #include "ui/message_center/message_center_switches.h"
12 #include "ui/message_center/views/message_center_view.h" 14 #include "ui/message_center/views/message_center_view.h"
13 #include "ui/message_center/views/message_list_view.h" 15 #include "ui/message_center/views/message_list_view.h"
14 #include "ui/message_center/views/message_view.h" 16 #include "ui/message_center/views/message_view.h"
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 if (GetContentsBounds().IsEmpty()) 95 if (GetContentsBounds().IsEmpty())
94 return; 96 return;
95 97
96 adding_views_.insert(view); 98 adding_views_.insert(view);
97 DoUpdateIfPossible(); 99 DoUpdateIfPossible();
98 } 100 }
99 101
100 void MessageListView::RemoveNotification(MessageView* view) { 102 void MessageListView::RemoveNotification(MessageView* view) {
101 DCHECK_EQ(view->parent(), this); 103 DCHECK_EQ(view->parent(), this);
102 104
105 // TODO(yhananda): We should consider consolidating clearing_all_views_,
106 // deleting_views_ and deleted_when_done_.
107 if (std::find(clearing_all_views_.begin(), clearing_all_views_.end(), view) !=
108 clearing_all_views_.end() ||
109 deleting_views_.find(view) != deleting_views_.end() ||
110 deleted_when_done_.find(view) != deleted_when_done_.end()) {
111 // Let's skip deleting the view if it's already scheduled for deleting.
112 // Even if we check clearing_all_views_ here, we actualy have no idea
113 // whether the view is due to be removed or not because it could be in its
114 // animation before removal.
115 // In short, we could delete the view twice even if we check these three
116 // lists.
117 return;
118 }
103 119
104 if (GetContentsBounds().IsEmpty()) { 120 if (GetContentsBounds().IsEmpty()) {
105 delete view; 121 delete view;
106 } else { 122 } else {
107 if (adding_views_.find(view) != adding_views_.end()) 123 if (adding_views_.find(view) != adding_views_.end())
108 adding_views_.erase(view); 124 adding_views_.erase(view);
109 if (animator_.IsAnimating(view)) 125 if (animator_.IsAnimating(view))
110 animator_.StopAnimatingView(view); 126 animator_.StopAnimatingView(view);
111 127
112 if (view->layer()) { 128 if (view->layer()) {
113 deleting_views_.insert(view); 129 deleting_views_.insert(view);
114 } else { 130 } else {
115 delete view; 131 delete view;
116 } 132 }
117 DoUpdateIfPossible(); 133 DoUpdateIfPossible();
118 } 134 }
119 } 135 }
120 136
121 void MessageListView::UpdateNotification(MessageView* view, 137 void MessageListView::UpdateNotification(MessageView* view,
122 const Notification& notification) { 138 const Notification& notification) {
139 // Skip updating the notification being cleared
140 if (std::find(clearing_all_views_.begin(), clearing_all_views_.end(), view) !=
141 clearing_all_views_.end())
142 return;
143
123 int index = GetIndexOf(view); 144 int index = GetIndexOf(view);
124 DCHECK_LE(0, index); // GetIndexOf is negative if not a child. 145 DCHECK_LE(0, index); // GetIndexOf is negative if not a child.
125 146
126 animator_.StopAnimatingView(view); 147 animator_.StopAnimatingView(view);
127 if (deleting_views_.find(view) != deleting_views_.end()) 148 if (deleting_views_.find(view) != deleting_views_.end())
128 deleting_views_.erase(view); 149 deleting_views_.erase(view);
129 if (deleted_when_done_.find(view) != deleted_when_done_.end()) 150 if (deleted_when_done_.find(view) != deleted_when_done_.end())
130 deleted_when_done_.erase(view); 151 deleted_when_done_.erase(view);
131 view->UpdateWithNotification(notification); 152 view->UpdateWithNotification(notification);
132 DoUpdateIfPossible(); 153 DoUpdateIfPossible();
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 const gfx::Rect& visible_scroll_rect) { 256 const gfx::Rect& visible_scroll_rect) {
236 for (int i = 0; i < child_count(); ++i) { 257 for (int i = 0; i < child_count(); ++i) {
237 // Safe cast since all views in MessageListView are MessageViews. 258 // Safe cast since all views in MessageListView are MessageViews.
238 MessageView* child = (MessageView*)child_at(i); 259 MessageView* child = (MessageView*)child_at(i);
239 if (!child->visible()) 260 if (!child->visible())
240 continue; 261 continue;
241 if (gfx::IntersectRects(child->bounds(), visible_scroll_rect).IsEmpty()) 262 if (gfx::IntersectRects(child->bounds(), visible_scroll_rect).IsEmpty())
242 continue; 263 continue;
243 if (child->IsPinned()) 264 if (child->IsPinned())
244 continue; 265 continue;
266 if (deleting_views_.find(child) != deleting_views_.end() ||
267 deleted_when_done_.find(child) != deleted_when_done_.end()) {
268 // We don't check clearing_all_views_ here, so this can lead to a
269 // notification being deleted twice. Even if we do check it, there is a
270 // problem similar to the problem in RemoveNotification(), it could be
271 // currently in its animation before removal, and we could similarly
272 // delete it twice. This is a bug.
273 continue;
274 }
245 clearing_all_views_.push_back(child); 275 clearing_all_views_.push_back(child);
246 } 276 }
247 if (clearing_all_views_.empty()) { 277 if (clearing_all_views_.empty()) {
248 for (auto& observer : observers_) 278 for (auto& observer : observers_)
249 observer.OnAllNotificationsCleared(); 279 observer.OnAllNotificationsCleared();
250 } else { 280 } else {
251 DoUpdateIfPossible(); 281 DoUpdateIfPossible();
252 } 282 }
253 } 283 }
254 284
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 321
292 if (quit_message_loop_after_animation_for_test_) 322 if (quit_message_loop_after_animation_for_test_)
293 base::MessageLoop::current()->QuitWhenIdle(); 323 base::MessageLoop::current()->QuitWhenIdle();
294 } 324 }
295 325
296 bool MessageListView::IsValidChild(const views::View* child) const { 326 bool MessageListView::IsValidChild(const views::View* child) const {
297 return child->visible() && 327 return child->visible() &&
298 deleting_views_.find(const_cast<views::View*>(child)) == 328 deleting_views_.find(const_cast<views::View*>(child)) ==
299 deleting_views_.end() && 329 deleting_views_.end() &&
300 deleted_when_done_.find(const_cast<views::View*>(child)) == 330 deleted_when_done_.find(const_cast<views::View*>(child)) ==
301 deleted_when_done_.end(); 331 deleted_when_done_.end() &&
332 std::find(clearing_all_views_.begin(), clearing_all_views_.end(),
333 child) == clearing_all_views_.end();
302 } 334 }
303 335
304 void MessageListView::DoUpdateIfPossible() { 336 void MessageListView::DoUpdateIfPossible() {
305 gfx::Rect child_area = GetContentsBounds(); 337 gfx::Rect child_area = GetContentsBounds();
306 if (child_area.IsEmpty()) 338 if (child_area.IsEmpty())
307 return; 339 return;
308 340
309 if (animator_.IsAnimating()) { 341 if (animator_.IsAnimating()) {
310 has_deferred_task_ = true; 342 has_deferred_task_ = true;
311 return; 343 return;
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 base::TimeDelta::FromMilliseconds( 566 base::TimeDelta::FromMilliseconds(
535 kAnimateClearingNextNotificationDelayMS)); 567 kAnimateClearingNextNotificationDelayMS));
536 } 568 }
537 } 569 }
538 570
539 void MessageListView::SetRepositionTargetForTest(const gfx::Rect& target_rect) { 571 void MessageListView::SetRepositionTargetForTest(const gfx::Rect& target_rect) {
540 SetRepositionTarget(target_rect); 572 SetRepositionTarget(target_rect);
541 } 573 }
542 574
543 } // namespace message_center 575 } // namespace message_center
OLDNEW
« no previous file with comments | « ui/message_center/views/message_center_view.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698