1 // Copyright (c) 2011 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. 4 5 #include "chrome/test/ui/ui_test.h" 6 7 #include "base/file_path.h" 8 #include "base/memory/singleton.h" 9 #include "base/message_loop.h" 10 #include "chrome/browser/ui/views/html_dialog_view.h" 11 #include "chrome/browser/ui/webui/html_dialog_ui.h" 12 #include "chrome/common/url_constants.h" 13 #include "chrome/test/in_process_browser_test.h" 14 #include "chrome/test/ui_test_utils.h" 15 #include "content/browser/renderer_host/render_widget_host_view.h" 16 #include "content/browser/tab_contents/tab_contents.h" 17 #include "testing/gmock/include/gmock/gmock.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 #include "views/widget/widget.h" 20 #include "views/window/window.h" 21 22 using testing::Eq; 23 24 namespace { 25 26 // Window non-client-area means that the minimum size for the window 27 // won't be the actual minimum size - our layout and resizing code 28 // makes sure the chrome is always visible. 29 const int kMinimumWidthToTestFor = 20; 30 const int kMinimumHeightToTestFor = 30; 31 32 class TestHtmlDialogUIDelegate : public HtmlDialogUIDelegate { 33 public: 34 TestHtmlDialogUIDelegate() {} 35 virtual ~TestHtmlDialogUIDelegate() {} 36 37 // HTMLDialogUIDelegate implementation: 38 virtual bool IsDialogModal() const { 39 return true; 40 } 41 virtual std::wstring GetDialogTitle() const { 42 return std::wstring(L"Test"); 43 } 44 virtual GURL GetDialogContentURL() const { 45 return GURL(chrome::kAboutBlankURL); 46 } 47 virtual void GetWebUIMessageHandlers( 48 std::vector<WebUIMessageHandler*>* handlers) const { } 49 virtual void GetDialogSize(gfx::Size* size) const { 50 size->set_width(40); 51 size->set_height(40); 52 } 53 virtual std::string GetDialogArgs() const { 54 return std::string(); 55 } 56 virtual void OnDialogClosed(const std::string& json_retval) { } 57 virtual void OnCloseContents(TabContents* source, bool* out_close_dialog) { 58 if (out_close_dialog) 59 *out_close_dialog = true; 60 } 61 virtual bool ShouldShowDialogTitle() const { return true; } 62 }; 63 64 } // namespace 65 66 class HtmlDialogBrowserTest : public InProcessBrowserTest { 67 public: 68 HtmlDialogBrowserTest() {} 69 70 #if defined(OS_WIN) 71 class WindowChangedObserver : public base::MessagePumpForUI::Observer { 72 public: 73 WindowChangedObserver() {} 74 75 static WindowChangedObserver* GetInstance() { 76 return Singleton<WindowChangedObserver>::get(); 77 } 78 79 // This method is called before processing a message. 80 virtual void WillProcessMessage(const MSG& msg) {} 81 82 // This method is called after processing a message. 83 virtual void DidProcessMessage(const MSG& msg) { 84 // Either WM_PAINT or WM_TIMER indicates the actual work of 85 // pushing through the window resizing messages is done since 86 // they are lower priority (we don't get to see the 87 // WM_WINDOWPOSCHANGED message here). 88 if (msg.message == WM_PAINT || msg.message == WM_TIMER) 89 MessageLoop::current()->Quit(); 90 } 91 }; 92 #elif !defined(OS_MACOSX) 93 class WindowChangedObserver : public base::MessagePumpForUI::Observer { 94 public: 95 WindowChangedObserver() {} 96 97 static WindowChangedObserver* GetInstance() { 98 return Singleton<WindowChangedObserver>::get(); 99 } 100 101 // This method is called before processing a message. 102 virtual void WillProcessEvent(GdkEvent* event) {} 103 104 // This method is called after processing a message. 105 virtual void DidProcessEvent(GdkEvent* event) { 106 // Quit once the GDK_CONFIGURE event has been processed - seeing 107 // this means the window sizing request that was made actually 108 // happened. 109 if (event->type == GDK_CONFIGURE) 110 MessageLoop::current()->Quit(); 111 } 112 }; 113 #endif 114 }; 115 116 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 117 #define MAYBE_SizeWindow SizeWindow 118 #else 119 // http://code.google.com/p/chromium/issues/detail?id=52602 120 // Windows has some issues resizing windows- an off by one problem, 121 // and a minimum size that seems too big. This file isn't included in 122 // Mac builds yet. On Chrome OS, this test doesn't apply since ChromeOS 123 // doesn't allow resizing of windows. 124 #define MAYBE_SizeWindow DISABLED_SizeWindow 125 #endif 126 127 IN_PROC_BROWSER_TEST_F(HtmlDialogBrowserTest, MAYBE_SizeWindow) { 128 HtmlDialogUIDelegate* delegate = new TestHtmlDialogUIDelegate(); 129 130 HtmlDialogView* html_view = 131 new HtmlDialogView(browser()->profile(), delegate); 132 TabContents* tab_contents = browser()->GetSelectedTabContents(); 133 ASSERT_TRUE(tab_contents != NULL); 134 views::Window::CreateChromeWindow(tab_contents->GetMessageBoxRootWindow(), 135 gfx::Rect(), html_view); 136 html_view->InitDialog(); 137 html_view->window()->Show(); 138 139 MessageLoopForUI::current()->AddObserver( 140 WindowChangedObserver::GetInstance()); 141 142 gfx::Rect bounds = html_view->GetWidget()->GetClientAreaScreenBounds(); 143 144 gfx::Rect set_bounds = bounds; 145 gfx::Rect actual_bounds, rwhv_bounds; 146 147 // Bigger than the default in both dimensions. 148 set_bounds.set_width(400); 149 set_bounds.set_height(300); 150 151 html_view->MoveContents(tab_contents, set_bounds); 152 ui_test_utils::RunMessageLoop(); 153 actual_bounds = html_view->GetWidget()->GetClientAreaScreenBounds(); 154 EXPECT_EQ(set_bounds, actual_bounds); 155 156 rwhv_bounds = 157 html_view->tab_contents()->GetRenderWidgetHostView()->GetViewBounds(); 158 EXPECT_LT(0, rwhv_bounds.width()); 159 EXPECT_LT(0, rwhv_bounds.height()); 160 EXPECT_GE(set_bounds.width(), rwhv_bounds.width()); 161 EXPECT_GE(set_bounds.height(), rwhv_bounds.height()); 162 163 // Larger in one dimension and smaller in the other. 164 set_bounds.set_width(550); 165 set_bounds.set_height(250); 166 167 html_view->MoveContents(tab_contents, set_bounds); 168 ui_test_utils::RunMessageLoop(); 169 actual_bounds = html_view->GetWidget()->GetClientAreaScreenBounds(); 170 EXPECT_EQ(set_bounds, actual_bounds); 171 172 rwhv_bounds = 173 html_view->tab_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()); 178 179 // Get very small. 180 set_bounds.set_width(kMinimumWidthToTestFor); 181 set_bounds.set_height(kMinimumHeightToTestFor); 182 183 html_view->MoveContents(tab_contents, set_bounds); 184 ui_test_utils::RunMessageLoop(); 185 actual_bounds = html_view->GetWidget()->GetClientAreaScreenBounds(); 186 EXPECT_EQ(set_bounds, actual_bounds); 187 188 rwhv_bounds = 189 html_view->tab_contents()->GetRenderWidgetHostView()->GetViewBounds(); 190 EXPECT_LT(0, rwhv_bounds.width()); 191 EXPECT_LT(0, rwhv_bounds.height()); 192 EXPECT_GE(set_bounds.width(), rwhv_bounds.width()); 193 EXPECT_GE(set_bounds.height(), rwhv_bounds.height()); 194 195 // Check to make sure we can't get to 0x0 196 set_bounds.set_width(0); 197 set_bounds.set_height(0); 198 199 html_view->MoveContents(tab_contents, set_bounds); 200 ui_test_utils::RunMessageLoop(); 201 actual_bounds = html_view->GetWidget()->GetClientAreaScreenBounds(); 202 EXPECT_LT(0, actual_bounds.width()); 203 EXPECT_LT(0, actual_bounds.height()); 204 205 MessageLoopForUI::current()->RemoveObserver( 206 WindowChangedObserver::GetInstance()); 207 } 208