diff options
author | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-30 22:55:31 +0000 |
---|---|---|
committer | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-30 22:55:31 +0000 |
commit | cb03bc2910dd2675fdd66f171a95b90e04be9dfb (patch) | |
tree | 2074e62e390642496cac81afa1b6c305fa3439b2 /ui/base/events | |
parent | bd182a69fc2c119cabff620795e705eafd2ef539 (diff) | |
download | chromium_src-cb03bc2910dd2675fdd66f171a95b90e04be9dfb.zip chromium_src-cb03bc2910dd2675fdd66f171a95b90e04be9dfb.tar.gz chromium_src-cb03bc2910dd2675fdd66f171a95b90e04be9dfb.tar.bz2 |
Fix crash in ash::internal::WorkspaceEventHandler::OnMouseEvent
Stop event processing if the event target is invalidated or deleted during
processing of a list of events.
BUG=158332
TEST=added to ui_unittests:EventDispatcherTest
Review URL: https://chromiumcodereview.appspot.com/11339052
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@165045 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base/events')
-rw-r--r-- | ui/base/events/event_dispatcher.h | 3 | ||||
-rw-r--r-- | ui/base/events/event_dispatcher_unittest.cc | 52 |
2 files changed, 53 insertions, 2 deletions
diff --git a/ui/base/events/event_dispatcher.h b/ui/base/events/event_dispatcher.h index ff58e3b..33cb043 100644 --- a/ui/base/events/event_dispatcher.h +++ b/ui/base/events/event_dispatcher.h @@ -91,6 +91,9 @@ class UI_EXPORT EventDispatcher { // dispatching the event to the event handler. template<class T> int DispatchEvent(EventHandler* handler, T* event) { + // If the target has been invalidated or deleted, don't dispatch the event. + if (!CanDispatchToTarget(event->target())) + return ui::ER_CONSUMED; bool destroyed = false; set_on_destroy_ = &destroyed; int result = DispatchEventToSingleHandler(handler, event); diff --git a/ui/base/events/event_dispatcher_unittest.cc b/ui/base/events/event_dispatcher_unittest.cc index 36cbd43..89285e4 100644 --- a/ui/base/events/event_dispatcher_unittest.cc +++ b/ui/base/events/event_dispatcher_unittest.cc @@ -12,11 +12,14 @@ namespace { class TestTarget : public EventTarget { public: - TestTarget() : parent_(NULL) {} + TestTarget() : parent_(NULL), valid_(true) {} virtual ~TestTarget() {} void set_parent(TestTarget* parent) { parent_ = parent; } + bool valid() const { return valid_; } + void set_valid(bool valid) { valid_ = valid; } + void AddHandlerId(int id) { handler_list_.push_back(id); } @@ -39,6 +42,7 @@ class TestTarget : public EventTarget { TestTarget* parent_; std::vector<int> handler_list_; + bool valid_; DISALLOW_COPY_AND_ASSIGN(TestTarget); }; @@ -132,6 +136,22 @@ class EventHandlerDestroyDispatcher : public TestEventHandler { DISALLOW_COPY_AND_ASSIGN(EventHandlerDestroyDispatcher); }; +// Invalidates the target when it receives any event. +class InvalidateTargetEventHandler : public TestEventHandler { + public: + InvalidateTargetEventHandler(int id) : TestEventHandler(id) {} + virtual ~InvalidateTargetEventHandler() {} + + private: + virtual void ReceivedEvent(Event* event) { + TestEventHandler::ReceivedEvent(event); + TestTarget* target = static_cast<TestTarget*>(event->target()); + target->set_valid(false); + } + + DISALLOW_COPY_AND_ASSIGN(InvalidateTargetEventHandler); +}; + class TestEventDispatcher : public EventDispatcher { public: TestEventDispatcher() {} @@ -140,7 +160,8 @@ class TestEventDispatcher : public EventDispatcher { private: // Overridden from EventDispatcher: virtual bool CanDispatchToTarget(EventTarget* target) OVERRIDE { - return true; + TestTarget* test_target = static_cast<TestTarget*>(target); + return test_target->valid(); } DISALLOW_COPY_AND_ASSIGN(TestEventDispatcher); @@ -317,4 +338,31 @@ TEST(EventDispatcherTest, EventDispatcherDestroyTarget) { } } +// Tests that a target becoming invalid in the middle of pre- or post-target +// event processing aborts processing. +TEST(EventDispatcherTest, EventDispatcherInvalidateTarget) { + TestEventDispatcher dispatcher; + TestTarget target; + TestEventHandler h1(1); + InvalidateTargetEventHandler invalidate_handler(2); + TestEventHandler h3(3); + + target.AddPreTargetHandler(&h1); + target.AddPreTargetHandler(&invalidate_handler); + target.AddPreTargetHandler(&h3); + + h1.set_expect_pre_target(true); + invalidate_handler.set_expect_pre_target(true); + // |h3| should not receive events as the target will be invalidated. + h3.set_expect_pre_target(false); + + MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(3, 4), gfx::Point(3, 4), 0); + int result = dispatcher.ProcessEvent(&target, &mouse); + EXPECT_FALSE(target.valid()); + EXPECT_EQ(ER_CONSUMED, result); + EXPECT_EQ(2U, target.handler_list().size()); + EXPECT_EQ(1, target.handler_list()[0]); + EXPECT_EQ(2, target.handler_list()[1]); +} + } // namespace ui |