browser_uitest.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2006-2008 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 "base/base_paths.h" 6#include "base/file_path.h" 7#include "base/file_util.h" 8#include "base/path_service.h" 9#include "base/string_util.h" 10#include "base/sys_info.h" 11#include "base/test/test_file_util.h" 12#include "base/values.h" 13#include "chrome/app/chrome_command_ids.h" 14#include "chrome/browser/platform_util.h" 15#include "chrome/browser/ui/browser.h" 16#include "chrome/common/chrome_switches.h" 17#include "chrome/common/chrome_constants.h" 18#include "chrome/common/pref_names.h" 19#include "chrome/test/automation/browser_proxy.h" 20#include "chrome/test/automation/tab_proxy.h" 21#include "chrome/test/automation/window_proxy.h" 22#include "chrome/test/ui/ui_test.h" 23#include "gfx/native_widget_types.h" 24#include "grit/chromium_strings.h" 25#include "grit/generated_resources.h" 26#include "net/base/net_util.h" 27#include "net/test/test_server.h" 28 29namespace { 30 31class BrowserTest : public UITest { 32}; 33 34class VisibleBrowserTest : public UITest { 35 protected: 36 VisibleBrowserTest() : UITest() { 37 show_window_ = true; 38 } 39}; 40 41#if defined(OS_WIN) 42// The browser should quit quickly if it receives a WM_ENDSESSION message. 43TEST_F(BrowserTest, WindowsSessionEnd) { 44#elif defined(OS_POSIX) 45// The browser should quit gracefully and quickly if it receives a SIGTERM. 46TEST_F(BrowserTest, PosixSessionEnd) { 47#endif 48 FilePath test_file(test_data_directory_); 49 test_file = test_file.AppendASCII("title1.html"); 50 51 NavigateToURL(net::FilePathToFileURL(test_file)); 52 TerminateBrowser(); 53 ASSERT_FALSE(IsBrowserRunning()); 54 55 // Make sure the UMA metrics say we didn't crash. 56 scoped_ptr<DictionaryValue> local_prefs(GetLocalState()); 57 bool exited_cleanly; 58 ASSERT_TRUE(local_prefs.get()); 59 ASSERT_TRUE(local_prefs->GetBoolean(prefs::kStabilityExitedCleanly, 60 &exited_cleanly)); 61 ASSERT_TRUE(exited_cleanly); 62 63 // And that session end was successful. 64 bool session_end_completed; 65 ASSERT_TRUE(local_prefs->GetBoolean(prefs::kStabilitySessionEndCompleted, 66 &session_end_completed)); 67 ASSERT_TRUE(session_end_completed); 68 69 // Make sure session restore says we didn't crash. 70 scoped_ptr<DictionaryValue> profile_prefs(GetDefaultProfilePreferences()); 71 ASSERT_TRUE(profile_prefs.get()); 72 ASSERT_TRUE(profile_prefs->GetBoolean(prefs::kSessionExitedCleanly, 73 &exited_cleanly)); 74 ASSERT_TRUE(exited_cleanly); 75} 76 77// Test that scripts can fork a new renderer process for a tab in a particular 78// case (which matches following a link in Gmail). The script must open a new 79// tab, set its window.opener to null, and redirect it to a cross-site URL. 80// (Bug 1115708) 81// This test can only run if V8 is in use, and not KJS, because KJS will not 82// set window.opener to null properly. 83#ifdef CHROME_V8 84TEST_F(BrowserTest, NullOpenerRedirectForksProcess) { 85 // This test only works in multi-process mode 86 if (ProxyLauncher::in_process_renderer()) 87 return; 88 89 net::TestServer test_server(net::TestServer::TYPE_HTTP, 90 FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 91 ASSERT_TRUE(test_server.Start()); 92 93 FilePath test_file(test_data_directory_); 94 scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); 95 ASSERT_TRUE(window.get()); 96 scoped_refptr<TabProxy> tab(window->GetActiveTab()); 97 ASSERT_TRUE(tab.get()); 98 99 // Start with a file:// url 100 test_file = test_file.AppendASCII("title2.html"); 101 tab->NavigateToURL(net::FilePathToFileURL(test_file)); 102 int orig_tab_count = -1; 103 ASSERT_TRUE(window->GetTabCount(&orig_tab_count)); 104 int orig_process_count = GetBrowserProcessCount(); 105 ASSERT_GE(orig_process_count, 1); 106 107 // Use JavaScript URL to "fork" a new tab, just like Gmail. (Open tab to a 108 // blank page, set its opener to null, and redirect it cross-site.) 109 std::wstring url_prefix(L"javascript:(function(){w=window.open();"); 110 GURL fork_url(url_prefix + 111 L"w.opener=null;w.document.location=\"http://localhost:1337\";})()"); 112 113 // Make sure that a new tab has been created and that we have a new renderer 114 // process for it. 115 ASSERT_TRUE(tab->NavigateToURLAsync(fork_url)); 116 PlatformThread::Sleep(sleep_timeout_ms()); 117 ASSERT_EQ(orig_process_count + 1, GetBrowserProcessCount()); 118 int new_tab_count = -1; 119 ASSERT_TRUE(window->GetTabCount(&new_tab_count)); 120 ASSERT_EQ(orig_tab_count + 1, new_tab_count); 121} 122#endif // CHROME_V8 123 124// This test fails on ChromeOS (it has never been known to work on it). 125// Currently flaky on Windows - it has crashed a couple of times. 126// http://crbug.com/32799 127#if defined(OS_CHROMEOS) 128#define MAYBE_OtherRedirectsDontForkProcess DISABLED_OtherRedirectsDontForkProcess 129#else 130#define MAYBE_OtherRedirectsDontForkProcess FLAKY_OtherRedirectsDontForkProcess 131#endif 132 133// Tests that non-Gmail-like script redirects (i.e., non-null window.opener) or 134// a same-page-redirect) will not fork a new process. 135TEST_F(BrowserTest, MAYBE_OtherRedirectsDontForkProcess) { 136 // This test only works in multi-process mode 137 if (ProxyLauncher::in_process_renderer()) 138 return; 139 140 net::TestServer test_server(net::TestServer::TYPE_HTTP, 141 FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 142 ASSERT_TRUE(test_server.Start()); 143 144 FilePath test_file(test_data_directory_); 145 scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0)); 146 ASSERT_TRUE(window.get()); 147 scoped_refptr<TabProxy> tab(window->GetActiveTab()); 148 ASSERT_TRUE(tab.get()); 149 150 // Start with a file:// url 151 test_file = test_file.AppendASCII("title2.html"); 152 ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, 153 tab->NavigateToURL(net::FilePathToFileURL(test_file))); 154 int orig_tab_count = -1; 155 ASSERT_TRUE(window->GetTabCount(&orig_tab_count)); 156 int orig_process_count = GetBrowserProcessCount(); 157 ASSERT_GE(orig_process_count, 1); 158 159 // Use JavaScript URL to almost fork a new tab, but not quite. (Leave the 160 // opener non-null.) Should not fork a process. 161 std::string url_str = "javascript:(function(){w=window.open(); "; 162 url_str += "w.document.location=\""; 163 url_str += test_server.GetURL("").spec(); 164 url_str += "\";})()"; 165 GURL dont_fork_url(url_str); 166 167 // Make sure that a new tab but not new process has been created. 168 ASSERT_TRUE(tab->NavigateToURLAsync(dont_fork_url)); 169 base::PlatformThread::Sleep(sleep_timeout_ms()); 170 ASSERT_EQ(orig_process_count, GetBrowserProcessCount()); 171 int new_tab_count = -1; 172 ASSERT_TRUE(window->GetTabCount(&new_tab_count)); 173 ASSERT_EQ(orig_tab_count + 1, new_tab_count); 174 175 // Same thing if the current tab tries to redirect itself. 176 url_str = "javascript:(function(){w=window.open(); "; 177 url_str += "document.location=\""; 178 url_str += test_server.GetURL("").spec(); 179 url_str += "\";})()"; 180 GURL dont_fork_url2(url_str); 181 182 // Make sure that no new process has been created. 183 ASSERT_TRUE(tab->NavigateToURLAsync(dont_fork_url2)); 184 base::PlatformThread::Sleep(sleep_timeout_ms()); 185 ASSERT_EQ(orig_process_count, GetBrowserProcessCount()); 186} 187 188TEST_F(VisibleBrowserTest, WindowOpenClose) { 189 FilePath test_file(test_data_directory_); 190 test_file = test_file.AppendASCII("window.close.html"); 191 192 NavigateToURLBlockUntilNavigationsComplete( 193 net::FilePathToFileURL(test_file), 2); 194 EXPECT_EQ(L"Title Of Awesomeness", GetActiveTabTitle()); 195} 196 197class ShowModalDialogTest : public UITest { 198 public: 199 ShowModalDialogTest() { 200 launch_arguments_.AppendSwitch(switches::kDisablePopupBlocking); 201 } 202}; 203 204// Flakiness returned. Re-opened crbug.com/17806 205TEST_F(ShowModalDialogTest, FLAKY_BasicTest) { 206 FilePath test_file(test_data_directory_); 207 test_file = test_file.AppendASCII("showmodaldialog.html"); 208 209 // This navigation should show a modal dialog that will be immediately 210 // closed, but the fact that it was shown should be recorded. 211 NavigateToURL(net::FilePathToFileURL(test_file)); 212 213 // At this point the modal dialog should not be showing. 214 int window_count = 0; 215 EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count)); 216 EXPECT_EQ(1, window_count); 217 218 // Verify that we set a mark on successful dialog show. 219 scoped_refptr<BrowserProxy> browser = automation()->GetBrowserWindow(0); 220 ASSERT_TRUE(browser.get()); 221 scoped_refptr<TabProxy> tab = browser->GetActiveTab(); 222 ASSERT_TRUE(tab.get()); 223 std::wstring title; 224 ASSERT_TRUE(tab->GetTabTitle(&title)); 225 ASSERT_EQ(L"SUCCESS", title); 226} 227 228class SecurityTest : public UITest { 229}; 230 231TEST_F(SecurityTest, DisallowFileUrlUniversalAccessTest) { 232 scoped_refptr<TabProxy> tab(GetActiveTab()); 233 ASSERT_TRUE(tab.get()); 234 235 FilePath test_file(test_data_directory_); 236 test_file = test_file.AppendASCII("fileurl_universalaccess.html"); 237 238 GURL url = net::FilePathToFileURL(test_file); 239 ASSERT_TRUE(tab->NavigateToURL(url)); 240 241 std::string value = WaitUntilCookieNonEmpty(tab.get(), url, 242 "status", action_max_timeout_ms()); 243 ASSERT_STREQ("Disallowed", value.c_str()); 244} 245 246#if !defined(OS_MACOSX) 247class KioskModeTest : public UITest { 248 public: 249 KioskModeTest() { 250 launch_arguments_.AppendSwitch(switches::kKioskMode); 251 } 252}; 253 254TEST_F(KioskModeTest, EnableKioskModeTest) { 255 // Load a local file. 256 FilePath test_file(test_data_directory_); 257 test_file = test_file.AppendASCII("title1.html"); 258 259 // Verify that the window is present. 260 scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); 261 ASSERT_TRUE(browser.get()); 262 263 // Check if browser is in fullscreen mode. 264 bool is_visible; 265 ASSERT_TRUE(browser->IsFullscreen(&is_visible)); 266 EXPECT_TRUE(is_visible); 267 ASSERT_TRUE(browser->IsFullscreenBubbleVisible(&is_visible)); 268 EXPECT_FALSE(is_visible); 269} 270#endif // !defined(OS_MACOSX) 271 272#if defined(OS_WIN) 273// This test verifies that Chrome can be launched with a user-data-dir path 274// which contains non ASCII characters. 275class LaunchBrowserWithNonAsciiUserDatadir : public UITest { 276public: 277 void SetUp() { 278 PathService::Get(base::DIR_TEMP, &tmp_profile_); 279 tmp_profile_ = tmp_profile_.AppendASCII("tmp_profile"); 280 tmp_profile_ = tmp_profile_.Append(L"Test Chrome G�raldine"); 281 282 // Create a fresh, empty copy of this directory. 283 file_util::Delete(tmp_profile_, true); 284 file_util::CreateDirectory(tmp_profile_); 285 286 launch_arguments_.AppendSwitchPath(switches::kUserDataDir, tmp_profile_); 287 } 288 289 bool LaunchAppWithProfile() { 290 UITest::SetUp(); 291 return true; 292 } 293 294 void TearDown() { 295 UITest::TearDown(); 296 EXPECT_TRUE(file_util::DieFileDie(tmp_profile_, true)); 297 } 298 299public: 300 FilePath tmp_profile_; 301}; 302 303TEST_F(LaunchBrowserWithNonAsciiUserDatadir, TestNonAsciiUserDataDir) { 304 ASSERT_TRUE(LaunchAppWithProfile()); 305 // Verify that the window is present. 306 scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); 307 ASSERT_TRUE(browser.get()); 308} 309#endif // defined(OS_WIN) 310 311class AppModeTest : public UITest { 312 public: 313 AppModeTest() { 314 // Load a local file. 315 FilePath test_file(test_data_directory_); 316 test_file = test_file.AppendASCII("title1.html"); 317 GURL test_file_url(net::FilePathToFileURL(test_file)); 318 319 launch_arguments_.AppendSwitchASCII(switches::kApp, test_file_url.spec()); 320 } 321}; 322 323TEST_F(AppModeTest, EnableAppModeTest) { 324 // Test that an application browser window loads correctly. 325 326 // Verify that the window is present. 327 scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); 328 ASSERT_TRUE(browser.get()); 329 330 // Verify the browser is an application. 331 Browser::Type type; 332 ASSERT_TRUE(browser->GetType(&type)); 333 EXPECT_EQ(Browser::TYPE_APP, type); 334} 335 336// Tests to ensure that the browser continues running in the background after 337// the last window closes. 338class RunInBackgroundTest : public UITest { 339 public: 340 RunInBackgroundTest() { 341 launch_arguments_.AppendSwitch(switches::kKeepAliveForTest); 342 } 343}; 344 345TEST_F(RunInBackgroundTest, RunInBackgroundBasicTest) { 346 // Close the browser window, then open a new one - the browser should keep 347 // running. 348 scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); 349 ASSERT_TRUE(browser.get()); 350 int window_count; 351 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count)); 352 EXPECT_EQ(1, window_count); 353 ASSERT_TRUE(browser->RunCommand(IDC_CLOSE_WINDOW)); 354 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count)); 355 EXPECT_EQ(0, window_count); 356 ASSERT_TRUE(IsBrowserRunning()); 357 ASSERT_TRUE(automation()->OpenNewBrowserWindow(Browser::TYPE_NORMAL, true)); 358 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count)); 359 EXPECT_EQ(1, window_count); 360} 361 362// Tests to ensure that the browser continues running in the background after 363// the last window closes. 364class NoStartupWindowTest : public UITest { 365 public: 366 NoStartupWindowTest() { 367 launch_arguments_.AppendSwitch(switches::kNoStartupWindow); 368 launch_arguments_.AppendSwitch(switches::kKeepAliveForTest); 369 } 370}; 371 372TEST_F(NoStartupWindowTest, NoStartupWindowBasicTest) { 373 // No browser window should be started by default. 374 int window_count; 375 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count)); 376 EXPECT_EQ(0, window_count); 377 378 // Starting a browser window should work just fine. 379 ASSERT_TRUE(IsBrowserRunning()); 380 ASSERT_TRUE(automation()->OpenNewBrowserWindow(Browser::TYPE_NORMAL, true)); 381 ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count)); 382 EXPECT_EQ(1, window_count); 383} 384 385} // namespace 386