browser_browsertest.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
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 <string> 6 7#include "base/compiler_specific.h" 8#include "base/file_path.h" 9#include "base/sys_info.h" 10#include "base/utf_string_conversions.h" 11#include "chrome/app/chrome_command_ids.h" 12#include "chrome/browser/defaults.h" 13#include "chrome/browser/extensions/extension_browsertest.h" 14#include "chrome/browser/extensions/extension_service.h" 15#include "chrome/browser/profiles/profile.h" 16#include "chrome/browser/renderer_host/render_process_host.h" 17#include "chrome/browser/renderer_host/render_view_host.h" 18#include "chrome/browser/tab_contents/tab_contents.h" 19#include "chrome/browser/tabs/pinned_tab_codec.h" 20#include "chrome/browser/tabs/tab_strip_model.h" 21#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h" 22#include "chrome/browser/ui/app_modal_dialogs/js_modal_dialog.h" 23#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" 24#include "chrome/browser/ui/browser.h" 25#include "chrome/browser/ui/browser_init.h" 26#include "chrome/browser/ui/browser_list.h" 27#include "chrome/browser/ui/browser_navigator.h" 28#include "chrome/browser/ui/browser_window.h" 29#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 30#include "chrome/common/chrome_switches.h" 31#include "chrome/common/extensions/extension.h" 32#include "chrome/common/notification_source.h" 33#include "chrome/common/page_transition_types.h" 34#include "chrome/common/url_constants.h" 35#include "chrome/test/in_process_browser_test.h" 36#include "chrome/test/ui_test_utils.h" 37#include "grit/chromium_strings.h" 38#include "grit/generated_resources.h" 39#include "net/base/mock_host_resolver.h" 40#include "net/test/test_server.h" 41#include "ui/base/l10n/l10n_util.h" 42 43#if defined(OS_WIN) 44#include "base/i18n/rtl.h" 45#include "chrome/browser/browser_process.h" 46#endif 47 48namespace { 49 50const char* kBeforeUnloadHTML = 51 "<html><head><title>beforeunload</title></head><body>" 52 "<script>window.onbeforeunload=function(e){return 'foo'}</script>" 53 "</body></html>"; 54 55const char* kOpenNewBeforeUnloadPage = 56 "w=window.open(); w.onbeforeunload=function(e){return 'foo'};"; 57 58const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html"); 59const FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html"); 60 61const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data"); 62 63// Given a page title, returns the expected window caption string. 64std::wstring WindowCaptionFromPageTitle(std::wstring page_title) { 65#if defined(OS_MACOSX) || defined(OS_CHROMEOS) 66 // On Mac or ChromeOS, we don't want to suffix the page title with 67 // the application name. 68 if (page_title.empty()) { 69 return UTF16ToWideHack( 70 l10n_util::GetStringUTF16(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED)); 71 } 72 return page_title; 73#else 74 if (page_title.empty()) 75 return UTF16ToWideHack(l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 76 77 return UTF16ToWideHack( 78 l10n_util::GetStringFUTF16(IDS_BROWSER_WINDOW_TITLE_FORMAT, 79 WideToUTF16Hack(page_title))); 80#endif 81} 82 83// Returns the number of active RenderProcessHosts. 84int CountRenderProcessHosts() { 85 int result = 0; 86 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); 87 !i.IsAtEnd(); i.Advance()) 88 ++result; 89 return result; 90} 91 92class MockTabStripModelObserver : public TabStripModelObserver { 93 public: 94 MockTabStripModelObserver() : closing_count_(0) {} 95 96 virtual void TabClosingAt(TabStripModel* tab_strip_model, 97 TabContentsWrapper* contents, 98 int index) { 99 closing_count_++; 100 } 101 102 int closing_count() const { return closing_count_; } 103 104 private: 105 int closing_count_; 106 107 DISALLOW_COPY_AND_ASSIGN(MockTabStripModelObserver); 108}; 109 110// Used by CloseWithAppMenuOpen. Invokes CloseWindow on the supplied browser. 111class CloseWindowTask : public Task { 112 public: 113 explicit CloseWindowTask(Browser* browser) : browser_(browser) {} 114 115 virtual void Run() { 116 browser_->CloseWindow(); 117 } 118 119 private: 120 Browser* browser_; 121 122 DISALLOW_COPY_AND_ASSIGN(CloseWindowTask); 123}; 124 125// Used by CloseWithAppMenuOpen. Posts a CloseWindowTask and shows the app menu. 126class RunCloseWithAppMenuTask : public Task { 127 public: 128 explicit RunCloseWithAppMenuTask(Browser* browser) : browser_(browser) {} 129 130 virtual void Run() { 131 // ShowAppMenu is modal under views. Schedule a task that closes the window. 132 MessageLoop::current()->PostTask(FROM_HERE, new CloseWindowTask(browser_)); 133 browser_->ShowAppMenu(); 134 } 135 136 private: 137 Browser* browser_; 138 139 DISALLOW_COPY_AND_ASSIGN(RunCloseWithAppMenuTask); 140}; 141 142} // namespace 143 144class BrowserTest : public ExtensionBrowserTest { 145 protected: 146 // In RTL locales wrap the page title with RTL embedding characters so that it 147 // matches the value returned by GetWindowTitle(). 148 std::wstring LocaleWindowCaptionFromPageTitle( 149 const std::wstring& expected_title) { 150 std::wstring page_title = WindowCaptionFromPageTitle(expected_title); 151#if defined(OS_WIN) 152 std::string locale = g_browser_process->GetApplicationLocale(); 153 if (base::i18n::GetTextDirectionForLocale(locale.c_str()) == 154 base::i18n::RIGHT_TO_LEFT) { 155 base::i18n::WrapStringWithLTRFormatting(&page_title); 156 } 157 158 return page_title; 159#else 160 // Do we need to use the above code on POSIX as well? 161 return page_title; 162#endif 163 } 164 165 // Returns the app extension aptly named "App Test". 166 const Extension* GetExtension() { 167 const ExtensionList* extensions = 168 browser()->profile()->GetExtensionService()->extensions(); 169 for (size_t i = 0; i < extensions->size(); ++i) { 170 if ((*extensions)[i]->name() == "App Test") 171 return (*extensions)[i]; 172 } 173 NOTREACHED(); 174 return NULL; 175 } 176}; 177 178// Launch the app on a page with no title, check that the app title was set 179// correctly. 180IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) { 181 ui_test_utils::NavigateToURL(browser(), 182 ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 183 FilePath(kTitle1File))); 184 EXPECT_EQ(LocaleWindowCaptionFromPageTitle(L"title1.html"), 185 UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab())); 186 string16 tab_title; 187 ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title)); 188 EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title); 189} 190 191// Launch the app, navigate to a page with a title, check that the app title 192// was set correctly. 193IN_PROC_BROWSER_TEST_F(BrowserTest, Title) { 194 ui_test_utils::NavigateToURL(browser(), 195 ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 196 FilePath(kTitle2File))); 197 const std::wstring test_title(L"Title Of Awesomeness"); 198 EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title), 199 UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab())); 200 string16 tab_title; 201 ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title)); 202 EXPECT_EQ(WideToUTF16(test_title), tab_title); 203} 204 205IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) { 206 GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 207 FilePath(kTitle1File))); 208 ui_test_utils::NavigateToURL(browser(), url); 209 AddTabAtIndex(0, url, PageTransition::TYPED); 210 EXPECT_EQ(2, browser()->tab_count()); 211 EXPECT_EQ(0, browser()->selected_index()); 212 TabContents* second_tab = browser()->GetTabContentsAt(1); 213 ASSERT_TRUE(second_tab); 214 second_tab->render_view_host()->ExecuteJavascriptInWebFrame( 215 string16(), 216 ASCIIToUTF16("alert('Activate!');")); 217 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 218 alert->CloseModalDialog(); 219 EXPECT_EQ(2, browser()->tab_count()); 220 EXPECT_EQ(1, browser()->selected_index()); 221} 222 223// Create 34 tabs and verify that a lot of processes have been created. The 224// exact number of processes depends on the amount of memory. Previously we 225// had a hard limit of 31 processes and this test is mainly directed at 226// verifying that we don't crash when we pass this limit. 227// Warning: this test can take >30 seconds when running on a slow (low 228// memory?) Mac builder. 229IN_PROC_BROWSER_TEST_F(BrowserTest, ThirtyFourTabs) { 230 GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 231 FilePath(kTitle2File))); 232 233 // There is one initial tab. 234 for (int ix = 0; ix != 33; ++ix) 235 browser()->AddSelectedTabWithURL(url, PageTransition::TYPED); 236 EXPECT_EQ(34, browser()->tab_count()); 237 238 // See browser\renderer_host\render_process_host.cc for the algorithm to 239 // decide how many processes to create. 240 if (base::SysInfo::AmountOfPhysicalMemoryMB() >= 2048) { 241 EXPECT_GE(CountRenderProcessHosts(), 24); 242 } else { 243 EXPECT_LE(CountRenderProcessHosts(), 23); 244 } 245} 246 247// Test for crbug.com/22004. Reloading a page with a before unload handler and 248// then canceling the dialog should not leave the throbber spinning. 249IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) { 250 GURL url(std::string("data:text/html,") + kBeforeUnloadHTML); 251 ui_test_utils::NavigateToURL(browser(), url); 252 253 // Navigate to another page, but click cancel in the dialog. Make sure that 254 // the throbber stops spinning. 255 browser()->Reload(CURRENT_TAB); 256 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 257 alert->CloseModalDialog(); 258 EXPECT_FALSE(browser()->GetSelectedTabContents()->is_loading()); 259 260 // Clear the beforeunload handler so the test can easily exit. 261 browser()->GetSelectedTabContents()->render_view_host()-> 262 ExecuteJavascriptInWebFrame(string16(), 263 ASCIIToUTF16("onbeforeunload=null;")); 264} 265 266// Crashy on mac. http://crbug.com/38522 267#if defined(OS_MACOSX) 268#define MAYBE_SingleBeforeUnloadAfterWindowClose \ 269 DISABLED_SingleBeforeUnloadAfterWindowClose 270#else 271#define MAYBE_SingleBeforeUnloadAfterWindowClose \ 272 SingleBeforeUnloadAfterWindowClose 273#endif 274 275// Test for crbug.com/11647. A page closed with window.close() should not have 276// two beforeunload dialogs shown. 277IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_SingleBeforeUnloadAfterWindowClose) { 278 browser()->GetSelectedTabContents()->render_view_host()-> 279 ExecuteJavascriptInWebFrame(string16(), 280 ASCIIToUTF16(kOpenNewBeforeUnloadPage)); 281 282 // Close the new window with JavaScript, which should show a single 283 // beforeunload dialog. Then show another alert, to make it easy to verify 284 // that a second beforeunload dialog isn't shown. 285 browser()->GetTabContentsAt(0)->render_view_host()-> 286 ExecuteJavascriptInWebFrame(string16(), 287 ASCIIToUTF16("w.close(); alert('bar');")); 288 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 289 alert->native_dialog()->AcceptAppModalDialog(); 290 291 alert = ui_test_utils::WaitForAppModalDialog(); 292 EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)-> 293 is_before_unload_dialog()); 294 alert->native_dialog()->AcceptAppModalDialog(); 295} 296 297// Test that get_process_idle_time() returns reasonable values when compared 298// with time deltas measured locally. 299IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) { 300 base::TimeTicks start = base::TimeTicks::Now(); 301 ui_test_utils::NavigateToURL(browser(), 302 ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 303 FilePath(kTitle1File))); 304 RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); 305 for (; !it.IsAtEnd(); it.Advance()) { 306 base::TimeDelta renderer_td = 307 it.GetCurrentValue()->get_child_process_idle_time(); 308 base::TimeDelta browser_td = base::TimeTicks::Now() - start; 309 EXPECT_TRUE(browser_td >= renderer_td); 310 } 311} 312 313// Test IDC_CREATE_SHORTCUTS command is enabled for url scheme file, ftp, http 314// and https and disabled for chrome://, about:// etc. 315// TODO(pinkerton): Disable app-mode in the model until we implement it 316// on the Mac. http://crbug.com/13148 317#if !defined(OS_MACOSX) 318IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFile) { 319 CommandUpdater* command_updater = browser()->command_updater(); 320 321 static const FilePath::CharType* kEmptyFile = FILE_PATH_LITERAL("empty.html"); 322 GURL file_url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 323 FilePath(kEmptyFile))); 324 ASSERT_TRUE(file_url.SchemeIs(chrome::kFileScheme)); 325 ui_test_utils::NavigateToURL(browser(), file_url); 326 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 327} 328 329IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttp) { 330 CommandUpdater* command_updater = browser()->command_updater(); 331 332 ASSERT_TRUE(test_server()->Start()); 333 GURL http_url(test_server()->GetURL("")); 334 ASSERT_TRUE(http_url.SchemeIs(chrome::kHttpScheme)); 335 ui_test_utils::NavigateToURL(browser(), http_url); 336 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 337} 338 339IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttps) { 340 CommandUpdater* command_updater = browser()->command_updater(); 341 342 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath(kDocRoot)); 343 ASSERT_TRUE(test_server.Start()); 344 GURL https_url(test_server.GetURL("/")); 345 ASSERT_TRUE(https_url.SchemeIs(chrome::kHttpsScheme)); 346 ui_test_utils::NavigateToURL(browser(), https_url); 347 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 348} 349 350IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFtp) { 351 CommandUpdater* command_updater = browser()->command_updater(); 352 353 net::TestServer test_server(net::TestServer::TYPE_FTP, FilePath(kDocRoot)); 354 ASSERT_TRUE(test_server.Start()); 355 GURL ftp_url(test_server.GetURL("")); 356 ASSERT_TRUE(ftp_url.SchemeIs(chrome::kFtpScheme)); 357 ui_test_utils::NavigateToURL(browser(), ftp_url); 358 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 359} 360 361IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutInvalid) { 362 CommandUpdater* command_updater = browser()->command_updater(); 363 364 // Urls that should not have shortcuts. 365 GURL new_tab_url(chrome::kChromeUINewTabURL); 366 ui_test_utils::NavigateToURL(browser(), new_tab_url); 367 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 368 369 GURL history_url(chrome::kChromeUIHistoryURL); 370 ui_test_utils::NavigateToURL(browser(), history_url); 371 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 372 373 GURL downloads_url(chrome::kChromeUIDownloadsURL); 374 ui_test_utils::NavigateToURL(browser(), downloads_url); 375 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 376 377 GURL blank_url(chrome::kAboutBlankURL); 378 ui_test_utils::NavigateToURL(browser(), blank_url); 379 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 380} 381 382// Change a tab into an application window. 383// DISABLED: http://crbug.com/72310 384IN_PROC_BROWSER_TEST_F(BrowserTest, DISABLED_ConvertTabToAppShortcut) { 385 ASSERT_TRUE(test_server()->Start()); 386 GURL http_url(test_server()->GetURL("")); 387 ASSERT_TRUE(http_url.SchemeIs(chrome::kHttpScheme)); 388 389 ASSERT_EQ(1, browser()->tab_count()); 390 TabContents* initial_tab = browser()->GetTabContentsAt(0); 391 TabContents* app_tab = browser()->AddSelectedTabWithURL( 392 http_url, PageTransition::TYPED)->tab_contents(); 393 ASSERT_EQ(2, browser()->tab_count()); 394 ASSERT_EQ(1u, BrowserList::GetBrowserCount(browser()->profile())); 395 396 // Normal tabs should accept load drops. 397 EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops); 398 EXPECT_TRUE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops); 399 400 // Turn |app_tab| into a tab in an app panel. 401 browser()->ConvertContentsToApplication(app_tab); 402 403 // The launch should have created a new browser. 404 ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); 405 406 // Find the new browser. 407 Browser* app_browser = NULL; 408 for (BrowserList::const_iterator i = BrowserList::begin(); 409 i != BrowserList::end() && !app_browser; ++i) { 410 if (*i != browser()) 411 app_browser = *i; 412 } 413 ASSERT_TRUE(app_browser); 414 415 // Check that the tab contents is in the new browser, and not in the old. 416 ASSERT_EQ(1, browser()->tab_count()); 417 ASSERT_EQ(initial_tab, browser()->GetTabContentsAt(0)); 418 419 // Check that the appliaction browser has a single tab, and that tab contains 420 // the content that we app-ified. 421 ASSERT_EQ(1, app_browser->tab_count()); 422 ASSERT_EQ(app_tab, app_browser->GetTabContentsAt(0)); 423 424 // Normal tabs should accept load drops. 425 EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops); 426 427 // The tab in an app window should not. 428 EXPECT_FALSE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops); 429} 430 431#endif // !defined(OS_MACOSX) 432 433// Test RenderView correctly send back favicon url for web page that redirects 434// to an anchor in javascript body.onload handler. 435IN_PROC_BROWSER_TEST_F(BrowserTest, FaviconOfOnloadRedirectToAnchorPage) { 436 ASSERT_TRUE(test_server()->Start()); 437 GURL url(test_server()->GetURL("files/onload_redirect_to_anchor.html")); 438 GURL expected_favicon_url(test_server()->GetURL("files/test.png")); 439 440 ui_test_utils::NavigateToURL(browser(), url); 441 442 NavigationEntry* entry = browser()->GetSelectedTabContents()-> 443 controller().GetActiveEntry(); 444 EXPECT_EQ(expected_favicon_url.spec(), entry->favicon().url().spec()); 445} 446 447// Test that an icon can be changed from JS. 448IN_PROC_BROWSER_TEST_F(BrowserTest, FaviconChange) { 449 static const FilePath::CharType* kFile = 450 FILE_PATH_LITERAL("onload_change_favicon.html"); 451 GURL file_url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 452 FilePath(kFile))); 453 ASSERT_TRUE(file_url.SchemeIs(chrome::kFileScheme)); 454 ui_test_utils::NavigateToURL(browser(), file_url); 455 456 NavigationEntry* entry = browser()->GetSelectedTabContents()-> 457 controller().GetActiveEntry(); 458 static const FilePath::CharType* kIcon = 459 FILE_PATH_LITERAL("test1.png"); 460 GURL expected_favicon_url( 461 ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 462 FilePath(kIcon))); 463 EXPECT_EQ(expected_favicon_url.spec(), entry->favicon().url().spec()); 464} 465 466// Makes sure TabClosing is sent when uninstalling an extension that is an app 467// tab. 468IN_PROC_BROWSER_TEST_F(BrowserTest, TabClosingWhenRemovingExtension) { 469 ASSERT_TRUE(test_server()->Start()); 470 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 471 GURL url(test_server()->GetURL("empty.html")); 472 TabStripModel* model = browser()->tabstrip_model(); 473 474 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 475 476 const Extension* extension_app = GetExtension(); 477 478 ui_test_utils::NavigateToURL(browser(), url); 479 480 TabContentsWrapper* app_contents = 481 Browser::TabContentsFactory(browser()->profile(), NULL, 482 MSG_ROUTING_NONE, NULL, NULL); 483 app_contents->tab_contents()->SetExtensionApp(extension_app); 484 485 model->AddTabContents(app_contents, 0, 0, TabStripModel::ADD_NONE); 486 model->SetTabPinned(0, true); 487 ui_test_utils::NavigateToURL(browser(), url); 488 489 MockTabStripModelObserver observer; 490 model->AddObserver(&observer); 491 492 // Uninstall the extension and make sure TabClosing is sent. 493 ExtensionService* service = browser()->profile()->GetExtensionService(); 494 service->UninstallExtension(GetExtension()->id(), false); 495 EXPECT_EQ(1, observer.closing_count()); 496 497 model->RemoveObserver(&observer); 498 499 // There should only be one tab now. 500 ASSERT_EQ(1, browser()->tab_count()); 501} 502 503#if !defined(OS_MACOSX) 504// Open with --app-id=<id>, and see that an app window opens. 505IN_PROC_BROWSER_TEST_F(BrowserTest, AppIdSwitch) { 506 ASSERT_TRUE(test_server()->Start()); 507 508 // Load an app. 509 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 510 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 511 const Extension* extension_app = GetExtension(); 512 513 CommandLine command_line(CommandLine::NO_PROGRAM); 514 command_line.AppendSwitchASCII(switches::kAppId, extension_app->id()); 515 516 BrowserInit::LaunchWithProfile launch(FilePath(), command_line); 517 ASSERT_TRUE(launch.OpenApplicationWindow(browser()->profile())); 518 519 // Check that the new browser has an app name. 520 // The launch should have created a new browser. 521 ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); 522 523 // Find the new browser. 524 Browser* new_browser = NULL; 525 for (BrowserList::const_iterator i = BrowserList::begin(); 526 i != BrowserList::end() && !new_browser; ++i) { 527 if (*i != browser()) 528 new_browser = *i; 529 } 530 ASSERT_TRUE(new_browser); 531 ASSERT_TRUE(new_browser != browser()); 532 533 // The browser's app_name should include the app's ID. 534 ASSERT_NE( 535 new_browser->app_name_.find(extension_app->id()), 536 std::string::npos) << new_browser->app_name_; 537 538} 539#endif 540 541#if defined(OS_WIN) 542// http://crbug.com/46198. On XP/Vista, the failure rate is 5 ~ 6%. 543#define MAYBE_PageLanguageDetection FLAKY_PageLanguageDetection 544#else 545#define MAYBE_PageLanguageDetection PageLanguageDetection 546#endif 547// Tests that the CLD (Compact Language Detection) works properly. 548IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_PageLanguageDetection) { 549 ASSERT_TRUE(test_server()->Start()); 550 551 TabContents* current_tab = browser()->GetSelectedTabContents(); 552 Source<TabContents> source(current_tab); 553 554 // Navigate to a page in English. 555 ui_test_utils::WindowedNotificationObserverWithDetails<std::string> 556 en_language_detected_signal(NotificationType::TAB_LANGUAGE_DETERMINED, 557 source); 558 ui_test_utils::NavigateToURL( 559 browser(), GURL(test_server()->GetURL("files/english_page.html"))); 560 EXPECT_TRUE(current_tab->language_state().original_language().empty()); 561 en_language_detected_signal.Wait(); 562 std::string lang; 563 EXPECT_TRUE(en_language_detected_signal.GetDetailsFor( 564 source.map_key(), &lang)); 565 EXPECT_EQ("en", lang); 566 EXPECT_EQ("en", current_tab->language_state().original_language()); 567 568 // Now navigate to a page in French. 569 ui_test_utils::WindowedNotificationObserverWithDetails<std::string> 570 fr_language_detected_signal(NotificationType::TAB_LANGUAGE_DETERMINED, 571 source); 572 ui_test_utils::NavigateToURL( 573 browser(), GURL(test_server()->GetURL("files/french_page.html"))); 574 EXPECT_TRUE(current_tab->language_state().original_language().empty()); 575 fr_language_detected_signal.Wait(); 576 lang.clear(); 577 EXPECT_TRUE(fr_language_detected_signal.GetDetailsFor( 578 source.map_key(), &lang)); 579 EXPECT_EQ("fr", lang); 580 EXPECT_EQ("fr", current_tab->language_state().original_language()); 581} 582 583// Chromeos defaults to restoring the last session, so this test isn't 584// applicable. 585#if !defined(OS_CHROMEOS) 586#if defined(OS_MACOSX) 587// Crashy, http://crbug.com/38522 588#define RestorePinnedTabs DISABLED_RestorePinnedTabs 589#endif 590// Makes sure pinned tabs are restored correctly on start. 591IN_PROC_BROWSER_TEST_F(BrowserTest, RestorePinnedTabs) { 592 ASSERT_TRUE(test_server()->Start()); 593 594 // Add an pinned app tab. 595 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 596 GURL url(test_server()->GetURL("empty.html")); 597 TabStripModel* model = browser()->tabstrip_model(); 598 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 599 const Extension* extension_app = GetExtension(); 600 ui_test_utils::NavigateToURL(browser(), url); 601 TabContentsWrapper* app_contents = 602 Browser::TabContentsFactory(browser()->profile(), NULL, 603 MSG_ROUTING_NONE, NULL, NULL); 604 app_contents->tab_contents()->SetExtensionApp(extension_app); 605 model->AddTabContents(app_contents, 0, 0, TabStripModel::ADD_NONE); 606 model->SetTabPinned(0, true); 607 ui_test_utils::NavigateToURL(browser(), url); 608 609 // Add a non pinned tab. 610 browser()->NewTab(); 611 612 // Add a pinned non-app tab. 613 browser()->NewTab(); 614 ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); 615 model->SetTabPinned(2, true); 616 617 // Write out the pinned tabs. 618 PinnedTabCodec::WritePinnedTabs(browser()->profile()); 619 620 // Simulate launching again. 621 CommandLine dummy(CommandLine::NO_PROGRAM); 622 BrowserInit::LaunchWithProfile launch(FilePath(), dummy); 623 launch.profile_ = browser()->profile(); 624 launch.ProcessStartupURLs(std::vector<GURL>()); 625 626 // The launch should have created a new browser. 627 ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); 628 629 // Find the new browser. 630 Browser* new_browser = NULL; 631 for (BrowserList::const_iterator i = BrowserList::begin(); 632 i != BrowserList::end() && !new_browser; ++i) { 633 if (*i != browser()) 634 new_browser = *i; 635 } 636 ASSERT_TRUE(new_browser); 637 ASSERT_TRUE(new_browser != browser()); 638 639 // We should get back an additional tab for the app. 640 ASSERT_EQ(2, new_browser->tab_count()); 641 642 // Make sure the state matches. 643 TabStripModel* new_model = new_browser->tabstrip_model(); 644 EXPECT_TRUE(new_model->IsAppTab(0)); 645 EXPECT_FALSE(new_model->IsAppTab(1)); 646 647 EXPECT_TRUE(new_model->IsTabPinned(0)); 648 EXPECT_TRUE(new_model->IsTabPinned(1)); 649 650 EXPECT_TRUE( 651 new_model->GetTabContentsAt(0)->tab_contents()->extension_app() == 652 extension_app); 653} 654#endif // !defined(OS_CHROMEOS) 655 656// This test verifies we don't crash when closing the last window and the app 657// menu is showing. 658IN_PROC_BROWSER_TEST_F(BrowserTest, CloseWithAppMenuOpen) { 659 if (browser_defaults::kBrowserAliveWithNoWindows) 660 return; 661 662 // We need a message loop running for menus on windows. 663 MessageLoop::current()->PostTask(FROM_HERE, 664 new RunCloseWithAppMenuTask(browser())); 665} 666 667#if !defined(OS_MACOSX) 668IN_PROC_BROWSER_TEST_F(BrowserTest, OpenAppWindowLikeNtp) { 669 ASSERT_TRUE(test_server()->Start()); 670 671 // Load an app 672 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 673 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 674 const Extension* extension_app = GetExtension(); 675 676 // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would. 677 TabContents* app_window = Browser::OpenApplication( 678 browser()->profile(), extension_app, extension_misc::LAUNCH_WINDOW, NULL); 679 ASSERT_TRUE(app_window); 680 681 // Apps launched in a window from the NTP do not have extension_app set in 682 // tab contents. 683 EXPECT_FALSE(app_window->extension_app()); 684 EXPECT_EQ(extension_app->GetFullLaunchURL(), app_window->GetURL()); 685 686 // The launch should have created a new browser. 687 ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); 688 689 // Find the new browser. 690 Browser* new_browser = NULL; 691 for (BrowserList::const_iterator i = BrowserList::begin(); 692 i != BrowserList::end() && !new_browser; ++i) { 693 if (*i != browser()) 694 new_browser = *i; 695 } 696 ASSERT_TRUE(new_browser); 697 ASSERT_TRUE(new_browser != browser()); 698 699 EXPECT_EQ(Browser::TYPE_APP, new_browser->type()); 700 701 // The browser's app name should include the extension's id. 702 std::string app_name = new_browser->app_name_; 703 EXPECT_NE(app_name.find(extension_app->id()), std::string::npos) 704 << "Name " << app_name << " should contain id "<< extension_app->id(); 705} 706#endif // !defined(OS_MACOSX) 707 708// TODO(ben): this test was never enabled. It has bit-rotted since being added. 709// It originally lived in browser_unittest.cc, but has been moved here to make 710// room for real browser unit tests. 711#if 0 712class BrowserTest2 : public InProcessBrowserTest { 713 public: 714 BrowserTest2() { 715 host_resolver_proc_ = new net::RuleBasedHostResolverProc(NULL); 716 // Avoid making external DNS lookups. In this test we don't need this 717 // to succeed. 718 host_resolver_proc_->AddSimulatedFailure("*.google.com"); 719 scoped_host_resolver_proc_.Init(host_resolver_proc_.get()); 720 } 721 722 private: 723 scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc_; 724 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc_; 725}; 726 727IN_PROC_BROWSER_TEST_F(BrowserTest2, NoTabsInPopups) { 728 Browser::RegisterAppPrefs(L"Test"); 729 730 // We start with a normal browser with one tab. 731 EXPECT_EQ(1, browser()->tab_count()); 732 733 // Open a popup browser with a single blank foreground tab. 734 Browser* popup_browser = browser()->CreateForType(Browser::TYPE_POPUP, 735 browser()->profile()); 736 popup_browser->AddBlankTab(true); 737 EXPECT_EQ(1, popup_browser->tab_count()); 738 739 // Now try opening another tab in the popup browser. 740 AddTabWithURLParams params1(url, PageTransition::TYPED); 741 popup_browser->AddTabWithURL(¶ms1); 742 EXPECT_EQ(popup_browser, params1.target); 743 744 // The popup should still only have one tab. 745 EXPECT_EQ(1, popup_browser->tab_count()); 746 747 // The normal browser should now have two. 748 EXPECT_EQ(2, browser()->tab_count()); 749 750 // Open an app frame browser with a single blank foreground tab. 751 Browser* app_browser = 752 browser()->CreateForApp(L"Test", browser()->profile(), false); 753 app_browser->AddBlankTab(true); 754 EXPECT_EQ(1, app_browser->tab_count()); 755 756 // Now try opening another tab in the app browser. 757 AddTabWithURLParams params2(GURL(chrome::kAboutBlankURL), 758 PageTransition::TYPED); 759 app_browser->AddTabWithURL(¶ms2); 760 EXPECT_EQ(app_browser, params2.target); 761 762 // The popup should still only have one tab. 763 EXPECT_EQ(1, app_browser->tab_count()); 764 765 // The normal browser should now have three. 766 EXPECT_EQ(3, browser()->tab_count()); 767 768 // Open an app frame popup browser with a single blank foreground tab. 769 Browser* app_popup_browser = 770 browser()->CreateForApp(L"Test", browser()->profile(), false); 771 app_popup_browser->AddBlankTab(true); 772 EXPECT_EQ(1, app_popup_browser->tab_count()); 773 774 // Now try opening another tab in the app popup browser. 775 AddTabWithURLParams params3(GURL(chrome::kAboutBlankURL), 776 PageTransition::TYPED); 777 app_popup_browser->AddTabWithURL(¶ms3); 778 EXPECT_EQ(app_popup_browser, params3.target); 779 780 // The popup should still only have one tab. 781 EXPECT_EQ(1, app_popup_browser->tab_count()); 782 783 // The normal browser should now have four. 784 EXPECT_EQ(4, browser()->tab_count()); 785 786 // Close the additional browsers. 787 popup_browser->CloseAllTabs(); 788 app_browser->CloseAllTabs(); 789 app_popup_browser->CloseAllTabs(); 790} 791#endif 792