Chromium Code Reviews| Index: chrome/browser/ui/views/exclusive_access_bubble_views_interactive_uitest.cc |
| diff --git a/chrome/browser/ui/views/exclusive_access_bubble_views_interactive_uitest.cc b/chrome/browser/ui/views/exclusive_access_bubble_views_interactive_uitest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..729f1b2ecb97ac3ea1bb820f072cc4341e2c4fd6 |
| --- /dev/null |
| +++ b/chrome/browser/ui/views/exclusive_access_bubble_views_interactive_uitest.cc |
| @@ -0,0 +1,78 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/ui/exclusive_access/fullscreen_controller_test.h" |
| +#include "chrome/browser/ui/views/exclusive_access_bubble_views.h" |
| +#include "chrome/browser/ui/views/frame/browser_view.h" |
| +#include "ui/views/widget/widget.h" |
| +#include "ui/views/widget/widget_observer.h" |
| + |
| +class ExclusiveAccessBubbleViewsTest : public FullscreenControllerTest, |
| + public views::WidgetObserver { |
| + public: |
| + ExclusiveAccessBubbleViewsTest() {} |
| + |
| + ExclusiveAccessBubbleViews* bubble() { |
| + BrowserView* browser_view = |
| + BrowserView::GetBrowserViewForBrowser(browser()); |
| + return browser_view->exclusive_access_bubble(); |
| + } |
| + |
| + // WidgetObserver: |
| + void OnWidgetDestroying(views::Widget* widget) override { |
| + was_observing_in_destroying_ = widget->HasObserver(bubble()); |
| + was_destroying_ = true; |
| + } |
| + void OnWidgetDestroyed(views::Widget* widget) override { |
| + widget->RemoveObserver(this); |
|
msw
2017/05/03 18:48:33
optional nit: move this into OnWidgetDestroying?
tapted
2017/05/04 06:42:08
Done.
|
| + } |
| + |
| + protected: |
| + bool was_destroying_ = false; |
| + bool was_observing_in_destroying_ = false; |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(ExclusiveAccessBubbleViewsTest); |
| +}; |
| + |
| +// Simulate obscure codepaths resulting in the bubble Widget being Closed before |
|
msw
2017/05/03 18:48:34
nit: "closed"?
tapted
2017/05/04 06:42:08
Done.
|
| +// the ExclusiveAccessBubbleViews destructor will tear down the bubble and any |
|
msw
2017/05/03 18:48:34
nit: this sentence is a bit run-on and could be cl
tapted
2017/05/04 06:42:07
Done.
|
| +// running animations that could trigger crashes. |
| +IN_PROC_BROWSER_TEST_F(ExclusiveAccessBubbleViewsTest, NativeClose) { |
|
msw
2017/05/03 18:48:34
nit: maybe make a test for the normal close codepa
tapted
2017/05/04 06:42:07
Yup - most of the tests in FullscreenControllerInt
|
| + EXPECT_FALSE(bubble()); |
| + EnterActiveTabFullscreen(); |
| + EXPECT_TRUE(bubble()); |
| + |
| + bubble()->GetView()->GetWidget()->AddObserver(this); |
| + |
| + // It's hard to nail down a codepath that results in the bubble Widget being |
|
msw
2017/05/03 18:48:34
Maybe this comment should just say "Simulate the b
tapted
2017/05/04 06:42:07
Done. Yeah is probably too much info.
|
| + // destroyed before the call to the ExclusiveAccessBubbleViewsTest destructor. |
|
msw
2017/05/03 18:48:34
q: Did you mean ExclusiveAccessBubbleViewsTest? (I
tapted
2017/05/04 06:42:07
Ahh yep - I meant the ExclusiveAccessBubbleViews d
|
| + // CloseAllTabs() will destroy the bubble via the ExclusiveAccessBubbleViews |
| + // destructor (via RenderViewTerminated -> ExitFullscreenMode). |
| + // CloseAllBrowsers() does a graceful exit via Browser::OnWindowClosing() |
| + // (which triggers CloseAllTabs()). |
| + // However, when closing via BrowserWindow::DestroyBrowser(), BrowserView |
| + // first stops observing its Widget, so never sees an OnWindowClosing(). |
| + // DestroyBrowser is triggered by chrome::SessionEnding() which ends up in |
| + // RenderProcessHostImpl::FastShutdownIfPossible() and only if fast shutdown |
| + // IS possible, does it call ProcessDied() which also results in graceful |
| + // termination via RenderViewTerminated. |
| + // If fast shutdown is NOT possible (e.g. unload handlers), then the browser |
| + // window can be torn down before RenderViewTerminated is sent and since the |
| + // bubble is a child window it will get town down as well. |
| + // That's all a bit complicated for a test, but it boils down to the window |
| + // being closed by the OS or by DesktopWindowTreeHost::OnHostClosed() rather |
| + // than by Widget::Close, and that needs to be handled. Widget::CloseNow() is |
| + // a close approximation of this. |
| + bubble()->GetView()->GetWidget()->CloseNow(); |
|
msw
2017/05/03 18:48:34
aside: you could also potentially delete the bubbl
tapted
2017/05/04 06:42:07
That works for NativeWidgetAura, and views::Platfo
|
| + EXPECT_FALSE(bubble()); |
| + |
| + // Verify that teardown is really happening via OnWidgetDestroyed() rather |
| + // than the usual path via the ExclusiveAccessBubbleViews destructor. Since |
| + // the destructor always first removes ExclusiveAccessBubbleViews as an |
| + // observer before starting the close, checking in OnWidgetDestroyed that it's |
| + // still observing achieves this. |
| + EXPECT_TRUE(was_observing_in_destroying_); |
| + EXPECT_TRUE(was_destroying_); |
| +} |