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