| // Copyright (c) 2012 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 "components/constrained_window/constrained_window_views.h" |
| |
| #include "base/memory/scoped_ptr.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_commands.h" |
| #include "chrome/browser/ui/host_desktop.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/browser/ui/views/tab_modal_confirm_dialog_views.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/interactive_test_utils.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "components/web_modal/web_contents_modal_dialog_host.h" |
| #include "components/web_modal/web_contents_modal_dialog_manager.h" |
| #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "ui/base/accelerators/accelerator.h" |
| #include "ui/views/focus/focus_manager.h" |
| #include "ui/views/widget/widget.h" |
| |
| #if defined(OS_WIN) |
| #include "base/win/windows_version.h" |
| #endif |
| |
| namespace { |
| |
| class TestDialog : public views::DialogDelegateView { |
| public: |
| TestDialog() { SetFocusable(true); } |
| ~TestDialog() override {} |
| |
| views::View* GetInitiallyFocusedView() override { return this; } |
| // Don't delete the delegate yet. Keep it around for inspection later. |
| void DeleteDelegate() override {} |
| |
| ui::ModalType GetModalType() const override { |
| #if defined(USE_ASH) |
| return ui::MODAL_TYPE_CHILD; |
| #else |
| return views::WidgetDelegate::GetModalType(); |
| #endif |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TestDialog); |
| }; |
| |
| // A helper function to create and show a web contents modal dialog. |
| scoped_ptr<TestDialog> ShowModalDialog(content::WebContents* web_contents) { |
| scoped_ptr<TestDialog> dialog(new TestDialog()); |
| ShowWebModalDialogViews(dialog.get(), web_contents); |
| return dialog.Pass(); |
| } |
| |
| } // namespace |
| |
| typedef InProcessBrowserTest ConstrainedWindowViewTest; |
| |
| // Tests the intial focus of tab-modal dialogs, the restoration of focus to the |
| // browser when they close, and that queued dialogs don't register themselves as |
| // accelerator targets until they are displayed. |
| IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, FocusTest) { |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); |
| scoped_ptr<TestDialog> dialog1 = ShowModalDialog(web_contents); |
| |
| // |dialog1| should be active and focused. |
| EXPECT_TRUE(dialog1->GetWidget()->IsVisible()); |
| views::FocusManager* focus_manager = dialog1->GetWidget()->GetFocusManager(); |
| EXPECT_EQ(dialog1->GetContentsView(), focus_manager->GetFocusedView()); |
| |
| // Create a second dialog. This will also be modal to |web_contents|, but will |
| // remain hidden since the |dialog1| is still showing. |
| scoped_ptr<TestDialog> dialog2 = ShowModalDialog(web_contents); |
| EXPECT_FALSE(dialog2->GetWidget()->IsVisible()); |
| EXPECT_TRUE(dialog1->GetWidget()->IsVisible()); |
| EXPECT_EQ(focus_manager, dialog2->GetWidget()->GetFocusManager()); |
| EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); |
| EXPECT_EQ(dialog1->GetContentsView(), focus_manager->GetFocusedView()); |
| |
| // Pressing return should close |dialog1|. |
| EXPECT_TRUE(focus_manager->ProcessAccelerator( |
| ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE))); |
| content::RunAllPendingInMessageLoop(); |
| EXPECT_EQ(NULL, dialog1->GetWidget()); |
| |
| // |dialog2| should be visible and focused. |
| EXPECT_TRUE(dialog2->GetWidget()->IsVisible()); |
| EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); |
| EXPECT_EQ(dialog2->GetContentsView(), focus_manager->GetFocusedView()); |
| |
| // Creating a new tab should take focus away from the other tab's dialog. |
| const int tab_with_dialog = browser()->tab_strip_model()->active_index(); |
| chrome::NewTab(browser()); |
| EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); |
| EXPECT_NE(dialog2->GetContentsView(), focus_manager->GetFocusedView()); |
| |
| // Activating the previous tab should bring focus to the dialog. |
| browser()->tab_strip_model()->ActivateTabAt(tab_with_dialog, false); |
| EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); |
| EXPECT_EQ(dialog2->GetContentsView(), focus_manager->GetFocusedView()); |
| |
| // Pressing enter again should close |dialog2|. |
| EXPECT_TRUE(focus_manager->ProcessAccelerator( |
| ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE))); |
| content::RunAllPendingInMessageLoop(); |
| EXPECT_EQ(NULL, dialog2->GetWidget()); |
| EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER)); |
| } |
| |
| // Tests that the tab-modal window is closed properly when its tab is closed. |
| IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabCloseTest) { |
| scoped_ptr<TestDialog> dialog = ShowModalDialog( |
| browser()->tab_strip_model()->GetActiveWebContents()); |
| EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| chrome::CloseTab(browser()); |
| content::RunAllPendingInMessageLoop(); |
| EXPECT_EQ(NULL, dialog->GetWidget()); |
| } |
| |
| // Tests that the tab-modal window is hidden when an other tab is selected and |
| // shown when its tab is selected again. |
| IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabSwitchTest) { |
| scoped_ptr<TestDialog> dialog = ShowModalDialog( |
| browser()->tab_strip_model()->GetActiveWebContents()); |
| EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| |
| // Open a new tab. The tab-modal window should hide itself. |
| chrome::NewTab(browser()); |
| EXPECT_FALSE(dialog->GetWidget()->IsVisible()); |
| |
| // Close the new tab. The tab-modal window should show itself again. |
| chrome::CloseTab(browser()); |
| EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| |
| // Close the original tab. |
| chrome::CloseTab(browser()); |
| content::RunAllPendingInMessageLoop(); |
| EXPECT_EQ(NULL, dialog->GetWidget()); |
| } |
| |
| // Tests that tab-modal dialogs follow tabs dragged between browser windows. |
| IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabMoveTest) { |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| scoped_ptr<TestDialog> dialog = ShowModalDialog(web_contents); |
| EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| |
| // Move the tab to a second browser window; but first create another tab. |
| // That prevents the first browser window from closing when its tab is moved. |
| chrome::NewTab(browser()); |
| browser()->tab_strip_model()->DetachWebContentsAt( |
| browser()->tab_strip_model()->GetIndexOfWebContents(web_contents)); |
| Browser* browser2 = CreateBrowser(browser()->profile()); |
| browser2->tab_strip_model()->AppendWebContents(web_contents, true); |
| EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| |
| // Close the first browser. |
| chrome::CloseWindow(browser()); |
| content::RunAllPendingInMessageLoop(); |
| EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| |
| // Close the dialog's browser window. |
| chrome::CloseTab(browser2); |
| content::RunAllPendingInMessageLoop(); |
| EXPECT_EQ(NULL, dialog->GetWidget()); |
| } |
| |
| // Tests that the web contents navigates when backspace is pressed. |
| IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, NavigationOnBackspace) { |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| content::WaitForLoadStop(web_contents); |
| const GURL original_url = web_contents->GetURL(); |
| EXPECT_NE(GURL(chrome::kChromeUIVersionURL), original_url); |
| ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL)); |
| content::WaitForLoadStop(web_contents); |
| EXPECT_EQ(GURL(chrome::kChromeUIVersionURL), web_contents->GetURL()); |
| |
| scoped_ptr<TestDialog> dialog = ShowModalDialog(web_contents); |
| EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| EXPECT_EQ(dialog->GetContentsView(), |
| dialog->GetWidget()->GetFocusManager()->GetFocusedView()); |
| |
| // Pressing backspace should navigate back and close the dialog. |
| EXPECT_TRUE(chrome::CanGoBack(browser())); |
| EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_BACK, |
| false, false, false, false)); |
| content::RunAllPendingInMessageLoop(); |
| content::WaitForLoadStop(web_contents); |
| EXPECT_EQ(NULL, dialog->GetWidget()); |
| EXPECT_EQ(original_url, web_contents->GetURL()); |
| } |
| |
| // Tests that the dialog closes when the escape key is pressed. |
| IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, ClosesOnEscape) { |
| #if defined(OS_WIN) |
| // TODO(msw): The widget is not made NULL on XP. http://crbug.com/177482 |
| if (base::win::GetVersion() < base::win::VERSION_VISTA) |
| return; |
| #endif |
| |
| scoped_ptr<TestDialog> dialog = ShowModalDialog( |
| browser()->tab_strip_model()->GetActiveWebContents()); |
| EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE, |
| false, false, false, false)); |
| content::RunAllPendingInMessageLoop(); |
| EXPECT_EQ(NULL, dialog->GetWidget()); |
| } |