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/scoped_ptr.h" | 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/search/search.h" |
6 #include "chrome/browser/ui/browser.h" | 9 #include "chrome/browser/ui/browser.h" |
7 #include "chrome/browser/ui/browser_commands.h" | 10 #include "chrome/browser/ui/browser_commands.h" |
8 #include "chrome/browser/ui/host_desktop.h" | |
9 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 11 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
10 #include "chrome/browser/ui/views/tab_modal_confirm_dialog_views.h" | 12 #include "chrome/browser/ui/views/constrained_window_views.h" |
| 13 #include "chrome/browser/ui/views/frame/browser_view.h" |
| 14 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" |
11 #include "chrome/common/url_constants.h" | 15 #include "chrome/common/url_constants.h" |
12 #include "chrome/test/base/in_process_browser_test.h" | 16 #include "chrome/test/base/in_process_browser_test.h" |
13 #include "chrome/test/base/interactive_test_utils.h" | |
14 #include "chrome/test/base/ui_test_utils.h" | 17 #include "chrome/test/base/ui_test_utils.h" |
15 #include "components/web_modal/web_contents_modal_dialog_host.h" | 18 #include "components/web_modal/web_contents_modal_dialog_host.h" |
16 #include "components/web_modal/web_contents_modal_dialog_manager.h" | 19 #include "components/web_modal/web_contents_modal_dialog_manager.h" |
17 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" | 20 #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" |
18 #include "content/public/browser/web_contents.h" | 25 #include "content/public/browser/web_contents.h" |
19 #include "content/public/test/browser_test_utils.h" | 26 #include "ipc/ipc_message.h" |
20 #include "ui/base/accelerators/accelerator.h" | 27 #include "ui/base/accelerators/accelerator.h" |
| 28 #include "ui/views/controls/textfield/textfield.h" |
21 #include "ui/views/focus/focus_manager.h" | 29 #include "ui/views/focus/focus_manager.h" |
22 #include "ui/views/widget/widget.h" | 30 #include "ui/views/layout/fill_layout.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 |
| 35 #if defined(USE_AURA) && defined(USE_X11) |
| 36 #include <X11/Xlib.h> |
| 37 #include "ui/events/test/events_test_utils_x11.h" |
| 38 #endif |
| 39 |
| 40 using web_modal::WebContentsModalDialogManager; |
| 41 using web_modal::WebContentsModalDialogManagerDelegate; |
23 | 42 |
24 namespace { | 43 namespace { |
25 | 44 |
26 class TestDialog : public views::DialogDelegateView { | 45 class TestConstrainedDialogContentsView |
| 46 : public views::View, |
| 47 public base::SupportsWeakPtr<TestConstrainedDialogContentsView> { |
27 public: | 48 public: |
28 TestDialog() { SetFocusable(true); } | 49 TestConstrainedDialogContentsView() |
29 virtual ~TestDialog() {} | 50 : text_field_(new views::Textfield) { |
| 51 SetLayoutManager(new views::FillLayout); |
| 52 AddChildView(text_field_); |
| 53 } |
30 | 54 |
31 virtual views::View* GetInitiallyFocusedView() OVERRIDE { return this; } | 55 views::View* GetInitiallyFocusedView() { |
32 // Don't delete the delegate yet. Keep it around for inspection later. | 56 return text_field_; |
33 virtual void DeleteDelegate() OVERRIDE {} | 57 } |
| 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 } |
34 | 104 |
35 virtual ui::ModalType GetModalType() const OVERRIDE { | 105 virtual ui::ModalType GetModalType() const OVERRIDE { |
36 #if defined(USE_ASH) | 106 #if defined(USE_ASH) |
37 return ui::MODAL_TYPE_CHILD; | 107 return ui::MODAL_TYPE_CHILD; |
38 #else | 108 #else |
39 return views::WidgetDelegate::GetModalType(); | 109 return views::WidgetDelegate::GetModalType(); |
40 #endif | 110 #endif |
41 } | 111 } |
42 | 112 |
| 113 bool done() { |
| 114 return done_; |
| 115 } |
| 116 |
43 private: | 117 private: |
44 DISALLOW_COPY_AND_ASSIGN(TestDialog); | 118 // contents_ will be freed when the View goes away. |
| 119 base::WeakPtr<TestConstrainedDialogContentsView> contents_; |
| 120 bool done_; |
| 121 |
| 122 DISALLOW_COPY_AND_ASSIGN(TestConstrainedDialog); |
45 }; | 123 }; |
46 | 124 |
47 // A helper function to create and show a web contents modal dialog. | |
48 scoped_ptr<TestDialog> ShowModalDialog(content::WebContents* web_contents) { | |
49 scoped_ptr<TestDialog> dialog(new TestDialog()); | |
50 views::Widget* window = views::Widget::CreateWindowAsFramelessChild( | |
51 dialog.get(), web_contents->GetNativeView()); | |
52 web_modal::WebContentsModalDialogManager::FromWebContents(web_contents)-> | |
53 ShowModalDialog(window->GetNativeView()); | |
54 return dialog.Pass(); | |
55 } | |
56 | |
57 } // namespace | 125 } // namespace |
58 | 126 |
59 typedef InProcessBrowserTest ConstrainedWindowViewTest; | 127 class ConstrainedWindowViewTest : public InProcessBrowserTest { |
60 | 128 public: |
61 // Tests the intial focus of tab-modal dialogs, the restoration of focus to the | 129 ConstrainedWindowViewTest() { |
62 // browser when they close, and that queued dialogs don't register themselves as | 130 } |
63 // accelerator targets until they are displayed. | 131 }; |
64 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, FocusTest) { | 132 |
65 content::WebContents* web_contents = | 133 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA) |
66 browser()->tab_strip_model()->GetActiveWebContents(); | 134 // TODO(erg): linux_aura bringup: http://crbug.com/163931 |
67 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); | 135 #define MAYBE_FocusTest DISABLED_FocusTest |
68 scoped_ptr<TestDialog> dialog1 = ShowModalDialog(web_contents); | 136 #else |
69 | 137 #define MAYBE_FocusTest FocusTest |
70 // |dialog1| should be active and focused. | 138 #endif |
71 EXPECT_TRUE(dialog1->GetWidget()->IsVisible()); | 139 |
72 views::FocusManager* focus_manager = dialog1->GetWidget()->GetFocusManager(); | 140 // Tests the following: |
73 EXPECT_EQ(dialog1->GetContentsView(), focus_manager->GetFocusedView()); | 141 // |
74 | 142 // *) Initially focused view in a constrained dialog receives focus reliably. |
75 // Create a second dialog. This will also be modal to |web_contents|, but will | 143 // |
76 // remain hidden since the |dialog1| is still showing. | 144 // *) Constrained windows that are queued don't register themselves as |
77 scoped_ptr<TestDialog> dialog2 = ShowModalDialog(web_contents); | 145 // accelerator targets until they are displayed. |
78 EXPECT_FALSE(dialog2->GetWidget()->IsVisible()); | 146 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, MAYBE_FocusTest) { |
79 EXPECT_TRUE(dialog1->GetWidget()->IsVisible()); | 147 content::WebContents* web_contents = |
80 EXPECT_EQ(focus_manager, dialog2->GetWidget()->GetFocusManager()); | 148 browser()->tab_strip_model()->GetActiveWebContents(); |
81 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); | 149 ASSERT_TRUE(web_contents != NULL); |
82 EXPECT_EQ(dialog1->GetContentsView(), focus_manager->GetFocusedView()); | 150 WebContentsModalDialogManager* web_contents_modal_dialog_manager = |
83 | 151 WebContentsModalDialogManager::FromWebContents(web_contents); |
84 // Pressing return should close |dialog1|. | 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 |
| 157 // Create a constrained dialog. It will attach itself to web_contents. |
| 158 scoped_ptr<TestConstrainedDialog> test_dialog1(new TestConstrainedDialog); |
| 159 views::Widget* window1 = views::Widget::CreateWindowAsFramelessChild( |
| 160 test_dialog1.get(), |
| 161 modal_delegate->GetWebContentsModalDialogHost()->GetHostView()); |
| 162 web_contents_modal_dialog_manager->ShowModalDialog(window1->GetNativeView()); |
| 163 |
| 164 views::FocusManager* focus_manager = window1->GetFocusManager(); |
| 165 ASSERT_TRUE(focus_manager); |
| 166 |
| 167 // test_dialog1's text field should be focused. |
| 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. |
85 EXPECT_TRUE(focus_manager->ProcessAccelerator( | 189 EXPECT_TRUE(focus_manager->ProcessAccelerator( |
86 ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE))); | 190 ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE))); |
87 content::RunAllPendingInMessageLoop(); | 191 content::RunAllPendingInMessageLoop(); |
88 EXPECT_EQ(NULL, dialog1->GetWidget()); | 192 |
89 | 193 EXPECT_TRUE(test_dialog1->done()); |
90 // |dialog2| should be visible and focused. | 194 EXPECT_FALSE(test_dialog2->done()); |
91 EXPECT_TRUE(dialog2->GetWidget()->IsVisible()); | 195 EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive()); |
92 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); | 196 |
93 EXPECT_EQ(dialog2->GetContentsView(), focus_manager->GetFocusedView()); | 197 // test_dialog2 will be shown. Focus should be on test_dialog2's text field. |
94 | 198 EXPECT_EQ(test_dialog2->GetInitiallyFocusedView(), |
95 // Creating a new tab should take focus away from the other tab's dialog. | 199 focus_manager->GetFocusedView()); |
96 const int tab_with_dialog = browser()->tab_strip_model()->active_index(); | 200 |
| 201 int tab_with_constrained_window = |
| 202 browser()->tab_strip_model()->active_index(); |
| 203 |
| 204 // Create a new tab. |
97 chrome::NewTab(browser()); | 205 chrome::NewTab(browser()); |
98 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); | 206 |
99 EXPECT_NE(dialog2->GetContentsView(), focus_manager->GetFocusedView()); | 207 // The constrained dialog should no longer be selected. |
100 | 208 EXPECT_NE(test_dialog2->GetInitiallyFocusedView(), |
101 // Activating the previous tab should bring focus to the dialog. | 209 focus_manager->GetFocusedView()); |
102 browser()->tab_strip_model()->ActivateTabAt(tab_with_dialog, false); | 210 |
103 EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); | 211 browser()->tab_strip_model()->ActivateTabAt(tab_with_constrained_window, |
104 EXPECT_EQ(dialog2->GetContentsView(), focus_manager->GetFocusedView()); | 212 false); |
105 | 213 |
106 // Pressing enter again should close |dialog2|. | 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 |
107 EXPECT_TRUE(focus_manager->ProcessAccelerator( | 219 EXPECT_TRUE(focus_manager->ProcessAccelerator( |
108 ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE))); | 220 ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE))); |
109 content::RunAllPendingInMessageLoop(); | 221 content::RunAllPendingInMessageLoop(); |
110 EXPECT_EQ(NULL, dialog2->GetWidget()); | 222 EXPECT_TRUE(test_dialog2->done()); |
111 EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER)); | 223 EXPECT_FALSE(web_contents_modal_dialog_manager->IsDialogActive()); |
112 } | 224 } |
113 | 225 |
114 // Tests that the tab-modal window is closed properly when its tab is closed. | 226 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA) |
115 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabCloseTest) { | 227 // TODO(erg): linux_aura bringup: http://crbug.com/163931 |
116 scoped_ptr<TestDialog> dialog = ShowModalDialog( | 228 #define MAYBE_TabCloseTest DISABLED_TabCloseTest |
117 browser()->tab_strip_model()->GetActiveWebContents()); | 229 #else |
118 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); | 230 #define MAYBE_TabCloseTest TabCloseTest |
119 chrome::CloseTab(browser()); | 231 #endif |
120 content::RunAllPendingInMessageLoop(); | 232 |
121 EXPECT_EQ(NULL, dialog->GetWidget()); | 233 // Tests that the constrained window is closed properly when its tab is |
122 } | 234 // closed. |
123 | 235 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, MAYBE_TabCloseTest) { |
124 // Tests that the tab-modal window is hidden when an other tab is selected and | 236 content::WebContents* web_contents = |
| 237 browser()->tab_strip_model()->GetActiveWebContents(); |
| 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(); |
| 259 EXPECT_TRUE(test_dialog->done()); |
| 260 } |
| 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 |
125 // shown when its tab is selected again. | 270 // shown when its tab is selected again. |
126 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabSwitchTest) { | 271 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, MAYBE_TabSwitchTest) { |
127 scoped_ptr<TestDialog> dialog = ShowModalDialog( | 272 content::WebContents* web_contents = |
128 browser()->tab_strip_model()->GetActiveWebContents()); | 273 browser()->tab_strip_model()->GetActiveWebContents(); |
129 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); | 274 ASSERT_TRUE(web_contents != NULL); |
130 | 275 |
131 // Open a new tab. The tab-modal window should hide itself. | 276 // Create a constrained dialog. It will attach itself to web_contents. |
132 chrome::NewTab(browser()); | 277 scoped_ptr<TestConstrainedDialog> test_dialog(new TestConstrainedDialog); |
133 EXPECT_FALSE(dialog->GetWidget()->IsVisible()); | 278 WebContentsModalDialogManager* web_contents_modal_dialog_manager = |
134 | 279 WebContentsModalDialogManager::FromWebContents(web_contents); |
135 // Close the new tab. The tab-modal window should show itself again. | 280 WebContentsModalDialogManagerDelegate* modal_delegate = |
136 chrome::CloseTab(browser()); | 281 web_contents_modal_dialog_manager->delegate(); |
137 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); | 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()); |
138 | 303 |
139 // Close the original tab. | 304 // Close the original tab. |
140 chrome::CloseTab(browser()); | 305 browser()->tab_strip_model()->CloseWebContentsAt( |
141 content::RunAllPendingInMessageLoop(); | 306 browser()->tab_strip_model()->active_index(), |
142 EXPECT_EQ(NULL, dialog->GetWidget()); | 307 TabStripModel::CLOSE_NONE); |
143 } | 308 content::RunAllPendingInMessageLoop(); |
144 | 309 EXPECT_TRUE(test_dialog->done()); |
145 // Tests that tab-modal dialogs follow tabs dragged between browser windows. | 310 } |
| 311 |
| 312 // Tests that the constrained window behaves properly when moving its tab |
| 313 // between browser windows. |
146 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabMoveTest) { | 314 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, TabMoveTest) { |
147 content::WebContents* web_contents = | 315 // Open a second browser. |
148 browser()->tab_strip_model()->GetActiveWebContents(); | |
149 scoped_ptr<TestDialog> dialog = ShowModalDialog(web_contents); | |
150 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); | |
151 | |
152 // Move the tab to a second browser window; but first create another tab. | |
153 // That prevents the first browser window from closing when its tab is moved. | |
154 chrome::NewTab(browser()); | |
155 browser()->tab_strip_model()->DetachWebContentsAt( | |
156 browser()->tab_strip_model()->GetIndexOfWebContents(web_contents)); | |
157 Browser* browser2 = CreateBrowser(browser()->profile()); | 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())); |
158 browser2->tab_strip_model()->AppendWebContents(web_contents, true); | 323 browser2->tab_strip_model()->AppendWebContents(web_contents, true); |
159 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); | 324 ASSERT_EQ(web_contents, browser2->tab_strip_model()->GetActiveWebContents()); |
160 | 325 |
161 // Close the first browser. | 326 // Create a constrained dialog. It will attach itself to web_contents. |
162 chrome::CloseWindow(browser()); | 327 scoped_ptr<TestConstrainedDialog> test_dialog(new TestConstrainedDialog); |
163 content::RunAllPendingInMessageLoop(); | 328 WebContentsModalDialogManager* web_contents_modal_dialog_manager = |
164 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); | 329 WebContentsModalDialogManager::FromWebContents(web_contents); |
165 | 330 WebContentsModalDialogManagerDelegate* modal_delegate = |
166 // Close the dialog's browser window. | 331 web_contents_modal_dialog_manager->delegate(); |
167 chrome::CloseTab(browser2); | 332 ASSERT_TRUE(modal_delegate != NULL); |
168 content::RunAllPendingInMessageLoop(); | 333 views::Widget* window = views::Widget::CreateWindowAsFramelessChild( |
169 EXPECT_EQ(NULL, dialog->GetWidget()); | 334 test_dialog.get(), |
170 } | 335 modal_delegate->GetWebContentsModalDialogHost()->GetHostView()); |
171 | 336 web_contents_modal_dialog_manager->ShowModalDialog(window->GetNativeView()); |
172 // Tests that the web contents navigates when backspace is pressed. | 337 EXPECT_TRUE(window->IsVisible()); |
173 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, NavigationOnBackspace) { | 338 |
174 content::WebContents* web_contents = | 339 // Detach the web contents from the second browser's tab strip. |
175 browser()->tab_strip_model()->GetActiveWebContents(); | 340 browser2->tab_strip_model()->DetachWebContentsAt( |
176 content::WaitForLoadStop(web_contents); | 341 browser2->tab_strip_model()->GetIndexOfWebContents(web_contents)); |
177 const GURL original_url = web_contents->GetURL(); | 342 |
178 EXPECT_NE(GURL(chrome::kChromeUIVersionURL), original_url); | 343 // Append the web contents to the first browser. |
179 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL)); | 344 browser()->tab_strip_model()->AppendWebContents(web_contents, true); |
180 content::WaitForLoadStop(web_contents); | 345 EXPECT_TRUE(window->IsVisible()); |
181 EXPECT_EQ(GURL(chrome::kChromeUIVersionURL), web_contents->GetURL()); | 346 |
182 | 347 // Close the second browser. |
183 scoped_ptr<TestDialog> dialog = ShowModalDialog(web_contents); | 348 browser2->tab_strip_model()->CloseAllTabs(); |
184 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); | 349 content::RunAllPendingInMessageLoop(); |
185 EXPECT_EQ(dialog->GetContentsView(), | 350 EXPECT_TRUE(window->IsVisible()); |
186 dialog->GetWidget()->GetFocusManager()->GetFocusedView()); | 351 |
187 | 352 // Close the dialog's tab. |
188 // Pressing backspace should navigate back and close the dialog. | 353 bool closed = |
189 EXPECT_TRUE(chrome::CanGoBack(browser())); | 354 browser()->tab_strip_model()->CloseWebContentsAt( |
190 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_BACK, | 355 browser()->tab_strip_model()->GetIndexOfWebContents(web_contents), |
191 false, false, false, false)); | 356 TabStripModel::CLOSE_NONE); |
192 content::RunAllPendingInMessageLoop(); | 357 EXPECT_TRUE(closed); |
193 content::WaitForLoadStop(web_contents); | 358 content::RunAllPendingInMessageLoop(); |
194 EXPECT_EQ(NULL, dialog->GetWidget()); | 359 EXPECT_TRUE(test_dialog->done()); |
195 EXPECT_EQ(original_url, web_contents->GetURL()); | 360 } |
196 } | 361 |
197 | 362 #if defined(OS_WIN) || (defined(USE_AURA) && defined(USE_X11)) |
198 // Tests that the dialog closes when the escape key is pressed. | 363 |
199 IN_PROC_BROWSER_TEST_F(ConstrainedWindowViewTest, ClosesOnEscape) { | 364 // Forwards the key event which has |key_code| to the renderer. |
200 scoped_ptr<TestDialog> dialog = ShowModalDialog( | 365 void ForwardKeyEvent(content::RenderViewHost* host, ui::KeyboardCode key_code) { |
201 browser()->tab_strip_model()->GetActiveWebContents()); | 366 #if defined(OS_WIN) |
202 EXPECT_TRUE(dialog->GetWidget()->IsVisible()); | 367 MSG native_key_event = { NULL, WM_KEYDOWN, key_code, 0 }; |
203 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_ESCAPE, | 368 #elif defined(USE_X11) |
204 false, false, false, false)); | 369 ui::ScopedXI2Event x_event; |
205 content::RunAllPendingInMessageLoop(); | 370 x_event.InitKeyEvent(ui::ET_KEY_PRESSED, key_code, ui::EF_NONE); |
206 EXPECT_EQ(NULL, dialog->GetWidget()); | 371 XEvent* native_key_event = x_event; |
207 } | 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 |