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

Side by Side Diff: ui/views/controls/menu/menu_controller.cc

Issue 10154013: Fixes crash in closing menus. There are two issues here: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: OnOwnerClosing and more comments Created 8 years, 7 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_controller.h" 5 #include "ui/views/controls/menu/menu_controller.h"
6 6
7 #include "base/i18n/case_conversion.h" 7 #include "base/i18n/case_conversion.h"
8 #include "base/i18n/rtl.h" 8 #include "base/i18n/rtl.h"
9 #include "base/time.h" 9 #include "base/time.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 owner_ = parent; 299 owner_ = parent;
300 300
301 // Set the selection, which opens the initial menu. 301 // Set the selection, which opens the initial menu.
302 SetSelection(root, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); 302 SetSelection(root, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY);
303 303
304 if (!blocking_run_) { 304 if (!blocking_run_) {
305 // Start the timer to hide the menu. This is needed as we get no 305 // Start the timer to hide the menu. This is needed as we get no
306 // notification when the drag has finished. 306 // notification when the drag has finished.
307 StartCancelAllTimer(); 307 StartCancelAllTimer();
308 return NULL; 308 return NULL;
309 } else if (button) { 309 }
310
311 if (button)
310 menu_button_ = button; 312 menu_button_ = button;
311 }
312 313
313 // Make sure Chrome doesn't attempt to shut down while the menu is showing. 314 // Make sure Chrome doesn't attempt to shut down while the menu is showing.
314 if (ViewsDelegate::views_delegate) 315 if (ViewsDelegate::views_delegate)
315 ViewsDelegate::views_delegate->AddRef(); 316 ViewsDelegate::views_delegate->AddRef();
316 317
317 // We need to turn on nestable tasks as in some situations (pressing alt-f for 318 // We need to turn on nestable tasks as in some situations (pressing alt-f for
318 // one) the menus are run from a task. If we don't do this and are invoked 319 // one) the menus are run from a task. If we don't do this and are invoked
319 // from a task none of the tasks we schedule are processed and the menu 320 // from a task none of the tasks we schedule are processed and the menu
320 // appears totally broken. 321 // appears totally broken.
322 message_loop_depth_++;
323 DCHECK_LE(message_loop_depth_, 2);
321 #if defined(USE_AURA) 324 #if defined(USE_AURA)
322 aura::client::GetDispatcherClient( 325 aura::client::GetDispatcherClient(
323 parent->GetNativeWindow()->GetRootWindow())-> 326 parent->GetNativeWindow()->GetRootWindow())->
324 RunWithDispatcher(this, parent->GetNativeWindow(), true); 327 RunWithDispatcher(this, parent->GetNativeWindow(), true);
325 #else 328 #else
326 { 329 {
327 MessageLoopForUI* loop = MessageLoopForUI::current(); 330 MessageLoopForUI* loop = MessageLoopForUI::current();
328 MessageLoop::ScopedNestableTaskAllower allow(loop); 331 MessageLoop::ScopedNestableTaskAllower allow(loop);
329 loop->RunWithDispatcher(this); 332 loop->RunWithDispatcher(this);
330 } 333 }
331 #endif 334 #endif
335 message_loop_depth_--;
332 336
333 if (ViewsDelegate::views_delegate) 337 if (ViewsDelegate::views_delegate)
334 ViewsDelegate::views_delegate->ReleaseRef(); 338 ViewsDelegate::views_delegate->ReleaseRef();
335 339
336 // Close any open menus. 340 // Close any open menus.
337 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); 341 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
338 342
339 if (nested_menu) { 343 if (nested_menu) {
340 DCHECK(!menu_stack_.empty()); 344 DCHECK(!menu_stack_.empty());
341 // We're running from within a menu, restore the previous state. 345 // We're running from within a menu, restore the previous state.
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after
1020 drop_target_(NULL), 1024 drop_target_(NULL),
1021 drop_position_(MenuDelegate::DROP_UNKNOWN), 1025 drop_position_(MenuDelegate::DROP_UNKNOWN),
1022 owner_(NULL), 1026 owner_(NULL),
1023 possible_drag_(false), 1027 possible_drag_(false),
1024 drag_in_progress_(false), 1028 drag_in_progress_(false),
1025 valid_drop_coordinates_(false), 1029 valid_drop_coordinates_(false),
1026 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), 1030 last_drop_operation_(MenuDelegate::DROP_UNKNOWN),
1027 showing_submenu_(false), 1031 showing_submenu_(false),
1028 menu_button_(NULL), 1032 menu_button_(NULL),
1029 active_mouse_view_(NULL), 1033 active_mouse_view_(NULL),
1030 delegate_(delegate) { 1034 delegate_(delegate),
1035 message_loop_depth_(0) {
1031 active_instance_ = this; 1036 active_instance_ = this;
1032 } 1037 }
1033 1038
1034 MenuController::~MenuController() { 1039 MenuController::~MenuController() {
1035 DCHECK(!showing_); 1040 DCHECK(!showing_);
1036 if (active_instance_ == this) 1041 if (active_instance_ == this)
1037 active_instance_ = NULL; 1042 active_instance_ = NULL;
1038 StopShowTimer(); 1043 StopShowTimer();
1039 StopCancelAllTimer(); 1044 StopCancelAllTimer();
1040 } 1045 }
(...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after
1965 1970
1966 // Reset the active_mouse_view_ before sending mouse capture lost. That way if 1971 // Reset the active_mouse_view_ before sending mouse capture lost. That way if
1967 // it calls back to us, we aren't in a weird state. 1972 // it calls back to us, we aren't in a weird state.
1968 View* active_view = active_mouse_view_; 1973 View* active_view = active_mouse_view_;
1969 active_mouse_view_ = NULL; 1974 active_mouse_view_ = NULL;
1970 active_view->OnMouseCaptureLost(); 1975 active_view->OnMouseCaptureLost();
1971 } 1976 }
1972 1977
1973 void MenuController::SetExitType(ExitType type) { 1978 void MenuController::SetExitType(ExitType type) {
1974 exit_type_ = type; 1979 exit_type_ = type;
1975 #if defined(USE_AURA) 1980 // Exit nested message loops as soon as possible. We do this as
1976 // On aura, closing menu may not trigger next native event, which 1981 // MessageLoop::Dispatcher is only invoked before native events, which means
1977 // is necessary to exit from nested loop (See Dispatch methods). 1982 // its entirely possible for a Widget::CloseNow() task to be processed before
1978 // Send non-op event so that Dispatch method will always be called. 1983 // the next native message. By using QuitNow() we ensures the nested message
1979 // crbug.com/104684. 1984 // loop returns as soon as possible and avoids having deleted views classes
1980 if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED) { 1985 // (such as widgets and rootviews) on the stack when the nested message loop
1981 owner_->GetNativeView()->GetRootWindow()->PostNativeEvent( 1986 // stops.
1982 ui::CreateNoopEvent()); 1987 //
1983 } 1988 // It's safe to invoke QuitNow multiple times, it only effects the current
1984 #endif 1989 // loop.
1990 if (exit_type_ != EXIT_NONE && message_loop_depth_)
1991 MessageLoop::current()->QuitNow();
1985 } 1992 }
1986 1993
1987 void MenuController::HandleMouseLocation(SubmenuView* source, 1994 void MenuController::HandleMouseLocation(SubmenuView* source,
1988 const gfx::Point& mouse_location) { 1995 const gfx::Point& mouse_location) {
1989 if (showing_submenu_) 1996 if (showing_submenu_)
1990 return; 1997 return;
1991 1998
1992 MenuPart part = GetMenuPart(source, mouse_location); 1999 MenuPart part = GetMenuPart(source, mouse_location);
1993 2000
1994 UpdateScrolling(part); 2001 UpdateScrolling(part);
(...skipping 11 matching lines...) Expand all
2006 (!pending_state_.item->HasSubmenu() || 2013 (!pending_state_.item->HasSubmenu() ||
2007 !pending_state_.item->GetSubmenu()->IsShowing())) { 2014 !pending_state_.item->GetSubmenu()->IsShowing())) {
2008 // On exit if the user hasn't selected an item with a submenu, move the 2015 // On exit if the user hasn't selected an item with a submenu, move the
2009 // selection back to the parent menu item. 2016 // selection back to the parent menu item.
2010 SetSelection(pending_state_.item->GetParentMenuItem(), 2017 SetSelection(pending_state_.item->GetParentMenuItem(),
2011 SELECTION_OPEN_SUBMENU); 2018 SELECTION_OPEN_SUBMENU);
2012 } 2019 }
2013 } 2020 }
2014 2021
2015 } // namespace views 2022 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698