browser_browsertest.cc revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2010 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 "app/l10n_util.h" 8#include "base/compiler_specific.h" 9#include "base/file_path.h" 10#include "base/sys_info.h" 11#include "base/utf_string_conversions.h" 12#include "chrome/app/chrome_command_ids.h" 13#include "chrome/browser/app_modal_dialog.h" 14#include "chrome/browser/browser.h" 15#include "chrome/browser/browser_init.h" 16#include "chrome/browser/browser_list.h" 17#include "chrome/browser/browser_navigator.h" 18#include "chrome/browser/browser_process.h" 19#include "chrome/browser/browser_window.h" 20#include "chrome/browser/defaults.h" 21#include "chrome/browser/extensions/extension_browsertest.h" 22#include "chrome/browser/extensions/extensions_service.h" 23#include "chrome/browser/js_modal_dialog.h" 24#include "chrome/browser/native_app_modal_dialog.h" 25#include "chrome/browser/profile.h" 26#include "chrome/browser/renderer_host/render_process_host.h" 27#include "chrome/browser/renderer_host/render_view_host.h" 28#include "chrome/browser/tab_contents/tab_contents.h" 29#include "chrome/browser/tabs/pinned_tab_codec.h" 30#include "chrome/browser/tabs/tab_strip_model.h" 31#include "chrome/common/chrome_switches.h" 32#include "chrome/common/extensions/extension.h" 33#include "chrome/common/url_constants.h" 34#include "chrome/common/page_transition_types.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 42#if defined(OS_WIN) 43#include "base/i18n/rtl.h" 44#endif 45 46namespace { 47 48const std::string BEFORE_UNLOAD_HTML = 49 "<html><head><title>beforeunload</title></head><body>" 50 "<script>window.onbeforeunload=function(e){return 'foo'}</script>" 51 "</body></html>"; 52 53const std::wstring OPEN_NEW_BEFOREUNLOAD_PAGE = 54 L"w=window.open(); w.onbeforeunload=function(e){return 'foo'};"; 55 56const FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html"); 57const FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html"); 58 59const FilePath::CharType kDocRoot[] = FILE_PATH_LITERAL("chrome/test/data"); 60 61// Given a page title, returns the expected window caption string. 62std::wstring WindowCaptionFromPageTitle(std::wstring page_title) { 63#if defined(OS_MACOSX) || defined(OS_CHROMEOS) 64 // On Mac or ChromeOS, we don't want to suffix the page title with 65 // the application name. 66 if (page_title.empty()) 67 return l10n_util::GetString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED); 68 return page_title; 69#else 70 if (page_title.empty()) 71 return l10n_util::GetString(IDS_PRODUCT_NAME); 72 73 return l10n_util::GetStringF(IDS_BROWSER_WINDOW_TITLE_FORMAT, page_title); 74#endif 75} 76 77// Returns the number of active RenderProcessHosts. 78int CountRenderProcessHosts() { 79 int result = 0; 80 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); 81 !i.IsAtEnd(); i.Advance()) 82 ++result; 83 return result; 84} 85 86class MockTabStripModelObserver : public TabStripModelObserver { 87 public: 88 MockTabStripModelObserver() : closing_count_(0) {} 89 90 virtual void TabClosingAt(TabStripModel* tab_strip_model, 91 TabContents* contents, 92 int index) { 93 closing_count_++; 94 } 95 96 int closing_count() const { return closing_count_; } 97 98 private: 99 int closing_count_; 100 101 DISALLOW_COPY_AND_ASSIGN(MockTabStripModelObserver); 102}; 103 104// Used by CloseWithAppMenuOpen. Invokes CloseWindow on the supplied browser. 105class CloseWindowTask : public Task { 106 public: 107 explicit CloseWindowTask(Browser* browser) : browser_(browser) {} 108 109 virtual void Run() { 110 browser_->CloseWindow(); 111 } 112 113 private: 114 Browser* browser_; 115 116 DISALLOW_COPY_AND_ASSIGN(CloseWindowTask); 117}; 118 119// Used by CloseWithAppMenuOpen. Posts a CloseWindowTask and shows the app menu. 120class RunCloseWithAppMenuTask : public Task { 121 public: 122 explicit RunCloseWithAppMenuTask(Browser* browser) : browser_(browser) {} 123 124 virtual void Run() { 125 // ShowAppMenu is modal under views. Schedule a task that closes the window. 126 MessageLoop::current()->PostTask(FROM_HERE, new CloseWindowTask(browser_)); 127 browser_->ShowAppMenu(); 128 } 129 130 private: 131 Browser* browser_; 132 133 DISALLOW_COPY_AND_ASSIGN(RunCloseWithAppMenuTask); 134}; 135 136} // namespace 137 138class BrowserTest : public ExtensionBrowserTest { 139 protected: 140 // In RTL locales wrap the page title with RTL embedding characters so that it 141 // matches the value returned by GetWindowTitle(). 142 std::wstring LocaleWindowCaptionFromPageTitle( 143 const std::wstring& expected_title) { 144 std::wstring page_title = WindowCaptionFromPageTitle(expected_title); 145#if defined(OS_WIN) 146 std::string locale = g_browser_process->GetApplicationLocale(); 147 if (base::i18n::GetTextDirectionForLocale(locale.c_str()) == 148 base::i18n::RIGHT_TO_LEFT) { 149 base::i18n::WrapStringWithLTRFormatting(&page_title); 150 } 151 152 return page_title; 153#else 154 // Do we need to use the above code on POSIX as well? 155 return page_title; 156#endif 157 } 158 159 // Returns the app extension aptly named "App Test". 160 const Extension* GetExtension() { 161 const ExtensionList* extensions = 162 browser()->profile()->GetExtensionsService()->extensions(); 163 for (size_t i = 0; i < extensions->size(); ++i) { 164 if ((*extensions)[i]->name() == "App Test") 165 return (*extensions)[i]; 166 } 167 NOTREACHED(); 168 return NULL; 169 } 170}; 171 172// Launch the app on a page with no title, check that the app title was set 173// correctly. 174IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) { 175 ui_test_utils::NavigateToURL(browser(), 176 ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 177 FilePath(kTitle1File))); 178 EXPECT_EQ(LocaleWindowCaptionFromPageTitle(L"title1.html"), 179 UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab())); 180 string16 tab_title; 181 ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title)); 182 EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title); 183} 184 185// Launch the app, navigate to a page with a title, check that the app title 186// was set correctly. 187IN_PROC_BROWSER_TEST_F(BrowserTest, Title) { 188 ui_test_utils::NavigateToURL(browser(), 189 ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 190 FilePath(kTitle2File))); 191 const std::wstring test_title(L"Title Of Awesomeness"); 192 EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title), 193 UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab())); 194 string16 tab_title; 195 ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title)); 196 EXPECT_EQ(WideToUTF16(test_title), tab_title); 197} 198 199#if defined(OS_MACOSX) 200// Test is crashing on Mac, see http://crbug.com/29424. 201#define MAYBE_JavascriptAlertActivatesTab DISABLED_JavascriptAlertActivatesTab 202#else 203#define MAYBE_JavascriptAlertActivatesTab JavascriptAlertActivatesTab 204#endif 205 206IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_JavascriptAlertActivatesTab) { 207 GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 208 FilePath(kTitle1File))); 209 ui_test_utils::NavigateToURL(browser(), url); 210 AddTabAtIndex(0, url, PageTransition::TYPED); 211 EXPECT_EQ(2, browser()->tab_count()); 212 EXPECT_EQ(0, browser()->selected_index()); 213 TabContents* second_tab = browser()->GetTabContentsAt(1); 214 ASSERT_TRUE(second_tab); 215 second_tab->render_view_host()->ExecuteJavascriptInWebFrame(L"", 216 L"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("data:text/html," + BEFORE_UNLOAD_HTML); 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(L"", L"onbeforeunload=null;"); 263} 264 265// Crashy on mac. http://crbug.com/38522 266#if defined(OS_MACOSX) 267#define MAYBE_SingleBeforeUnloadAfterWindowClose \ 268 DISABLED_SingleBeforeUnloadAfterWindowClose 269#else 270#define MAYBE_SingleBeforeUnloadAfterWindowClose \ 271 SingleBeforeUnloadAfterWindowClose 272#endif 273 274// Test for crbug.com/11647. A page closed with window.close() should not have 275// two beforeunload dialogs shown. 276IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_SingleBeforeUnloadAfterWindowClose) { 277 browser()->GetSelectedTabContents()->render_view_host()-> 278 ExecuteJavascriptInWebFrame(L"", OPEN_NEW_BEFOREUNLOAD_PAGE); 279 280 // Close the new window with JavaScript, which should show a single 281 // beforeunload dialog. Then show another alert, to make it easy to verify 282 // that a second beforeunload dialog isn't shown. 283 browser()->GetTabContentsAt(0)->render_view_host()-> 284 ExecuteJavascriptInWebFrame(L"", L"w.close(); alert('bar');"); 285 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 286 alert->native_dialog()->AcceptAppModalDialog(); 287 288 alert = ui_test_utils::WaitForAppModalDialog(); 289 EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)-> 290 is_before_unload_dialog()); 291 alert->native_dialog()->AcceptAppModalDialog(); 292} 293 294// Test that get_process_idle_time() returns reasonable values when compared 295// with time deltas measured locally. 296IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) { 297 base::TimeTicks start = base::TimeTicks::Now(); 298 ui_test_utils::NavigateToURL(browser(), 299 ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 300 FilePath(kTitle1File))); 301 RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); 302 for (; !it.IsAtEnd(); it.Advance()) { 303 base::TimeDelta renderer_td = 304 it.GetCurrentValue()->get_child_process_idle_time(); 305 base::TimeDelta browser_td = base::TimeTicks::Now() - start; 306 EXPECT_TRUE(browser_td >= renderer_td); 307 } 308} 309 310// Test IDC_CREATE_SHORTCUTS command is enabled for url scheme file, ftp, http 311// and https and disabled for chrome://, about:// etc. 312// TODO(pinkerton): Disable app-mode in the model until we implement it 313// on the Mac. http://crbug.com/13148 314#if !defined(OS_MACOSX) 315IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFile) { 316 CommandUpdater* command_updater = browser()->command_updater(); 317 318 static const FilePath::CharType* kEmptyFile = FILE_PATH_LITERAL("empty.html"); 319 GURL file_url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 320 FilePath(kEmptyFile))); 321 ASSERT_TRUE(file_url.SchemeIs(chrome::kFileScheme)); 322 ui_test_utils::NavigateToURL(browser(), file_url); 323 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 324} 325 326IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttp) { 327 CommandUpdater* command_updater = browser()->command_updater(); 328 329 ASSERT_TRUE(test_server()->Start()); 330 GURL http_url(test_server()->GetURL("")); 331 ASSERT_TRUE(http_url.SchemeIs(chrome::kHttpScheme)); 332 ui_test_utils::NavigateToURL(browser(), http_url); 333 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 334} 335 336IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttps) { 337 CommandUpdater* command_updater = browser()->command_updater(); 338 339 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath(kDocRoot)); 340 ASSERT_TRUE(test_server.Start()); 341 GURL https_url(test_server.GetURL("/")); 342 ASSERT_TRUE(https_url.SchemeIs(chrome::kHttpsScheme)); 343 ui_test_utils::NavigateToURL(browser(), https_url); 344 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 345} 346 347IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFtp) { 348 CommandUpdater* command_updater = browser()->command_updater(); 349 350 net::TestServer test_server(net::TestServer::TYPE_FTP, FilePath(kDocRoot)); 351 ASSERT_TRUE(test_server.Start()); 352 GURL ftp_url(test_server.GetURL("")); 353 ASSERT_TRUE(ftp_url.SchemeIs(chrome::kFtpScheme)); 354 ui_test_utils::NavigateToURL(browser(), ftp_url); 355 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 356} 357 358IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutInvalid) { 359 CommandUpdater* command_updater = browser()->command_updater(); 360 361 // Urls that should not have shortcuts. 362 GURL new_tab_url(chrome::kChromeUINewTabURL); 363 ui_test_utils::NavigateToURL(browser(), new_tab_url); 364 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 365 366 GURL history_url(chrome::kChromeUIHistoryURL); 367 ui_test_utils::NavigateToURL(browser(), history_url); 368 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 369 370 GURL downloads_url(chrome::kChromeUIDownloadsURL); 371 ui_test_utils::NavigateToURL(browser(), downloads_url); 372 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 373 374 GURL blank_url(chrome::kAboutBlankURL); 375 ui_test_utils::NavigateToURL(browser(), blank_url); 376 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 377} 378#endif // !defined(OS_MACOSX) 379 380// Test RenderView correctly send back favicon url for web page that redirects 381// to an anchor in javascript body.onload handler. 382IN_PROC_BROWSER_TEST_F(BrowserTest, FaviconOfOnloadRedirectToAnchorPage) { 383 ASSERT_TRUE(test_server()->Start()); 384 GURL url(test_server()->GetURL("files/onload_redirect_to_anchor.html")); 385 GURL expected_favicon_url(test_server()->GetURL("files/test.png")); 386 387 ui_test_utils::NavigateToURL(browser(), url); 388 389 NavigationEntry* entry = browser()->GetSelectedTabContents()-> 390 controller().GetActiveEntry(); 391 EXPECT_EQ(expected_favicon_url.spec(), entry->favicon().url().spec()); 392} 393 394// Test that an icon can be changed from JS. 395IN_PROC_BROWSER_TEST_F(BrowserTest, FaviconChange) { 396 static const FilePath::CharType* kFile = 397 FILE_PATH_LITERAL("onload_change_favicon.html"); 398 GURL file_url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 399 FilePath(kFile))); 400 ASSERT_TRUE(file_url.SchemeIs(chrome::kFileScheme)); 401 ui_test_utils::NavigateToURL(browser(), file_url); 402 403 NavigationEntry* entry = browser()->GetSelectedTabContents()-> 404 controller().GetActiveEntry(); 405 static const FilePath::CharType* kIcon = 406 FILE_PATH_LITERAL("test1.png"); 407 GURL expected_favicon_url( 408 ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), 409 FilePath(kIcon))); 410 EXPECT_EQ(expected_favicon_url.spec(), entry->favicon().url().spec()); 411} 412 413// Makes sure TabClosing is sent when uninstalling an extension that is an app 414// tab. 415IN_PROC_BROWSER_TEST_F(BrowserTest, TabClosingWhenRemovingExtension) { 416 ASSERT_TRUE(test_server()->Start()); 417 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 418 GURL url(test_server()->GetURL("empty.html")); 419 TabStripModel* model = browser()->tabstrip_model(); 420 421 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 422 423 const Extension* extension_app = GetExtension(); 424 425 ui_test_utils::NavigateToURL(browser(), url); 426 427 TabContents* app_contents = new TabContents(browser()->profile(), NULL, 428 MSG_ROUTING_NONE, NULL, NULL); 429 app_contents->SetExtensionApp(extension_app); 430 431 model->AddTabContents(app_contents, 0, 0, TabStripModel::ADD_NONE); 432 model->SetTabPinned(0, true); 433 ui_test_utils::NavigateToURL(browser(), url); 434 435 MockTabStripModelObserver observer; 436 model->AddObserver(&observer); 437 438 // Uninstall the extension and make sure TabClosing is sent. 439 ExtensionsService* service = browser()->profile()->GetExtensionsService(); 440 service->UninstallExtension(GetExtension()->id(), false); 441 EXPECT_EQ(1, observer.closing_count()); 442 443 model->RemoveObserver(&observer); 444 445 // There should only be one tab now. 446 ASSERT_EQ(1, browser()->tab_count()); 447} 448 449#if defined(OS_WIN) 450// http://crbug.com/46198. On XP/Vista, the failure rate is 5 ~ 6%. 451#define MAYBE_PageLanguageDetection FLAKY_PageLanguageDetection 452#else 453#define MAYBE_PageLanguageDetection PageLanguageDetection 454#endif 455// Tests that the CLD (Compact Language Detection) works properly. 456IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_PageLanguageDetection) { 457 ASSERT_TRUE(test_server()->Start()); 458 459 TabContents* current_tab = browser()->GetSelectedTabContents(); 460 461 // Navigate to a page in English. 462 ui_test_utils::WindowedNotificationObserverWithDetails<TabContents, 463 std::string> 464 en_language_detected_signal(NotificationType::TAB_LANGUAGE_DETERMINED, 465 current_tab); 466 ui_test_utils::NavigateToURL( 467 browser(), GURL(test_server()->GetURL("files/english_page.html"))); 468 EXPECT_TRUE(current_tab->language_state().original_language().empty()); 469 en_language_detected_signal.Wait(); 470 std::string lang; 471 EXPECT_TRUE(en_language_detected_signal.GetDetailsFor(current_tab, &lang)); 472 EXPECT_EQ("en", lang); 473 EXPECT_EQ("en", current_tab->language_state().original_language()); 474 475 // Now navigate to a page in French. 476 ui_test_utils::WindowedNotificationObserverWithDetails<TabContents, 477 std::string> 478 fr_language_detected_signal(NotificationType::TAB_LANGUAGE_DETERMINED, 479 current_tab); 480 ui_test_utils::NavigateToURL( 481 browser(), GURL(test_server()->GetURL("files/french_page.html"))); 482 EXPECT_TRUE(current_tab->language_state().original_language().empty()); 483 fr_language_detected_signal.Wait(); 484 lang.clear(); 485 EXPECT_TRUE(fr_language_detected_signal.GetDetailsFor(current_tab, &lang)); 486 EXPECT_EQ("fr", lang); 487 EXPECT_EQ("fr", current_tab->language_state().original_language()); 488} 489 490// Chromeos defaults to restoring the last session, so this test isn't 491// applicable. 492#if !defined(OS_CHROMEOS) 493#if defined(OS_MACOSX) 494// Crashy, http://crbug.com/38522 495#define RestorePinnedTabs DISABLED_RestorePinnedTabs 496#endif 497// Makes sure pinned tabs are restored correctly on start. 498IN_PROC_BROWSER_TEST_F(BrowserTest, RestorePinnedTabs) { 499 ASSERT_TRUE(test_server()->Start()); 500 501 // Add an pinned app tab. 502 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 503 GURL url(test_server()->GetURL("empty.html")); 504 TabStripModel* model = browser()->tabstrip_model(); 505 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 506 const Extension* extension_app = GetExtension(); 507 ui_test_utils::NavigateToURL(browser(), url); 508 TabContents* app_contents = new TabContents(browser()->profile(), NULL, 509 MSG_ROUTING_NONE, NULL, NULL); 510 app_contents->SetExtensionApp(extension_app); 511 model->AddTabContents(app_contents, 0, 0, TabStripModel::ADD_NONE); 512 model->SetTabPinned(0, true); 513 ui_test_utils::NavigateToURL(browser(), url); 514 515 // Add a non pinned tab. 516 browser()->NewTab(); 517 518 // Add a pinned non-app tab. 519 browser()->NewTab(); 520 ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); 521 model->SetTabPinned(2, true); 522 523 // Write out the pinned tabs. 524 PinnedTabCodec::WritePinnedTabs(browser()->profile()); 525 526 // Simulate launching again. 527 CommandLine dummy(CommandLine::NO_PROGRAM); 528 BrowserInit::LaunchWithProfile launch(FilePath(), dummy); 529 launch.profile_ = browser()->profile(); 530 launch.ProcessStartupURLs(std::vector<GURL>()); 531 532 // The launch should have created a new browser. 533 ASSERT_EQ(2u, BrowserList::GetBrowserCount(browser()->profile())); 534 535 // Find the new browser. 536 Browser* new_browser = NULL; 537 for (BrowserList::const_iterator i = BrowserList::begin(); 538 i != BrowserList::end() && !new_browser; ++i) { 539 if (*i != browser()) 540 new_browser = *i; 541 } 542 ASSERT_TRUE(new_browser); 543 ASSERT_TRUE(new_browser != browser()); 544 545 // We should get back an additional tab for the app. 546 ASSERT_EQ(2, new_browser->tab_count()); 547 548 // Make sure the state matches. 549 TabStripModel* new_model = new_browser->tabstrip_model(); 550 EXPECT_TRUE(new_model->IsAppTab(0)); 551 EXPECT_FALSE(new_model->IsAppTab(1)); 552 553 EXPECT_TRUE(new_model->IsTabPinned(0)); 554 EXPECT_TRUE(new_model->IsTabPinned(1)); 555 556 EXPECT_TRUE(new_model->GetTabContentsAt(0)->extension_app() == 557 extension_app); 558} 559#endif // !defined(OS_CHROMEOS) 560 561// This test verifies we don't crash when closing the last window and the app 562// menu is showing. 563IN_PROC_BROWSER_TEST_F(BrowserTest, CloseWithAppMenuOpen) { 564 if (browser_defaults::kBrowserAliveWithNoWindows) 565 return; 566 567 // We need a message loop running for menus on windows. 568 MessageLoop::current()->PostTask(FROM_HERE, 569 new RunCloseWithAppMenuTask(browser())); 570} 571 572// TODO(ben): this test was never enabled. It has bit-rotted since being added. 573// It originally lived in browser_unittest.cc, but has been moved here to make 574// room for real browser unit tests. 575#if 0 576class BrowserTest2 : public InProcessBrowserTest { 577 public: 578 BrowserTest2() { 579 host_resolver_proc_ = new net::RuleBasedHostResolverProc(NULL); 580 // Avoid making external DNS lookups. In this test we don't need this 581 // to succeed. 582 host_resolver_proc_->AddSimulatedFailure("*.google.com"); 583 scoped_host_resolver_proc_.Init(host_resolver_proc_.get()); 584 } 585 586 private: 587 scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc_; 588 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc_; 589}; 590 591IN_PROC_BROWSER_TEST_F(BrowserTest2, NoTabsInPopups) { 592 Browser::RegisterAppPrefs(L"Test"); 593 594 // We start with a normal browser with one tab. 595 EXPECT_EQ(1, browser()->tab_count()); 596 597 // Open a popup browser with a single blank foreground tab. 598 Browser* popup_browser = browser()->CreateForType(Browser::TYPE_POPUP, 599 browser()->profile()); 600 popup_browser->AddBlankTab(true); 601 EXPECT_EQ(1, popup_browser->tab_count()); 602 603 // Now try opening another tab in the popup browser. 604 AddTabWithURLParams params1(url, PageTransition::TYPED); 605 popup_browser->AddTabWithURL(¶ms1); 606 EXPECT_EQ(popup_browser, params1.target); 607 608 // The popup should still only have one tab. 609 EXPECT_EQ(1, popup_browser->tab_count()); 610 611 // The normal browser should now have two. 612 EXPECT_EQ(2, browser()->tab_count()); 613 614 // Open an app frame browser with a single blank foreground tab. 615 Browser* app_browser = 616 browser()->CreateForApp(L"Test", browser()->profile(), false); 617 app_browser->AddBlankTab(true); 618 EXPECT_EQ(1, app_browser->tab_count()); 619 620 // Now try opening another tab in the app browser. 621 AddTabWithURLParams params2(GURL(chrome::kAboutBlankURL), 622 PageTransition::TYPED); 623 app_browser->AddTabWithURL(¶ms2); 624 EXPECT_EQ(app_browser, params2.target); 625 626 // The popup should still only have one tab. 627 EXPECT_EQ(1, app_browser->tab_count()); 628 629 // The normal browser should now have three. 630 EXPECT_EQ(3, browser()->tab_count()); 631 632 // Open an app frame popup browser with a single blank foreground tab. 633 Browser* app_popup_browser = 634 browser()->CreateForApp(L"Test", browser()->profile(), false); 635 app_popup_browser->AddBlankTab(true); 636 EXPECT_EQ(1, app_popup_browser->tab_count()); 637 638 // Now try opening another tab in the app popup browser. 639 AddTabWithURLParams params3(GURL(chrome::kAboutBlankURL), 640 PageTransition::TYPED); 641 app_popup_browser->AddTabWithURL(¶ms3); 642 EXPECT_EQ(app_popup_browser, params3.target); 643 644 // The popup should still only have one tab. 645 EXPECT_EQ(1, app_popup_browser->tab_count()); 646 647 // The normal browser should now have four. 648 EXPECT_EQ(4, browser()->tab_count()); 649 650 // Close the additional browsers. 651 popup_browser->CloseAllTabs(); 652 app_browser->CloseAllTabs(); 653 app_popup_browser->CloseAllTabs(); 654} 655#endif 656