Index: ui/views/widget/widget_unittest.cc |
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc |
index 41bbe8198d7b40b9136deaf3ae068bb795c3be87..57235012eee16f786ca0c6d8b49c0f1c7aca4366 100644 |
--- a/ui/views/widget/widget_unittest.cc |
+++ b/ui/views/widget/widget_unittest.cc |
@@ -3213,7 +3213,8 @@ TEST_F(WidgetTest, CharMessagesAsKeyboardMessagesDoesNotCrash) { |
class SubclassWindowHelper { |
public: |
explicit SubclassWindowHelper(HWND window) |
- : window_(window) { |
+ : window_(window), |
+ message_to_destroy_on_(0) { |
EXPECT_EQ(instance_, nullptr); |
instance_ = this; |
EXPECT_TRUE(Subclass()); |
@@ -3233,6 +3234,10 @@ class SubclassWindowHelper { |
messages_.clear(); |
} |
+ void set_message_to_destroy_on(unsigned int message) { |
+ message_to_destroy_on_ = message; |
+ } |
+ |
private: |
bool Subclass() { |
old_proc_ = reinterpret_cast<WNDPROC>( |
@@ -3258,14 +3263,20 @@ class SubclassWindowHelper { |
// Keep track of messags received for this window. |
instance_->messages_.insert(message); |
- return ::CallWindowProc(instance_->old_proc_, window, message, w_param, |
- l_param); |
+ LRESULT ret = ::CallWindowProc(instance_->old_proc_, window, message, |
+ w_param, l_param); |
+ if (message == instance_->message_to_destroy_on_) { |
+ instance_->Unsubclass(); |
+ ::DestroyWindow(window); |
+ } |
+ return ret; |
} |
WNDPROC old_proc_; |
HWND window_; |
static SubclassWindowHelper* instance_; |
std::set<unsigned int> messages_; |
+ unsigned int message_to_destroy_on_; |
DISALLOW_COPY_AND_ASSIGN(SubclassWindowHelper); |
}; |
@@ -3347,6 +3358,38 @@ TEST_F(WidgetTest, SysCommandMoveOnNCLButtonDownOnCaptionAndMoveTest) { |
widget.CloseNow(); |
} |
+ |
+// This test validates that destroying the window in the context of the |
+// WM_SYSCOMMAND message with SC_MOVE does not crash. |
+TEST_F(WidgetTest, DestroyInSysCommandNCLButtonDownOnCaption) { |
+ Widget widget; |
+ Widget::InitParams params = |
+ CreateParams(Widget::InitParams::TYPE_WINDOW); |
+ params.native_widget = new PlatformDesktopNativeWidget(&widget); |
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
+ widget.Init(params); |
+ widget.SetBounds(gfx::Rect(0, 0, 200, 200)); |
+ widget.Show(); |
+ ::SetCursorPos(500, 500); |
+ |
+ HWND window = widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(); |
+ |
+ SubclassWindowHelper subclass_helper(window); |
+ |
+ // Destroying the window in the context of the WM_SYSCOMMAND message |
+ // should not crash. |
+ subclass_helper.set_message_to_destroy_on(WM_SYSCOMMAND); |
+ |
+ ::PostMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(100, 100)); |
+ ::PostMessage(window, WM_NCMOUSEMOVE, HTCAPTION, MAKELPARAM(110, 110)); |
+ RunPendingMessages(); |
+ |
+ EXPECT_TRUE(subclass_helper.received_message(WM_NCLBUTTONDOWN)); |
+ EXPECT_TRUE(subclass_helper.received_message(WM_SYSCOMMAND)); |
+ |
+ widget.CloseNow(); |
+} |
+ |
#endif |
// Test that SetAlwaysOnTop and IsAlwaysOnTop are consistent. |