Commit 9406979e authored by Mike Wasserman's avatar Mike Wasserman Committed by Commit Bot

Fix event monitoring teardown on window destruction

Add WindowMonitorAura; removes pre-target handler in OnWindowDestroying.
Fixes UAF when EventMonitors are destroyed late in window destruction.
(avoid EventTarget::RemovePreTargetHandler calls later in destruction)

Add a simple unit test.

Bug: 932922
Test: No crash when quitting Chrome with a fullscreen tab.
Change-Id: I2ace83b9de127d8fa70a57021dda94561f5bd4c4
Reviewed-on: https://chromium-review.googlesource.com/c/1487353Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Michael Wasserman <msw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#635284}
parent 6b51e335
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
#include "ui/views/event_monitor_aura.h" #include "ui/views/event_monitor_aura.h"
#include <memory>
#include "base/logging.h" #include "base/logging.h"
#include "base/scoped_observer.h"
#include "ui/aura/env.h" #include "ui/aura/env.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/events/event_observer.h" #include "ui/events/event_observer.h"
...@@ -12,6 +15,38 @@ ...@@ -12,6 +15,38 @@
namespace views { namespace views {
namespace {
// An EventMonitorAura that removes its event observer on window destruction.
class WindowMonitorAura : public EventMonitorAura, public aura::WindowObserver {
public:
WindowMonitorAura(aura::Env* env,
ui::EventObserver* event_observer,
aura::Window* target_window,
const std::set<ui::EventType>& types)
: EventMonitorAura(env, event_observer, target_window, types),
target_window_(target_window) {
window_observer_.Add(target_window);
}
~WindowMonitorAura() override = default;
// aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override {
DCHECK_EQ(window, target_window_);
window_observer_.Remove(target_window_);
target_window_ = nullptr;
TearDown();
}
private:
aura::Window* target_window_;
ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this};
DISALLOW_COPY_AND_ASSIGN(WindowMonitorAura);
};
} // namespace
// static // static
std::unique_ptr<EventMonitor> EventMonitor::CreateApplicationMonitor( std::unique_ptr<EventMonitor> EventMonitor::CreateApplicationMonitor(
ui::EventObserver* event_observer, ui::EventObserver* event_observer,
...@@ -26,7 +61,7 @@ std::unique_ptr<EventMonitor> EventMonitor::CreateWindowMonitor( ...@@ -26,7 +61,7 @@ std::unique_ptr<EventMonitor> EventMonitor::CreateWindowMonitor(
ui::EventObserver* event_observer, ui::EventObserver* event_observer,
gfx::NativeWindow target_window, gfx::NativeWindow target_window,
const std::set<ui::EventType>& types) { const std::set<ui::EventType>& types) {
return std::make_unique<EventMonitorAura>( return std::make_unique<WindowMonitorAura>(
target_window->env(), event_observer, target_window, types); target_window->env(), event_observer, target_window, types);
} }
...@@ -42,11 +77,17 @@ EventMonitorAura::EventMonitorAura(aura::Env* env, ...@@ -42,11 +77,17 @@ EventMonitorAura::EventMonitorAura(aura::Env* env,
} }
EventMonitorAura::~EventMonitorAura() { EventMonitorAura::~EventMonitorAura() {
env_->RemoveEventObserver(event_observer_); TearDown();
} }
gfx::Point EventMonitorAura::GetLastMouseLocation() { gfx::Point EventMonitorAura::GetLastMouseLocation() {
return env_->last_mouse_location(); return env_->last_mouse_location();
} }
void EventMonitorAura::TearDown() {
if (event_observer_)
env_->RemoveEventObserver(event_observer_);
event_observer_ = nullptr;
}
} // namespace views } // namespace views
...@@ -18,6 +18,7 @@ class EventTarget; ...@@ -18,6 +18,7 @@ class EventTarget;
namespace views { namespace views {
// Observes events by installing a pre-target handler on the ui::EventTarget.
class EventMonitorAura : public EventMonitor { class EventMonitorAura : public EventMonitor {
public: public:
EventMonitorAura(aura::Env* env, EventMonitorAura(aura::Env* env,
...@@ -29,6 +30,10 @@ class EventMonitorAura : public EventMonitor { ...@@ -29,6 +30,10 @@ class EventMonitorAura : public EventMonitor {
// EventMonitor: // EventMonitor:
gfx::Point GetLastMouseLocation() override; gfx::Point GetLastMouseLocation() override;
protected:
// Removes the pre-target handler. Called by window monitors on window close.
void TearDown();
private: private:
aura::Env* env_; // Weak. aura::Env* env_; // Weak.
ui::EventObserver* event_observer_; // Weak. Owned by our owner. ui::EventObserver* event_observer_; // Weak. Owned by our owner.
......
...@@ -112,6 +112,18 @@ TEST_F(EventMonitorTest, ShouldOnlyReceiveRequestedEventTypes) { ...@@ -112,6 +112,18 @@ TEST_F(EventMonitorTest, ShouldOnlyReceiveRequestedEventTypes) {
monitor.reset(); monitor.reset();
} }
TEST_F(EventMonitorTest, WindowMonitorTornDownOnWindowClose) {
Widget* widget2 = CreateTopLevelNativeWidget();
widget2->Show();
std::unique_ptr<EventMonitor> monitor(EventMonitor::CreateWindowMonitor(
&observer_, widget2->GetNativeWindow(), {ui::ET_MOUSE_PRESSED}));
// Closing the widget before destroying the monitor should not crash.
widget2->CloseNow();
monitor.reset();
}
namespace { namespace {
class DeleteOtherOnEventObserver : public ui::EventObserver { class DeleteOtherOnEventObserver : public ui::EventObserver {
public: public:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment