// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include "app/l10n_util.h" #include "base/sys_info.h" #include "chrome/browser/app_modal_dialog.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/page_transition_types.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" const std::string BEFORE_UNLOAD_HTML = "beforeunload" "" ""; const std::wstring OPEN_NEW_BEFOREUNLOAD_PAGE = L"w=window.open(); w.onbeforeunload=function(e){return 'foo'};"; namespace { // Given a page title, returns the expected window caption string. std::wstring WindowCaptionFromPageTitle(std::wstring page_title) { #if defined(OS_MACOSX) || defined(OS_CHROMEOS) // On Mac or ChromeOS, we don't want to suffix the page title with // the application name. if (page_title.empty()) return l10n_util::GetString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED); return page_title; #elif defined(OS_WIN) || defined(OS_LINUX) if (page_title.empty()) return l10n_util::GetString(IDS_PRODUCT_NAME); return l10n_util::GetStringF(IDS_BROWSER_WINDOW_TITLE_FORMAT, page_title); #endif } // Returns the number of active RenderProcessHosts. int CountRenderProcessHosts() { int result = 0; for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); !i.IsAtEnd(); i.Advance()) ++result; return result; } } // namespace class BrowserTest : public InProcessBrowserTest { protected: // In RTL locales wrap the page title with RTL embedding characters so that it // matches the value returned by GetWindowTitle(). std::wstring LocaleWindowCaptionFromPageTitle( const std::wstring& expected_title) { std::wstring page_title = WindowCaptionFromPageTitle(expected_title); #if defined(OS_WIN) std::string locale = g_browser_process->GetApplicationLocale(); if (l10n_util::GetTextDirectionForLocale(locale.c_str()) == l10n_util::RIGHT_TO_LEFT) { l10n_util::WrapStringWithLTRFormatting(&page_title); } return page_title; #else // Do we need to use the above code on POSIX as well? return page_title; #endif } }; // Launch the app on a page with no title, check that the app title was set // correctly. IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) { ui_test_utils::NavigateToURL(browser(), ui_test_utils::GetTestUrl(L".", L"title1.html")); EXPECT_EQ(LocaleWindowCaptionFromPageTitle(L"title1.html"), UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab())); string16 tab_title; ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title)); EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title); } // Launch the app, navigate to a page with a title, check that the app title // was set correctly. IN_PROC_BROWSER_TEST_F(BrowserTest, Title) { ui_test_utils::NavigateToURL(browser(), ui_test_utils::GetTestUrl(L".", L"title2.html")); const std::wstring test_title(L"Title Of Awesomeness"); EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title), UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab())); string16 tab_title; ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title)); EXPECT_EQ(WideToUTF16(test_title), tab_title); } #if !defined(OS_MACOSX) // TODO(port): BUG16322 IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) { GURL url(ui_test_utils::GetTestUrl(L".", L"title1.html")); ui_test_utils::NavigateToURL(browser(), url); browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED, true, 0, false, NULL); EXPECT_EQ(2, browser()->tab_count()); EXPECT_EQ(0, browser()->selected_index()); TabContents* second_tab = browser()->GetTabContentsAt(1); ASSERT_TRUE(second_tab); second_tab->render_view_host()->ExecuteJavascriptInWebFrame(L"", L"alert('Activate!');"); AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); alert->CloseModalDialog(); EXPECT_EQ(2, browser()->tab_count()); EXPECT_EQ(1, browser()->selected_index()); } #endif // !defined(OS_MACOSX) // Create 34 tabs and verify that a lot of processes have been created. The // exact number of processes depends on the amount of memory. Previously we // had a hard limit of 31 processes and this test is mainly directed at // verifying that we don't crash when we pass this limit. IN_PROC_BROWSER_TEST_F(BrowserTest, ThirtyFourTabs) { GURL url(ui_test_utils::GetTestUrl(L".", L"title2.html")); // There is one initial tab. for (int ix = 0; ix != 33; ++ix) { browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED, true, 0, false, NULL); } EXPECT_EQ(34, browser()->tab_count()); // See browser\renderer_host\render_process_host.cc for the algorithm to // decide how many processes to create. if (base::SysInfo::AmountOfPhysicalMemoryMB() >= 2048) { EXPECT_GE(CountRenderProcessHosts(), 24); } else { EXPECT_LE(CountRenderProcessHosts(), 23); } } // Test for crbug.com/22004. Reloading a page with a before unload handler and // then canceling the dialog should not leave the throbber spinning. IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) { GURL url("data:text/html," + BEFORE_UNLOAD_HTML); ui_test_utils::NavigateToURL(browser(), url); // Navigate to another page, but click cancel in the dialog. Make sure that // the throbber stops spinning. browser()->Reload(); AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); alert->CloseModalDialog(); EXPECT_FALSE(browser()->GetSelectedTabContents()->is_loading()); // Clear the beforeunload handler so the test can easily exit. browser()->GetSelectedTabContents()->render_view_host()-> ExecuteJavascriptInWebFrame(L"", L"onbeforeunload=null;"); } // Test for crbug.com/11647. A page closed with window.close() should not have // two beforeunload dialogs shown. IN_PROC_BROWSER_TEST_F(BrowserTest, FLAKY_SingleBeforeUnloadAfterWindowClose) { browser()->GetSelectedTabContents()->render_view_host()-> ExecuteJavascriptInWebFrame(L"", OPEN_NEW_BEFOREUNLOAD_PAGE); // Close the new window with JavaScript, which should show a single // beforeunload dialog. Then show another alert, to make it easy to verify // that a second beforeunload dialog isn't shown. browser()->GetTabContentsAt(0)->render_view_host()-> ExecuteJavascriptInWebFrame(L"", L"w.close(); alert('bar');"); AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); alert->AcceptWindow(); alert = ui_test_utils::WaitForAppModalDialog(); EXPECT_FALSE(alert->is_before_unload_dialog()); alert->AcceptWindow(); } // Test that get_process_idle_time() returns reasonable values when compared // with time deltas measured locally. IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) { base::TimeTicks start = base::TimeTicks::Now(); ui_test_utils::NavigateToURL(browser(), ui_test_utils::GetTestUrl(L".", L"title1.html")); RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); for (; !it.IsAtEnd(); it.Advance()) { base::TimeDelta renderer_td = it.GetCurrentValue()->get_child_process_idle_time(); base::TimeDelta browser_td = base::TimeTicks::Now() - start; EXPECT_TRUE(browser_td >= renderer_td); } }