Index: views/controls/menu/menu_controller.cc |
diff --git a/views/controls/menu/menu_controller.cc b/views/controls/menu/menu_controller.cc |
index b162c724dcfc8c9e25b88d8ce9cf231ce01598a7..dfbb5f1e111eb51ca86248fbc9d0a9bc7d8a341c 100644 |
--- a/views/controls/menu/menu_controller.cc |
+++ b/views/controls/menu/menu_controller.cc |
@@ -16,8 +16,10 @@ |
#include "views/drag_utils.h" |
#include "views/screen.h" |
#include "views/view_constants.h" |
+#include "views/views_delegate.h" |
#include "views/widget/root_view.h" |
#include "views/widget/widget.h" |
+ |
#if defined(OS_LINUX) |
#include "base/keyboard_code_conversion_gtk.h" |
#endif |
@@ -191,6 +193,10 @@ MenuItemView* MenuController::Run(gfx::NativeWindow parent, |
DLOG(INFO) << " entering nested loop, depth=" << nested_depth; |
#endif |
+ // Make sure Chrome doesn't attempt to shut down while the menu is showing. |
+ if (ViewsDelegate::views_delegate) |
+ ViewsDelegate::views_delegate->AddRef(); |
+ |
MessageLoopForUI* loop = MessageLoopForUI::current(); |
if (MenuItemView::allow_task_nesting_during_run_) { |
bool did_allow_task_nesting = loop->NestableTasksAllowed(); |
@@ -201,6 +207,9 @@ MenuItemView* MenuController::Run(gfx::NativeWindow parent, |
loop->Run(this); |
} |
+ if (ViewsDelegate::views_delegate) |
+ ViewsDelegate::views_delegate->ReleaseRef(); |
+ |
#ifdef DEBUG_MENU |
nested_depth--; |
DLOG(INFO) << " exiting nested loop, depth=" << nested_depth; |
@@ -238,11 +247,14 @@ MenuItemView* MenuController::Run(gfx::NativeWindow parent, |
CloseAllNestedMenus(); |
// Set exit_all_, which makes sure all nested loops exit immediately. |
- exit_type_ = EXIT_ALL; |
+ if (exit_type_ != EXIT_DESTROYED) |
+ exit_type_ = EXIT_ALL; |
} |
} |
- if (menu_button_) { |
+ // If we stopped running because one of the menus was destroyed chances are |
+ // the button was also destroyed. |
+ if (exit_type_ != EXIT_DESTROYED && menu_button_) { |
menu_button_->SetState(CustomButton::BS_NORMAL); |
menu_button_->SchedulePaint(); |
} |
@@ -286,7 +298,7 @@ void MenuController::SetSelection(MenuItemView* menu_item, |
StartShowTimer(); |
} |
-void MenuController::Cancel(bool all) { |
+void MenuController::Cancel(ExitType type) { |
if (!showing_) { |
// This occurs if we're in the process of notifying the delegate for a drop |
// and the delegate cancels us. |
@@ -294,7 +306,7 @@ void MenuController::Cancel(bool all) { |
} |
MenuItemView* selected = state_.item; |
- exit_type_ = all ? EXIT_ALL : EXIT_OUTERMOST; |
+ exit_type_ = type; |
// Hide windows immediately. |
SetSelection(NULL, false, true); |
@@ -336,7 +348,7 @@ void MenuController::OnMousePressed(SubmenuView* source, |
#endif |
// And close. |
- Cancel(true); |
+ Cancel(EXIT_ALL); |
return; |
} |
@@ -394,7 +406,7 @@ void MenuController::OnMouseDragged(SubmenuView* source, |
if (showing_) { |
// We're still showing, close all menus. |
CloseAllNestedMenus(); |
- Cancel(true); |
+ Cancel(EXIT_ALL); |
} // else case, drop was on us. |
} // else case, someone canceled us, don't do anything |
} |
@@ -637,7 +649,7 @@ void MenuController::SetActiveInstance(MenuController* controller) { |
bool MenuController::Dispatch(const MSG& msg) { |
DCHECK(blocking_run_); |
- if (exit_type_ == EXIT_ALL) { |
+ if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED) { |
// We must translate/dispatch the message here, otherwise we would drop |
// the message on the floor. |
TranslateMessage(&msg); |
@@ -678,7 +690,7 @@ bool MenuController::Dispatch(const MSG& msg) { |
case WM_CANCELMODE: |
case WM_SYSKEYDOWN: |
// Exit immediately on system keys. |
- Cancel(true); |
+ Cancel(EXIT_ALL); |
return false; |
default: |
@@ -693,7 +705,7 @@ bool MenuController::Dispatch(const MSG& msg) { |
bool MenuController::Dispatch(GdkEvent* event) { |
gtk_main_do_event(event); |
- if (exit_type_ == EXIT_ALL) |
+ if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED) |
return false; |
switch (event->type) { |
@@ -766,7 +778,7 @@ bool MenuController::OnKeyDown(int key_code |
(!state_.item->HasSubmenu() || |
!state_.item->GetSubmenu()->IsShowing()))) { |
// User pressed escape and only one menu is shown, cancel it. |
- Cancel(false); |
+ Cancel(EXIT_OUTERMOST); |
return false; |
} else { |
CloseSubmenu(); |