Remove the ConstrainedWindowViews class
[chromium-blink-merge.git] / chrome / browser / ui / views / constrained_window_views_browsertest.cc
bloba50ec56da9994e0ffa481248e0cb0eb30787c68e
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
3 // found in the LICENSE file.
5 #include "base/memory/weak_ptr.h"
6 #include "chrome/browser/platform_util.h"
7 #include "chrome/browser/profiles/profile.h"
8 #include "chrome/browser/ui/browser.h"
9 #include "chrome/browser/ui/browser_commands.h"
10 #include "chrome/browser/ui/tabs/tab_strip_model.h"
11 #include "chrome/browser/ui/views/constrained_window_views.h"
12 #include "chrome/browser/ui/views/frame/browser_view.h"
13 #include "chrome/browser/ui/web_contents_modal_dialog_manager.h"
14 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
15 #include "chrome/common/url_constants.h"
16 #include "chrome/test/base/in_process_browser_test.h"
17 #include "chrome/test/base/ui_test_utils.h"
18 #include "content/public/browser/native_web_keyboard_event.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/web_contents.h"
21 #include "content/public/browser/web_contents_view.h"
22 #include "ipc/ipc_message.h"
23 #include "ui/base/accelerators/accelerator.h"
24 #include "ui/views/controls/textfield/textfield.h"
25 #include "ui/views/focus/focus_manager.h"
26 #include "ui/views/layout/fill_layout.h"
27 #include "ui/views/test/test_widget_observer.h"
28 #include "ui/views/window/dialog_delegate.h"
29 #include "ui/web_dialogs/test/test_web_dialog_delegate.h"
31 #if defined(USE_AURA) && defined(USE_X11)
32 #include <X11/Xlib.h>
33 #include "ui/base/x/x11_util.h"
34 #endif
36 namespace {
38 class TestConstrainedDialogContentsView
39 : public views::View,
40 public base::SupportsWeakPtr<TestConstrainedDialogContentsView> {
41 public:
42 TestConstrainedDialogContentsView()
43 : text_field_(new views::Textfield) {
44 SetLayoutManager(new views::FillLayout);
45 AddChildView(text_field_);
48 views::View* GetInitiallyFocusedView() {
49 return text_field_;
52 private:
53 views::Textfield* text_field_;
54 DISALLOW_COPY_AND_ASSIGN(TestConstrainedDialogContentsView);
57 class TestConstrainedDialog : public views::DialogDelegate {
58 public:
59 TestConstrainedDialog()
60 : contents_((new TestConstrainedDialogContentsView())->AsWeakPtr()),
61 done_(false) {
64 virtual ~TestConstrainedDialog() {}
66 virtual views::View* GetInitiallyFocusedView() OVERRIDE {
67 return contents_ ? contents_->GetInitiallyFocusedView() : NULL;
70 virtual views::View* GetContentsView() OVERRIDE {
71 return contents_.get();
74 virtual views::Widget* GetWidget() OVERRIDE {
75 return contents_ ? contents_->GetWidget() : NULL;
78 virtual const views::Widget* GetWidget() const OVERRIDE {
79 return contents_ ? contents_->GetWidget() : NULL;
82 virtual void DeleteDelegate() OVERRIDE {
83 // Don't delete the delegate yet. We need to keep it around for inspection
84 // later.
85 EXPECT_TRUE(done_);
88 virtual bool Accept() OVERRIDE {
89 done_ = true;
90 return true;
93 virtual bool Cancel() OVERRIDE {
94 done_ = true;
95 return true;
98 virtual ui::ModalType GetModalType() const OVERRIDE {
99 #if defined(USE_ASH)
100 return ui::MODAL_TYPE_CHILD;
101 #else
102 return views::WidgetDelegate::GetModalType();
103 #endif
106 bool done() {
107 return done_;
110 private:
111 // contents_ will be freed when the View goes away.
112 base::WeakPtr<TestConstrainedDialogContentsView> contents_;
113 bool done_;
115 DISALLOW_COPY_AND_ASSIGN(TestConstrainedDialog);
118 } // namespace
120 class ConstrainedWindowViewTest : public InProcessBrowserTest {
121 public:
122 ConstrainedWindowViewTest() {
126 // Tests the following:
128 // *) Initially focused view in a constrained dialog receives focus reliably.
130 // *) Constrained windows that are queued don't register themselves as
131 // accelerator targets until they are displayed.
132 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, FocusTest) {
133 content::WebContents* web_contents =
134 browser()->tab_strip_model()->GetActiveWebContents();
135 ASSERT_TRUE(web_contents != NULL);
136 WebContentsModalDialogManager* web_contents_modal_dialog_manager =
137 WebContentsModalDialogManager::FromWebContents(web_contents);
138 ASSERT_TRUE(web_contents_modal_dialog_manager != NULL);
140 // Create a constrained dialog. It will attach itself to web_contents.
141 scoped_ptr<TestConstrainedDialog> test_dialog1(new TestConstrainedDialog);
142 views::Widget* window1 = CreateWebContentsModalDialogViews(
143 test_dialog1.get(),
144 web_contents->GetView()->GetNativeView());
145 web_contents_modal_dialog_manager->ShowDialog(window1->GetNativeView());
147 views::FocusManager* focus_manager = window1->GetFocusManager();
148 ASSERT_TRUE(focus_manager);
150 // test_dialog1's text field should be focused.
151 EXPECT_EQ(test_dialog1->GetInitiallyFocusedView(),
152 focus_manager->GetFocusedView());
154 // Now create a second constrained dialog. This will also be attached to
155 // web_contents, but will remain hidden since the test_dialog1 is still
156 // showing.
157 scoped_ptr<TestConstrainedDialog> test_dialog2(new TestConstrainedDialog);
158 views::Widget* window2 = CreateWebContentsModalDialogViews(
159 test_dialog2.get(),
160 web_contents->GetView()->GetNativeView());
161 web_contents_modal_dialog_manager->ShowDialog(window2->GetNativeView());
162 // Should be the same focus_manager.
163 ASSERT_EQ(focus_manager, window2->GetFocusManager());
165 // test_dialog1's text field should still be the view that has focus.
166 EXPECT_EQ(test_dialog1->GetInitiallyFocusedView(),
167 focus_manager->GetFocusedView());
168 ASSERT_TRUE(web_contents_modal_dialog_manager->IsShowingDialog());
170 // Now send a VKEY_RETURN to the browser. This should result in closing
171 // test_dialog1.
172 EXPECT_TRUE(focus_manager->ProcessAccelerator(
173 ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE)));
174 content::RunAllPendingInMessageLoop();
176 EXPECT_TRUE(test_dialog1->done());
177 EXPECT_FALSE(test_dialog2->done());
178 EXPECT_TRUE(web_contents_modal_dialog_manager->IsShowingDialog());
180 // test_dialog2 will be shown. Focus should be on test_dialog2's text field.
181 EXPECT_EQ(test_dialog2->GetInitiallyFocusedView(),
182 focus_manager->GetFocusedView());
184 int tab_with_constrained_window =
185 browser()->tab_strip_model()->active_index();
187 // Create a new tab.
188 chrome::NewTab(browser());
190 // The constrained dialog should no longer be selected.
191 EXPECT_NE(test_dialog2->GetInitiallyFocusedView(),
192 focus_manager->GetFocusedView());
194 browser()->tab_strip_model()->ActivateTabAt(tab_with_constrained_window,
195 false);
197 // Activating the previous tab should bring focus to the constrained window.
198 EXPECT_EQ(test_dialog2->GetInitiallyFocusedView(),
199 focus_manager->GetFocusedView());
201 // Send another VKEY_RETURN, closing test_dialog2
202 EXPECT_TRUE(focus_manager->ProcessAccelerator(
203 ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE)));
204 content::RunAllPendingInMessageLoop();
205 EXPECT_TRUE(test_dialog2->done());
206 EXPECT_FALSE(web_contents_modal_dialog_manager->IsShowingDialog());
209 // Tests that the constrained window is closed properly when its tab is
210 // closed.
211 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabCloseTest) {
212 content::WebContents* web_contents =
213 browser()->tab_strip_model()->GetActiveWebContents();
214 ASSERT_TRUE(web_contents != NULL);
215 WebContentsModalDialogManager* web_contents_modal_dialog_manager =
216 WebContentsModalDialogManager::FromWebContents(web_contents);
217 ASSERT_TRUE(web_contents_modal_dialog_manager != NULL);
219 // Create a constrained dialog. It will attach itself to web_contents.
220 scoped_ptr<TestConstrainedDialog> test_dialog(new TestConstrainedDialog);
221 views::Widget* window = CreateWebContentsModalDialogViews(
222 test_dialog.get(),
223 web_contents->GetView()->GetNativeView());
224 web_contents_modal_dialog_manager->ShowDialog(window->GetNativeView());
226 bool closed =
227 browser()->tab_strip_model()->CloseWebContentsAt(
228 browser()->tab_strip_model()->active_index(),
229 TabStripModel::CLOSE_NONE);
230 EXPECT_TRUE(closed);
231 content::RunAllPendingInMessageLoop();
232 EXPECT_TRUE(test_dialog->done());
235 // Tests that the constrained window is hidden when an other tab is selected and
236 // shown when its tab is selected again.
237 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabSwitchTest) {
238 content::WebContents* web_contents =
239 browser()->tab_strip_model()->GetActiveWebContents();
240 ASSERT_TRUE(web_contents != NULL);
242 // Create a constrained dialog. It will attach itself to web_contents.
243 scoped_ptr<TestConstrainedDialog> test_dialog(new TestConstrainedDialog);
244 views::Widget* window = CreateWebContentsModalDialogViews(
245 test_dialog.get(),
246 web_contents->GetView()->GetNativeView());
247 WebContentsModalDialogManager* web_contents_modal_dialog_manager =
248 WebContentsModalDialogManager::FromWebContents(web_contents);
249 web_contents_modal_dialog_manager->ShowDialog(window->GetNativeView());
250 EXPECT_TRUE(window->IsVisible());
252 // Open a new tab. The constrained window should hide itself.
253 browser()->tab_strip_model()->AppendWebContents(
254 content::WebContents::Create(
255 content::WebContents::CreateParams(browser()->profile())),
256 true);
257 EXPECT_FALSE(window->IsVisible());
259 // Close the new tab. The constrained window should show itself again.
260 bool closed =
261 browser()->tab_strip_model()->CloseWebContentsAt(
262 browser()->tab_strip_model()->active_index(),
263 TabStripModel::CLOSE_NONE);
264 EXPECT_TRUE(closed);
265 EXPECT_TRUE(window->IsVisible());
267 // Close the original tab.
268 browser()->tab_strip_model()->CloseWebContentsAt(
269 browser()->tab_strip_model()->active_index(),
270 TabStripModel::CLOSE_NONE);
271 content::RunAllPendingInMessageLoop();
272 EXPECT_TRUE(test_dialog->done());
275 #if defined(OS_WIN) || (defined(USE_AURA) && defined(USE_X11))
277 // Forwards the key event which has |key_code| to the renderer.
278 void ForwardKeyEvent(content::RenderViewHost* host, ui::KeyboardCode key_code) {
279 #if defined(OS_WIN)
280 MSG native_key_event = { NULL, WM_KEYDOWN, key_code, 0 };
281 #elif defined(USE_X11)
282 XEvent x_event;
283 ui::InitXKeyEventForTesting(
284 ui::ET_KEY_PRESSED, key_code, ui::EF_NONE, &x_event);
285 XEvent* native_key_event = &x_event;
286 #endif
288 #if defined(USE_AURA)
289 ui::KeyEvent key(native_key_event, false);
290 ui::KeyEvent* native_ui_key_event = &key;
291 #elif defined(OS_WIN)
292 MSG native_ui_key_event = native_key_event;
293 #endif
295 host->ForwardKeyboardEvent(
296 content::NativeWebKeyboardEvent(native_ui_key_event));
299 // Tests that backspace is not processed before it's sent to the web contents.
300 // Flaky on win aura. crbug.com/170331
301 #if defined(OS_WIN) && defined(USE_AURA)
302 #define MAYBE_BackspaceSentToWebContent DISABLED_BackspaceSentToWebContent
303 #else
304 #define MAYBE_BackspaceSentToWebContent BackspaceSentToWebContent
305 #endif
306 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest,
307 MAYBE_BackspaceSentToWebContent) {
308 content::WebContents* web_contents =
309 browser()->tab_strip_model()->GetActiveWebContents();
310 ASSERT_TRUE(web_contents != NULL);
312 GURL new_tab_url(chrome::kChromeUINewTabURL);
313 ui_test_utils::NavigateToURL(browser(), new_tab_url);
314 GURL about_url(chrome::kChromeUIAboutURL);
315 ui_test_utils::NavigateToURL(browser(), about_url);
317 ConstrainedWebDialogDelegate* cwdd = CreateConstrainedWebDialog(
318 browser()->profile(),
319 new ui::test::TestWebDialogDelegate(about_url),
320 NULL,
321 web_contents);
323 content::RenderViewHost* render_view_host =
324 cwdd->GetWebContents()->GetRenderViewHost();
325 ForwardKeyEvent(render_view_host, ui::VKEY_BACK);
327 // Backspace is not processed as accelerator before it's sent to web contents.
328 EXPECT_EQ(about_url.spec(), web_contents->GetURL().spec());
330 content::RunAllPendingInMessageLoop();
332 // Backspace is processed as accelerator after it's sent to web contents.
333 EXPECT_EQ(new_tab_url.spec(), web_contents->GetURL().spec());
336 // Fails flakily (once per 10-20 runs) on Win Aura only. http://crbug.com/177482
337 #if defined(OS_WIN)
338 #define MAYBE_EscapeCloseConstrainedWindow DISABLED_EscapeCloseConstrainedWindow
339 #else
340 #define MAYBE_EscapeCloseConstrainedWindow EscapeCloseConstrainedWindow
341 #endif
343 // Tests that escape closes the constrained window.
344 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest,
345 MAYBE_EscapeCloseConstrainedWindow) {
346 content::WebContents* web_contents =
347 browser()->tab_strip_model()->GetActiveWebContents();
348 ASSERT_TRUE(web_contents != NULL);
350 GURL new_tab_url(chrome::kChromeUINewTabURL);
351 ui_test_utils::NavigateToURL(browser(), new_tab_url);
352 ConstrainedWebDialogDelegate* cwdd = CreateConstrainedWebDialog(
353 browser()->profile(),
354 new ui::test::TestWebDialogDelegate(new_tab_url),
355 NULL,
356 web_contents);
358 views::Widget* widget =
359 views::Widget::GetWidgetForNativeView(cwdd->GetNativeDialog());
360 views::test::TestWidgetObserver observer(widget);
362 content::RenderViewHost* render_view_host =
363 cwdd->GetWebContents()->GetRenderViewHost();
364 ForwardKeyEvent(render_view_host, ui::VKEY_ESCAPE);
366 // Escape is not processed as accelerator before it's sent to web contents.
367 EXPECT_FALSE(observer.widget_closed());
369 content::RunAllPendingInMessageLoop();
371 // Escape is processed as accelerator after it's sent to web contents.
372 EXPECT_TRUE(observer.widget_closed());
375 #endif // defined(OS_WIN) || (defined(USE_AURA) && defined(USE_X11))