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

Unified Diff: ui/views/controls/menu/menu_controller.cc

Issue 2654093005: Fix MenuRunner Releasing (Closed)
Patch Set: Clarification and renaming Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/controls/menu/menu_controller.h ('k') | ui/views/controls/menu/menu_runner_impl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/controls/menu/menu_controller.cc
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 79ff77c75f2c375f07f12cac10116b21a5829cb0..aa002f26882d79ca43b067baf83c580db4b26f93 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -1026,14 +1026,18 @@ void MenuController::OnDragComplete(bool should_close) {
// Only attempt to close if the MenuHost said to.
if (should_close) {
if (showing_) {
- // Close showing widgets.
+ // During a drag operation there are several ways in which this can be
+ // canceled and deleted. Verify that this is still active before closing
+ // the widgets.
if (GetActiveInstance() == this) {
+ base::WeakPtr<MenuController> this_ref = AsWeakPtr();
CloseAllNestedMenus();
Cancel(EXIT_ALL);
- }
- // The above may have deleted us. If not perform a full shutdown.
- if (GetActiveInstance() == this)
+ // The above may have deleted us. If not perform a full shutdown.
+ if (!this_ref)
+ return;
ExitAsyncRun();
+ }
} else if (exit_type_ == EXIT_ALL) {
// We may have been canceled during the drag. If so we still need to fully
// shutdown.
@@ -1062,9 +1066,10 @@ ui::PostDispatchAction MenuController::OnWillDispatchKeyEvent(
event->StopPropagation();
if (event->type() == ui::ET_KEY_PRESSED) {
+ base::WeakPtr<MenuController> this_ref = AsWeakPtr();
OnKeyDown(event->key_code());
- // Menu controller might have been deleted.
- if (!GetActiveInstance())
+ // Key events can lead to this being deleted.
+ if (!this_ref)
return ui::POST_DISPATCH_NONE;
// Do not check mnemonics if the Alt or Ctrl modifiers are pressed. For
@@ -1074,8 +1079,8 @@ ui::PostDispatchAction MenuController::OnWillDispatchKeyEvent(
if (exit_type() == EXIT_NONE && (flags & kKeyFlagsMask) == 0) {
base::char16 c = event->GetCharacter();
SelectByChar(c);
- // Menu controller might have been deleted.
- if (!GetActiveInstance())
+ // SelectByChar can lead to this being deleted.
+ if (!this_ref)
return ui::POST_DISPATCH_NONE;
}
}
@@ -1112,6 +1117,11 @@ bool MenuController::IsCancelAllTimerRunningForTest() {
return cancel_all_timer_.IsRunning();
}
+void MenuController::ClearStateForTest() {
+ state_ = State();
+ pending_state_ = State();
+}
+
// static
void MenuController::TurnOffMenuSelectionHoldForTest() {
menu_selection_hold_time_ms = -1;
@@ -1249,12 +1259,13 @@ void MenuController::StartDrag(SubmenuView* source,
StopScrolling();
int drag_ops = item->GetDelegate()->GetDragOperations(item);
did_initiate_drag_ = true;
+ base::WeakPtr<MenuController> this_ref = AsWeakPtr();
// TODO(varunjain): Properly determine and send DRAG_EVENT_SOURCE below.
item->GetWidget()->RunShellDrag(NULL, data, widget_loc, drag_ops,
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
- // MenuController may have been deleted if |async_run_| so check for an active
- // instance before accessing member variables.
- if (GetActiveInstance() == this)
+ // MenuController may have been deleted if |async_run_| so check before
+ // accessing member variables.
+ if (this_ref)
did_initiate_drag_ = false;
}
@@ -1415,10 +1426,11 @@ bool MenuController::SendAcceleratorToHotTrackedView() {
if (!hot_view)
return false;
+ base::WeakPtr<MenuController> this_ref = AsWeakPtr();
ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE);
hot_view->AcceleratorPressed(accelerator);
// An accelerator may have canceled the menu after activation.
- if (GetActiveInstance()) {
+ if (this_ref) {
CustomButton* button = static_cast<CustomButton*>(hot_view);
SetHotTrackedButton(button);
}
@@ -2384,9 +2396,13 @@ void MenuController::RepostEventAndCancel(SubmenuView* source,
#if defined(OS_WIN)
if (event->IsMouseEvent() || event->IsTouchEvent()) {
+ base::WeakPtr<MenuController> this_ref = AsWeakPtr();
bool async_run = async_run_;
if (state_.item) {
state_.item->GetRootMenuItem()->GetSubmenu()->ReleaseCapture();
+ // We're going to close and we own the event capture. We need to repost
+ // the event, otherwise the window the user clicked on won't get the
+ // event.
RepostEventImpl(event, screen_loc, native_view, window);
} else {
// We some times get an event after closing all the menus. Ignore it. Make
@@ -2395,13 +2411,8 @@ void MenuController::RepostEventAndCancel(SubmenuView* source,
DCHECK(!source->GetWidget()->IsVisible());
}
- // We're going to close and we own the event capture. We need to repost the
- // event, otherwise the window the user clicked on won't get the event.
- // RepostEvent(source, event, screen_loc, native_view, window);
- // MenuController may have been deleted if |async_run_| so check for an
- // active
- // instance before accessing member variables.
- if (!GetActiveInstance()) {
+ // Reposting the event may have deleted this, if so exit.
+ if (!this_ref) {
DCHECK(async_run);
return;
}
@@ -2579,22 +2590,25 @@ void MenuController::ExitAsyncRun() {
// However as |delegate| can outlive this, it must still be notified of the
// menu closing so that it can perform teardown.
int accept_event_flags = accept_event_flags_;
+ base::WeakPtr<MenuController> this_ref = AsWeakPtr();
MenuItemView* result = ExitMenuRun();
delegate->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
result, accept_event_flags);
- // MenuController may have been deleted by |delegate|.
- if (GetActiveInstance() && nested && exit_type_ == EXIT_ALL)
+ // |delegate| may have deleted this.
+ if (this_ref && nested && exit_type_ == EXIT_ALL)
ExitAsyncRun();
}
MenuItemView* MenuController::ExitMenuRun() {
+ base::WeakPtr<MenuController> this_ref = AsWeakPtr();
+
// Release the lock which prevents Chrome from shutting down while the menu is
// showing.
if (async_run_ && ViewsDelegate::GetInstance())
ViewsDelegate::GetInstance()->ReleaseRef();
// Releasing the lock can result in Chrome shutting down, deleting this.
- if (!GetActiveInstance())
+ if (!this_ref)
return nullptr;
// Close any open menus.
« no previous file with comments | « ui/views/controls/menu/menu_controller.h ('k') | ui/views/controls/menu/menu_runner_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698