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

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

Issue 2680863002: Prevent nested Menu Cancelling (Closed)
Patch Set: Created 3 years, 10 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
« no previous file with comments | « no previous file | ui/views/controls/menu/menu_runner_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/macros.h" 9 #include "base/macros.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 508
509 void MenuController::Cancel(ExitType type) { 509 void MenuController::Cancel(ExitType type) {
510 // If the menu has already been destroyed, no further cancellation is 510 // If the menu has already been destroyed, no further cancellation is
511 // needed. We especially don't want to set the |exit_type_| to a lesser 511 // needed. We especially don't want to set the |exit_type_| to a lesser
512 // value. 512 // value.
513 if (exit_type_ == EXIT_DESTROYED || exit_type_ == type) 513 if (exit_type_ == EXIT_DESTROYED || exit_type_ == type)
514 return; 514 return;
515 515
516 if (!showing_) { 516 if (!showing_) {
517 // This occurs if we're in the process of notifying the delegate for a drop 517 // This occurs if we're in the process of notifying the delegate for a drop
518 // and the delegate cancels us. 518 // and the delegate cancels us. Or if the releasing of ViewsDelegate causes
519 // an immediate shutdown.
519 return; 520 return;
520 } 521 }
521 522
522 MenuItemView* selected = state_.item; 523 MenuItemView* selected = state_.item;
523 SetExitType(type); 524 SetExitType(type);
524 525
525 SendMouseCaptureLostToActiveView(); 526 SendMouseCaptureLostToActiveView();
526 527
527 // Hide windows immediately. 528 // Hide windows immediately.
528 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); 529 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
529 530
530 if (!blocking_run_) { 531 if (!blocking_run_) {
531 // TODO(jonross): remove after tracking down the cause of 532 // TODO(jonross): remove after tracking down the cause of
532 // (crbug.com/683087). 533 // (crbug.com/683087).
533 bool nested = delegate_stack_.size() > 1; 534 bool nested = delegate_stack_.size() > 1;
534 CHECK(!nested); 535 CHECK(!nested);
535 base::WeakPtr<MenuController> this_ref = AsWeakPtr(); 536 base::WeakPtr<MenuController> this_ref = AsWeakPtr();
536 // If we didn't block the caller we need to notify the menu, which 537 // If we didn't block the caller we need to notify the menu, which
537 // triggers deleting us. 538 // triggers deleting us.
538 DCHECK(selected); 539 DCHECK(selected);
539 showing_ = false; 540 showing_ = false;
540 delegate_->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, 541 delegate_->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
541 selected->GetRootMenuItem(), accept_event_flags_); 542 selected->GetRootMenuItem(), accept_event_flags_);
542 // WARNING: the call to MenuClosed deletes us. 543 // WARNING: the call to MenuClosed deletes us.
543 CHECK(!this_ref); 544 CHECK(!this_ref);
544 return; 545 return;
545 } 546 }
546 547
548 // If |type| is EXIT_ALL we update the state of the menu to not showing. For
549 // dragging this ensures that the correct visual state is reported until the
550 // drag operation completes. For non-dragging cases it is possible that the
551 // release of ViewsDelegate leads immediately to shutdown, which can trigger
552 // nested calls to Cancel. We want to reject these to prevent attempting a
553 // nested tear down of this and |delegate_|.
554 if (type == EXIT_ALL)
555 showing_ = false;
556
547 // On Windows and Linux the destruction of this menu's Widget leads to the 557 // On Windows and Linux the destruction of this menu's Widget leads to the
548 // teardown of the platform specific drag-and-drop Widget. Do not shutdown 558 // teardown of the platform specific drag-and-drop Widget. Do not shutdown
549 // while dragging, leave the Widget hidden until drag-and-drop has completed, 559 // while dragging, leave the Widget hidden until drag-and-drop has completed,
550 // at which point all menus will be destroyed. 560 // at which point all menus will be destroyed.
551 //
552 // If |type| is EXIT_ALL we update the state of the menu to not showing. So
553 // that during the completion of a drag we are not incorrectly reporting the
554 // visual state.
555 if (!drag_in_progress_) 561 if (!drag_in_progress_)
556 ExitAsyncRun(); 562 ExitAsyncRun();
557 else if (type == EXIT_ALL)
558 showing_ = false;
559 } 563 }
560 564
561 void MenuController::AddNestedDelegate( 565 void MenuController::AddNestedDelegate(
562 internal::MenuControllerDelegate* delegate) { 566 internal::MenuControllerDelegate* delegate) {
563 // TODO(jonross): remove after tracking down the cause of (crbug.com/683087). 567 // TODO(jonross): remove after tracking down the cause of (crbug.com/683087).
564 for (auto delegates : delegate_stack_) { 568 for (auto delegates : delegate_stack_) {
565 // Having the same delegate in the stack could cause deletion order issues. 569 // Having the same delegate in the stack could cause deletion order issues.
566 CHECK_NE(delegates.first, delegate); 570 CHECK_NE(delegates.first, delegate);
567 } 571 }
568 572
(...skipping 2056 matching lines...) Expand 10 before | Expand all | Expand 10 after
2625 if (this_ref && nested && exit_type_ == EXIT_ALL) 2629 if (this_ref && nested && exit_type_ == EXIT_ALL)
2626 ExitAsyncRun(); 2630 ExitAsyncRun();
2627 } 2631 }
2628 2632
2629 MenuItemView* MenuController::ExitMenuRun() { 2633 MenuItemView* MenuController::ExitMenuRun() {
2630 base::WeakPtr<MenuController> this_ref = AsWeakPtr(); 2634 base::WeakPtr<MenuController> this_ref = AsWeakPtr();
2631 2635
2632 // Release the lock which prevents Chrome from shutting down while the menu is 2636 // Release the lock which prevents Chrome from shutting down while the menu is
2633 // showing. 2637 // showing.
2634 if (async_run_ && ViewsDelegate::GetInstance()) 2638 if (async_run_ && ViewsDelegate::GetInstance())
2635 ViewsDelegate::GetInstance()->ReleaseRef(); 2639 ViewsDelegate::GetInstance()->ReleaseRef();
sky 2017/02/07 19:23:51 Is your worry that this line is causing reentrancy
jonross 2017/02/07 20:07:21 So I only seem to have a partial stack trace from
2636 2640
2637 // Releasing the lock can result in Chrome shutting down, deleting this. 2641 // Releasing the lock can result in Chrome shutting down, deleting this.
2638 if (!this_ref) 2642 if (!this_ref)
2639 return nullptr; 2643 return nullptr;
2640 2644
2641 // Close any open menus. 2645 // Close any open menus.
2642 SetSelection(nullptr, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); 2646 SetSelection(nullptr, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
2643 2647
2644 #if defined(OS_WIN) 2648 #if defined(OS_WIN)
2645 // On Windows, if we select the menu item by touch and if the window at the 2649 // On Windows, if we select the menu item by touch and if the window at the
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
2776 if (hot_button_) 2780 if (hot_button_)
2777 hot_button_->SetHotTracked(false); 2781 hot_button_->SetHotTracked(false);
2778 hot_button_ = hot_button; 2782 hot_button_ = hot_button;
2779 if (hot_button) { 2783 if (hot_button) {
2780 hot_button->SetHotTracked(true); 2784 hot_button->SetHotTracked(true);
2781 hot_button->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); 2785 hot_button->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true);
2782 } 2786 }
2783 } 2787 }
2784 2788
2785 } // namespace views 2789 } // namespace views
OLDNEW
« no previous file with comments | « no previous file | ui/views/controls/menu/menu_runner_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698