| Index: ui/views/window/dialog_client_view.cc
|
| diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc
|
| index 3cd043e2eb325ade6518cbbba973ce97210df3ad..f3638cd6d56e20a2e11ce6083e311dd377c5a445 100644
|
| --- a/ui/views/window/dialog_client_view.cc
|
| +++ b/ui/views/window/dialog_client_view.cc
|
| @@ -87,19 +87,11 @@ DialogClientView::DialogClientView(Widget* owner, View* contents_view)
|
| DialogClientView::~DialogClientView() {}
|
|
|
| void DialogClientView::AcceptWindow() {
|
| - // Only notify the delegate once. See |delegate_allowed_close_|'s comment.
|
| - if (!delegate_allowed_close_ && GetDialogDelegate()->Accept()) {
|
| - delegate_allowed_close_ = true;
|
| - GetWidget()->Close();
|
| - }
|
| + CloseWithDelegateMethod(&DialogDelegate::Accept, true);
|
| }
|
|
|
| void DialogClientView::CancelWindow() {
|
| - // Only notify the delegate once. See |delegate_allowed_close_|'s comment.
|
| - if (!delegate_allowed_close_ && GetDialogDelegate()->Cancel()) {
|
| - delegate_allowed_close_ = true;
|
| - GetWidget()->Close();
|
| - }
|
| + CloseWithDelegateMethod(&DialogDelegate::Cancel, true);
|
| }
|
|
|
| void DialogClientView::UpdateDialogButtons() {
|
| @@ -111,10 +103,24 @@ void DialogClientView::UpdateDialogButtons() {
|
| // DialogClientView, ClientView overrides:
|
|
|
| bool DialogClientView::CanClose() {
|
| + if (delegate_allowed_close_) {
|
| + DCHECK(!asking_delegate_whether_to_close_);
|
| + return true;
|
| + }
|
| +
|
| + // The delegate may perform an action that causes the Widget to lose focus and
|
| + // (for some bubbles) attempt to close again. Widget::Close() has protection
|
| + // against multiple calls to Widget::Close(), but that method is above
|
| + // CanClose() in the stack: CanClose() has not yet told the first
|
| + // Widget::Close() whether it may proceed, so that protection can't be used.
|
| + // Detect this situation and always return false from the nested call to
|
| + // CanClose() so that Widget::Close() bails out early.
|
| + if (asking_delegate_whether_to_close_)
|
| + return false;
|
| +
|
| // If the dialog is closing but no Accept or Cancel action has been performed
|
| // before, it's a Close action.
|
| - if (!delegate_allowed_close_)
|
| - delegate_allowed_close_ = GetDialogDelegate()->Close();
|
| + CloseWithDelegateMethod(&DialogDelegate::Close, false);
|
| return delegate_allowed_close_;
|
| }
|
|
|
| @@ -419,4 +425,20 @@ void DialogClientView::SetupViews() {
|
| extra_view_->SetGroup(kButtonGroup);
|
| }
|
|
|
| +void DialogClientView::CloseWithDelegateMethod(bool (DialogDelegate::*method)(),
|
| + bool close) {
|
| + DCHECK(!asking_delegate_whether_to_close_);
|
| +
|
| + // Only notify the delegate once. See |delegate_allowed_close_|'s comment.
|
| + if (delegate_allowed_close_)
|
| + return;
|
| +
|
| + {
|
| + base::AutoReset<bool> auto_reset(&asking_delegate_whether_to_close_, true);
|
| + delegate_allowed_close_ = (GetDialogDelegate()->*method)();
|
| + }
|
| + if (close && delegate_allowed_close_)
|
| + GetWidget()->Close();
|
| +}
|
| +
|
| } // namespace views
|
|
|