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

Unified Diff: ui/views/widget/root_view.cc

Issue 169443005: Fix crash which occurs when a widget destroys itself as a result of ET_GESTURE_TAP_DOWN (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/widget/root_view.h ('k') | ui/views/widget/widget_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/widget/root_view.cc
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc
index f3ad2a08d6849b779e7bf5634218b57b6144176f..35e85a37a00f975c5cc780bf40ed941a84c365ef 100644
--- a/ui/views/widget/root_view.cc
+++ b/ui/views/widget/root_view.cc
@@ -19,7 +19,6 @@
#include "ui/views/views_switches.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
-#include "ui/views/widget/widget_deletion_observer.h"
#if defined(USE_AURA)
#include "ui/base/cursor/cursor.h"
@@ -141,7 +140,11 @@ void RootView::DispatchKeyEvent(ui::KeyEvent* event) {
void RootView::DispatchScrollEvent(ui::ScrollEvent* event) {
for (View* v = GetEventHandlerForPoint(event->location());
v && v != this && !event->stopped_propagation(); v = v->parent()) {
- DispatchEventToTarget(v, event);
+ ui::EventDispatchDetails dispatch_details = DispatchEventToTarget(v, event);
+ if (dispatch_details.dispatcher_destroyed ||
+ dispatch_details.target_destroyed) {
+ return;
+ }
}
if (event->handled() || event->type() != ui::ET_SCROLL)
@@ -165,11 +168,14 @@ void RootView::DispatchTouchEvent(ui::TouchEvent* event) {
if (touch_pressed_handler_) {
ui::TouchEvent touch_event(*event, static_cast<View*>(this),
touch_pressed_handler_);
- DispatchEventToTarget(touch_pressed_handler_, &touch_event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(touch_pressed_handler_, &touch_event);
if (touch_event.handled())
event->SetHandled();
if (touch_event.stopped_propagation())
event->StopPropagation();
+ if (dispatch_details.dispatcher_destroyed)
+ return;
return;
}
@@ -185,11 +191,14 @@ void RootView::DispatchTouchEvent(ui::TouchEvent* event) {
// See if this view wants to handle the touch
ui::TouchEvent touch_event(*event, static_cast<View*>(this),
touch_pressed_handler_);
- DispatchEventToTarget(touch_pressed_handler_, &touch_event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(touch_pressed_handler_, &touch_event);
if (touch_event.handled())
event->SetHandled();
if (touch_event.stopped_propagation())
event->StopPropagation();
+ if (dispatch_details.dispatcher_destroyed)
+ return;
// The view could have removed itself from the tree when handling
// OnTouchEvent(). So handle as per OnMousePressed. NB: we
@@ -224,7 +233,10 @@ void RootView::DispatchGestureEvent(ui::GestureEvent* event) {
(event->IsScrollGestureEvent() || event->IsFlingScrollEvent()) ?
scroll_gesture_handler_ : gesture_handler_;
ui::GestureEvent handler_event(*event, static_cast<View*>(this), handler);
- DispatchEventToTarget(handler, &handler_event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(handler, &handler_event);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
if (event->type() == ui::ET_GESTURE_END &&
event->details().touch_points() <= 1) {
@@ -261,13 +273,16 @@ void RootView::DispatchGestureEvent(ui::GestureEvent* event) {
scroll_gesture_handler_ = scroll_gesture_handler_->parent()) {
ui::GestureEvent gesture_event(*event, static_cast<View*>(this),
scroll_gesture_handler_);
- DispatchEventToTarget(scroll_gesture_handler_, &gesture_event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(scroll_gesture_handler_, &gesture_event);
if (gesture_event.stopped_propagation()) {
event->StopPropagation();
return;
} else if (gesture_event.handled()) {
event->SetHandled();
return;
+ } else if (dispatch_details.dispatcher_destroyed) {
+ return;
}
}
scroll_gesture_handler_ = NULL;
@@ -312,7 +327,10 @@ void RootView::DispatchGestureEvent(ui::GestureEvent* event) {
// See if this view wants to handle the Gesture.
ui::GestureEvent gesture_event(*event, static_cast<View*>(this),
gesture_handler_);
- DispatchEventToTarget(gesture_handler_, &gesture_event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(gesture_handler_, &gesture_event);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
// The view could have removed itself from the tree when handling
// OnGestureEvent(). So handle as per OnMousePressed. NB: we
@@ -419,7 +437,10 @@ bool RootView::OnMousePressed(const ui::MouseEvent& event) {
ui::MouseEvent mouse_pressed_event(event, static_cast<View*>(this),
mouse_pressed_handler_);
drag_info_.Reset();
- DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event);
+ if (dispatch_details.dispatcher_destroyed)
+ return true;
return true;
}
DCHECK(!explicit_mouse_handler_);
@@ -447,12 +468,10 @@ bool RootView::OnMousePressed(const ui::MouseEvent& event) {
mouse_pressed_event.set_flags(event.flags() & ~ui::EF_IS_DOUBLE_CLICK);
drag_info_.Reset();
- {
- WidgetDeletionObserver widget_deletion_observer(widget_);
- DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event);
- if (!widget_deletion_observer.IsWidgetAlive())
- return mouse_pressed_event.handled();
- }
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event);
+ if (dispatch_details.dispatcher_destroyed)
+ return mouse_pressed_event.handled();
// The view could have removed itself from the tree when handling
// OnMousePressed(). In this case, the removal notification will have
@@ -495,7 +514,10 @@ bool RootView::OnMouseDragged(const ui::MouseEvent& event) {
ui::MouseEvent mouse_event(event, static_cast<View*>(this),
mouse_pressed_handler_);
- DispatchEventToTarget(mouse_pressed_handler_, &mouse_event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(mouse_pressed_handler_, &mouse_event);
+ if (dispatch_details.dispatcher_destroyed)
+ return false;
}
return false;
}
@@ -510,8 +532,10 @@ void RootView::OnMouseReleased(const ui::MouseEvent& event) {
// configure state such that we're done first, then call View.
View* mouse_pressed_handler = mouse_pressed_handler_;
SetMouseHandler(NULL);
- DispatchEventToTarget(mouse_pressed_handler, &mouse_released);
- // WARNING: we may have been deleted.
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(mouse_pressed_handler, &mouse_released);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
}
}
@@ -555,7 +579,10 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) {
(!mouse_move_handler_->notify_enter_exit_on_child() ||
!mouse_move_handler_->Contains(v))) {
MouseEnterExitEvent exit(event, ui::ET_MOUSE_EXITED);
- DispatchEventToTarget(mouse_move_handler_, &exit);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(mouse_move_handler_, &exit);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED,
mouse_move_handler_, v);
}
@@ -566,7 +593,10 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) {
MouseEnterExitEvent entered(event, ui::ET_MOUSE_ENTERED);
entered.ConvertLocationToTarget(static_cast<View*>(this),
mouse_move_handler_);
- DispatchEventToTarget(mouse_move_handler_, &entered);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(mouse_move_handler_, &entered);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
NotifyEnterExitOfDescendant(entered, ui::ET_MOUSE_ENTERED, v,
old_handler);
}
@@ -578,7 +608,10 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) {
widget_->SetCursor(mouse_move_handler_->GetCursor(moved_event));
} else if (mouse_move_handler_ != NULL) {
MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED);
- DispatchEventToTarget(mouse_move_handler_, &exited);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(mouse_move_handler_, &exited);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED,
mouse_move_handler_, v);
// On Aura the non-client area extends slightly outside the root view for
@@ -593,7 +626,10 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) {
void RootView::OnMouseExited(const ui::MouseEvent& event) {
if (mouse_move_handler_ != NULL) {
MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED);
- DispatchEventToTarget(mouse_move_handler_, &exited);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(mouse_move_handler_, &exited);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED,
mouse_move_handler_, NULL);
mouse_move_handler_ = NULL;
@@ -602,8 +638,14 @@ void RootView::OnMouseExited(const ui::MouseEvent& event) {
bool RootView::OnMouseWheel(const ui::MouseWheelEvent& event) {
for (View* v = GetEventHandlerForPoint(event.location());
- v && v != this && !event.handled(); v = v->parent())
- DispatchEventToTarget(v, const_cast<ui::MouseWheelEvent*>(&event));
+ v && v != this && !event.handled(); v = v->parent()) {
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(v, const_cast<ui::MouseWheelEvent*>(&event));
+ if (dispatch_details.dispatcher_destroyed ||
+ dispatch_details.target_destroyed) {
+ return event.handled();
+ }
+ }
return event.handled();
}
@@ -702,12 +744,14 @@ void RootView::SetMouseLocationAndFlags(const ui::MouseEvent& event) {
last_mouse_event_y_ = event.y();
}
-void RootView::DispatchEventToTarget(View* target, ui::Event* event) {
+ui::EventDispatchDetails RootView::DispatchEventToTarget(View* target,
+ ui::Event* event) {
View* old_target = event_dispatch_target_;
event_dispatch_target_ = target;
ui::EventDispatchDetails details = DispatchEvent(target, event);
if (!details.dispatcher_destroyed)
event_dispatch_target_ = old_target;
+ return details;
}
void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event,
@@ -723,20 +767,24 @@ void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event,
// of the callbacks can mark the event as handled, and that would cause
// incorrect event dispatch.
MouseEnterExitEvent notify_event(event, type);
- DispatchEventToTarget(p, &notify_event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(p, &notify_event);
+ if (dispatch_details.dispatcher_destroyed ||
+ dispatch_details.target_destroyed) {
+ return;
+ }
}
}
void RootView::DispatchKeyEventStartAt(View* view, ui::KeyEvent* event) {
- if (event->handled() || !view)
- return;
-
- for (; view && view != this; view = view->parent()) {
- DispatchEventToTarget(view, event);
- // Do this check here rather than in the if as |view| may have been deleted.
- if (event->handled())
+ for (; view && view != this && !event->handled(); view = view->parent()) {
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEventToTarget(view, event);
+ if (dispatch_details.dispatcher_destroyed ||
sadrul 2014/02/20 15:45:49 Perhaps we are not setting |target_destroyed| corr
+ dispatch_details.target_destroyed) {
return;
+ }
}
}
« no previous file with comments | « ui/views/widget/root_view.h ('k') | ui/views/widget/widget_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698