Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / web_dialog_view_browsertest.cc
blob286bcd8ddf50cc7293f443ae622d892cc452d396
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/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/location.h"
8 #include "base/message_loop/message_loop.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/browser_window.h"
12 #include "chrome/browser/ui/tabs/tab_strip_model.h"
13 #include "chrome/browser/ui/webui/chrome_web_contents_handler.h"
14 #include "chrome/common/url_constants.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "content/public/browser/browser_context.h"
18 #include "content/public/browser/render_widget_host_view.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/test/test_utils.h"
21 #include "ui/views/controls/webview/web_dialog_view.h"
22 #include "ui/views/widget/widget.h"
23 #include "ui/web_dialogs/test/test_web_dialog_delegate.h"
25 namespace {
27 // Initial size of WebDialog for SizeWindow test case. Note the height must be
28 // at least 59 on Windows.
29 const int kInitialWidth = 60;
30 const int kInitialHeight = 60;
32 class TestWebDialogView : public views::WebDialogView {
33 public:
34 TestWebDialogView(content::BrowserContext* context,
35 ui::WebDialogDelegate* delegate,
36 bool* observed_destroy)
37 : views::WebDialogView(context, delegate, new ChromeWebContentsHandler),
38 should_quit_on_size_change_(false),
39 observed_destroy_(observed_destroy) {
40 EXPECT_FALSE(*observed_destroy_);
41 delegate->GetDialogSize(&last_size_);
44 ~TestWebDialogView() override { *observed_destroy_ = true; }
46 void set_should_quit_on_size_change(bool should_quit) {
47 should_quit_on_size_change_ = should_quit;
50 private:
51 // TODO(xiyuan): Update this when WidgetDelegate has bounds change hook.
52 void SaveWindowPlacement(const gfx::Rect& bounds,
53 ui::WindowShowState show_state) override {
54 if (should_quit_on_size_change_ && last_size_ != bounds.size()) {
55 // Schedule message loop quit because we could be called while
56 // the bounds change call is on the stack and not in the nested message
57 // loop.
58 base::MessageLoop::current()->task_runner()->PostTask(
59 FROM_HERE,
60 base::Bind(&base::MessageLoop::Quit,
61 base::Unretained(base::MessageLoop::current())));
64 last_size_ = bounds.size();
67 void OnDialogClosed(const std::string& json_retval) override {
68 should_quit_on_size_change_ = false; // No quit when we are closing.
69 views::WebDialogView::OnDialogClosed(json_retval); // Deletes this.
72 // Whether we should quit message loop when size change is detected.
73 bool should_quit_on_size_change_;
74 gfx::Size last_size_;
75 bool* observed_destroy_;
77 DISALLOW_COPY_AND_ASSIGN(TestWebDialogView);
80 class WebDialogBrowserTest : public InProcessBrowserTest {
81 public:
82 WebDialogBrowserTest() {}
84 // content::BrowserTestBase:
85 void SetUpOnMainThread() override;
87 protected:
88 TestWebDialogView* view_ = nullptr;
89 bool web_dialog_delegate_destroyed_ = false;
90 bool web_dialog_view_destroyed_ = false;
92 private:
93 DISALLOW_COPY_AND_ASSIGN(WebDialogBrowserTest);
96 void WebDialogBrowserTest::SetUpOnMainThread() {
97 ui::test::TestWebDialogDelegate* delegate =
98 new ui::test::TestWebDialogDelegate(GURL(chrome::kChromeUIChromeURLsURL));
99 delegate->set_size(kInitialWidth, kInitialHeight);
100 delegate->SetDeleteOnClosedAndObserve(&web_dialog_delegate_destroyed_);
102 view_ = new TestWebDialogView(browser()->profile(), delegate,
103 &web_dialog_view_destroyed_);
104 gfx::NativeView parent_view =
105 browser()->tab_strip_model()->GetActiveWebContents()->GetNativeView();
106 views::Widget::CreateWindowWithParent(view_, parent_view);
107 view_->GetWidget()->Show();
110 } // namespace
112 // Windows has some issues resizing windows. An off by one problem, and a
113 // minimum size that seems too big. See http://crbug.com/52602.
114 #if defined(OS_WIN)
115 #define MAYBE_SizeWindow DISABLED_SizeWindow
116 #else
117 #define MAYBE_SizeWindow SizeWindow
118 #endif
119 IN_PROC_BROWSER_TEST_F(WebDialogBrowserTest, MAYBE_SizeWindow) {
120 // TestWebDialogView should quit current message loop on size change.
121 view_->set_should_quit_on_size_change(true);
123 gfx::Rect set_bounds = view_->GetWidget()->GetClientAreaBoundsInScreen();
124 gfx::Rect actual_bounds, rwhv_bounds;
126 // Bigger than the default in both dimensions.
127 set_bounds.set_width(400);
128 set_bounds.set_height(300);
130 // WebDialogView ignores the WebContents* |source| argument to MoveContents.
131 // We could pass view_->web_contents(), but it's not relevant for the test.
132 view_->MoveContents(nullptr, set_bounds);
133 content::RunMessageLoop(); // TestWebDialogView will quit.
134 actual_bounds = view_->GetWidget()->GetClientAreaBoundsInScreen();
135 EXPECT_EQ(set_bounds, actual_bounds);
137 rwhv_bounds =
138 view_->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
139 EXPECT_LT(0, rwhv_bounds.width());
140 EXPECT_LT(0, rwhv_bounds.height());
141 EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
142 EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
144 // Larger in one dimension and smaller in the other.
145 set_bounds.set_width(550);
146 set_bounds.set_height(250);
148 view_->MoveContents(nullptr, set_bounds);
149 content::RunMessageLoop(); // TestWebDialogView will quit.
150 actual_bounds = view_->GetWidget()->GetClientAreaBoundsInScreen();
151 EXPECT_EQ(set_bounds, actual_bounds);
153 rwhv_bounds =
154 view_->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
155 EXPECT_LT(0, rwhv_bounds.width());
156 EXPECT_LT(0, rwhv_bounds.height());
157 EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
158 EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
160 // Get very small.
161 const gfx::Size min_size = view_->GetWidget()->GetMinimumSize();
162 EXPECT_LT(0, min_size.width());
163 EXPECT_LT(0, min_size.height());
165 set_bounds.set_size(min_size);
167 view_->MoveContents(nullptr, set_bounds);
168 content::RunMessageLoop(); // TestWebDialogView will quit.
169 actual_bounds = view_->GetWidget()->GetClientAreaBoundsInScreen();
170 EXPECT_EQ(set_bounds, actual_bounds);
172 rwhv_bounds =
173 view_->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
174 EXPECT_LT(0, rwhv_bounds.width());
175 EXPECT_LT(0, rwhv_bounds.height());
176 EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
177 EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
179 // Check to make sure we can't get to 0x0. First expand beyond the minimum
180 // size that was set above so that TestWebDialogView has a change to pick up.
181 set_bounds.set_height(250);
182 view_->MoveContents(nullptr, set_bounds);
183 content::RunMessageLoop(); // TestWebDialogView will quit.
184 actual_bounds = view_->GetWidget()->GetClientAreaBoundsInScreen();
185 EXPECT_EQ(set_bounds, actual_bounds);
187 // Now verify that attempts to re-size to 0x0 enforces the minimum size.
188 set_bounds.set_width(0);
189 set_bounds.set_height(0);
191 view_->MoveContents(nullptr, set_bounds);
192 content::RunMessageLoop(); // TestWebDialogView will quit.
193 actual_bounds = view_->GetWidget()->GetClientAreaBoundsInScreen();
194 EXPECT_EQ(min_size, actual_bounds.size());
196 // And that the render view is also non-zero.
197 rwhv_bounds =
198 view_->web_contents()->GetRenderWidgetHostView()->GetViewBounds();
199 EXPECT_LT(0, rwhv_bounds.width());
200 EXPECT_LT(0, rwhv_bounds.height());
202 // WebDialogView::CanClose() returns true only after before-unload handlers
203 // have run (or the dialog has none and gets fast-closed via
204 // RenderViewHostImpl::ClosePageIgnoringUnloadEvents which is the case here).
205 // Close via WebContents for more authentic coverage (vs Widget::CloseNow()).
206 EXPECT_FALSE(web_dialog_delegate_destroyed_);
207 view_->web_contents()->Close();
208 EXPECT_TRUE(web_dialog_delegate_destroyed_);
210 // The close of the actual widget should happen asynchronously.
211 EXPECT_FALSE(web_dialog_view_destroyed_);
212 content::RunAllPendingInMessageLoop();
213 EXPECT_TRUE(web_dialog_view_destroyed_);
216 // Test that closing the parent of a window-modal web dialog properly destroys
217 // the dialog and delegate.
218 IN_PROC_BROWSER_TEST_F(WebDialogBrowserTest, CloseParentWindow) {
219 // Open a second browser window so we don't trigger shutdown.
220 ui_test_utils::NavigateToURLWithDisposition(
221 browser(), GURL(url::kAboutBlankURL), NEW_WINDOW,
222 ui_test_utils::BROWSER_TEST_NONE);
224 // TestWebDialogDelegate defaults to window-modal, so closing the browser
225 // Window (as opposed to closing merely the tab) should close the dialog.
226 EXPECT_EQ(ui::MODAL_TYPE_WINDOW,
227 view_->GetWidget()->widget_delegate()->GetModalType());
229 // Close the parent window. Tear down may happen asynchronously.
230 EXPECT_FALSE(web_dialog_delegate_destroyed_);
231 EXPECT_FALSE(web_dialog_view_destroyed_);
232 browser()->window()->Close();
233 content::RunAllPendingInMessageLoop();
234 EXPECT_TRUE(web_dialog_delegate_destroyed_);
235 EXPECT_TRUE(web_dialog_view_destroyed_);