diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-28 16:25:14 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-28 16:25:14 +0000 |
commit | de4943f2cb9c8ce44812b94efa878bfb1c0f5e97 (patch) | |
tree | 95646f1151727c6f6df63df3189ed8b55a7ab8ac /chrome/browser/ui/browser_browsertest.cc | |
parent | 03b2dba54bfbc9cc9cce3ff08f8ca8101d891956 (diff) | |
download | chromium_src-de4943f2cb9c8ce44812b94efa878bfb1c0f5e97.zip chromium_src-de4943f2cb9c8ce44812b94efa878bfb1c0f5e97.tar.gz chromium_src-de4943f2cb9c8ce44812b94efa878bfb1c0f5e97.tar.bz2 |
Attempt 2 at:
Adds a test to make sure Chrome doesn't crash on startup when
configure to open maximized. Also, I'm making OnWidgetMove a little
less error prone.
BUG=89843
TEST=none
R=pkasting@chromium.org
TBR=pkasting@chromium.org
Review URL: http://codereview.chromium.org/7514044
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94476 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui/browser_browsertest.cc')
-rw-r--r-- | chrome/browser/ui/browser_browsertest.cc | 871 |
1 files changed, 871 insertions, 0 deletions
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc new file mode 100644 index 0000000..0b20a83 --- /dev/null +++ b/chrome/browser/ui/browser_browsertest.cc @@ -0,0 +1,871 @@ +// Copyright (c) 2011 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 <string> + +#include "base/compiler_specific.h" +#include "base/file_path.h" +#include "base/sys_info.h" +#include "base/utf_string_conversions.h" +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/defaults.h" +#include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_tab_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/tabs/pinned_tab_codec.h" +#include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/translate/translate_tab_helper.h" +#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h" +#include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h" +#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_init.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" +#include "chrome/common/chrome_notification_types.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" +#include "content/browser/renderer_host/render_process_host.h" +#include "content/browser/renderer_host/render_view_host.h" +#include "content/browser/tab_contents/tab_contents.h" +#include "content/common/notification_source.h" +#include "content/common/page_transition_types.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "net/base/mock_host_resolver.h" +#include "net/test/test_server.h" +#include "ui/base/l10n/l10n_util.h" + +#if defined(OS_WIN) +#include "base/i18n/rtl.h" +#include "chrome/browser/browser_process.h" +#endif + +namespace { + +const char* kBeforeUnloadHTML = + "<html><head><title>beforeunload</title></head><body>" + "<script>window.onbeforeunload=function(e){return 'foo'}</script>" + "</body></html>"; + +const char* kOpenNewBeforeUnloadPage = + "w=window.open(); w.onbeforeunload=function(e){return 'foo'};"; + +const FilePath::CharType* kBeforeUnloadFile = + FILE_PATH_LITERAL("beforeunload.html"); + +const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html"); +const FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html"); + +const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data"); + +// 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 UTF16ToWideHack( + l10n_util::GetStringUTF16(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED)); + } + return page_title; +#else + if (page_title.empty()) + return UTF16ToWideHack(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); + + return UTF16ToWideHack( + l10n_util::GetStringFUTF16(IDS_BROWSER_WINDOW_TITLE_FORMAT, + WideToUTF16Hack(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; +} + +class MockTabStripModelObserver : public TabStripModelObserver { + public: + MockTabStripModelObserver() : closing_count_(0) {} + + virtual void TabClosingAt(TabStripModel* tab_strip_model, + TabContentsWrapper* contents, + int index) { + closing_count_++; + } + + int closing_count() const { return closing_count_; } + + private: + int closing_count_; + + DISALLOW_COPY_AND_ASSIGN(MockTabStripModelObserver); +}; + +// Used by CloseWithAppMenuOpen. Invokes CloseWindow on the supplied browser. +class CloseWindowTask : public Task { + public: + explicit CloseWindowTask(Browser* browser) : browser_(browser) {} + + virtual void Run() { + browser_->CloseWindow(); + } + + private: + Browser* browser_; + + DISALLOW_COPY_AND_ASSIGN(CloseWindowTask); +}; + +// Used by CloseWithAppMenuOpen. Posts a CloseWindowTask and shows the app menu. +class RunCloseWithAppMenuTask : public Task { + public: + explicit RunCloseWithAppMenuTask(Browser* browser) : browser_(browser) {} + + virtual void Run() { + // ShowAppMenu is modal under views. Schedule a task that closes the window. + MessageLoop::current()->PostTask(FROM_HERE, new CloseWindowTask(browser_)); + browser_->ShowAppMenu(); + } + + private: + Browser* browser_; + + DISALLOW_COPY_AND_ASSIGN(RunCloseWithAppMenuTask); +}; + +} // namespace + +class BrowserTest : public ExtensionBrowserTest { + 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 (base::i18n::GetTextDirectionForLocale(locale.c_str()) == + base::i18n::RIGHT_TO_LEFT) { + base::i18n::WrapStringWithLTRFormatting(&page_title); + } + + return page_title; +#else + // Do we need to use the above code on POSIX as well? + return page_title; +#endif + } + + // Returns the app extension aptly named "App Test". + const Extension* GetExtension() { + const ExtensionList* extensions = + browser()->profile()->GetExtensionService()->extensions(); + for (size_t i = 0; i < extensions->size(); ++i) { + if ((*extensions)[i]->name() == "App Test") + return (*extensions)[i]; + } + NOTREACHED(); + return NULL; + } +}; + +// 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(FilePath(FilePath::kCurrentDirectory), + FilePath(kTitle1File))); + 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(FilePath(FilePath::kCurrentDirectory), + FilePath(kTitle2File))); + 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); +} + +IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) { + GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), + FilePath(kTitle1File))); + ui_test_utils::NavigateToURL(browser(), url); + AddTabAtIndex(0, url, PageTransition::TYPED); + EXPECT_EQ(2, browser()->tab_count()); + EXPECT_EQ(0, browser()->active_index()); + TabContents* second_tab = browser()->GetTabContentsAt(1); + ASSERT_TRUE(second_tab); + second_tab->render_view_host()->ExecuteJavascriptInWebFrame( + string16(), + ASCIIToUTF16("alert('Activate!');")); + AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); + alert->CloseModalDialog(); + EXPECT_EQ(2, browser()->tab_count()); + EXPECT_EQ(1, browser()->active_index()); +} + + + +#if defined(OS_WIN) +// http://crbug.com/75274. On XP crashes inside +// URLFetcher::Core::Registry::RemoveURLFetcherCore. +#define MAYBE_ThirtyFourTabs FLAKY_ThirtyFourTabs +#else +#define MAYBE_ThirtyFourTabs ThirtyFourTabs +#endif + +// 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. +// Warning: this test can take >30 seconds when running on a slow (low +// memory?) Mac builder. +IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_ThirtyFourTabs) { + GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), + FilePath(kTitle2File))); + + // There is one initial tab. + for (int ix = 0; ix != 33; ++ix) + browser()->AddSelectedTabWithURL(url, PageTransition::TYPED); + 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(std::string("data:text/html,") + kBeforeUnloadHTML); + 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(CURRENT_TAB); + AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); + alert->CloseModalDialog(); + EXPECT_FALSE(browser()->GetSelectedTabContents()->IsLoading()); + + // Clear the beforeunload handler so the test can easily exit. + browser()->GetSelectedTabContents()->render_view_host()-> + ExecuteJavascriptInWebFrame(string16(), + ASCIIToUTF16("onbeforeunload=null;")); +} + +// Test for crbug.com/80401. Canceling a before unload dialog should reset +// the URL to the previous page's URL. +IN_PROC_BROWSER_TEST_F(BrowserTest, CancelBeforeUnloadResetsURL) { + GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), + FilePath(kBeforeUnloadFile))); + ui_test_utils::NavigateToURL(browser(), url); + + // Navigate to a page that triggers a cross-site transition. + ASSERT_TRUE(test_server()->Start()); + GURL url2(test_server()->GetURL("files/title1.html")); + browser()->OpenURL(url2, GURL(), CURRENT_TAB, PageTransition::TYPED); + + // Cancel the dialog. + AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); + alert->CloseModalDialog(); + EXPECT_FALSE(browser()->GetSelectedTabContents()->IsLoading()); + + // Wait for the ShouldClose_ACK to arrive. We can detect it by waiting for + // the pending RVH to be destroyed. + ui_test_utils::WaitForNotification( + content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED); + EXPECT_EQ(url.spec(), WideToUTF8(browser()->toolbar_model()->GetText())); + + // Clear the beforeunload handler so the test can easily exit. + browser()->GetSelectedTabContents()->render_view_host()-> + ExecuteJavascriptInWebFrame(string16(), + ASCIIToUTF16("onbeforeunload=null;")); +} + +// Crashy on mac. http://crbug.com/38522 +#if defined(OS_MACOSX) +#define MAYBE_SingleBeforeUnloadAfterWindowClose \ + DISABLED_SingleBeforeUnloadAfterWindowClose +#else +#define MAYBE_SingleBeforeUnloadAfterWindowClose \ + SingleBeforeUnloadAfterWindowClose +#endif + +// Test for crbug.com/11647. A page closed with window.close() should not have +// two beforeunload dialogs shown. +IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_SingleBeforeUnloadAfterWindowClose) { + browser()->GetSelectedTabContents()->render_view_host()-> + ExecuteJavascriptInWebFrame(string16(), + ASCIIToUTF16(kOpenNewBeforeUnloadPage)); + + // 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(string16(), + ASCIIToUTF16("w.close(); alert('bar');")); + AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); + alert->native_dialog()->AcceptAppModalDialog(); + + alert = ui_test_utils::WaitForAppModalDialog(); + EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)-> + is_before_unload_dialog()); + alert->native_dialog()->AcceptAppModalDialog(); +} + +// 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(FilePath(FilePath::kCurrentDirectory), + FilePath(kTitle1File))); + 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); + } +} + +// Test IDC_CREATE_SHORTCUTS command is enabled for url scheme file, ftp, http +// and https and disabled for chrome://, about:// etc. +// TODO(pinkerton): Disable app-mode in the model until we implement it +// on the Mac. http://crbug.com/13148 +#if !defined(OS_MACOSX) +IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFile) { + CommandUpdater* command_updater = browser()->command_updater(); + + static const FilePath::CharType* kEmptyFile = FILE_PATH_LITERAL("empty.html"); + GURL file_url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), + FilePath(kEmptyFile))); + ASSERT_TRUE(file_url.SchemeIs(chrome::kFileScheme)); + ui_test_utils::NavigateToURL(browser(), file_url); + EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); +} + +IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttp) { + CommandUpdater* command_updater = browser()->command_updater(); + + ASSERT_TRUE(test_server()->Start()); + GURL http_url(test_server()->GetURL("")); + ASSERT_TRUE(http_url.SchemeIs(chrome::kHttpScheme)); + ui_test_utils::NavigateToURL(browser(), http_url); + EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); +} + +IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttps) { + CommandUpdater* command_updater = browser()->command_updater(); + + net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath(kDocRoot)); + ASSERT_TRUE(test_server.Start()); + GURL https_url(test_server.GetURL("/")); + ASSERT_TRUE(https_url.SchemeIs(chrome::kHttpsScheme)); + ui_test_utils::NavigateToURL(browser(), https_url); + EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); +} + +IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFtp) { + CommandUpdater* command_updater = browser()->command_updater(); + + net::TestServer test_server(net::TestServer::TYPE_FTP, FilePath(kDocRoot)); + ASSERT_TRUE(test_server.Start()); + GURL ftp_url(test_server.GetURL("")); + ASSERT_TRUE(ftp_url.SchemeIs(chrome::kFtpScheme)); + ui_test_utils::NavigateToURL(browser(), ftp_url); + EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); +} + +IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutInvalid) { + CommandUpdater* command_updater = browser()->command_updater(); + + // Urls that should not have shortcuts. + GURL new_tab_url(chrome::kChromeUINewTabURL); + ui_test_utils::NavigateToURL(browser(), new_tab_url); + EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); + + GURL history_url(chrome::kChromeUIHistoryURL); + ui_test_utils::NavigateToURL(browser(), history_url); + EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); + + GURL downloads_url(chrome::kChromeUIDownloadsURL); + ui_test_utils::NavigateToURL(browser(), downloads_url); + EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); + + GURL blank_url(chrome::kAboutBlankURL); + ui_test_utils::NavigateToURL(browser(), blank_url); + EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); +} + +// Change a tab into an application window. +// DISABLED: http://crbug.com/72310 +IN_PROC_BROWSER_TEST_F(BrowserTest, DISABLED_ConvertTabToAppShortcut) { + ASSERT_TRUE(test_server()->Start()); + GURL http_url(test_server()->GetURL("")); + ASSERT_TRUE(http_url.SchemeIs(chrome::kHttpScheme)); + + ASSERT_EQ(1, browser()->tab_count()); + TabContents* initial_tab = browser()->GetTabContentsAt(0); + TabContents* app_tab = browser()->AddSelectedTabWithURL( + http_url, PageTransition::TYPED)->tab_contents(); + ASSERT_EQ(2, browser()->tab_count()); + ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile())); + + // Normal tabs should accept load drops. + EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops); + EXPECT_TRUE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops); + + // Turn |app_tab| into a tab in an app panel. + browser()->ConvertContentsToApplication(app_tab); + + // The launch should have created a new browser. + ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); + + // Find the new browser. + Browser* app_browser = NULL; + for (BrowserList::const_iterator i = BrowserList::begin(); + i != BrowserList::end() && !app_browser; ++i) { + if (*i != browser()) + app_browser = *i; + } + ASSERT_TRUE(app_browser); + + // Check that the tab contents is in the new browser, and not in the old. + ASSERT_EQ(1, browser()->tab_count()); + ASSERT_EQ(initial_tab, browser()->GetTabContentsAt(0)); + + // Check that the appliaction browser has a single tab, and that tab contains + // the content that we app-ified. + ASSERT_EQ(1, app_browser->tab_count()); + ASSERT_EQ(app_tab, app_browser->GetTabContentsAt(0)); + + // Normal tabs should accept load drops. + EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops); + + // The tab in an app window should not. + EXPECT_FALSE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops); +} + +#endif // !defined(OS_MACOSX) + +// Test RenderView correctly send back favicon url for web page that redirects +// to an anchor in javascript body.onload handler. +IN_PROC_BROWSER_TEST_F(BrowserTest, + DISABLED_FaviconOfOnloadRedirectToAnchorPage) { + ASSERT_TRUE(test_server()->Start()); + GURL url(test_server()->GetURL("files/onload_redirect_to_anchor.html")); + GURL expected_favicon_url(test_server()->GetURL("files/test.png")); + + ui_test_utils::NavigateToURL(browser(), url); + + NavigationEntry* entry = browser()->GetSelectedTabContents()-> + controller().GetActiveEntry(); + EXPECT_EQ(expected_favicon_url.spec(), entry->favicon().url().spec()); +} + +#if defined(OS_MACOSX) || defined(OS_LINUX) +// http://crbug.com/83828. On Mac 10.6, the failure rate is 14% +#define MAYBE_FaviconChange FLAKY_FaviconChange +#else +#define MAYBE_FaviconChange FaviconChange +#endif +// Test that an icon can be changed from JS. +IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_FaviconChange) { + static const FilePath::CharType* kFile = + FILE_PATH_LITERAL("onload_change_favicon.html"); + GURL file_url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), + FilePath(kFile))); + ASSERT_TRUE(file_url.SchemeIs(chrome::kFileScheme)); + ui_test_utils::NavigateToURL(browser(), file_url); + + NavigationEntry* entry = browser()->GetSelectedTabContents()-> + controller().GetActiveEntry(); + static const FilePath::CharType* kIcon = + FILE_PATH_LITERAL("test1.png"); + GURL expected_favicon_url( + ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), + FilePath(kIcon))); + EXPECT_EQ(expected_favicon_url.spec(), entry->favicon().url().spec()); +} + +// Makes sure TabClosing is sent when uninstalling an extension that is an app +// tab. +IN_PROC_BROWSER_TEST_F(BrowserTest, TabClosingWhenRemovingExtension) { + ASSERT_TRUE(test_server()->Start()); + host_resolver()->AddRule("www.example.com", "127.0.0.1"); + GURL url(test_server()->GetURL("empty.html")); + TabStripModel* model = browser()->tabstrip_model(); + + ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); + + const Extension* extension_app = GetExtension(); + + ui_test_utils::NavigateToURL(browser(), url); + + TabContentsWrapper* app_contents = + Browser::TabContentsFactory(browser()->profile(), NULL, + MSG_ROUTING_NONE, NULL, NULL); + app_contents->extension_tab_helper()->SetExtensionApp(extension_app); + + model->AddTabContents(app_contents, 0, 0, TabStripModel::ADD_NONE); + model->SetTabPinned(0, true); + ui_test_utils::NavigateToURL(browser(), url); + + MockTabStripModelObserver observer; + model->AddObserver(&observer); + + // Uninstall the extension and make sure TabClosing is sent. + ExtensionService* service = browser()->profile()->GetExtensionService(); + service->UninstallExtension(GetExtension()->id(), false, NULL); + EXPECT_EQ(1, observer.closing_count()); + + model->RemoveObserver(&observer); + + // There should only be one tab now. + ASSERT_EQ(1, browser()->tab_count()); +} + +#if !defined(OS_MACOSX) +// Open with --app-id=<id>, and see that an app window opens. +IN_PROC_BROWSER_TEST_F(BrowserTest, AppIdSwitch) { + ASSERT_TRUE(test_server()->Start()); + + // Load an app. + host_resolver()->AddRule("www.example.com", "127.0.0.1"); + ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); + const Extension* extension_app = GetExtension(); + + CommandLine command_line(CommandLine::NO_PROGRAM); + command_line.AppendSwitchASCII(switches::kAppId, extension_app->id()); + + BrowserInit::LaunchWithProfile launch(FilePath(), command_line); + ASSERT_TRUE(launch.OpenApplicationWindow(browser()->profile())); + + // Check that the new browser has an app name. + // The launch should have created a new browser. + ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); + + // Find the new browser. + Browser* new_browser = NULL; + for (BrowserList::const_iterator i = BrowserList::begin(); + i != BrowserList::end() && !new_browser; ++i) { + if (*i != browser()) + new_browser = *i; + } + ASSERT_TRUE(new_browser); + ASSERT_TRUE(new_browser != browser()); + + // The browser's app_name should include the app's ID. + ASSERT_NE( + new_browser->app_name_.find(extension_app->id()), + std::string::npos) << new_browser->app_name_; +} +#endif + +#if defined(OS_WIN) || defined(OS_MACOSX) +// http://crbug.com/46198: On XP/Vista, the failure rate is 5 ~ 6%. +// On OS 10.5 it's 1%, 10.6 currently 4%. +#define MAYBE_PageLanguageDetection FLAKY_PageLanguageDetection +#else +#define MAYBE_PageLanguageDetection PageLanguageDetection +#endif +// Tests that the CLD (Compact Language Detection) works properly. +IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_PageLanguageDetection) { + ASSERT_TRUE(test_server()->Start()); + + std::string lang; + + // Open a new tab with a page in English. + AddTabAtIndex(0, GURL(test_server()->GetURL("files/english_page.html")), + PageTransition::TYPED); + + TabContents* current_tab = browser()->GetSelectedTabContents(); + TabContentsWrapper* wrapper = browser()->GetSelectedTabContentsWrapper(); + TranslateTabHelper* helper = wrapper->translate_tab_helper(); + Source<TabContents> source(current_tab); + + ui_test_utils::WindowedNotificationObserverWithDetails<std::string> + en_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, + source); + EXPECT_EQ("", helper->language_state().original_language()); + en_language_detected_signal.Wait(); + EXPECT_TRUE(en_language_detected_signal.GetDetailsFor( + source.map_key(), &lang)); + EXPECT_EQ("en", lang); + EXPECT_EQ("en", helper->language_state().original_language()); + + // Now navigate to a page in French. + ui_test_utils::WindowedNotificationObserverWithDetails<std::string> + fr_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, + source); + ui_test_utils::NavigateToURL( + browser(), GURL(test_server()->GetURL("files/french_page.html"))); + fr_language_detected_signal.Wait(); + lang.clear(); + EXPECT_TRUE(fr_language_detected_signal.GetDetailsFor( + source.map_key(), &lang)); + EXPECT_EQ("fr", lang); + EXPECT_EQ("fr", helper->language_state().original_language()); +} + +// Chromeos defaults to restoring the last session, so this test isn't +// applicable. +#if !defined(OS_CHROMEOS) +#if defined(OS_MACOSX) +// Crashy, http://crbug.com/38522 +#define RestorePinnedTabs DISABLED_RestorePinnedTabs +#endif +// Makes sure pinned tabs are restored correctly on start. +IN_PROC_BROWSER_TEST_F(BrowserTest, RestorePinnedTabs) { + ASSERT_TRUE(test_server()->Start()); + + // Add an pinned app tab. + host_resolver()->AddRule("www.example.com", "127.0.0.1"); + GURL url(test_server()->GetURL("empty.html")); + TabStripModel* model = browser()->tabstrip_model(); + ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); + const Extension* extension_app = GetExtension(); + ui_test_utils::NavigateToURL(browser(), url); + TabContentsWrapper* app_contents = + Browser::TabContentsFactory(browser()->profile(), NULL, + MSG_ROUTING_NONE, NULL, NULL); + app_contents->extension_tab_helper()->SetExtensionApp(extension_app); + model->AddTabContents(app_contents, 0, 0, TabStripModel::ADD_NONE); + model->SetTabPinned(0, true); + ui_test_utils::NavigateToURL(browser(), url); + + // Add a non pinned tab. + browser()->NewTab(); + + // Add a pinned non-app tab. + browser()->NewTab(); + ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); + model->SetTabPinned(2, true); + + // Write out the pinned tabs. + PinnedTabCodec::WritePinnedTabs(browser()->profile()); + + // Simulate launching again. + CommandLine dummy(CommandLine::NO_PROGRAM); + BrowserInit::LaunchWithProfile launch(FilePath(), dummy); + launch.profile_ = browser()->profile(); + launch.ProcessStartupURLs(std::vector<GURL>()); + + // The launch should have created a new browser. + ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); + + // Find the new browser. + Browser* new_browser = NULL; + for (BrowserList::const_iterator i = BrowserList::begin(); + i != BrowserList::end() && !new_browser; ++i) { + if (*i != browser()) + new_browser = *i; + } + ASSERT_TRUE(new_browser); + ASSERT_TRUE(new_browser != browser()); + + // We should get back an additional tab for the app, and another for the + // default home page. + ASSERT_EQ(3, new_browser->tab_count()); + + // Make sure the state matches. + TabStripModel* new_model = new_browser->tabstrip_model(); + EXPECT_TRUE(new_model->IsAppTab(0)); + EXPECT_FALSE(new_model->IsAppTab(1)); + EXPECT_FALSE(new_model->IsAppTab(2)); + + EXPECT_TRUE(new_model->IsTabPinned(0)); + EXPECT_TRUE(new_model->IsTabPinned(1)); + EXPECT_FALSE(new_model->IsTabPinned(2)); + + EXPECT_EQ(browser()->GetHomePage(), + new_model->GetTabContentsAt(2)->tab_contents()->GetURL()); + + EXPECT_TRUE( + new_model->GetTabContentsAt(0)->extension_tab_helper()->extension_app() == + extension_app); +} +#endif // !defined(OS_CHROMEOS) + +// This test verifies we don't crash when closing the last window and the app +// menu is showing. +IN_PROC_BROWSER_TEST_F(BrowserTest, CloseWithAppMenuOpen) { + if (browser_defaults::kBrowserAliveWithNoWindows) + return; + + // We need a message loop running for menus on windows. + MessageLoop::current()->PostTask(FROM_HERE, + new RunCloseWithAppMenuTask(browser())); +} + +#if !defined(OS_MACOSX) +IN_PROC_BROWSER_TEST_F(BrowserTest, OpenAppWindowLikeNtp) { + ASSERT_TRUE(test_server()->Start()); + + // Load an app + host_resolver()->AddRule("www.example.com", "127.0.0.1"); + ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); + const Extension* extension_app = GetExtension(); + + // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would. + TabContents* app_window = + Browser::OpenApplication(browser()->profile(), + extension_app, + extension_misc::LAUNCH_WINDOW, + NEW_WINDOW); + ASSERT_TRUE(app_window); + + // Apps launched in a window from the NTP do not have extension_app set in + // tab contents. + TabContentsWrapper* wrapper = + TabContentsWrapper::GetCurrentWrapperForContents(app_window); + EXPECT_FALSE(wrapper->extension_tab_helper()->extension_app()); + EXPECT_EQ(extension_app->GetFullLaunchURL(), app_window->GetURL()); + + // The launch should have created a new browser. + ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); + + // Find the new browser. + Browser* new_browser = NULL; + for (BrowserList::const_iterator i = BrowserList::begin(); + i != BrowserList::end() && !new_browser; ++i) { + if (*i != browser()) + new_browser = *i; + } + ASSERT_TRUE(new_browser); + ASSERT_TRUE(new_browser != browser()); + + EXPECT_TRUE(new_browser->is_app()); + + // The browser's app name should include the extension's id. + std::string app_name = new_browser->app_name_; + EXPECT_NE(app_name.find(extension_app->id()), std::string::npos) + << "Name " << app_name << " should contain id "<< extension_app->id(); +} +#endif // !defined(OS_MACOSX) + +// Makes sure the browser doesn't crash when +// set_maximized_state(MAXIMIZED_STATE_MAXIMIZED) has been invoked. +IN_PROC_BROWSER_TEST_F(BrowserTest, StartMaximized) { + // Can't test TYPE_PANEL as they are currently created differently (and can't + // end up maximized). + Browser::Type types[] = { Browser::TYPE_TABBED, Browser::TYPE_POPUP }; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(types); ++i) { + Browser* max_browser = new Browser(types[i], browser()->profile()); + max_browser->set_maximized_state(Browser::MAXIMIZED_STATE_MAXIMIZED); + max_browser->InitBrowserWindow(); + AddBlankTabAndShow(max_browser); + } +} + +// TODO(ben): this test was never enabled. It has bit-rotted since being added. +// It originally lived in browser_unittest.cc, but has been moved here to make +// room for real browser unit tests. +#if 0 +class BrowserTest2 : public InProcessBrowserTest { + public: + BrowserTest2() { + host_resolver_proc_ = new net::RuleBasedHostResolverProc(NULL); + // Avoid making external DNS lookups. In this test we don't need this + // to succeed. + host_resolver_proc_->AddSimulatedFailure("*.google.com"); + scoped_host_resolver_proc_.Init(host_resolver_proc_.get()); + } + + private: + scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc_; + net::ScopedDefaultHostResolverProc scoped_host_resolver_proc_; +}; + +IN_PROC_BROWSER_TEST_F(BrowserTest2, NoTabsInPopups) { + Browser::RegisterAppPrefs(L"Test"); + + // We start with a normal browser with one tab. + EXPECT_EQ(1, browser()->tab_count()); + + // Open a popup browser with a single blank foreground tab. + Browser* popup_browser = browser()->CreateForType(Browser::TYPE_POPUP, + browser()->profile()); + popup_browser->AddBlankTab(true); + EXPECT_EQ(1, popup_browser->tab_count()); + + // Now try opening another tab in the popup browser. + AddTabWithURLParams params1(url, PageTransition::TYPED); + popup_browser->AddTabWithURL(¶ms1); + EXPECT_EQ(popup_browser, params1.target); + + // The popup should still only have one tab. + EXPECT_EQ(1, popup_browser->tab_count()); + + // The normal browser should now have two. + EXPECT_EQ(2, browser()->tab_count()); + + // Open an app frame browser with a single blank foreground tab. + Browser* app_browser = + browser()->CreateForApp(L"Test", browser()->profile(), false); + app_browser->AddBlankTab(true); + EXPECT_EQ(1, app_browser->tab_count()); + + // Now try opening another tab in the app browser. + AddTabWithURLParams params2(GURL(chrome::kAboutBlankURL), + PageTransition::TYPED); + app_browser->AddTabWithURL(¶ms2); + EXPECT_EQ(app_browser, params2.target); + + // The popup should still only have one tab. + EXPECT_EQ(1, app_browser->tab_count()); + + // The normal browser should now have three. + EXPECT_EQ(3, browser()->tab_count()); + + // Open an app frame popup browser with a single blank foreground tab. + Browser* app_popup_browser = + browser()->CreateForApp(L"Test", browser()->profile(), false); + app_popup_browser->AddBlankTab(true); + EXPECT_EQ(1, app_popup_browser->tab_count()); + + // Now try opening another tab in the app popup browser. + AddTabWithURLParams params3(GURL(chrome::kAboutBlankURL), + PageTransition::TYPED); + app_popup_browser->AddTabWithURL(¶ms3); + EXPECT_EQ(app_popup_browser, params3.target); + + // The popup should still only have one tab. + EXPECT_EQ(1, app_popup_browser->tab_count()); + + // The normal browser should now have four. + EXPECT_EQ(4, browser()->tab_count()); + + // Close the additional browsers. + popup_browser->CloseAllTabs(); + app_browser->CloseAllTabs(); + app_popup_browser->CloseAllTabs(); +} +#endif |