Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "ui/views/controls/menu/menu_runner.h" | 5 #include "ui/views/controls/menu/menu_runner.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 208 } | 208 } |
| 209 | 209 |
| 210 MenuRunner* runner_; | 210 MenuRunner* runner_; |
| 211 Widget* owner_; | 211 Widget* owner_; |
| 212 | 212 |
| 213 DISALLOW_COPY_AND_ASSIGN(MenuLauncherEventHandler); | 213 DISALLOW_COPY_AND_ASSIGN(MenuLauncherEventHandler); |
| 214 }; | 214 }; |
| 215 | 215 |
| 216 } // namespace | 216 } // namespace |
| 217 | 217 |
| 218 class MenuRunnerWidgetTest : public MenuRunnerTest { | |
|
tapted
2016/10/30 23:25:53
nit: brief comment like
// Test harness that inclu
themblsha
2016/10/31 12:19:22
Done.
| |
| 219 public: | |
| 220 MenuRunnerWidgetTest() {} | |
| 221 | |
| 222 Widget* widget() { return widget_; } | |
| 223 EventCountView* event_count_view() { return event_count_view_; } | |
| 224 | |
| 225 std::unique_ptr<ui::test::EventGenerator> EventGeneratorForWidget( | |
| 226 Widget* widget) { | |
| 227 return base::MakeUnique<ui::test::EventGenerator>( | |
| 228 IsMus() ? widget->GetNativeWindow() : GetContext(), | |
| 229 widget->GetNativeWindow()); | |
| 230 } | |
| 231 | |
| 232 void AddMenuLauncherEventHandler(Widget* widget) { | |
| 233 consumer_ = | |
| 234 base::MakeUnique<MenuLauncherEventHandler>(menu_runner(), widget); | |
| 235 event_count_view_->AddPostTargetHandler(consumer_.get()); | |
| 236 } | |
| 237 | |
| 238 // ViewsTestBase: | |
| 239 void SetUp() override { | |
| 240 MenuRunnerTest::SetUp(); | |
| 241 widget_ = new Widget; | |
| 242 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | |
| 243 widget_->Init(params); | |
| 244 widget_->Show(); | |
| 245 widget_->SetSize(gfx::Size(300, 300)); | |
| 246 | |
| 247 event_count_view_ = new EventCountView(); | |
| 248 event_count_view_->SetBounds(0, 0, 300, 300); | |
| 249 widget_->GetRootView()->AddChildView(event_count_view_); | |
| 250 | |
| 251 InitMenuRunner(MenuRunner::ASYNC); | |
| 252 } | |
| 253 | |
| 254 void TearDown() override { | |
| 255 widget_->CloseNow(); | |
| 256 MenuRunnerTest::TearDown(); | |
| 257 } | |
| 258 | |
| 259 private: | |
| 260 Widget* widget_; | |
|
tapted
2016/10/30 23:25:53
nit: = nullptr;, same below. (although it's not cr
themblsha
2016/10/31 12:19:23
Hopefully this would make possible future crashes
| |
| 261 EventCountView* event_count_view_; | |
| 262 std::unique_ptr<MenuLauncherEventHandler> consumer_; | |
| 263 | |
| 264 DISALLOW_COPY_AND_ASSIGN(MenuRunnerWidgetTest); | |
| 265 }; | |
| 266 | |
| 218 // Tests that when a mouse press launches a menu, that the target widget does | 267 // Tests that when a mouse press launches a menu, that the target widget does |
| 219 // not take explicit capture, nor closes the menu. | 268 // not take explicit capture, nor closes the menu. |
| 220 TEST_F(MenuRunnerTest, WidgetDoesntTakeCapture) { | 269 TEST_F(MenuRunnerWidgetTest, WidgetDoesntTakeCapture) { |
| 221 Widget* widget = new Widget; | 270 AddMenuLauncherEventHandler(owner()); |
| 222 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | |
| 223 widget->Init(params); | |
| 224 widget->Show(); | |
| 225 widget->SetSize(gfx::Size(300, 300)); | |
| 226 | 271 |
| 227 EventCountView* event_count_view = new EventCountView(); | |
| 228 event_count_view->SetBounds(0, 0, 300, 300); | |
| 229 widget->GetRootView()->AddChildView(event_count_view); | |
| 230 | |
| 231 InitMenuRunner(MenuRunner::ASYNC); | |
| 232 MenuRunner* runner = menu_runner(); | |
| 233 | |
| 234 MenuLauncherEventHandler consumer(runner, owner()); | |
| 235 event_count_view->AddPostTargetHandler(&consumer); | |
| 236 EXPECT_EQ(nullptr, internal::NativeWidgetPrivate::GetGlobalCapture( | 272 EXPECT_EQ(nullptr, internal::NativeWidgetPrivate::GetGlobalCapture( |
| 237 widget->GetNativeView())); | 273 widget()->GetNativeView())); |
| 238 std::unique_ptr<ui::test::EventGenerator> generator( | 274 auto generator(EventGeneratorForWidget(widget())); |
| 239 new ui::test::EventGenerator( | |
| 240 IsMus() ? widget->GetNativeWindow() : GetContext(), | |
| 241 widget->GetNativeWindow())); | |
| 242 // Implicit capture should not be held by |widget|. | 275 // Implicit capture should not be held by |widget|. |
| 243 generator->PressLeftButton(); | 276 generator->PressLeftButton(); |
| 244 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED)); | 277 EXPECT_EQ(1, event_count_view()->GetEventCount(ui::ET_MOUSE_PRESSED)); |
| 245 EXPECT_NE( | 278 EXPECT_NE(widget()->GetNativeView(), |
| 246 widget->GetNativeView(), | 279 internal::NativeWidgetPrivate::GetGlobalCapture( |
| 247 internal::NativeWidgetPrivate::GetGlobalCapture(widget->GetNativeView())); | 280 widget()->GetNativeView())); |
| 248 | 281 |
| 249 // The menu should still be open. | 282 // The menu should still be open. |
| 250 TestMenuDelegate* delegate = menu_delegate(); | 283 TestMenuDelegate* delegate = menu_delegate(); |
| 251 EXPECT_TRUE(runner->IsRunning()); | 284 EXPECT_TRUE(menu_runner()->IsRunning()); |
| 252 EXPECT_EQ(0, delegate->on_menu_closed_called()); | 285 EXPECT_EQ(0, delegate->on_menu_closed_called()); |
| 286 } | |
| 253 | 287 |
| 254 widget->CloseNow(); | 288 // Tests that after showing a menu on mouse press, that the subsequent mouse |
| 289 // will be delivered to the correct view, and not to the one that showed the | |
| 290 // menu. | |
| 291 // | |
| 292 // The original bug is reproducible only when showing the menu on mouse press, | |
| 293 // as RootView::OnMouseReleased() doesn't have the same behavior. | |
| 294 TEST_F(MenuRunnerWidgetTest, ClearsMouseHandlerOnRun) { | |
| 295 AddMenuLauncherEventHandler(widget()); | |
| 296 | |
| 297 // Create a second view that's supposed to get the second mouse press. | |
| 298 EventCountView* second_event_count_view = new EventCountView(); | |
| 299 widget()->GetRootView()->AddChildView(second_event_count_view); | |
| 300 | |
| 301 widget()->SetSize(gfx::Size(200, 100)); | |
| 302 event_count_view()->SetBounds(0, 0, 100, 100); | |
| 303 second_event_count_view->SetBounds(100, 0, 100, 100); | |
| 304 | |
| 305 // Click on the first view to show the menu. | |
| 306 auto generator(EventGeneratorForWidget(widget())); | |
| 307 generator->MoveMouseTo(event_count_view()->bounds().CenterPoint()); | |
| 308 generator->PressLeftButton(); | |
| 309 | |
| 310 // Pretend we dismissed the menu using normal means, as it doesn't matter. | |
| 311 EXPECT_TRUE(menu_runner()->IsRunning()); | |
| 312 menu_runner()->Cancel(); | |
| 313 | |
| 314 // EventGenerator won't allow us to re-send the left button press without | |
| 315 // releasing it first. We can't send the release event using the same | |
| 316 // generator as it would be handled by the RootView in the main Widget. | |
| 317 // In actual application the RootView doesn't see the release event. | |
| 318 generator.reset(); | |
| 319 generator = EventGeneratorForWidget(widget()); | |
| 320 | |
| 321 generator->MoveMouseTo(second_event_count_view->bounds().CenterPoint()); | |
| 322 generator->PressLeftButton(); | |
| 323 EXPECT_EQ(1, second_event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED)); | |
| 255 } | 324 } |
| 256 | 325 |
| 257 typedef MenuRunnerTest MenuRunnerImplTest; | 326 typedef MenuRunnerTest MenuRunnerImplTest; |
| 258 | 327 |
| 259 // Tests that when nested menu runners are destroyed out of order, that | 328 // Tests that when nested menu runners are destroyed out of order, that |
| 260 // MenuController is not accessed after it has been destroyed. This should not | 329 // MenuController is not accessed after it has been destroyed. This should not |
| 261 // crash on ASAN bots. | 330 // crash on ASAN bots. |
| 262 TEST_F(MenuRunnerImplTest, NestedMenuRunnersDestroyedOutOfOrder) { | 331 TEST_F(MenuRunnerImplTest, NestedMenuRunnersDestroyedOutOfOrder) { |
| 263 internal::MenuRunnerImpl* menu_runner = | 332 internal::MenuRunnerImpl* menu_runner = |
| 264 new internal::MenuRunnerImpl(menu_item_view()); | 333 new internal::MenuRunnerImpl(menu_item_view()); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 285 menu_runner->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 354 menu_runner->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
| 286 nullptr, 0); | 355 nullptr, 0); |
| 287 | 356 |
| 288 // This should not access the destroyed MenuController | 357 // This should not access the destroyed MenuController |
| 289 menu_runner2->Release(); | 358 menu_runner2->Release(); |
| 290 menu_runner->Release(); | 359 menu_runner->Release(); |
| 291 } | 360 } |
| 292 | 361 |
| 293 } // namespace test | 362 } // namespace test |
| 294 } // namespace views | 363 } // namespace views |
| OLD | NEW |