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 "base/memory/weak_ptr.h" | 5 #include "base/memory/scoped_ptr.h" |
6 #include "chrome/browser/platform_util.h" | |
7 #include "chrome/browser/profiles/profile.h" | |
8 #include "chrome/browser/search/search.h" | |
9 #include "chrome/browser/ui/browser.h" | 6 #include "chrome/browser/ui/browser.h" |
10 #include "chrome/browser/ui/browser_commands.h" | 7 #include "chrome/browser/ui/browser_commands.h" |
| 8 #include "chrome/browser/ui/host_desktop.h" |
11 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 9 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
12 #include "chrome/browser/ui/views/constrained_window_views.h" | 10 #include "chrome/browser/ui/views/tab_modal_confirm_dialog_views.h" |
13 #include "chrome/browser/ui/views/frame/browser_view.h" | |
14 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" | |
15 #include "chrome/common/url_constants.h" | 11 #include "chrome/common/url_constants.h" |
16 #include "chrome/test/base/in_process_browser_test.h" | 12 #include "chrome/test/base/in_process_browser_test.h" |
| 13 #include "chrome/test/base/interactive_test_utils.h" |
17 #include "chrome/test/base/ui_test_utils.h" | 14 #include "chrome/test/base/ui_test_utils.h" |
18 #include "components/web_modal/web_contents_modal_dialog_host.h" | 15 #include "components/web_modal/web_contents_modal_dialog_host.h" |
19 #include "components/web_modal/web_contents_modal_dialog_manager.h" | 16 #include "components/web_modal/web_contents_modal_dialog_manager.h" |
20 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" | 17 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" |
21 #include "content/public/browser/native_web_keyboard_event.h" | |
22 #include "content/public/browser/navigation_controller.h" | |
23 #include "content/public/browser/notification_types.h" | |
24 #include "content/public/browser/render_view_host.h" | |
25 #include "content/public/browser/web_contents.h" | 18 #include "content/public/browser/web_contents.h" |
26 #include "ipc/ipc_message.h" | 19 #include "content/public/test/browser_test_utils.h" |
27 #include "ui/base/accelerators/accelerator.h" | 20 #include "ui/base/accelerators/accelerator.h" |
28 #include "ui/views/controls/textfield/textfield.h" | |
29 #include "ui/views/focus/focus_manager.h" | 21 #include "ui/views/focus/focus_manager.h" |
30 #include "ui/views/layout/fill_layout.h" | 22 #include "ui/views/widget/widget.h" |
31 #include "ui/views/test/test_widget_observer.h" | |
32 #include "ui/views/window/dialog_delegate.h" | |
33 #include "ui/web_dialogs/test/test_web_dialog_delegate.h" | |
34 | 23 |
35 #if defined(USE_AURA) && defined(USE_X11) | 24 #if defined(OS_WIN) |
36 #include <X11/Xlib.h> | 25 #include "base/win/windows_version.h" |
37 #include "ui/events/test/events_test_utils_x11.h" | |
38 #endif | 26 #endif |
39 | 27 |
40 using web_modal::WebContentsModalDialogManager; | |
41 using web_modal::WebContentsModalDialogManagerDelegate; | |
42 | |
43 namespace { | 28 namespace { |
44 | 29 |
45 class TestConstrainedDialogContentsView | 30 class TestDialog : public views::DialogDelegateView { |
46 : public views::View, | |
47 public base::SupportsWeakPtr<TestConstrainedDialogContentsView> { | |
48 public: | 31 public: |
49 TestConstrainedDialogContentsView() | 32 TestDialog() { SetFocusable(true); } |
50 : text_field_(new views::Textfield) { | 33 virtual ~TestDialog() {} |
51 SetLayoutManager(new views::FillLayout); | |
52 AddChildView(text_field_); | |
53 } | |
54 | 34 |
55 views::View* GetInitiallyFocusedView() { | 35 virtual views::View* GetInitiallyFocusedView() OVERRIDE { return this; } |
56 return text_field_; | 36 // Don't delete the delegate yet. Keep it around for inspection later. |
57 } | 37 virtual void DeleteDelegate() OVERRIDE {} |
58 | |
59 private: | |
60 views::Textfield* text_field_; | |
61 DISALLOW_COPY_AND_ASSIGN(TestConstrainedDialogContentsView); | |
62 }; | |
63 | |
64 class TestConstrainedDialog : public views::DialogDelegate { | |
65 public: | |
66 TestConstrainedDialog() | |
67 : contents_((new TestConstrainedDialogContentsView())->AsWeakPtr()), | |
68 done_(false) { | |
69 } | |
70 | |
71 virtual ~TestConstrainedDialog() {} | |
72 | |
73 virtual views::View* GetInitiallyFocusedView() OVERRIDE { | |
74 return contents_ ? contents_->GetInitiallyFocusedView() : NULL; | |
75 } | |
76 | |
77 virtual views::View* GetContentsView() OVERRIDE { | |
78 return contents_.get(); | |
79 } | |
80 | |
81 virtual views::Widget* GetWidget() OVERRIDE { | |
82 return contents_ ? contents_->GetWidget() : NULL; | |
83 } | |
84 | |
85 virtual const views::Widget* GetWidget() const OVERRIDE { | |
86 return contents_ ? contents_->GetWidget() : NULL; | |
87 } | |
88 | |
89 virtual void DeleteDelegate() OVERRIDE { | |
90 // Don't delete the delegate yet. We need to keep it around for inspection | |
91 // later. | |
92 EXPECT_TRUE(done_); | |
93 } | |
94 | |
95 virtual bool Accept() OVERRIDE { | |
96 done_ = true; | |
97 return true; | |
98 } | |
99 | |
100 virtual bool Cancel() OVERRIDE { | |
101 done_ = true; | |
102 return true; | |
103 } | |
104 | 38 |
105 virtual ui::ModalType GetModalType() const OVERRIDE { | 39 virtual ui::ModalType GetModalType() const OVERRIDE { |
106 #if defined(USE_ASH) | 40 #if defined(USE_ASH) |
107 return ui::MODAL_TYPE_CHILD; | 41 return ui::MODAL_TYPE_CHILD; |
108 #else | 42 #else |
109 return views::WidgetDelegate::GetModalType(); | 43 return views::WidgetDelegate::GetModalType(); |
110 #endif | 44 #endif |
111 } | 45 } |
112 | 46 |
113 bool done() { | 47 private: |
114 return done_; | 48 DISALLOW_COPY_AND_ASSIGN(TestDialog); |
115 } | 49 }; |
116 | 50 |
117 private: | 51 // A helper function to create and show a web contents modal dialog. |
118 // contents_ will be freed when the View goes away. | 52 scoped_ptr<TestDialog> ShowModalDialog(content::WebContents* web_contents) { |
119 base::WeakPtr<TestConstrainedDialogContentsView> contents_; | 53 scoped_ptr<TestDialog> dialog(new TestDialog()); |
120 bool done_; | 54 views::Widget* window = views::Widget::CreateWindowAsFramelessChild( |
121 | 55 dialog.get(), web_contents->GetNativeView()); |
122 DISALLOW_COPY_AND_ASSIGN(TestConstrainedDialog); | 56 web_modal::WebContentsModalDialogManager::FromWebContents(web_contents)-> |
123 }; | 57 ShowModalDialog(window->GetNativeView()); |
| 58 return dialog.Pass(); |
| 59 } |
124 | 60 |
125 } // namespace | 61 } // namespace |
126 | 62 |
127 class ConstrainedWindowViewTest : public InProcessBrowserTest { | 63 typedef InProcessBrowserTest ConstrainedWindowViewTest; |
128 public: | |
129 ConstrainedWindowViewTest() { | |
130 } | |
131 }; | |
132 | 64 |
133 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA) | 65 // Tests the intial focus of tab-modal dialogs, the restoration of focus to the |
134 // TODO(erg): linux_aura bringup: http://crbug.com/163931 | 66 // browser when they close, and that queued dialogs don't register themselves as |
135 #define MAYBE_FocusTest DISABLED_FocusTest | 67 // accelerator targets until they are displayed. |
136 #else | 68 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, FocusTest) { |
137 #define MAYBE_FocusTest FocusTest | |
138 #endif | |
139 | |
140 // Tests the following: | |
141 // | |
142 // *) Initially focused view in a constrained dialog receives focus reliably. | |
143 // | |
144 // *) Constrained windows that are queued don't register themselves as | |
145 // accelerator targets until they are displayed. | |
146 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, MAYBE_FocusTest) { | |
147 content::WebContents* web_contents = | 69 content::WebContents* web_contents = |
148 browser()->tab_strip_model()->GetActiveWebContents(); | 70 browser()->tab_strip_model()->GetActiveWebContents(); |
149 ASSERT_TRUE(web_contents != NULL); | 71 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); |
150 WebContentsModalDialogManager* web_contents_modal_dialog_manager = | 72 scoped_ptr<TestDialog> dialog1 = ShowModalDialog(web_contents); |
151 WebContentsModalDialogManager::FromWebContents(web_contents); | |
152 ASSERT_TRUE(web_contents_modal_dialog_manager != NULL); | |
153 WebContentsModalDialogManagerDelegate* modal_delegate = | |
154 web_contents_modal_dialog_manager->delegate(); | |
155 ASSERT_TRUE(modal_delegate != NULL); | |
156 | 73 |
157 // Create a constrained dialog. It will attach itself to web_contents. | 74 // |dialog1| should be active and focused. |
158 scoped_ptr<TestConstrainedDialog> test_dialog1(new TestConstrainedDialog); | 75 EXPECT_TRUE(dialog1->GetWidget()->IsVisible()); |
159 views::Widget* window1 = views::Widget::CreateWindowAsFramelessChild( | 76 views::FocusManager* focus_manager = dialog1->GetWidget()->GetFocusManager(); |
160 test_dialog1.get(), | 77 EXPECT_EQ(dialog1->GetContentsView(), focus_manager->GetFocusedView()); |
161 modal_delegate->GetWebContentsModalDialogHost()->GetHostView()); | |
162 web_contents_modal_dialog_manager->ShowModalDialog(window1->GetNativeView()); | |
163 | 78 |
164 views::FocusManager* focus_manager = window1->GetFocusManager(); | 79 // Create a second dialog. This will also be modal to |web_contents|, but will |
165 ASSERT_TRUE(focus_manager); | 80 // remain hidden since the |dialog1| is still showing. |
| 81 scoped_ptr<TestDialog> dialog2 = ShowModalDialog(web_contents); |
| 82 EXPECT_FALSE(dialog2->GetWidget()->IsVisible()); |
| 83 EXPECT_TRUE(dialog1->GetWidget()->IsVisible()); |
| 84 EXPECT_EQ(focus_manager, dialog2->GetWidget()->GetFocusManager()); |
| 85 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); |
| 86 EXPECT_EQ(dialog1->GetContentsView(), focus_manager->GetFocusedView()); |
166 | 87 |
167 // test_dialog1's text field should be focused. | 88 // Pressing return should close |dialog1|. |
168 EXPECT_EQ(test_dialog1->GetInitiallyFocusedView(), | |
169 focus_manager->GetFocusedView()); | |
170 | |
171 // Now create a second constrained dialog. This will also be attached to | |
172 // web_contents, but will remain hidden since the test_dialog1 is still | |
173 // showing. | |
174 scoped_ptr<TestConstrainedDialog> test_dialog2(new TestConstrainedDialog); | |
175 views::Widget* window2 = views::Widget::CreateWindowAsFramelessChild( | |
176 test_dialog2.get(), | |
177 modal_delegate->GetWebContentsModalDialogHost()->GetHostView()); | |
178 web_contents_modal_dialog_manager->ShowModalDialog(window2->GetNativeView()); | |
179 // Should be the same focus_manager. | |
180 ASSERT_EQ(focus_manager, window2->GetFocusManager()); | |
181 | |
182 // test_dialog1's text field should still be the view that has focus. | |
183 EXPECT_EQ(test_dialog1->GetInitiallyFocusedView(), | |
184 focus_manager->GetFocusedView()); | |
185 ASSERT_TRUE(web_contents_modal_dialog_manager->IsDialogActive()); | |
186 | |
187 // Now send a VKEY_RETURN to the browser. This should result in closing | |
188 // test_dialog1. | |
189 EXPECT_TRUE(focus_manager->ProcessAccelerator( | 89 EXPECT_TRUE(focus_manager->ProcessAccelerator( |
190 ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE))); | 90 ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE))); |
191 content::RunAllPendingInMessageLoop(); | 91 content::RunAllPendingInMessageLoop(); |
| 92 EXPECT_EQ(NULL, dialog1->GetWidget()); |
192 | 93 |
193 EXPECT_TRUE(test_dialog1->done()); | 94 // |dialog2| should be visible and focused. |
194 EXPECT_FALSE(test_dialog2->done()); | 95 EXPECT_TRUE(dialog2->GetWidget()->IsVisible()); |
195 EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive()); | 96 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); |
| 97 EXPECT_EQ(dialog2->GetContentsView(), focus_manager->GetFocusedView()); |
196 | 98 |
197 // test_dialog2 will be shown. Focus should be on test_dialog2's text field. | 99 // Creating a new tab should take focus away from the other tab's dialog. |
198 EXPECT_EQ(test_dialog2->GetInitiallyFocusedView(), | 100 const int tab_with_dialog = browser()->tab_strip_model()->active_index(); |
199 focus_manager->GetFocusedView()); | 101 chrome::NewTab(browser()); |
| 102 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); |
| 103 EXPECT_NE(dialog2->GetContentsView(), focus_manager->GetFocusedView()); |
200 | 104 |
201 int tab_with_constrained_window = | 105 // Activating the previous tab should bring focus to the dialog. |
202 browser()->tab_strip_model()->active_index(); | 106 browser()->tab_strip_model()->ActivateTabAt(tab_with_dialog, false); |
| 107 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); |
| 108 EXPECT_EQ(dialog2->GetContentsView(), focus_manager->GetFocusedView()); |
203 | 109 |
204 // Create a new tab. | 110 // Pressing enter again should close |dialog2|. |
205 chrome::NewTab(browser()); | |
206 | |
207 // The constrained dialog should no longer be selected. | |
208 EXPECT_NE(test_dialog2->GetInitiallyFocusedView(), | |
209 focus_manager->GetFocusedView()); | |
210 | |
211 browser()->tab_strip_model()->ActivateTabAt(tab_with_constrained_window, | |
212 false); | |
213 | |
214 // Activating the previous tab should bring focus to the constrained window. | |
215 EXPECT_EQ(test_dialog2->GetInitiallyFocusedView(), | |
216 focus_manager->GetFocusedView()); | |
217 | |
218 // Send another VKEY_RETURN, closing test_dialog2 | |
219 EXPECT_TRUE(focus_manager->ProcessAccelerator( | 111 EXPECT_TRUE(focus_manager->ProcessAccelerator( |
220 ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE))); | 112 ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE))); |
221 content::RunAllPendingInMessageLoop(); | 113 content::RunAllPendingInMessageLoop(); |
222 EXPECT_TRUE(test_dialog2->done()); | 114 EXPECT_EQ(NULL, dialog2->GetWidget()); |
223 EXPECT_FALSE(web_contents_modal_dialog_manager->IsDialogActive()); | 115 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER)); |
224 } | 116 } |
225 | 117 |
226 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA) | 118 // Tests that the tab-modal window is closed properly when its tab is closed. |
227 // TODO(erg): linux_aura bringup: http://crbug.com/163931 | 119 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabCloseTest) { |
228 #define MAYBE_TabCloseTest DISABLED_TabCloseTest | 120 scoped_ptr<TestDialog> dialog = ShowModalDialog( |
229 #else | 121 browser()->tab_strip_model()->GetActiveWebContents()); |
230 #define MAYBE_TabCloseTest TabCloseTest | 122 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| 123 chrome::CloseTab(browser()); |
| 124 content::RunAllPendingInMessageLoop(); |
| 125 EXPECT_EQ(NULL, dialog->GetWidget()); |
| 126 } |
| 127 |
| 128 // Tests that the tab-modal window is hidden when an other tab is selected and |
| 129 // shown when its tab is selected again. |
| 130 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabSwitchTest) { |
| 131 scoped_ptr<TestDialog> dialog = ShowModalDialog( |
| 132 browser()->tab_strip_model()->GetActiveWebContents()); |
| 133 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| 134 |
| 135 // Open a new tab. The tab-modal window should hide itself. |
| 136 chrome::NewTab(browser()); |
| 137 EXPECT_FALSE(dialog->GetWidget()->IsVisible()); |
| 138 |
| 139 // Close the new tab. The tab-modal window should show itself again. |
| 140 chrome::CloseTab(browser()); |
| 141 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| 142 |
| 143 // Close the original tab. |
| 144 chrome::CloseTab(browser()); |
| 145 content::RunAllPendingInMessageLoop(); |
| 146 EXPECT_EQ(NULL, dialog->GetWidget()); |
| 147 } |
| 148 |
| 149 // Tests that tab-modal dialogs follow tabs dragged between browser windows. |
| 150 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabMoveTest) { |
| 151 content::WebContents* web_contents = |
| 152 browser()->tab_strip_model()->GetActiveWebContents(); |
| 153 scoped_ptr<TestDialog> dialog = ShowModalDialog(web_contents); |
| 154 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| 155 |
| 156 // Move the tab to a second browser window; but first create another tab. |
| 157 // That prevents the first browser window from closing when its tab is moved. |
| 158 chrome::NewTab(browser()); |
| 159 browser()->tab_strip_model()->DetachWebContentsAt( |
| 160 browser()->tab_strip_model()->GetIndexOfWebContents(web_contents)); |
| 161 Browser* browser2 = CreateBrowser(browser()->profile()); |
| 162 browser2->tab_strip_model()->AppendWebContents(web_contents, true); |
| 163 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| 164 |
| 165 // Close the first browser. |
| 166 chrome::CloseWindow(browser()); |
| 167 content::RunAllPendingInMessageLoop(); |
| 168 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| 169 |
| 170 // Close the dialog's browser window. |
| 171 chrome::CloseTab(browser2); |
| 172 content::RunAllPendingInMessageLoop(); |
| 173 EXPECT_EQ(NULL, dialog->GetWidget()); |
| 174 } |
| 175 |
| 176 // Tests that the web contents navigates when backspace is pressed. |
| 177 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, NavigationOnBackspace) { |
| 178 content::WebContents* web_contents = |
| 179 browser()->tab_strip_model()->GetActiveWebContents(); |
| 180 content::WaitForLoadStop(web_contents); |
| 181 const GURL original_url = web_contents->GetURL(); |
| 182 EXPECT_NE(GURL(chrome::kChromeUIVersionURL), original_url); |
| 183 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL)); |
| 184 content::WaitForLoadStop(web_contents); |
| 185 EXPECT_EQ(GURL(chrome::kChromeUIVersionURL), web_contents->GetURL()); |
| 186 |
| 187 scoped_ptr<TestDialog> dialog = ShowModalDialog(web_contents); |
| 188 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
| 189 EXPECT_EQ(dialog->GetContentsView(), |
| 190 dialog->GetWidget()->GetFocusManager()->GetFocusedView()); |
| 191 |
| 192 // Pressing backspace should navigate back and close the dialog. |
| 193 EXPECT_TRUE(chrome::CanGoBack(browser())); |
| 194 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_BACK, |
| 195 false, false, false, false)); |
| 196 content::RunAllPendingInMessageLoop(); |
| 197 content::WaitForLoadStop(web_contents); |
| 198 EXPECT_EQ(NULL, dialog->GetWidget()); |
| 199 EXPECT_EQ(original_url, web_contents->GetURL()); |
| 200 } |
| 201 |
| 202 // Tests that the dialog closes when the escape key is pressed. |
| 203 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, ClosesOnEscape) { |
| 204 #if defined(OS_WIN) |
| 205 // TODO(msw): The widget is not made NULL on XP. http://crbug.com/177482 |
| 206 if (base::win::GetVersion() < base::win::VERSION_VISTA) |
| 207 return; |
231 #endif | 208 #endif |
232 | 209 |
233 // Tests that the constrained window is closed properly when its tab is | 210 scoped_ptr<TestDialog> dialog = ShowModalDialog( |
234 // closed. | 211 browser()->tab_strip_model()->GetActiveWebContents()); |
235 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, MAYBE_TabCloseTest) { | 212 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); |
236 content::WebContents* web_contents = | 213 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE, |
237 browser()->tab_strip_model()->GetActiveWebContents(); | 214 false, false, false, false)); |
238 ASSERT_TRUE(web_contents != NULL); | |
239 WebContentsModalDialogManager* web_contents_modal_dialog_manager = | |
240 WebContentsModalDialogManager::FromWebContents(web_contents); | |
241 ASSERT_TRUE(web_contents_modal_dialog_manager != NULL); | |
242 WebContentsModalDialogManagerDelegate* modal_delegate = | |
243 web_contents_modal_dialog_manager->delegate(); | |
244 ASSERT_TRUE(modal_delegate != NULL); | |
245 | |
246 // Create a constrained dialog. It will attach itself to web_contents. | |
247 scoped_ptr<TestConstrainedDialog> test_dialog(new TestConstrainedDialog); | |
248 views::Widget* window = views::Widget::CreateWindowAsFramelessChild( | |
249 test_dialog.get(), | |
250 modal_delegate->GetWebContentsModalDialogHost()->GetHostView()); | |
251 web_contents_modal_dialog_manager->ShowModalDialog(window->GetNativeView()); | |
252 | |
253 bool closed = | |
254 browser()->tab_strip_model()->CloseWebContentsAt( | |
255 browser()->tab_strip_model()->active_index(), | |
256 TabStripModel::CLOSE_NONE); | |
257 EXPECT_TRUE(closed); | |
258 content::RunAllPendingInMessageLoop(); | 215 content::RunAllPendingInMessageLoop(); |
259 EXPECT_TRUE(test_dialog->done()); | 216 EXPECT_EQ(NULL, dialog->GetWidget()); |
260 } | 217 } |
261 | |
262 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA) | |
263 // TODO(erg): linux_aura bringup: http://crbug.com/163931 | |
264 #define MAYBE_TabSwitchTest DISABLED_TabSwitchTest | |
265 #else | |
266 #define MAYBE_TabSwitchTest TabSwitchTest | |
267 #endif | |
268 | |
269 // Tests that the constrained window is hidden when an other tab is selected and | |
270 // shown when its tab is selected again. | |
271 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, MAYBE_TabSwitchTest) { | |
272 content::WebContents* web_contents = | |
273 browser()->tab_strip_model()->GetActiveWebContents(); | |
274 ASSERT_TRUE(web_contents != NULL); | |
275 | |
276 // Create a constrained dialog. It will attach itself to web_contents. | |
277 scoped_ptr<TestConstrainedDialog> test_dialog(new TestConstrainedDialog); | |
278 WebContentsModalDialogManager* web_contents_modal_dialog_manager = | |
279 WebContentsModalDialogManager::FromWebContents(web_contents); | |
280 WebContentsModalDialogManagerDelegate* modal_delegate = | |
281 web_contents_modal_dialog_manager->delegate(); | |
282 ASSERT_TRUE(modal_delegate != NULL); | |
283 views::Widget* window = views::Widget::CreateWindowAsFramelessChild( | |
284 test_dialog.get(), | |
285 modal_delegate->GetWebContentsModalDialogHost()->GetHostView()); | |
286 web_contents_modal_dialog_manager->ShowModalDialog(window->GetNativeView()); | |
287 EXPECT_TRUE(window->IsVisible()); | |
288 | |
289 // Open a new tab. The constrained window should hide itself. | |
290 browser()->tab_strip_model()->AppendWebContents( | |
291 content::WebContents::Create( | |
292 content::WebContents::CreateParams(browser()->profile())), | |
293 true); | |
294 EXPECT_FALSE(window->IsVisible()); | |
295 | |
296 // Close the new tab. The constrained window should show itself again. | |
297 bool closed = | |
298 browser()->tab_strip_model()->CloseWebContentsAt( | |
299 browser()->tab_strip_model()->active_index(), | |
300 TabStripModel::CLOSE_NONE); | |
301 EXPECT_TRUE(closed); | |
302 EXPECT_TRUE(window->IsVisible()); | |
303 | |
304 // Close the original tab. | |
305 browser()->tab_strip_model()->CloseWebContentsAt( | |
306 browser()->tab_strip_model()->active_index(), | |
307 TabStripModel::CLOSE_NONE); | |
308 content::RunAllPendingInMessageLoop(); | |
309 EXPECT_TRUE(test_dialog->done()); | |
310 } | |
311 | |
312 // Tests that the constrained window behaves properly when moving its tab | |
313 // between browser windows. | |
314 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabMoveTest) { | |
315 // Open a second browser. | |
316 Browser* browser2 = CreateBrowser(browser()->profile()); | |
317 | |
318 // Create a second WebContents in the second browser, so that moving the | |
319 // WebContents does not trigger the browser to close immediately. This mimics | |
320 // the behavior when a user drags tabs between browsers. | |
321 content::WebContents* web_contents = content::WebContents::Create( | |
322 content::WebContents::CreateParams(browser()->profile())); | |
323 browser2->tab_strip_model()->AppendWebContents(web_contents, true); | |
324 ASSERT_EQ(web_contents, browser2->tab_strip_model()->GetActiveWebContents()); | |
325 | |
326 // Create a constrained dialog. It will attach itself to web_contents. | |
327 scoped_ptr<TestConstrainedDialog> test_dialog(new TestConstrainedDialog); | |
328 WebContentsModalDialogManager* web_contents_modal_dialog_manager = | |
329 WebContentsModalDialogManager::FromWebContents(web_contents); | |
330 WebContentsModalDialogManagerDelegate* modal_delegate = | |
331 web_contents_modal_dialog_manager->delegate(); | |
332 ASSERT_TRUE(modal_delegate != NULL); | |
333 views::Widget* window = views::Widget::CreateWindowAsFramelessChild( | |
334 test_dialog.get(), | |
335 modal_delegate->GetWebContentsModalDialogHost()->GetHostView()); | |
336 web_contents_modal_dialog_manager->ShowModalDialog(window->GetNativeView()); | |
337 EXPECT_TRUE(window->IsVisible()); | |
338 | |
339 // Detach the web contents from the second browser's tab strip. | |
340 browser2->tab_strip_model()->DetachWebContentsAt( | |
341 browser2->tab_strip_model()->GetIndexOfWebContents(web_contents)); | |
342 | |
343 // Append the web contents to the first browser. | |
344 browser()->tab_strip_model()->AppendWebContents(web_contents, true); | |
345 EXPECT_TRUE(window->IsVisible()); | |
346 | |
347 // Close the second browser. | |
348 browser2->tab_strip_model()->CloseAllTabs(); | |
349 content::RunAllPendingInMessageLoop(); | |
350 EXPECT_TRUE(window->IsVisible()); | |
351 | |
352 // Close the dialog's tab. | |
353 bool closed = | |
354 browser()->tab_strip_model()->CloseWebContentsAt( | |
355 browser()->tab_strip_model()->GetIndexOfWebContents(web_contents), | |
356 TabStripModel::CLOSE_NONE); | |
357 EXPECT_TRUE(closed); | |
358 content::RunAllPendingInMessageLoop(); | |
359 EXPECT_TRUE(test_dialog->done()); | |
360 } | |
361 | |
362 #if defined(OS_WIN) || (defined(USE_AURA) && defined(USE_X11)) | |
363 | |
364 // Forwards the key event which has |key_code| to the renderer. | |
365 void ForwardKeyEvent(content::RenderViewHost* host, ui::KeyboardCode key_code) { | |
366 #if defined(OS_WIN) | |
367 MSG native_key_event = { NULL, WM_KEYDOWN, key_code, 0 }; | |
368 #elif defined(USE_X11) | |
369 ui::ScopedXI2Event x_event; | |
370 x_event.InitKeyEvent(ui::ET_KEY_PRESSED, key_code, ui::EF_NONE); | |
371 XEvent* native_key_event = x_event; | |
372 #endif | |
373 | |
374 #if defined(USE_AURA) | |
375 ui::KeyEvent key(native_key_event, false); | |
376 ui::KeyEvent* native_ui_key_event = &key; | |
377 #elif defined(OS_WIN) | |
378 MSG native_ui_key_event = native_key_event; | |
379 #endif | |
380 | |
381 host->ForwardKeyboardEvent( | |
382 content::NativeWebKeyboardEvent(native_ui_key_event)); | |
383 } | |
384 | |
385 // Tests that backspace is not processed before it's sent to the web contents. | |
386 // Flaky on Win Aura and Linux ChromiumOS. See http://crbug.com/170331 | |
387 #if defined(USE_AURA) | |
388 #define MAYBE_BackspaceSentToWebContent DISABLED_BackspaceSentToWebContent | |
389 #else | |
390 #define MAYBE_BackspaceSentToWebContent BackspaceSentToWebContent | |
391 #endif | |
392 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, | |
393 MAYBE_BackspaceSentToWebContent) { | |
394 content::WebContents* web_contents = | |
395 browser()->tab_strip_model()->GetActiveWebContents(); | |
396 ASSERT_TRUE(web_contents != NULL); | |
397 | |
398 GURL new_tab_url(chrome::kChromeUINewTabURL); | |
399 ui_test_utils::NavigateToURL(browser(), new_tab_url); | |
400 GURL about_url(chrome::kChromeUIAboutURL); | |
401 ui_test_utils::NavigateToURL(browser(), about_url); | |
402 | |
403 ConstrainedWebDialogDelegate* cwdd = CreateConstrainedWebDialog( | |
404 browser()->profile(), | |
405 new ui::test::TestWebDialogDelegate(about_url), | |
406 NULL, | |
407 web_contents); | |
408 | |
409 content::WindowedNotificationObserver back_observer( | |
410 content::NOTIFICATION_LOAD_STOP, | |
411 content::Source<content::NavigationController>( | |
412 &web_contents->GetController())); | |
413 content::RenderViewHost* render_view_host = | |
414 cwdd->GetWebContents()->GetRenderViewHost(); | |
415 ForwardKeyEvent(render_view_host, ui::VKEY_BACK); | |
416 | |
417 // Backspace is not processed as accelerator before it's sent to web contents. | |
418 EXPECT_FALSE(web_contents->GetController().GetPendingEntry()); | |
419 EXPECT_EQ(about_url.spec(), web_contents->GetURL().spec()); | |
420 | |
421 // Backspace is processed as accelerator after it's sent to web contents. | |
422 content::RunAllPendingInMessageLoop(); | |
423 EXPECT_TRUE(web_contents->GetController().GetPendingEntry()); | |
424 | |
425 // Wait for the navigation to commit, since the URL will not be visible | |
426 // until then. | |
427 back_observer.Wait(); | |
428 EXPECT_TRUE(chrome::IsNTPURL(web_contents->GetURL(), browser()->profile())); | |
429 } | |
430 | |
431 // Fails flakily (once per 10-20 runs) on Win Aura only. http://crbug.com/177482 | |
432 // Also fails on CrOS. | |
433 // Also fails on linux_aura (http://crbug.com/163931) | |
434 #if defined(TOOLKIT_VIEWS) | |
435 #define MAYBE_EscapeCloseConstrainedWindow DISABLED_EscapeCloseConstrainedWindow | |
436 #else | |
437 #define MAYBE_EscapeCloseConstrainedWindow EscapeCloseConstrainedWindow | |
438 #endif | |
439 | |
440 // Tests that escape closes the constrained window. | |
441 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, | |
442 MAYBE_EscapeCloseConstrainedWindow) { | |
443 content::WebContents* web_contents = | |
444 browser()->tab_strip_model()->GetActiveWebContents(); | |
445 ASSERT_TRUE(web_contents != NULL); | |
446 | |
447 GURL new_tab_url(chrome::kChromeUINewTabURL); | |
448 ui_test_utils::NavigateToURL(browser(), new_tab_url); | |
449 ConstrainedWebDialogDelegate* cwdd = CreateConstrainedWebDialog( | |
450 browser()->profile(), | |
451 new ui::test::TestWebDialogDelegate(new_tab_url), | |
452 NULL, | |
453 web_contents); | |
454 | |
455 views::Widget* widget = | |
456 views::Widget::GetWidgetForNativeView(cwdd->GetNativeDialog()); | |
457 views::test::TestWidgetObserver observer(widget); | |
458 | |
459 content::RenderViewHost* render_view_host = | |
460 cwdd->GetWebContents()->GetRenderViewHost(); | |
461 ForwardKeyEvent(render_view_host, ui::VKEY_ESCAPE); | |
462 | |
463 // Escape is not processed as accelerator before it's sent to web contents. | |
464 EXPECT_FALSE(observer.widget_closed()); | |
465 | |
466 content::RunAllPendingInMessageLoop(); | |
467 | |
468 // Escape is processed as accelerator after it's sent to web contents. | |
469 EXPECT_TRUE(observer.widget_closed()); | |
470 } | |
471 | |
472 #endif // defined(OS_WIN) || (defined(USE_AURA) && defined(USE_X11)) | |
OLD | NEW |