Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |