1 // Copyright (c) 2012 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/bind.h" 8 #include "base/command_line.h" 9 #include "base/compiler_specific.h" 10 #include "base/files/file_path.h" 11 #include "base/prefs/pref_service.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "base/sys_info.h" 14 #include "chrome/app/chrome_command_ids.h" 15 #include "chrome/browser/chrome_content_browser_client.h" 16 #include "chrome/browser/chrome_notification_types.h" 17 #include "chrome/browser/command_updater.h" 18 #include "chrome/browser/content_settings/host_content_settings_map.h" 19 #include "chrome/browser/defaults.h" 20 #include "chrome/browser/devtools/devtools_window.h" 21 #include "chrome/browser/extensions/extension_browsertest.h" 22 #include "chrome/browser/extensions/extension_service.h" 23 #include "chrome/browser/extensions/tab_helper.h" 24 #include "chrome/browser/first_run/first_run.h" 25 #include "chrome/browser/lifetime/application_lifetime.h" 26 #include "chrome/browser/prefs/incognito_mode_prefs.h" 27 #include "chrome/browser/profiles/profile.h" 28 #include "chrome/browser/profiles/profile_manager.h" 29 #include "chrome/browser/search/search.h" 30 #include "chrome/browser/sessions/session_backend.h" 31 #include "chrome/browser/sessions/session_service_factory.h" 32 #include "chrome/browser/translate/chrome_translate_client.h" 33 #include "chrome/browser/translate/translate_browser_test_utils.h" 34 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h" 35 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h" 36 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h" 37 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" 38 #include "chrome/browser/ui/browser.h" 39 #include "chrome/browser/ui/browser_command_controller.h" 40 #include "chrome/browser/ui/browser_commands.h" 41 #include "chrome/browser/ui/browser_finder.h" 42 #include "chrome/browser/ui/browser_iterator.h" 43 #include "chrome/browser/ui/browser_navigator.h" 44 #include "chrome/browser/ui/browser_tabstrip.h" 45 #include "chrome/browser/ui/browser_ui_prefs.h" 46 #include "chrome/browser/ui/browser_window.h" 47 #include "chrome/browser/ui/extensions/application_launch.h" 48 #include "chrome/browser/ui/host_desktop.h" 49 #include "chrome/browser/ui/startup/startup_browser_creator.h" 50 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h" 51 #include "chrome/browser/ui/tabs/pinned_tab_codec.h" 52 #include "chrome/browser/ui/tabs/tab_strip_model.h" 53 #include "chrome/common/chrome_switches.h" 54 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 55 #include "chrome/common/pref_names.h" 56 #include "chrome/common/url_constants.h" 57 #include "chrome/test/base/in_process_browser_test.h" 58 #include "chrome/test/base/test_switches.h" 59 #include "chrome/test/base/ui_test_utils.h" 60 #include "components/translate/core/browser/language_state.h" 61 #include "components/translate/core/common/language_detection_details.h" 62 #include "content/public/browser/favicon_status.h" 63 #include "content/public/browser/host_zoom_map.h" 64 #include "content/public/browser/interstitial_page.h" 65 #include "content/public/browser/interstitial_page_delegate.h" 66 #include "content/public/browser/navigation_entry.h" 67 #include "content/public/browser/notification_service.h" 68 #include "content/public/browser/render_frame_host.h" 69 #include "content/public/browser/render_process_host.h" 70 #include "content/public/browser/render_view_host.h" 71 #include "content/public/browser/render_widget_host_view.h" 72 #include "content/public/browser/resource_context.h" 73 #include "content/public/browser/web_contents.h" 74 #include "content/public/browser/web_contents_observer.h" 75 #include "content/public/common/frame_navigate_params.h" 76 #include "content/public/common/page_transition_types.h" 77 #include "content/public/common/renderer_preferences.h" 78 #include "content/public/common/url_constants.h" 79 #include "content/public/test/browser_test_utils.h" 80 #include "content/public/test/test_navigation_observer.h" 81 #include "extensions/browser/extension_system.h" 82 #include "extensions/common/extension.h" 83 #include "extensions/common/extension_set.h" 84 #include "grit/chromium_strings.h" 85 #include "grit/generated_resources.h" 86 #include "net/dns/mock_host_resolver.h" 87 #include "net/test/spawned_test_server/spawned_test_server.h" 88 #include "ui/base/l10n/l10n_util.h" 89 90 #if defined(OS_MACOSX) 91 #include "base/mac/mac_util.h" 92 #include "base/mac/scoped_nsautorelease_pool.h" 93 #include "chrome/browser/ui/cocoa/run_loop_testing.h" 94 #endif 95 96 #if defined(OS_WIN) 97 #include "base/i18n/rtl.h" 98 #include "chrome/browser/browser_process.h" 99 #endif 100 101 using base::ASCIIToUTF16; 102 using content::InterstitialPage; 103 using content::HostZoomMap; 104 using content::NavigationController; 105 using content::NavigationEntry; 106 using content::OpenURLParams; 107 using content::Referrer; 108 using content::WebContents; 109 using content::WebContentsObserver; 110 using extensions::Extension; 111 112 namespace { 113 114 const char* kBeforeUnloadHTML = 115 "<html><head><title>beforeunload</title></head><body>" 116 "<script>window.onbeforeunload=function(e){return 'foo'}</script>" 117 "</body></html>"; 118 119 const char* kOpenNewBeforeUnloadPage = 120 "w=window.open(); w.onbeforeunload=function(e){return 'foo'};"; 121 122 const base::FilePath::CharType* kBeforeUnloadFile = 123 FILE_PATH_LITERAL("beforeunload.html"); 124 125 const base::FilePath::CharType* kTitle1File = FILE_PATH_LITERAL("title1.html"); 126 const base::FilePath::CharType* kTitle2File = FILE_PATH_LITERAL("title2.html"); 127 128 const base::FilePath::CharType kDocRoot[] = 129 FILE_PATH_LITERAL("chrome/test/data"); 130 131 // Given a page title, returns the expected window caption string. 132 base::string16 WindowCaptionFromPageTitle(const base::string16& page_title) { 133 #if defined(OS_MACOSX) || defined(OS_CHROMEOS) 134 // On Mac or ChromeOS, we don't want to suffix the page title with 135 // the application name. 136 if (page_title.empty()) 137 return l10n_util::GetStringUTF16(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED); 138 return page_title; 139 #else 140 if (page_title.empty()) 141 return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); 142 143 return l10n_util::GetStringFUTF16(IDS_BROWSER_WINDOW_TITLE_FORMAT, 144 page_title); 145 #endif 146 } 147 148 // Returns the number of active RenderProcessHosts. 149 int CountRenderProcessHosts() { 150 int result = 0; 151 for (content::RenderProcessHost::iterator i( 152 content::RenderProcessHost::AllHostsIterator()); 153 !i.IsAtEnd(); i.Advance()) 154 ++result; 155 return result; 156 } 157 158 class MockTabStripModelObserver : public TabStripModelObserver { 159 public: 160 MockTabStripModelObserver() : closing_count_(0) {} 161 162 virtual void TabClosingAt(TabStripModel* tab_strip_model, 163 WebContents* contents, 164 int index) OVERRIDE { 165 ++closing_count_; 166 } 167 168 int closing_count() const { return closing_count_; } 169 170 private: 171 int closing_count_; 172 173 DISALLOW_COPY_AND_ASSIGN(MockTabStripModelObserver); 174 }; 175 176 class InterstitialObserver : public content::WebContentsObserver { 177 public: 178 InterstitialObserver(content::WebContents* web_contents, 179 const base::Closure& attach_callback, 180 const base::Closure& detach_callback) 181 : WebContentsObserver(web_contents), 182 attach_callback_(attach_callback), 183 detach_callback_(detach_callback) { 184 } 185 186 virtual void DidAttachInterstitialPage() OVERRIDE { 187 attach_callback_.Run(); 188 } 189 190 virtual void DidDetachInterstitialPage() OVERRIDE { 191 detach_callback_.Run(); 192 } 193 194 private: 195 base::Closure attach_callback_; 196 base::Closure detach_callback_; 197 198 DISALLOW_COPY_AND_ASSIGN(InterstitialObserver); 199 }; 200 201 // Causes the browser to swap processes on a redirect to an HTTPS URL. 202 class TransferHttpsRedirectsContentBrowserClient 203 : public chrome::ChromeContentBrowserClient { 204 public: 205 virtual bool ShouldSwapProcessesForRedirect( 206 content::ResourceContext* resource_context, 207 const GURL& current_url, 208 const GURL& new_url) OVERRIDE { 209 return new_url.SchemeIs(url::kHttpsScheme); 210 } 211 }; 212 213 // Used by CloseWithAppMenuOpen. Invokes CloseWindow on the supplied browser. 214 void CloseWindowCallback(Browser* browser) { 215 chrome::CloseWindow(browser); 216 } 217 218 // Used by CloseWithAppMenuOpen. Posts a CloseWindowCallback and shows the app 219 // menu. 220 void RunCloseWithAppMenuCallback(Browser* browser) { 221 // ShowAppMenu is modal under views. Schedule a task that closes the window. 222 base::MessageLoop::current()->PostTask( 223 FROM_HERE, base::Bind(&CloseWindowCallback, browser)); 224 chrome::ShowAppMenu(browser); 225 } 226 227 // Displays "INTERSTITIAL" while the interstitial is attached. 228 // (InterstitialPage can be used in a test directly, but there would be no way 229 // to visually tell if it is showing or not.) 230 class TestInterstitialPage : public content::InterstitialPageDelegate { 231 public: 232 TestInterstitialPage(WebContents* tab, bool new_navigation, const GURL& url) { 233 interstitial_page_ = InterstitialPage::Create( 234 tab, new_navigation, url , this); 235 interstitial_page_->Show(); 236 } 237 virtual ~TestInterstitialPage() { } 238 void Proceed() { 239 interstitial_page_->Proceed(); 240 } 241 void DontProceed() { 242 interstitial_page_->DontProceed(); 243 } 244 245 virtual std::string GetHTMLContents() OVERRIDE { 246 return "<h1>INTERSTITIAL</h1>"; 247 } 248 249 private: 250 InterstitialPage* interstitial_page_; // Owns us. 251 }; 252 253 class RenderViewSizeObserver : public content::WebContentsObserver { 254 public: 255 RenderViewSizeObserver(content::WebContents* web_contents, 256 BrowserWindow* browser_window) 257 : WebContentsObserver(web_contents), 258 browser_window_(browser_window) { 259 } 260 261 void GetSizeForRenderViewHost( 262 content::RenderViewHost* render_view_host, 263 gfx::Size* rwhv_create_size, 264 gfx::Size* rwhv_commit_size, 265 gfx::Size* wcv_commit_size) { 266 RenderViewSizes::const_iterator result = render_view_sizes_.end(); 267 result = render_view_sizes_.find(render_view_host); 268 if (result != render_view_sizes_.end()) { 269 *rwhv_create_size = result->second.rwhv_create_size; 270 *rwhv_commit_size = result->second.rwhv_commit_size; 271 *wcv_commit_size = result->second.wcv_commit_size; 272 } 273 } 274 275 void set_wcv_resize_insets(const gfx::Size& wcv_resize_insets) { 276 wcv_resize_insets_ = wcv_resize_insets; 277 } 278 279 // Cache the size when RenderViewHost is first created. 280 virtual void RenderViewCreated( 281 content::RenderViewHost* render_view_host) OVERRIDE { 282 render_view_sizes_[render_view_host].rwhv_create_size = 283 render_view_host->GetView()->GetViewBounds().size(); 284 } 285 286 // Enlarge WebContentsView by |wcv_resize_insets_| while the navigation entry 287 // is pending. 288 virtual void DidStartNavigationToPendingEntry( 289 const GURL& url, 290 NavigationController::ReloadType reload_type) OVERRIDE { 291 if (wcv_resize_insets_.IsEmpty()) 292 return; 293 // Resizing the main browser window by |wcv_resize_insets_| will 294 // automatically resize the WebContentsView by the same amount. 295 // Just resizing WebContentsView directly doesn't work on Linux, because the 296 // next automatic layout of the browser window will resize WebContentsView 297 // back to the previous size. To make it consistent, resize main browser 298 // window on all platforms. 299 gfx::Rect bounds(browser_window_->GetBounds()); 300 gfx::Size size(bounds.size()); 301 size.Enlarge(wcv_resize_insets_.width(), wcv_resize_insets_.height()); 302 bounds.set_size(size); 303 browser_window_->SetBounds(bounds); 304 // Let the message loop run so that resize actually takes effect. 305 content::RunAllPendingInMessageLoop(); 306 } 307 308 // Cache the sizes of RenderWidgetHostView and WebContentsView when the 309 // navigation entry is committed, which is before 310 // WebContentsDelegate::DidNavigateMainFramePostCommit is called. 311 virtual void NavigationEntryCommitted( 312 const content::LoadCommittedDetails& details) OVERRIDE { 313 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); 314 render_view_sizes_[rvh].rwhv_commit_size = 315 web_contents()->GetRenderWidgetHostView()->GetViewBounds().size(); 316 render_view_sizes_[rvh].wcv_commit_size = 317 web_contents()->GetContainerBounds().size(); 318 } 319 320 private: 321 struct Sizes { 322 gfx::Size rwhv_create_size; // Size of RenderWidgetHostView when created. 323 gfx::Size rwhv_commit_size; // Size of RenderWidgetHostView when committed. 324 gfx::Size wcv_commit_size; // Size of WebContentsView when committed. 325 }; 326 327 typedef std::map<content::RenderViewHost*, Sizes> RenderViewSizes; 328 RenderViewSizes render_view_sizes_; 329 // Enlarge WebContentsView by this size insets in 330 // DidStartNavigationToPendingEntry. 331 gfx::Size wcv_resize_insets_; 332 BrowserWindow* browser_window_; // Weak ptr. 333 334 DISALLOW_COPY_AND_ASSIGN(RenderViewSizeObserver); 335 }; 336 337 } // namespace 338 339 class BrowserTest : public ExtensionBrowserTest { 340 protected: 341 // In RTL locales wrap the page title with RTL embedding characters so that it 342 // matches the value returned by GetWindowTitle(). 343 base::string16 LocaleWindowCaptionFromPageTitle( 344 const base::string16& expected_title) { 345 base::string16 page_title = WindowCaptionFromPageTitle(expected_title); 346 #if defined(OS_WIN) 347 std::string locale = g_browser_process->GetApplicationLocale(); 348 if (base::i18n::GetTextDirectionForLocale(locale.c_str()) == 349 base::i18n::RIGHT_TO_LEFT) { 350 base::i18n::WrapStringWithLTRFormatting(&page_title); 351 } 352 353 return page_title; 354 #else 355 // Do we need to use the above code on POSIX as well? 356 return page_title; 357 #endif 358 } 359 360 // Returns the app extension aptly named "App Test". 361 const Extension* GetExtension() { 362 const extensions::ExtensionSet* extensions = 363 extensions::ExtensionSystem::Get( 364 browser()->profile())->extension_service()->extensions(); 365 for (extensions::ExtensionSet::const_iterator it = extensions->begin(); 366 it != extensions->end(); ++it) { 367 if ((*it)->name() == "App Test") 368 return it->get(); 369 } 370 NOTREACHED(); 371 return NULL; 372 } 373 }; 374 375 // Launch the app on a page with no title, check that the app title was set 376 // correctly. 377 IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) { 378 #if defined(OS_WIN) && defined(USE_ASH) 379 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 380 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 381 return; 382 #endif 383 384 ui_test_utils::NavigateToURL( 385 browser(), ui_test_utils::GetTestUrl( 386 base::FilePath(base::FilePath::kCurrentDirectory), 387 base::FilePath(kTitle1File))); 388 EXPECT_EQ(LocaleWindowCaptionFromPageTitle(ASCIIToUTF16("title1.html")), 389 browser()->GetWindowTitleForCurrentTab()); 390 base::string16 tab_title; 391 ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title)); 392 EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title); 393 } 394 395 // Launch the app, navigate to a page with a title, check that the app title 396 // was set correctly. 397 IN_PROC_BROWSER_TEST_F(BrowserTest, Title) { 398 #if defined(OS_WIN) && defined(USE_ASH) 399 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 400 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 401 return; 402 #endif 403 404 ui_test_utils::NavigateToURL( 405 browser(), ui_test_utils::GetTestUrl( 406 base::FilePath(base::FilePath::kCurrentDirectory), 407 base::FilePath(kTitle2File))); 408 const base::string16 test_title(ASCIIToUTF16("Title Of Awesomeness")); 409 EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title), 410 browser()->GetWindowTitleForCurrentTab()); 411 base::string16 tab_title; 412 ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title)); 413 EXPECT_EQ(test_title, tab_title); 414 } 415 416 IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) { 417 GURL url(ui_test_utils::GetTestUrl(base::FilePath( 418 base::FilePath::kCurrentDirectory), base::FilePath(kTitle1File))); 419 ui_test_utils::NavigateToURL(browser(), url); 420 AddTabAtIndex(0, url, content::PAGE_TRANSITION_TYPED); 421 EXPECT_EQ(2, browser()->tab_strip_model()->count()); 422 EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); 423 WebContents* second_tab = browser()->tab_strip_model()->GetWebContentsAt(1); 424 ASSERT_TRUE(second_tab); 425 second_tab->GetMainFrame()->ExecuteJavaScript( 426 ASCIIToUTF16("alert('Activate!');")); 427 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 428 alert->CloseModalDialog(); 429 EXPECT_EQ(2, browser()->tab_strip_model()->count()); 430 EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); 431 } 432 433 434 #if defined(OS_WIN) && !defined(NDEBUG) 435 // http://crbug.com/114859. Times out frequently on Windows. 436 #define MAYBE_ThirtyFourTabs DISABLED_ThirtyFourTabs 437 #else 438 #define MAYBE_ThirtyFourTabs ThirtyFourTabs 439 #endif 440 441 // Create 34 tabs and verify that a lot of processes have been created. The 442 // exact number of processes depends on the amount of memory. Previously we 443 // had a hard limit of 31 processes and this test is mainly directed at 444 // verifying that we don't crash when we pass this limit. 445 // Warning: this test can take >30 seconds when running on a slow (low 446 // memory?) Mac builder. 447 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_ThirtyFourTabs) { 448 GURL url(ui_test_utils::GetTestUrl(base::FilePath( 449 base::FilePath::kCurrentDirectory), base::FilePath(kTitle2File))); 450 451 // There is one initial tab. 452 const int kTabCount = 34; 453 for (int ix = 0; ix != (kTabCount - 1); ++ix) { 454 chrome::AddSelectedTabWithURL(browser(), url, 455 content::PAGE_TRANSITION_TYPED); 456 } 457 EXPECT_EQ(kTabCount, browser()->tab_strip_model()->count()); 458 459 // See GetMaxRendererProcessCount() in 460 // content/browser/renderer_host/render_process_host_impl.cc 461 // for the algorithm to decide how many processes to create. 462 const int kExpectedProcessCount = 463 #if defined(ARCH_CPU_64_BITS) 464 17; 465 #else 466 25; 467 #endif 468 if (base::SysInfo::AmountOfPhysicalMemoryMB() >= 2048) { 469 EXPECT_GE(CountRenderProcessHosts(), kExpectedProcessCount); 470 } else { 471 EXPECT_LT(CountRenderProcessHosts(), kExpectedProcessCount); 472 } 473 } 474 475 // Test that a browser-initiated navigation to an aborted URL load leaves around 476 // a pending entry if we start from the NTP but not from a normal page. 477 // See http://crbug.com/355537. 478 IN_PROC_BROWSER_TEST_F(BrowserTest, ClearPendingOnFailUnlessNTP) { 479 ASSERT_TRUE(test_server()->Start()); 480 WebContents* web_contents = 481 browser()->tab_strip_model()->GetActiveWebContents(); 482 GURL ntp_url(chrome::GetNewTabPageURL(browser()->profile())); 483 ui_test_utils::NavigateToURL(browser(), ntp_url); 484 485 // Navigate to a 204 URL (aborts with no content) on the NTP and make sure it 486 // sticks around so that the user can edit it. 487 GURL abort_url(test_server()->GetURL("nocontent")); 488 { 489 content::WindowedNotificationObserver stop_observer( 490 content::NOTIFICATION_LOAD_STOP, 491 content::Source<NavigationController>( 492 &web_contents->GetController())); 493 browser()->OpenURL(OpenURLParams(abort_url, Referrer(), CURRENT_TAB, 494 content::PAGE_TRANSITION_TYPED, false)); 495 stop_observer.Wait(); 496 EXPECT_TRUE(web_contents->GetController().GetPendingEntry()); 497 EXPECT_EQ(abort_url, web_contents->GetVisibleURL()); 498 } 499 500 // Navigate to a real URL. 501 GURL real_url(test_server()->GetURL("title1.html")); 502 ui_test_utils::NavigateToURL(browser(), real_url); 503 EXPECT_EQ(real_url, web_contents->GetVisibleURL()); 504 505 // Now navigating to a 204 URL should clear the pending entry. 506 { 507 content::WindowedNotificationObserver stop_observer( 508 content::NOTIFICATION_LOAD_STOP, 509 content::Source<NavigationController>( 510 &web_contents->GetController())); 511 browser()->OpenURL(OpenURLParams(abort_url, Referrer(), CURRENT_TAB, 512 content::PAGE_TRANSITION_TYPED, false)); 513 stop_observer.Wait(); 514 EXPECT_FALSE(web_contents->GetController().GetPendingEntry()); 515 EXPECT_EQ(real_url, web_contents->GetVisibleURL()); 516 } 517 } 518 519 // Test for crbug.com/297289. Ensure that modal dialogs are closed when a 520 // cross-process navigation is ready to commit. 521 IN_PROC_BROWSER_TEST_F(BrowserTest, CrossProcessNavCancelsDialogs) { 522 ASSERT_TRUE(test_server()->Start()); 523 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 524 GURL url(test_server()->GetURL("empty.html")); 525 ui_test_utils::NavigateToURL(browser(), url); 526 527 // Test this with multiple alert dialogs to ensure that we can navigate away 528 // even if the renderer tries to synchronously create more. 529 // See http://crbug.com/312490. 530 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); 531 contents->GetMainFrame()->ExecuteJavaScript( 532 ASCIIToUTF16("alert('one'); alert('two');")); 533 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 534 EXPECT_TRUE(alert->IsValid()); 535 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance(); 536 EXPECT_TRUE(dialog_queue->HasActiveDialog()); 537 538 // A cross-site navigation should force the dialog to close. 539 GURL url2("http://www.example.com/empty.html"); 540 ui_test_utils::NavigateToURL(browser(), url2); 541 EXPECT_FALSE(dialog_queue->HasActiveDialog()); 542 543 // Make sure input events still work in the renderer process. 544 EXPECT_FALSE(contents->GetRenderProcessHost()->IgnoreInputEvents()); 545 } 546 547 // Make sure that dialogs are closed after a renderer process dies, and that 548 // subsequent navigations work. See http://crbug/com/343265. 549 IN_PROC_BROWSER_TEST_F(BrowserTest, SadTabCancelsDialogs) { 550 ASSERT_TRUE(test_server()->Start()); 551 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 552 GURL beforeunload_url(test_server()->GetURL("files/beforeunload.html")); 553 ui_test_utils::NavigateToURL(browser(), beforeunload_url); 554 555 // Start a navigation to trigger the beforeunload dialog. 556 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); 557 contents->GetMainFrame()->ExecuteJavaScript( 558 ASCIIToUTF16("window.location.href = 'data:text/html,foo'")); 559 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 560 EXPECT_TRUE(alert->IsValid()); 561 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance(); 562 EXPECT_TRUE(dialog_queue->HasActiveDialog()); 563 564 // Crash the renderer process and ensure the dialog is gone. 565 content::RenderProcessHost* child_process = contents->GetRenderProcessHost(); 566 content::RenderProcessHostWatcher crash_observer( 567 child_process, 568 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 569 base::KillProcess(child_process->GetHandle(), 0, false); 570 crash_observer.Wait(); 571 EXPECT_FALSE(dialog_queue->HasActiveDialog()); 572 573 // Make sure subsequent navigations work. 574 GURL url2("http://www.example.com/files/empty.html"); 575 ui_test_utils::NavigateToURL(browser(), url2); 576 } 577 578 // Make sure that dialogs opened by subframes are closed when the process dies. 579 // See http://crbug.com/366510. 580 IN_PROC_BROWSER_TEST_F(BrowserTest, SadTabCancelsSubframeDialogs) { 581 // Navigate to an iframe that opens an alert dialog. 582 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); 583 contents->GetMainFrame()->ExecuteJavaScript( 584 ASCIIToUTF16("window.location.href = 'data:text/html," 585 "<iframe srcdoc=\"<script>alert(1)</script>\">'")); 586 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 587 EXPECT_TRUE(alert->IsValid()); 588 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance(); 589 EXPECT_TRUE(dialog_queue->HasActiveDialog()); 590 591 // Crash the renderer process and ensure the dialog is gone. 592 content::RenderProcessHost* child_process = contents->GetRenderProcessHost(); 593 content::RenderProcessHostWatcher crash_observer( 594 child_process, 595 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 596 base::KillProcess(child_process->GetHandle(), 0, false); 597 crash_observer.Wait(); 598 EXPECT_FALSE(dialog_queue->HasActiveDialog()); 599 600 // Make sure subsequent navigations work. 601 GURL url2("data:text/html,foo"); 602 ui_test_utils::NavigateToURL(browser(), url2); 603 } 604 605 // Test for crbug.com/22004. Reloading a page with a before unload handler and 606 // then canceling the dialog should not leave the throbber spinning. 607 IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) { 608 GURL url(std::string("data:text/html,") + kBeforeUnloadHTML); 609 ui_test_utils::NavigateToURL(browser(), url); 610 611 // Navigate to another page, but click cancel in the dialog. Make sure that 612 // the throbber stops spinning. 613 chrome::Reload(browser(), CURRENT_TAB); 614 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 615 alert->CloseModalDialog(); 616 EXPECT_FALSE( 617 browser()->tab_strip_model()->GetActiveWebContents()->IsLoading()); 618 619 // Clear the beforeunload handler so the test can easily exit. 620 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()-> 621 ExecuteJavaScript(ASCIIToUTF16("onbeforeunload=null;")); 622 } 623 624 class RedirectObserver : public content::WebContentsObserver { 625 public: 626 explicit RedirectObserver(content::WebContents* web_contents) 627 : WebContentsObserver(web_contents) { 628 } 629 630 virtual void DidNavigateAnyFrame( 631 const content::LoadCommittedDetails& details, 632 const content::FrameNavigateParams& params) OVERRIDE { 633 params_ = params; 634 } 635 636 virtual void WebContentsDestroyed() OVERRIDE { 637 // Make sure we don't close the tab while the observer is in scope. 638 // See http://crbug.com/314036. 639 FAIL() << "WebContents closed during navigation (http://crbug.com/314036)."; 640 } 641 642 const content::FrameNavigateParams& params() const { 643 return params_; 644 } 645 646 private: 647 content::FrameNavigateParams params_; 648 649 DISALLOW_COPY_AND_ASSIGN(RedirectObserver); 650 }; 651 652 // Ensure that a transferred cross-process navigation does not generate 653 // DidStopLoading events until the navigation commits. If it did, then 654 // ui_test_utils::NavigateToURL would proceed before the URL had committed. 655 // http://crbug.com/243957. 656 IN_PROC_BROWSER_TEST_F(BrowserTest, NoStopDuringTransferUntilCommit) { 657 // Create HTTP and HTTPS servers for a cross-site transition. 658 ASSERT_TRUE(test_server()->Start()); 659 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS, 660 net::SpawnedTestServer::kLocalhost, 661 base::FilePath(kDocRoot)); 662 ASSERT_TRUE(https_test_server.Start()); 663 664 // Temporarily replace ContentBrowserClient with one that will cause a 665 // process swap on all redirects to HTTPS URLs. 666 TransferHttpsRedirectsContentBrowserClient new_client; 667 content::ContentBrowserClient* old_client = 668 SetBrowserClientForTesting(&new_client); 669 670 GURL init_url(test_server()->GetURL("files/title1.html")); 671 ui_test_utils::NavigateToURL(browser(), init_url); 672 673 // Navigate to a same-site page that redirects, causing a transfer. 674 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); 675 676 // Create a RedirectObserver that goes away before we close the tab. 677 { 678 RedirectObserver redirect_observer(contents); 679 GURL dest_url(https_test_server.GetURL("files/title2.html")); 680 GURL redirect_url(test_server()->GetURL("server-redirect?" + 681 dest_url.spec())); 682 ui_test_utils::NavigateToURL(browser(), redirect_url); 683 684 // We should immediately see the new committed entry. 685 EXPECT_FALSE(contents->GetController().GetPendingEntry()); 686 EXPECT_EQ(dest_url, 687 contents->GetController().GetLastCommittedEntry()->GetURL()); 688 689 // We should keep track of the original request URL, redirect chain, and 690 // page transition type during a transfer, since these are necessary for 691 // history autocomplete to work. 692 EXPECT_EQ(redirect_url, contents->GetController().GetLastCommittedEntry()-> 693 GetOriginalRequestURL()); 694 EXPECT_EQ(2U, redirect_observer.params().redirects.size()); 695 EXPECT_EQ(redirect_url, redirect_observer.params().redirects.at(0)); 696 EXPECT_EQ(dest_url, redirect_observer.params().redirects.at(1)); 697 EXPECT_TRUE(PageTransitionCoreTypeIs(redirect_observer.params().transition, 698 content::PAGE_TRANSITION_TYPED)); 699 } 700 701 // Restore previous browser client. 702 SetBrowserClientForTesting(old_client); 703 } 704 705 // Tests that a cross-process redirect will only cause the beforeunload 706 // handler to run once. 707 IN_PROC_BROWSER_TEST_F(BrowserTest, SingleBeforeUnloadAfterRedirect) { 708 // Create HTTP and HTTPS servers for a cross-site transition. 709 ASSERT_TRUE(test_server()->Start()); 710 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS, 711 net::SpawnedTestServer::kLocalhost, 712 base::FilePath(kDocRoot)); 713 ASSERT_TRUE(https_test_server.Start()); 714 715 // Temporarily replace ContentBrowserClient with one that will cause a 716 // process swap on all redirects to HTTPS URLs. 717 TransferHttpsRedirectsContentBrowserClient new_client; 718 content::ContentBrowserClient* old_client = 719 SetBrowserClientForTesting(&new_client); 720 721 // Navigate to a page with a beforeunload handler. 722 GURL url(test_server()->GetURL("files/beforeunload.html")); 723 ui_test_utils::NavigateToURL(browser(), url); 724 725 // Navigate to a URL that redirects to another process and approve the 726 // beforeunload dialog that pops up. 727 content::WindowedNotificationObserver nav_observer( 728 content::NOTIFICATION_NAV_ENTRY_COMMITTED, 729 content::NotificationService::AllSources()); 730 GURL https_url(https_test_server.GetURL("files/title1.html")); 731 GURL redirect_url(test_server()->GetURL("server-redirect?" + 732 https_url.spec())); 733 browser()->OpenURL(OpenURLParams(redirect_url, Referrer(), CURRENT_TAB, 734 content::PAGE_TRANSITION_TYPED, false)); 735 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 736 EXPECT_TRUE( 737 static_cast<JavaScriptAppModalDialog*>(alert)->is_before_unload_dialog()); 738 alert->native_dialog()->AcceptAppModalDialog(); 739 nav_observer.Wait(); 740 741 // Restore previous browser client. 742 SetBrowserClientForTesting(old_client); 743 } 744 745 // Test for crbug.com/80401. Canceling a before unload dialog should reset 746 // the URL to the previous page's URL. 747 IN_PROC_BROWSER_TEST_F(BrowserTest, CancelBeforeUnloadResetsURL) { 748 GURL url(ui_test_utils::GetTestUrl(base::FilePath( 749 base::FilePath::kCurrentDirectory), base::FilePath(kBeforeUnloadFile))); 750 ui_test_utils::NavigateToURL(browser(), url); 751 752 // Navigate to a page that triggers a cross-site transition. 753 ASSERT_TRUE(test_server()->Start()); 754 GURL url2(test_server()->GetURL("files/title1.html")); 755 browser()->OpenURL(OpenURLParams( 756 url2, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false)); 757 758 content::WindowedNotificationObserver host_destroyed_observer( 759 content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, 760 content::NotificationService::AllSources()); 761 762 // Cancel the dialog. 763 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 764 alert->CloseModalDialog(); 765 EXPECT_FALSE( 766 browser()->tab_strip_model()->GetActiveWebContents()->IsLoading()); 767 768 // Verify there are no pending history items after the dialog is cancelled. 769 // (see crbug.com/93858) 770 NavigationEntry* entry = browser()->tab_strip_model()-> 771 GetActiveWebContents()->GetController().GetPendingEntry(); 772 EXPECT_EQ(NULL, entry); 773 774 // Wait for the ShouldClose_ACK to arrive. We can detect it by waiting for 775 // the pending RVH to be destroyed. 776 host_destroyed_observer.Wait(); 777 EXPECT_EQ(url, browser()->toolbar_model()->GetURL()); 778 779 // Clear the beforeunload handler so the test can easily exit. 780 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()-> 781 ExecuteJavaScript(ASCIIToUTF16("onbeforeunload=null;")); 782 } 783 784 // Crashy on mac. http://crbug.com/38522 Crashy on win too (after 3 years). 785 #if defined(OS_MACOSX) || defined(OS_WIN) 786 #define MAYBE_SingleBeforeUnloadAfterWindowClose \ 787 DISABLED_SingleBeforeUnloadAfterWindowClose 788 #else 789 #define MAYBE_SingleBeforeUnloadAfterWindowClose \ 790 SingleBeforeUnloadAfterWindowClose 791 #endif 792 793 // Test for crbug.com/11647. A page closed with window.close() should not have 794 // two beforeunload dialogs shown. 795 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_SingleBeforeUnloadAfterWindowClose) { 796 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()-> 797 ExecuteJavaScript(ASCIIToUTF16(kOpenNewBeforeUnloadPage)); 798 799 // Close the new window with JavaScript, which should show a single 800 // beforeunload dialog. Then show another alert, to make it easy to verify 801 // that a second beforeunload dialog isn't shown. 802 browser()->tab_strip_model()->GetWebContentsAt(0)->GetMainFrame()-> 803 ExecuteJavaScript(ASCIIToUTF16("w.close(); alert('bar');")); 804 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 805 alert->native_dialog()->AcceptAppModalDialog(); 806 807 alert = ui_test_utils::WaitForAppModalDialog(); 808 EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)-> 809 is_before_unload_dialog()); 810 alert->native_dialog()->AcceptAppModalDialog(); 811 } 812 813 // BrowserTest.BeforeUnloadVsBeforeReload times out on Windows. 814 // http://crbug.com/130411 815 #if defined(OS_WIN) 816 #define MAYBE_BeforeUnloadVsBeforeReload DISABLED_BeforeUnloadVsBeforeReload 817 #else 818 #define MAYBE_BeforeUnloadVsBeforeReload BeforeUnloadVsBeforeReload 819 #endif 820 821 // Test that when a page has an onunload handler, reloading a page shows a 822 // different dialog than navigating to a different page. 823 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_BeforeUnloadVsBeforeReload) { 824 GURL url(std::string("data:text/html,") + kBeforeUnloadHTML); 825 ui_test_utils::NavigateToURL(browser(), url); 826 827 // Reload the page, and check that we get a "before reload" dialog. 828 chrome::Reload(browser(), CURRENT_TAB); 829 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 830 EXPECT_TRUE(static_cast<JavaScriptAppModalDialog*>(alert)->is_reload()); 831 832 // Cancel the reload. 833 alert->native_dialog()->CancelAppModalDialog(); 834 835 // Navigate to another url, and check that we get a "before unload" dialog. 836 GURL url2(url::kAboutBlankURL); 837 browser()->OpenURL(OpenURLParams( 838 url2, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false)); 839 840 alert = ui_test_utils::WaitForAppModalDialog(); 841 EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)->is_reload()); 842 843 // Accept the navigation so we end up on a page without a beforeunload hook. 844 alert->native_dialog()->AcceptAppModalDialog(); 845 } 846 847 // BeforeUnloadAtQuitWithTwoWindows is a regression test for 848 // http://crbug.com/11842. It opens two windows, one of which has a 849 // beforeunload handler and attempts to exit cleanly. 850 class BeforeUnloadAtQuitWithTwoWindows : public InProcessBrowserTest { 851 public: 852 // This test is for testing a specific shutdown behavior. This mimics what 853 // happens in InProcessBrowserTest::RunTestOnMainThread and QuitBrowsers, but 854 // ensures that it happens through the single IDC_EXIT of the test. 855 virtual void CleanUpOnMainThread() OVERRIDE { 856 // Cycle both the MessageLoop and the Cocoa runloop twice to flush out any 857 // Chrome work that generates Cocoa work. Do this twice since there are two 858 // Browsers that must be closed. 859 CycleRunLoops(); 860 CycleRunLoops(); 861 862 // Run the application event loop to completion, which will cycle the 863 // native MessagePump on all platforms. 864 base::MessageLoop::current()->PostTask(FROM_HERE, 865 base::MessageLoop::QuitClosure()); 866 base::MessageLoop::current()->Run(); 867 868 // Take care of any remaining Cocoa work. 869 CycleRunLoops(); 870 871 // At this point, quit should be for real now. 872 ASSERT_EQ(0u, chrome::GetTotalBrowserCount()); 873 } 874 875 // A helper function that cycles the MessageLoop, and on Mac, the Cocoa run 876 // loop. It also drains the NSAutoreleasePool. 877 void CycleRunLoops() { 878 content::RunAllPendingInMessageLoop(); 879 #if defined(OS_MACOSX) 880 chrome::testing::NSRunLoopRunAllPending(); 881 AutoreleasePool()->Recycle(); 882 #endif 883 } 884 }; 885 886 // Disabled, http://crbug.com/159214 . 887 IN_PROC_BROWSER_TEST_F(BeforeUnloadAtQuitWithTwoWindows, 888 DISABLED_IfThisTestTimesOutItIndicatesFAILURE) { 889 // In the first browser, set up a page that has a beforeunload handler. 890 GURL url(std::string("data:text/html,") + kBeforeUnloadHTML); 891 ui_test_utils::NavigateToURL(browser(), url); 892 893 // Open a second browser window at about:blank. 894 ui_test_utils::BrowserAddedObserver browser_added_observer; 895 chrome::NewEmptyWindow(browser()->profile(), chrome::GetActiveDesktop()); 896 Browser* second_window = browser_added_observer.WaitForSingleNewBrowser(); 897 ui_test_utils::NavigateToURL(second_window, GURL(url::kAboutBlankURL)); 898 899 // Tell the application to quit. IDC_EXIT calls AttemptUserExit, which on 900 // everything but ChromeOS allows unload handlers to block exit. On that 901 // platform, though, it exits unconditionally. See the comment and bug ID 902 // in AttemptUserExit() in application_lifetime.cc. 903 #if defined(OS_CHROMEOS) 904 chrome::AttemptExit(); 905 #else 906 chrome::ExecuteCommand(second_window, IDC_EXIT); 907 #endif 908 909 // The beforeunload handler will run at exit, ensure it does, and then accept 910 // it to allow shutdown to proceed. 911 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 912 ASSERT_TRUE(alert); 913 EXPECT_TRUE( 914 static_cast<JavaScriptAppModalDialog*>(alert)->is_before_unload_dialog()); 915 alert->native_dialog()->AcceptAppModalDialog(); 916 917 // But wait there's more! If this test times out, it likely means that the 918 // browser has not been able to quit correctly, indicating there's a 919 // regression of the bug noted above. 920 } 921 922 // Test that scripts can fork a new renderer process for a cross-site popup, 923 // based on http://www.google.com/chrome/intl/en/webmasters-faq.html#newtab. 924 // The script must open a new tab, set its window.opener to null, and navigate 925 // it to a cross-site URL. It should also work for meta-refreshes. 926 // See http://crbug.com/93517. 927 IN_PROC_BROWSER_TEST_F(BrowserTest, NullOpenerRedirectForksProcess) { 928 CommandLine::ForCurrentProcess()->AppendSwitch( 929 switches::kDisablePopupBlocking); 930 931 // Create http and https servers for a cross-site transition. 932 ASSERT_TRUE(test_server()->Start()); 933 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS, 934 net::SpawnedTestServer::kLocalhost, 935 base::FilePath(kDocRoot)); 936 ASSERT_TRUE(https_test_server.Start()); 937 GURL http_url(test_server()->GetURL("files/title1.html")); 938 GURL https_url(https_test_server.GetURL(std::string())); 939 940 // Start with an http URL. 941 ui_test_utils::NavigateToURL(browser(), http_url); 942 WebContents* oldtab = browser()->tab_strip_model()->GetActiveWebContents(); 943 content::RenderProcessHost* process = oldtab->GetRenderProcessHost(); 944 945 // Now open a tab to a blank page, set its opener to null, and redirect it 946 // cross-site. 947 std::string redirect_popup = "w=window.open();"; 948 redirect_popup += "w.opener=null;"; 949 redirect_popup += "w.document.location=\""; 950 redirect_popup += https_url.spec(); 951 redirect_popup += "\";"; 952 953 content::WindowedNotificationObserver popup_observer( 954 chrome::NOTIFICATION_TAB_ADDED, 955 content::NotificationService::AllSources()); 956 content::WindowedNotificationObserver nav_observer( 957 content::NOTIFICATION_NAV_ENTRY_COMMITTED, 958 content::NotificationService::AllSources()); 959 oldtab->GetMainFrame()->ExecuteJavaScript(ASCIIToUTF16(redirect_popup)); 960 961 // Wait for popup window to appear and finish navigating. 962 popup_observer.Wait(); 963 ASSERT_EQ(2, browser()->tab_strip_model()->count()); 964 WebContents* newtab = browser()->tab_strip_model()->GetActiveWebContents(); 965 EXPECT_TRUE(newtab); 966 EXPECT_NE(oldtab, newtab); 967 nav_observer.Wait(); 968 ASSERT_TRUE(newtab->GetController().GetLastCommittedEntry()); 969 EXPECT_EQ(https_url.spec(), 970 newtab->GetController().GetLastCommittedEntry()->GetURL().spec()); 971 972 // Popup window should not be in the opener's process. 973 content::RenderProcessHost* popup_process = 974 newtab->GetRenderProcessHost(); 975 EXPECT_NE(process, popup_process); 976 977 // Now open a tab to a blank page, set its opener to null, and use a 978 // meta-refresh to navigate it instead. 979 std::string refresh_popup = "w=window.open();"; 980 refresh_popup += "w.opener=null;"; 981 refresh_popup += "w.document.write("; 982 refresh_popup += "'<META HTTP-EQUIV=\"refresh\" content=\"0; url="; 983 refresh_popup += https_url.spec(); 984 refresh_popup += "\">');w.document.close();"; 985 986 content::WindowedNotificationObserver popup_observer2( 987 chrome::NOTIFICATION_TAB_ADDED, 988 content::NotificationService::AllSources()); 989 content::WindowedNotificationObserver nav_observer2( 990 content::NOTIFICATION_NAV_ENTRY_COMMITTED, 991 content::NotificationService::AllSources()); 992 oldtab->GetMainFrame()->ExecuteJavaScript(ASCIIToUTF16(refresh_popup)); 993 994 // Wait for popup window to appear and finish navigating. 995 popup_observer2.Wait(); 996 ASSERT_EQ(3, browser()->tab_strip_model()->count()); 997 WebContents* newtab2 = browser()->tab_strip_model()->GetActiveWebContents(); 998 EXPECT_TRUE(newtab2); 999 EXPECT_NE(oldtab, newtab2); 1000 nav_observer2.Wait(); 1001 ASSERT_TRUE(newtab2->GetController().GetLastCommittedEntry()); 1002 EXPECT_EQ(https_url.spec(), 1003 newtab2->GetController().GetLastCommittedEntry()->GetURL().spec()); 1004 1005 // This popup window should also not be in the opener's process. 1006 content::RenderProcessHost* popup_process2 = 1007 newtab2->GetRenderProcessHost(); 1008 EXPECT_NE(process, popup_process2); 1009 } 1010 1011 // Tests that other popup navigations that do not follow the steps at 1012 // http://www.google.com/chrome/intl/en/webmasters-faq.html#newtab will not 1013 // fork a new renderer process. 1014 IN_PROC_BROWSER_TEST_F(BrowserTest, OtherRedirectsDontForkProcess) { 1015 CommandLine::ForCurrentProcess()->AppendSwitch( 1016 switches::kDisablePopupBlocking); 1017 1018 // Create http and https servers for a cross-site transition. 1019 ASSERT_TRUE(test_server()->Start()); 1020 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS, 1021 net::SpawnedTestServer::kLocalhost, 1022 base::FilePath(kDocRoot)); 1023 ASSERT_TRUE(https_test_server.Start()); 1024 GURL http_url(test_server()->GetURL("files/title1.html")); 1025 GURL https_url(https_test_server.GetURL(std::string())); 1026 1027 // Start with an http URL. 1028 ui_test_utils::NavigateToURL(browser(), http_url); 1029 WebContents* oldtab = browser()->tab_strip_model()->GetActiveWebContents(); 1030 content::RenderProcessHost* process = oldtab->GetRenderProcessHost(); 1031 1032 // Now open a tab to a blank page, set its opener to null, and redirect it 1033 // cross-site. 1034 std::string dont_fork_popup = "w=window.open();"; 1035 dont_fork_popup += "w.document.location=\""; 1036 dont_fork_popup += https_url.spec(); 1037 dont_fork_popup += "\";"; 1038 1039 content::WindowedNotificationObserver popup_observer( 1040 chrome::NOTIFICATION_TAB_ADDED, 1041 content::NotificationService::AllSources()); 1042 content::WindowedNotificationObserver nav_observer( 1043 content::NOTIFICATION_NAV_ENTRY_COMMITTED, 1044 content::NotificationService::AllSources()); 1045 oldtab->GetMainFrame()->ExecuteJavaScript(ASCIIToUTF16(dont_fork_popup)); 1046 1047 // Wait for popup window to appear and finish navigating. 1048 popup_observer.Wait(); 1049 ASSERT_EQ(2, browser()->tab_strip_model()->count()); 1050 WebContents* newtab = browser()->tab_strip_model()->GetActiveWebContents(); 1051 EXPECT_TRUE(newtab); 1052 EXPECT_NE(oldtab, newtab); 1053 nav_observer.Wait(); 1054 ASSERT_TRUE(newtab->GetController().GetLastCommittedEntry()); 1055 EXPECT_EQ(https_url.spec(), 1056 newtab->GetController().GetLastCommittedEntry()->GetURL().spec()); 1057 1058 // Popup window should still be in the opener's process. 1059 content::RenderProcessHost* popup_process = 1060 newtab->GetRenderProcessHost(); 1061 EXPECT_EQ(process, popup_process); 1062 1063 // Same thing if the current tab tries to navigate itself. 1064 std::string navigate_str = "document.location=\""; 1065 navigate_str += https_url.spec(); 1066 navigate_str += "\";"; 1067 1068 content::WindowedNotificationObserver nav_observer2( 1069 content::NOTIFICATION_NAV_ENTRY_COMMITTED, 1070 content::NotificationService::AllSources()); 1071 oldtab->GetMainFrame()->ExecuteJavaScript(ASCIIToUTF16(navigate_str)); 1072 nav_observer2.Wait(); 1073 ASSERT_TRUE(oldtab->GetController().GetLastCommittedEntry()); 1074 EXPECT_EQ(https_url.spec(), 1075 oldtab->GetController().GetLastCommittedEntry()->GetURL().spec()); 1076 1077 // Original window should still be in the original process. 1078 content::RenderProcessHost* new_process = newtab->GetRenderProcessHost(); 1079 EXPECT_EQ(process, new_process); 1080 } 1081 1082 // Test that get_process_idle_time() returns reasonable values when compared 1083 // with time deltas measured locally. 1084 IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) { 1085 base::TimeTicks start = base::TimeTicks::Now(); 1086 ui_test_utils::NavigateToURL( 1087 browser(), ui_test_utils::GetTestUrl( 1088 base::FilePath(base::FilePath::kCurrentDirectory), 1089 base::FilePath(kTitle1File))); 1090 content::RenderProcessHost::iterator it( 1091 content::RenderProcessHost::AllHostsIterator()); 1092 for (; !it.IsAtEnd(); it.Advance()) { 1093 base::TimeDelta renderer_td = 1094 it.GetCurrentValue()->GetChildProcessIdleTime(); 1095 base::TimeDelta browser_td = base::TimeTicks::Now() - start; 1096 EXPECT_TRUE(browser_td >= renderer_td); 1097 } 1098 } 1099 1100 // Test IDC_CREATE_SHORTCUTS command is enabled for url scheme file, ftp, http 1101 // and https and disabled for chrome://, about:// etc. 1102 // TODO(pinkerton): Disable app-mode in the model until we implement it 1103 // on the Mac. http://crbug.com/13148 1104 #if !defined(OS_MACOSX) 1105 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFile) { 1106 CommandUpdater* command_updater = 1107 browser()->command_controller()->command_updater(); 1108 1109 static const base::FilePath::CharType* kEmptyFile = 1110 FILE_PATH_LITERAL("empty.html"); 1111 GURL file_url(ui_test_utils::GetTestUrl(base::FilePath( 1112 base::FilePath::kCurrentDirectory), base::FilePath(kEmptyFile))); 1113 ASSERT_TRUE(file_url.SchemeIs(url::kFileScheme)); 1114 ui_test_utils::NavigateToURL(browser(), file_url); 1115 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 1116 } 1117 1118 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttp) { 1119 CommandUpdater* command_updater = 1120 browser()->command_controller()->command_updater(); 1121 1122 ASSERT_TRUE(test_server()->Start()); 1123 GURL http_url(test_server()->GetURL(std::string())); 1124 ASSERT_TRUE(http_url.SchemeIs(url::kHttpScheme)); 1125 ui_test_utils::NavigateToURL(browser(), http_url); 1126 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 1127 } 1128 1129 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutHttps) { 1130 CommandUpdater* command_updater = 1131 browser()->command_controller()->command_updater(); 1132 1133 net::SpawnedTestServer test_server(net::SpawnedTestServer::TYPE_HTTPS, 1134 net::SpawnedTestServer::kLocalhost, 1135 base::FilePath(kDocRoot)); 1136 ASSERT_TRUE(test_server.Start()); 1137 GURL https_url(test_server.GetURL("/")); 1138 ASSERT_TRUE(https_url.SchemeIs(url::kHttpsScheme)); 1139 ui_test_utils::NavigateToURL(browser(), https_url); 1140 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 1141 } 1142 1143 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutFtp) { 1144 CommandUpdater* command_updater = 1145 browser()->command_controller()->command_updater(); 1146 1147 net::SpawnedTestServer test_server(net::SpawnedTestServer::TYPE_FTP, 1148 net::SpawnedTestServer::kLocalhost, 1149 base::FilePath(kDocRoot)); 1150 ASSERT_TRUE(test_server.Start()); 1151 GURL ftp_url(test_server.GetURL(std::string())); 1152 ASSERT_TRUE(ftp_url.SchemeIs(url::kFtpScheme)); 1153 ui_test_utils::NavigateToURL(browser(), ftp_url); 1154 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 1155 } 1156 1157 IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcutInvalid) { 1158 CommandUpdater* command_updater = 1159 browser()->command_controller()->command_updater(); 1160 1161 // Urls that should not have shortcuts. 1162 GURL new_tab_url(chrome::kChromeUINewTabURL); 1163 ui_test_utils::NavigateToURL(browser(), new_tab_url); 1164 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 1165 1166 GURL history_url(chrome::kChromeUIHistoryURL); 1167 ui_test_utils::NavigateToURL(browser(), history_url); 1168 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 1169 1170 GURL downloads_url(chrome::kChromeUIDownloadsURL); 1171 ui_test_utils::NavigateToURL(browser(), downloads_url); 1172 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 1173 1174 GURL blank_url(url::kAboutBlankURL); 1175 ui_test_utils::NavigateToURL(browser(), blank_url); 1176 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS)); 1177 } 1178 1179 // Change a tab into an application window. 1180 // DISABLED: http://crbug.com/72310 1181 IN_PROC_BROWSER_TEST_F(BrowserTest, DISABLED_ConvertTabToAppShortcut) { 1182 ASSERT_TRUE(test_server()->Start()); 1183 GURL http_url(test_server()->GetURL(std::string())); 1184 ASSERT_TRUE(http_url.SchemeIs(url::kHttpScheme)); 1185 1186 ASSERT_EQ(1, browser()->tab_strip_model()->count()); 1187 WebContents* initial_tab = browser()->tab_strip_model()->GetWebContentsAt(0); 1188 WebContents* app_tab = chrome::AddSelectedTabWithURL( 1189 browser(), http_url, content::PAGE_TRANSITION_TYPED); 1190 ASSERT_EQ(2, browser()->tab_strip_model()->count()); 1191 ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile(), 1192 browser()->host_desktop_type())); 1193 1194 // Normal tabs should accept load drops. 1195 EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops); 1196 EXPECT_TRUE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops); 1197 1198 // Turn |app_tab| into a tab in an app panel. 1199 chrome::ConvertTabToAppWindow(browser(), app_tab); 1200 1201 // The launch should have created a new browser. 1202 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(), 1203 browser()->host_desktop_type())); 1204 1205 // Find the new browser. 1206 Browser* app_browser = NULL; 1207 for (chrome::BrowserIterator it; !it.done() && !app_browser; it.Next()) { 1208 if (*it != browser()) 1209 app_browser = *it; 1210 } 1211 ASSERT_TRUE(app_browser); 1212 1213 // Check that the tab contents is in the new browser, and not in the old. 1214 ASSERT_EQ(1, browser()->tab_strip_model()->count()); 1215 ASSERT_EQ(initial_tab, browser()->tab_strip_model()->GetWebContentsAt(0)); 1216 1217 // Check that the appliaction browser has a single tab, and that tab contains 1218 // the content that we app-ified. 1219 ASSERT_EQ(1, app_browser->tab_strip_model()->count()); 1220 ASSERT_EQ(app_tab, app_browser->tab_strip_model()->GetWebContentsAt(0)); 1221 1222 // Normal tabs should accept load drops. 1223 EXPECT_TRUE(initial_tab->GetMutableRendererPrefs()->can_accept_load_drops); 1224 1225 // The tab in an app window should not. 1226 EXPECT_FALSE(app_tab->GetMutableRendererPrefs()->can_accept_load_drops); 1227 } 1228 1229 #endif // !defined(OS_MACOSX) 1230 1231 // Test RenderView correctly send back favicon url for web page that redirects 1232 // to an anchor in javascript body.onload handler. 1233 IN_PROC_BROWSER_TEST_F(BrowserTest, 1234 DISABLED_FaviconOfOnloadRedirectToAnchorPage) { 1235 ASSERT_TRUE(test_server()->Start()); 1236 GURL url(test_server()->GetURL("files/onload_redirect_to_anchor.html")); 1237 GURL expected_favicon_url(test_server()->GetURL("files/test.png")); 1238 1239 ui_test_utils::NavigateToURL(browser(), url); 1240 1241 NavigationEntry* entry = browser()->tab_strip_model()-> 1242 GetActiveWebContents()->GetController().GetLastCommittedEntry(); 1243 EXPECT_EQ(expected_favicon_url.spec(), entry->GetFavicon().url.spec()); 1244 } 1245 1246 #if defined(OS_MACOSX) || defined(OS_LINUX) || defined (OS_WIN) 1247 // http://crbug.com/83828. On Mac 10.6, the failure rate is 14% 1248 #define MAYBE_FaviconChange DISABLED_FaviconChange 1249 #else 1250 #define MAYBE_FaviconChange FaviconChange 1251 #endif 1252 // Test that an icon can be changed from JS. 1253 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_FaviconChange) { 1254 static const base::FilePath::CharType* kFile = 1255 FILE_PATH_LITERAL("onload_change_favicon.html"); 1256 GURL file_url(ui_test_utils::GetTestUrl(base::FilePath( 1257 base::FilePath::kCurrentDirectory), base::FilePath(kFile))); 1258 ASSERT_TRUE(file_url.SchemeIs(url::kFileScheme)); 1259 ui_test_utils::NavigateToURL(browser(), file_url); 1260 1261 NavigationEntry* entry = browser()->tab_strip_model()-> 1262 GetActiveWebContents()->GetController().GetLastCommittedEntry(); 1263 static const base::FilePath::CharType* kIcon = 1264 FILE_PATH_LITERAL("test1.png"); 1265 GURL expected_favicon_url(ui_test_utils::GetTestUrl(base::FilePath( 1266 base::FilePath::kCurrentDirectory), base::FilePath(kIcon))); 1267 EXPECT_EQ(expected_favicon_url.spec(), entry->GetFavicon().url.spec()); 1268 } 1269 1270 // http://crbug.com/172336 1271 #if defined(OS_WIN) 1272 #define MAYBE_TabClosingWhenRemovingExtension \ 1273 DISABLED_TabClosingWhenRemovingExtension 1274 #else 1275 #define MAYBE_TabClosingWhenRemovingExtension TabClosingWhenRemovingExtension 1276 #endif 1277 // Makes sure TabClosing is sent when uninstalling an extension that is an app 1278 // tab. 1279 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_TabClosingWhenRemovingExtension) { 1280 ASSERT_TRUE(test_server()->Start()); 1281 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 1282 GURL url(test_server()->GetURL("empty.html")); 1283 TabStripModel* model = browser()->tab_strip_model(); 1284 1285 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 1286 1287 const Extension* extension_app = GetExtension(); 1288 1289 ui_test_utils::NavigateToURL(browser(), url); 1290 1291 WebContents* app_contents = WebContents::Create( 1292 WebContents::CreateParams(browser()->profile())); 1293 extensions::TabHelper::CreateForWebContents(app_contents); 1294 extensions::TabHelper* extensions_tab_helper = 1295 extensions::TabHelper::FromWebContents(app_contents); 1296 extensions_tab_helper->SetExtensionApp(extension_app); 1297 1298 model->AddWebContents(app_contents, 0, content::PageTransitionFromInt(0), 1299 TabStripModel::ADD_NONE); 1300 model->SetTabPinned(0, true); 1301 ui_test_utils::NavigateToURL(browser(), url); 1302 1303 MockTabStripModelObserver observer; 1304 model->AddObserver(&observer); 1305 1306 // Uninstall the extension and make sure TabClosing is sent. 1307 ExtensionService* service = extensions::ExtensionSystem::Get( 1308 browser()->profile())->extension_service(); 1309 service->UninstallExtension(GetExtension()->id(), false, NULL); 1310 EXPECT_EQ(1, observer.closing_count()); 1311 1312 model->RemoveObserver(&observer); 1313 1314 // There should only be one tab now. 1315 ASSERT_EQ(1, browser()->tab_strip_model()->count()); 1316 } 1317 1318 #if !defined(OS_MACOSX) 1319 // Open with --app-id=<id>, and see that an app window opens. 1320 IN_PROC_BROWSER_TEST_F(BrowserTest, AppIdSwitch) { 1321 ASSERT_TRUE(test_server()->Start()); 1322 1323 // Load an app. 1324 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 1325 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 1326 const Extension* extension_app = GetExtension(); 1327 1328 CommandLine command_line(CommandLine::NO_PROGRAM); 1329 command_line.AppendSwitchASCII(switches::kAppId, extension_app->id()); 1330 1331 chrome::startup::IsFirstRun first_run = first_run::IsChromeFirstRun() ? 1332 chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN; 1333 StartupBrowserCreatorImpl launch(base::FilePath(), command_line, first_run); 1334 ASSERT_TRUE(launch.OpenApplicationWindow(browser()->profile(), NULL)); 1335 1336 // Check that the new browser has an app name. 1337 // The launch should have created a new browser. 1338 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(), 1339 browser()->host_desktop_type())); 1340 1341 // Find the new browser. 1342 Browser* new_browser = NULL; 1343 for (chrome::BrowserIterator it; !it.done() && !new_browser; it.Next()) { 1344 if (*it != browser()) 1345 new_browser = *it; 1346 } 1347 ASSERT_TRUE(new_browser); 1348 ASSERT_TRUE(new_browser != browser()); 1349 1350 // The browser's app_name should include the app's ID. 1351 ASSERT_NE( 1352 new_browser->app_name_.find(extension_app->id()), 1353 std::string::npos) << new_browser->app_name_; 1354 } 1355 1356 // Open an app window and the dev tools window and ensure that the location 1357 // bar settings are correct. 1358 IN_PROC_BROWSER_TEST_F(BrowserTest, ShouldShowLocationBar) { 1359 ASSERT_TRUE(test_server()->Start()); 1360 1361 // Load an app. 1362 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 1363 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 1364 const Extension* extension_app = GetExtension(); 1365 1366 // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would. 1367 WebContents* app_window = 1368 OpenApplication(AppLaunchParams(browser()->profile(), 1369 extension_app, 1370 extensions::LAUNCH_CONTAINER_WINDOW, 1371 NEW_WINDOW)); 1372 ASSERT_TRUE(app_window); 1373 1374 DevToolsWindow::OpenDevToolsWindowForTest( 1375 browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(), 1376 false); 1377 1378 // The launch should have created a new app browser and a dev tools browser. 1379 ASSERT_EQ(3u, 1380 chrome::GetBrowserCount(browser()->profile(), 1381 browser()->host_desktop_type())); 1382 1383 // Find the new browsers. 1384 Browser* app_browser = NULL; 1385 Browser* dev_tools_browser = NULL; 1386 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 1387 if (*it == browser()) { 1388 continue; 1389 } else if ((*it)->app_name() == DevToolsWindow::kDevToolsApp) { 1390 dev_tools_browser = *it; 1391 } else { 1392 app_browser = *it; 1393 } 1394 } 1395 ASSERT_TRUE(dev_tools_browser); 1396 ASSERT_TRUE(app_browser); 1397 ASSERT_TRUE(app_browser != browser()); 1398 1399 EXPECT_FALSE( 1400 dev_tools_browser->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR)); 1401 EXPECT_FALSE( 1402 app_browser->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR)); 1403 } 1404 #endif 1405 1406 // Tests that the CLD (Compact Language Detection) works properly. 1407 IN_PROC_BROWSER_TEST_F(BrowserTest, PageLanguageDetection) { 1408 test::ScopedCLDDynamicDataHarness dynamic_data_scope; 1409 ASSERT_NO_FATAL_FAILURE(dynamic_data_scope.Init()); 1410 ASSERT_TRUE(test_server()->Start()); 1411 1412 LanguageDetectionDetails details; 1413 1414 // Open a new tab with a page in English. 1415 AddTabAtIndex(0, GURL(test_server()->GetURL("files/english_page.html")), 1416 content::PAGE_TRANSITION_TYPED); 1417 1418 WebContents* current_web_contents = 1419 browser()->tab_strip_model()->GetActiveWebContents(); 1420 ChromeTranslateClient* chrome_translate_client = 1421 ChromeTranslateClient::FromWebContents(current_web_contents); 1422 content::Source<WebContents> source(current_web_contents); 1423 1424 ui_test_utils::WindowedNotificationObserverWithDetails< 1425 LanguageDetectionDetails> 1426 en_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, 1427 source); 1428 EXPECT_EQ("", 1429 chrome_translate_client->GetLanguageState().original_language()); 1430 en_language_detected_signal.Wait(); 1431 EXPECT_TRUE(en_language_detected_signal.GetDetailsFor( 1432 source.map_key(), &details)); 1433 EXPECT_EQ("en", details.adopted_language); 1434 EXPECT_EQ("en", 1435 chrome_translate_client->GetLanguageState().original_language()); 1436 1437 // Now navigate to a page in French. 1438 ui_test_utils::WindowedNotificationObserverWithDetails< 1439 LanguageDetectionDetails> 1440 fr_language_detected_signal(chrome::NOTIFICATION_TAB_LANGUAGE_DETERMINED, 1441 source); 1442 ui_test_utils::NavigateToURL( 1443 browser(), GURL(test_server()->GetURL("files/french_page.html"))); 1444 fr_language_detected_signal.Wait(); 1445 details.adopted_language.clear(); 1446 EXPECT_TRUE(fr_language_detected_signal.GetDetailsFor( 1447 source.map_key(), &details)); 1448 EXPECT_EQ("fr", details.adopted_language); 1449 EXPECT_EQ("fr", 1450 chrome_translate_client->GetLanguageState().original_language()); 1451 } 1452 1453 // Chromeos defaults to restoring the last session, so this test isn't 1454 // applicable. 1455 #if !defined(OS_CHROMEOS) 1456 #if defined(OS_MACOSX) 1457 // Crashy, http://crbug.com/38522 1458 #define RestorePinnedTabs DISABLED_RestorePinnedTabs 1459 #endif 1460 // Makes sure pinned tabs are restored correctly on start. 1461 IN_PROC_BROWSER_TEST_F(BrowserTest, RestorePinnedTabs) { 1462 ASSERT_TRUE(test_server()->Start()); 1463 1464 // Add an pinned app tab. 1465 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 1466 GURL url(test_server()->GetURL("empty.html")); 1467 TabStripModel* model = browser()->tab_strip_model(); 1468 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 1469 const Extension* extension_app = GetExtension(); 1470 ui_test_utils::NavigateToURL(browser(), url); 1471 WebContents* app_contents = WebContents::Create( 1472 WebContents::CreateParams(browser()->profile())); 1473 extensions::TabHelper::CreateForWebContents(app_contents); 1474 extensions::TabHelper* extensions_tab_helper = 1475 extensions::TabHelper::FromWebContents(app_contents); 1476 extensions_tab_helper->SetExtensionApp(extension_app); 1477 model->AddWebContents(app_contents, 0, content::PageTransitionFromInt(0), 1478 TabStripModel::ADD_NONE); 1479 model->SetTabPinned(0, true); 1480 ui_test_utils::NavigateToURL(browser(), url); 1481 1482 // Add a non pinned tab. 1483 chrome::NewTab(browser()); 1484 1485 // Add a pinned non-app tab. 1486 chrome::NewTab(browser()); 1487 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); 1488 model->SetTabPinned(2, true); 1489 1490 // Write out the pinned tabs. 1491 PinnedTabCodec::WritePinnedTabs(browser()->profile()); 1492 1493 // Simulate launching again. 1494 CommandLine dummy(CommandLine::NO_PROGRAM); 1495 chrome::startup::IsFirstRun first_run = first_run::IsChromeFirstRun() ? 1496 chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN; 1497 StartupBrowserCreatorImpl launch(base::FilePath(), dummy, first_run); 1498 launch.profile_ = browser()->profile(); 1499 launch.ProcessStartupURLs(std::vector<GURL>(), 1500 browser()->host_desktop_type()); 1501 1502 // The launch should have created a new browser. 1503 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(), 1504 browser()->host_desktop_type())); 1505 1506 // Find the new browser. 1507 Browser* new_browser = NULL; 1508 for (chrome::BrowserIterator it; !it.done() && !new_browser; it.Next()) { 1509 if (*it != browser()) 1510 new_browser = *it; 1511 } 1512 ASSERT_TRUE(new_browser); 1513 ASSERT_TRUE(new_browser != browser()); 1514 1515 // We should get back an additional tab for the app, and another for the 1516 // default home page. 1517 ASSERT_EQ(3, new_browser->tab_strip_model()->count()); 1518 1519 // Make sure the state matches. 1520 TabStripModel* new_model = new_browser->tab_strip_model(); 1521 EXPECT_TRUE(new_model->IsAppTab(0)); 1522 EXPECT_FALSE(new_model->IsAppTab(1)); 1523 EXPECT_FALSE(new_model->IsAppTab(2)); 1524 1525 EXPECT_TRUE(new_model->IsTabPinned(0)); 1526 EXPECT_TRUE(new_model->IsTabPinned(1)); 1527 EXPECT_FALSE(new_model->IsTabPinned(2)); 1528 1529 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), 1530 new_model->GetWebContentsAt(2)->GetURL()); 1531 1532 EXPECT_TRUE( 1533 extensions::TabHelper::FromWebContents( 1534 new_model->GetWebContentsAt(0))->extension_app() == extension_app); 1535 } 1536 #endif // !defined(OS_CHROMEOS) 1537 1538 // This test verifies we don't crash when closing the last window and the app 1539 // menu is showing. 1540 IN_PROC_BROWSER_TEST_F(BrowserTest, CloseWithAppMenuOpen) { 1541 if (browser_defaults::kBrowserAliveWithNoWindows) 1542 return; 1543 1544 // We need a message loop running for menus on windows. 1545 base::MessageLoop::current()->PostTask( 1546 FROM_HERE, base::Bind(&RunCloseWithAppMenuCallback, browser())); 1547 } 1548 1549 #if !defined(OS_MACOSX) 1550 IN_PROC_BROWSER_TEST_F(BrowserTest, OpenAppWindowLikeNtp) { 1551 ASSERT_TRUE(test_server()->Start()); 1552 1553 // Load an app 1554 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 1555 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app/"))); 1556 const Extension* extension_app = GetExtension(); 1557 1558 // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would. 1559 WebContents* app_window = OpenApplication( 1560 AppLaunchParams(browser()->profile(), extension_app, 1561 extensions::LAUNCH_CONTAINER_WINDOW, NEW_WINDOW)); 1562 ASSERT_TRUE(app_window); 1563 1564 // Apps launched in a window from the NTP have an extensions tab helper but 1565 // do not have extension_app set in it. 1566 ASSERT_TRUE(extensions::TabHelper::FromWebContents(app_window)); 1567 EXPECT_FALSE( 1568 extensions::TabHelper::FromWebContents(app_window)->extension_app()); 1569 EXPECT_EQ(extensions::AppLaunchInfo::GetFullLaunchURL(extension_app), 1570 app_window->GetURL()); 1571 1572 // The launch should have created a new browser. 1573 ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile(), 1574 browser()->host_desktop_type())); 1575 1576 // Find the new browser. 1577 Browser* new_browser = NULL; 1578 for (chrome::BrowserIterator it; !it.done() && !new_browser; it.Next()) { 1579 if (*it != browser()) 1580 new_browser = *it; 1581 } 1582 ASSERT_TRUE(new_browser); 1583 ASSERT_TRUE(new_browser != browser()); 1584 1585 EXPECT_TRUE(new_browser->is_app()); 1586 1587 // The browser's app name should include the extension's id. 1588 std::string app_name = new_browser->app_name_; 1589 EXPECT_NE(app_name.find(extension_app->id()), std::string::npos) 1590 << "Name " << app_name << " should contain id "<< extension_app->id(); 1591 } 1592 #endif // !defined(OS_MACOSX) 1593 1594 // Makes sure the browser doesn't crash when 1595 // set_show_state(ui::SHOW_STATE_MAXIMIZED) has been invoked. 1596 IN_PROC_BROWSER_TEST_F(BrowserTest, StartMaximized) { 1597 Browser::Type types[] = { Browser::TYPE_TABBED, Browser::TYPE_POPUP }; 1598 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(types); ++i) { 1599 Browser::CreateParams params(types[i], browser()->profile(), 1600 browser()->host_desktop_type()); 1601 params.initial_show_state = ui::SHOW_STATE_MAXIMIZED; 1602 AddBlankTabAndShow(new Browser(params)); 1603 } 1604 } 1605 1606 // Aura doesn't support minimized window. crbug.com/104571. 1607 #if defined(USE_AURA) 1608 #define MAYBE_StartMinimized DISABLED_StartMinimized 1609 #else 1610 #define MAYBE_StartMinimized StartMinimized 1611 #endif 1612 // Makes sure the browser doesn't crash when 1613 // set_show_state(ui::SHOW_STATE_MINIMIZED) has been invoked. 1614 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_StartMinimized) { 1615 Browser::Type types[] = { Browser::TYPE_TABBED, Browser::TYPE_POPUP }; 1616 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(types); ++i) { 1617 Browser::CreateParams params(types[i], browser()->profile(), 1618 browser()->host_desktop_type()); 1619 params.initial_show_state = ui::SHOW_STATE_MINIMIZED; 1620 AddBlankTabAndShow(new Browser(params)); 1621 } 1622 } 1623 1624 // Makes sure the forward button is disabled immediately when navigating 1625 // forward to a slow-to-commit page. 1626 IN_PROC_BROWSER_TEST_F(BrowserTest, ForwardDisabledOnForward) { 1627 GURL blank_url(url::kAboutBlankURL); 1628 ui_test_utils::NavigateToURL(browser(), blank_url); 1629 1630 ui_test_utils::NavigateToURL( 1631 browser(), ui_test_utils::GetTestUrl( 1632 base::FilePath(base::FilePath::kCurrentDirectory), 1633 base::FilePath(kTitle1File))); 1634 1635 content::WindowedNotificationObserver back_nav_load_observer( 1636 content::NOTIFICATION_LOAD_STOP, 1637 content::Source<NavigationController>( 1638 &browser()->tab_strip_model()->GetActiveWebContents()-> 1639 GetController())); 1640 chrome::GoBack(browser(), CURRENT_TAB); 1641 back_nav_load_observer.Wait(); 1642 CommandUpdater* command_updater = 1643 browser()->command_controller()->command_updater(); 1644 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_FORWARD)); 1645 1646 content::WindowedNotificationObserver forward_nav_load_observer( 1647 content::NOTIFICATION_LOAD_STOP, 1648 content::Source<NavigationController>( 1649 &browser()->tab_strip_model()->GetActiveWebContents()-> 1650 GetController())); 1651 chrome::GoForward(browser(), CURRENT_TAB); 1652 // This check will happen before the navigation completes, since the browser 1653 // won't process the renderer's response until the Wait() call below. 1654 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_FORWARD)); 1655 forward_nav_load_observer.Wait(); 1656 } 1657 1658 // Makes sure certain commands are disabled when Incognito mode is forced. 1659 IN_PROC_BROWSER_TEST_F(BrowserTest, DisableMenuItemsWhenIncognitoIsForced) { 1660 CommandUpdater* command_updater = 1661 browser()->command_controller()->command_updater(); 1662 // At the beginning, all commands are enabled. 1663 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW)); 1664 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW)); 1665 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER)); 1666 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); 1667 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS)); 1668 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_OPTIONS)); 1669 1670 // Set Incognito to FORCED. 1671 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(), 1672 IncognitoModePrefs::FORCED); 1673 // Bookmarks & Settings commands should get disabled. 1674 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW)); 1675 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER)); 1676 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); 1677 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS)); 1678 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS)); 1679 // New Incognito Window command, however, should be enabled. 1680 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW)); 1681 1682 // Create a new browser. 1683 Browser* new_browser = 1684 new Browser(Browser::CreateParams( 1685 browser()->profile()->GetOffTheRecordProfile(), 1686 browser()->host_desktop_type())); 1687 CommandUpdater* new_command_updater = 1688 new_browser->command_controller()->command_updater(); 1689 // It should have Bookmarks & Settings commands disabled by default. 1690 EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_NEW_WINDOW)); 1691 EXPECT_FALSE(new_command_updater->IsCommandEnabled( 1692 IDC_SHOW_BOOKMARK_MANAGER)); 1693 EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); 1694 EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS)); 1695 EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_OPTIONS)); 1696 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW)); 1697 } 1698 1699 // Makes sure New Incognito Window command is disabled when Incognito mode is 1700 // not available. 1701 IN_PROC_BROWSER_TEST_F(BrowserTest, 1702 NoNewIncognitoWindowWhenIncognitoIsDisabled) { 1703 CommandUpdater* command_updater = 1704 browser()->command_controller()->command_updater(); 1705 // Set Incognito to DISABLED. 1706 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(), 1707 IncognitoModePrefs::DISABLED); 1708 // Make sure New Incognito Window command is disabled. All remaining commands 1709 // should be enabled. 1710 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW)); 1711 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW)); 1712 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER)); 1713 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); 1714 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS)); 1715 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_OPTIONS)); 1716 1717 // Create a new browser. 1718 Browser* new_browser = 1719 new Browser(Browser::CreateParams(browser()->profile(), 1720 browser()->host_desktop_type())); 1721 CommandUpdater* new_command_updater = 1722 new_browser->command_controller()->command_updater(); 1723 EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW)); 1724 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_NEW_WINDOW)); 1725 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER)); 1726 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); 1727 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS)); 1728 EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_OPTIONS)); 1729 } 1730 1731 // Makes sure Extensions and Settings commands are disabled in certain 1732 // circumstances even though normally they should stay enabled. 1733 IN_PROC_BROWSER_TEST_F(BrowserTest, 1734 DisableExtensionsAndSettingsWhenIncognitoIsDisabled) { 1735 CommandUpdater* command_updater = 1736 browser()->command_controller()->command_updater(); 1737 // Disable extensions. This should disable Extensions menu. 1738 extensions::ExtensionSystem::Get(browser()->profile())->extension_service()-> 1739 set_extensions_enabled(false); 1740 // Set Incognito to DISABLED. 1741 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(), 1742 IncognitoModePrefs::DISABLED); 1743 // Make sure Manage Extensions command is disabled. 1744 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS)); 1745 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW)); 1746 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER)); 1747 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); 1748 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_OPTIONS)); 1749 1750 // Create a popup (non-main-UI-type) browser. Settings command as well 1751 // as Extensions should be disabled. 1752 Browser* popup_browser = new Browser( 1753 Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(), 1754 browser()->host_desktop_type())); 1755 CommandUpdater* popup_command_updater = 1756 popup_browser->command_controller()->command_updater(); 1757 EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS)); 1758 EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_OPTIONS)); 1759 EXPECT_TRUE(popup_command_updater->IsCommandEnabled( 1760 IDC_SHOW_BOOKMARK_MANAGER)); 1761 EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); 1762 } 1763 1764 // Makes sure Extensions and Settings commands are disabled in certain 1765 // circumstances even though normally they should stay enabled. 1766 IN_PROC_BROWSER_TEST_F(BrowserTest, 1767 DisableOptionsAndImportMenuItemsConsistently) { 1768 // Create a popup browser. 1769 Browser* popup_browser = new Browser( 1770 Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(), 1771 browser()->host_desktop_type())); 1772 CommandUpdater* command_updater = 1773 popup_browser->command_controller()->command_updater(); 1774 // OPTIONS and IMPORT_SETTINGS are disabled for a non-normal UI. 1775 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS)); 1776 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); 1777 1778 // Set Incognito to FORCED. 1779 IncognitoModePrefs::SetAvailability(popup_browser->profile()->GetPrefs(), 1780 IncognitoModePrefs::FORCED); 1781 // OPTIONS and IMPORT_SETTINGS are disabled when Incognito is forced. 1782 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS)); 1783 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); 1784 // Set Incognito to AVAILABLE. 1785 IncognitoModePrefs::SetAvailability(popup_browser->profile()->GetPrefs(), 1786 IncognitoModePrefs::ENABLED); 1787 // OPTIONS and IMPORT_SETTINGS are still disabled since it is a non-normal UI. 1788 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS)); 1789 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); 1790 } 1791 1792 namespace { 1793 1794 void OnZoomLevelChanged(const base::Closure& callback, 1795 const HostZoomMap::ZoomLevelChange& host) { 1796 callback.Run(); 1797 } 1798 1799 } // namespace 1800 1801 #if defined(OS_WIN) 1802 // Flakes regularly on Windows XP 1803 // http://crbug.com/146040 1804 #define MAYBE_PageZoom DISABLED_PageZoom 1805 #else 1806 #define MAYBE_PageZoom PageZoom 1807 #endif 1808 IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_PageZoom) { 1809 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); 1810 bool enable_plus, enable_minus; 1811 1812 { 1813 scoped_refptr<content::MessageLoopRunner> loop_runner( 1814 new content::MessageLoopRunner); 1815 content::HostZoomMap::ZoomLevelChangedCallback callback( 1816 base::Bind(&OnZoomLevelChanged, loop_runner->QuitClosure())); 1817 scoped_ptr<content::HostZoomMap::Subscription> sub = 1818 content::HostZoomMap::GetForBrowserContext( 1819 browser()->profile())->AddZoomLevelChangedCallback(callback); 1820 chrome::Zoom(browser(), content::PAGE_ZOOM_IN); 1821 loop_runner->Run(); 1822 sub.reset(); 1823 EXPECT_EQ(contents->GetZoomPercent(&enable_plus, &enable_minus), 110); 1824 EXPECT_TRUE(enable_plus); 1825 EXPECT_TRUE(enable_minus); 1826 } 1827 1828 { 1829 scoped_refptr<content::MessageLoopRunner> loop_runner( 1830 new content::MessageLoopRunner); 1831 content::HostZoomMap::ZoomLevelChangedCallback callback( 1832 base::Bind(&OnZoomLevelChanged, loop_runner->QuitClosure())); 1833 scoped_ptr<content::HostZoomMap::Subscription> sub = 1834 content::HostZoomMap::GetForBrowserContext( 1835 browser()->profile())->AddZoomLevelChangedCallback(callback); 1836 chrome::Zoom(browser(), content::PAGE_ZOOM_RESET); 1837 loop_runner->Run(); 1838 sub.reset(); 1839 EXPECT_EQ(contents->GetZoomPercent(&enable_plus, &enable_minus), 100); 1840 EXPECT_TRUE(enable_plus); 1841 EXPECT_TRUE(enable_minus); 1842 } 1843 1844 { 1845 scoped_refptr<content::MessageLoopRunner> loop_runner( 1846 new content::MessageLoopRunner); 1847 content::HostZoomMap::ZoomLevelChangedCallback callback( 1848 base::Bind(&OnZoomLevelChanged, loop_runner->QuitClosure())); 1849 scoped_ptr<content::HostZoomMap::Subscription> sub = 1850 content::HostZoomMap::GetForBrowserContext( 1851 browser()->profile())->AddZoomLevelChangedCallback(callback); 1852 chrome::Zoom(browser(), content::PAGE_ZOOM_OUT); 1853 loop_runner->Run(); 1854 sub.reset(); 1855 EXPECT_EQ(contents->GetZoomPercent(&enable_plus, &enable_minus), 90); 1856 EXPECT_TRUE(enable_plus); 1857 EXPECT_TRUE(enable_minus); 1858 } 1859 1860 chrome::Zoom(browser(), content::PAGE_ZOOM_RESET); 1861 } 1862 1863 IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialCommandDisable) { 1864 ASSERT_TRUE(test_server()->Start()); 1865 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 1866 GURL url(test_server()->GetURL("empty.html")); 1867 ui_test_utils::NavigateToURL(browser(), url); 1868 1869 CommandUpdater* command_updater = 1870 browser()->command_controller()->command_updater(); 1871 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_VIEW_SOURCE)); 1872 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_PRINT)); 1873 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SAVE_PAGE)); 1874 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_ENCODING_MENU)); 1875 1876 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); 1877 1878 TestInterstitialPage* interstitial = NULL; 1879 { 1880 scoped_refptr<content::MessageLoopRunner> loop_runner( 1881 new content::MessageLoopRunner); 1882 1883 InterstitialObserver observer(contents, 1884 loop_runner->QuitClosure(), 1885 base::Closure()); 1886 interstitial = new TestInterstitialPage(contents, false, GURL()); 1887 loop_runner->Run(); 1888 } 1889 1890 EXPECT_TRUE(contents->ShowingInterstitialPage()); 1891 1892 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_VIEW_SOURCE)); 1893 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_PRINT)); 1894 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SAVE_PAGE)); 1895 EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_ENCODING_MENU)); 1896 1897 { 1898 scoped_refptr<content::MessageLoopRunner> loop_runner( 1899 new content::MessageLoopRunner); 1900 1901 InterstitialObserver observer(contents, 1902 base::Closure(), 1903 loop_runner->QuitClosure()); 1904 interstitial->Proceed(); 1905 loop_runner->Run(); 1906 // interstitial is deleted now. 1907 } 1908 1909 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_VIEW_SOURCE)); 1910 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_PRINT)); 1911 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SAVE_PAGE)); 1912 EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_ENCODING_MENU)); 1913 } 1914 1915 // Ensure that creating an interstitial page closes any JavaScript dialogs 1916 // that were present on the previous page. See http://crbug.com/295695. 1917 IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialClosesDialogs) { 1918 ASSERT_TRUE(test_server()->Start()); 1919 host_resolver()->AddRule("www.example.com", "127.0.0.1"); 1920 GURL url(test_server()->GetURL("empty.html")); 1921 ui_test_utils::NavigateToURL(browser(), url); 1922 1923 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); 1924 contents->GetMainFrame()->ExecuteJavaScript( 1925 ASCIIToUTF16("alert('Dialog showing!');")); 1926 AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog(); 1927 EXPECT_TRUE(alert->IsValid()); 1928 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance(); 1929 EXPECT_TRUE(dialog_queue->HasActiveDialog()); 1930 1931 TestInterstitialPage* interstitial = NULL; 1932 { 1933 scoped_refptr<content::MessageLoopRunner> loop_runner( 1934 new content::MessageLoopRunner); 1935 1936 InterstitialObserver observer(contents, 1937 loop_runner->QuitClosure(), 1938 base::Closure()); 1939 interstitial = new TestInterstitialPage(contents, false, GURL()); 1940 loop_runner->Run(); 1941 } 1942 1943 // The interstitial should have closed the dialog. 1944 EXPECT_TRUE(contents->ShowingInterstitialPage()); 1945 EXPECT_FALSE(dialog_queue->HasActiveDialog()); 1946 1947 { 1948 scoped_refptr<content::MessageLoopRunner> loop_runner( 1949 new content::MessageLoopRunner); 1950 1951 InterstitialObserver observer(contents, 1952 base::Closure(), 1953 loop_runner->QuitClosure()); 1954 interstitial->DontProceed(); 1955 loop_runner->Run(); 1956 // interstitial is deleted now. 1957 } 1958 1959 // Make sure input events still work in the renderer process. 1960 EXPECT_FALSE(contents->GetRenderProcessHost()->IgnoreInputEvents()); 1961 } 1962 1963 1964 IN_PROC_BROWSER_TEST_F(BrowserTest, InterstitialCloseTab) { 1965 WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); 1966 1967 { 1968 scoped_refptr<content::MessageLoopRunner> loop_runner( 1969 new content::MessageLoopRunner); 1970 1971 InterstitialObserver observer(contents, 1972 loop_runner->QuitClosure(), 1973 base::Closure()); 1974 // Interstitial will delete itself when we close the tab. 1975 new TestInterstitialPage(contents, false, GURL()); 1976 loop_runner->Run(); 1977 } 1978 1979 EXPECT_TRUE(contents->ShowingInterstitialPage()); 1980 1981 { 1982 scoped_refptr<content::MessageLoopRunner> loop_runner( 1983 new content::MessageLoopRunner); 1984 1985 InterstitialObserver observer(contents, 1986 base::Closure(), 1987 loop_runner->QuitClosure()); 1988 chrome::CloseTab(browser()); 1989 loop_runner->Run(); 1990 // interstitial is deleted now. 1991 } 1992 } 1993 1994 class MockWebContentsObserver : public WebContentsObserver { 1995 public: 1996 explicit MockWebContentsObserver(WebContents* web_contents) 1997 : WebContentsObserver(web_contents), 1998 got_user_gesture_(false) { 1999 } 2000 2001 virtual void DidGetUserGesture() OVERRIDE { 2002 got_user_gesture_ = true; 2003 } 2004 2005 bool got_user_gesture() const { 2006 return got_user_gesture_; 2007 } 2008 2009 void set_got_user_gesture(bool got_it) { 2010 got_user_gesture_ = got_it; 2011 } 2012 2013 private: 2014 bool got_user_gesture_; 2015 2016 DISALLOW_COPY_AND_ASSIGN(MockWebContentsObserver); 2017 }; 2018 2019 IN_PROC_BROWSER_TEST_F(BrowserTest, UserGesturesReported) { 2020 // Regression test for http://crbug.com/110707. Also tests that a user 2021 // gesture is sent when a normal navigation (via e.g. the omnibox) is 2022 // performed. 2023 WebContents* web_contents = 2024 browser()->tab_strip_model()->GetActiveWebContents(); 2025 MockWebContentsObserver mock_observer(web_contents); 2026 2027 ASSERT_TRUE(test_server()->Start()); 2028 GURL url(test_server()->GetURL("empty.html")); 2029 2030 ui_test_utils::NavigateToURL(browser(), url); 2031 EXPECT_TRUE(mock_observer.got_user_gesture()); 2032 2033 mock_observer.set_got_user_gesture(false); 2034 chrome::Reload(browser(), CURRENT_TAB); 2035 EXPECT_TRUE(mock_observer.got_user_gesture()); 2036 } 2037 2038 // TODO(ben): this test was never enabled. It has bit-rotted since being added. 2039 // It originally lived in browser_unittest.cc, but has been moved here to make 2040 // room for real browser unit tests. 2041 #if 0 2042 class BrowserTest2 : public InProcessBrowserTest { 2043 public: 2044 BrowserTest2() { 2045 host_resolver_proc_ = new net::RuleBasedHostResolverProc(NULL); 2046 // Avoid making external DNS lookups. In this test we don't need this 2047 // to succeed. 2048 host_resolver_proc_->AddSimulatedFailure("*.google.com"); 2049 scoped_host_resolver_proc_.Init(host_resolver_proc_.get()); 2050 } 2051 2052 private: 2053 scoped_refptr<net::RuleBasedHostResolverProc> host_resolver_proc_; 2054 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc_; 2055 }; 2056 2057 IN_PROC_BROWSER_TEST_F(BrowserTest2, NoTabsInPopups) { 2058 chrome::RegisterAppPrefs(L"Test"); 2059 2060 // We start with a normal browser with one tab. 2061 EXPECT_EQ(1, browser()->tab_strip_model()->count()); 2062 2063 // Open a popup browser with a single blank foreground tab. 2064 Browser* popup_browser = new Browser( 2065 Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile())); 2066 chrome::AddTabAt(popup_browser, GURL(), -1, true); 2067 EXPECT_EQ(1, popup_browser->tab_strip_model()->count()); 2068 2069 // Now try opening another tab in the popup browser. 2070 AddTabWithURLParams params1(url, content::PAGE_TRANSITION_TYPED); 2071 popup_browser->AddTabWithURL(¶ms1); 2072 EXPECT_EQ(popup_browser, params1.target); 2073 2074 // The popup should still only have one tab. 2075 EXPECT_EQ(1, popup_browser->tab_strip_model()->count()); 2076 2077 // The normal browser should now have two. 2078 EXPECT_EQ(2, browser()->tab_strip_model()->count()); 2079 2080 // Open an app frame browser with a single blank foreground tab. 2081 Browser* app_browser = new Browser(Browser::CreateParams::CreateForApp( 2082 L"Test", browser()->profile(), false)); 2083 chrome::AddTabAt(app_browser, GURL(), -1, true); 2084 EXPECT_EQ(1, app_browser->tab_strip_model()->count()); 2085 2086 // Now try opening another tab in the app browser. 2087 AddTabWithURLParams params2(GURL(url::kAboutBlankURL), 2088 content::PAGE_TRANSITION_TYPED); 2089 app_browser->AddTabWithURL(¶ms2); 2090 EXPECT_EQ(app_browser, params2.target); 2091 2092 // The popup should still only have one tab. 2093 EXPECT_EQ(1, app_browser->tab_strip_model()->count()); 2094 2095 // The normal browser should now have three. 2096 EXPECT_EQ(3, browser()->tab_strip_model()->count()); 2097 2098 // Open an app frame popup browser with a single blank foreground tab. 2099 Browser* app_popup_browser = new Browser(Browser::CreateParams::CreateForApp( 2100 L"Test", browser()->profile(), false)); 2101 chrome::AddTabAt(app_popup_browser, GURL(), -1, true); 2102 EXPECT_EQ(1, app_popup_browser->tab_strip_model()->count()); 2103 2104 // Now try opening another tab in the app popup browser. 2105 AddTabWithURLParams params3(GURL(url::kAboutBlankURL), 2106 content::PAGE_TRANSITION_TYPED); 2107 app_popup_browser->AddTabWithURL(¶ms3); 2108 EXPECT_EQ(app_popup_browser, params3.target); 2109 2110 // The popup should still only have one tab. 2111 EXPECT_EQ(1, app_popup_browser->tab_strip_model()->count()); 2112 2113 // The normal browser should now have four. 2114 EXPECT_EQ(4, browser()->tab_strip_model()->count()); 2115 2116 // Close the additional browsers. 2117 popup_browser->tab_strip_model()->CloseAllTabs(); 2118 app_browser->tab_strip_model()->CloseAllTabs(); 2119 app_popup_browser->tab_strip_model()->CloseAllTabs(); 2120 } 2121 #endif 2122 2123 IN_PROC_BROWSER_TEST_F(BrowserTest, WindowOpenClose) { 2124 CommandLine::ForCurrentProcess()->AppendSwitch( 2125 switches::kDisablePopupBlocking); 2126 GURL url = ui_test_utils::GetTestUrl( 2127 base::FilePath(), base::FilePath().AppendASCII("window.close.html")); 2128 2129 base::string16 title = ASCIIToUTF16("Title Of Awesomeness"); 2130 content::TitleWatcher title_watcher( 2131 browser()->tab_strip_model()->GetActiveWebContents(), title); 2132 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 2); 2133 EXPECT_EQ(title, title_watcher.WaitAndGetTitle()); 2134 } 2135 2136 // TODO(linux_aura) http://crbug.com/163931 2137 // Mac disabled: http://crbug.com/169820 2138 #if !defined(OS_MACOSX) && \ 2139 !(defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)) 2140 IN_PROC_BROWSER_TEST_F(BrowserTest, FullscreenBookmarkBar) { 2141 #if defined(OS_WIN) && defined(USE_ASH) 2142 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 2143 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 2144 return; 2145 #endif 2146 2147 chrome::ToggleBookmarkBar(browser()); 2148 EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state()); 2149 chrome::ToggleFullscreenMode(browser()); 2150 EXPECT_TRUE(browser()->window()->IsFullscreen()); 2151 #if defined(OS_MACOSX) 2152 EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state()); 2153 #elif defined(OS_CHROMEOS) 2154 // TODO(jamescook): If immersive fullscreen is disabled by default, test 2155 // for BookmarkBar::HIDDEN. 2156 EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state()); 2157 #else 2158 EXPECT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state()); 2159 #endif 2160 } 2161 #endif 2162 2163 IN_PROC_BROWSER_TEST_F(BrowserTest, DisallowFileUrlUniversalAccessTest) { 2164 GURL url = ui_test_utils::GetTestUrl( 2165 base::FilePath(), 2166 base::FilePath().AppendASCII("fileurl_universalaccess.html")); 2167 2168 base::string16 expected_title(ASCIIToUTF16("Disallowed")); 2169 content::TitleWatcher title_watcher( 2170 browser()->tab_strip_model()->GetActiveWebContents(), expected_title); 2171 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("Allowed")); 2172 ui_test_utils::NavigateToURL(browser(), url); 2173 ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle()); 2174 } 2175 2176 class KioskModeTest : public BrowserTest { 2177 public: 2178 KioskModeTest() {} 2179 2180 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 2181 command_line->AppendSwitch(switches::kKioskMode); 2182 } 2183 }; 2184 2185 #if defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) 2186 // Mac: http://crbug.com/103912 2187 // Linux: http://crbug.com/163931 2188 #define MAYBE_EnableKioskModeTest DISABLED_EnableKioskModeTest 2189 #else 2190 #define MAYBE_EnableKioskModeTest EnableKioskModeTest 2191 #endif 2192 IN_PROC_BROWSER_TEST_F(KioskModeTest, MAYBE_EnableKioskModeTest) { 2193 // Check if browser is in fullscreen mode. 2194 ASSERT_TRUE(browser()->window()->IsFullscreen()); 2195 ASSERT_FALSE(browser()->window()->IsFullscreenBubbleVisible()); 2196 } 2197 2198 #if defined(OS_WIN) 2199 // This test verifies that Chrome can be launched with a user-data-dir path 2200 // which contains non ASCII characters. 2201 class LaunchBrowserWithNonAsciiUserDatadir : public BrowserTest { 2202 public: 2203 LaunchBrowserWithNonAsciiUserDatadir() {} 2204 2205 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 2206 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 2207 base::FilePath tmp_profile = temp_dir_.path().AppendASCII("tmp_profile"); 2208 tmp_profile = tmp_profile.Append(L"Test Chrome G\u00E9raldine"); 2209 2210 ASSERT_TRUE(base::CreateDirectory(tmp_profile)); 2211 command_line->AppendSwitchPath(switches::kUserDataDir, tmp_profile); 2212 } 2213 2214 base::ScopedTempDir temp_dir_; 2215 }; 2216 2217 IN_PROC_BROWSER_TEST_F(LaunchBrowserWithNonAsciiUserDatadir, 2218 TestNonAsciiUserDataDir) { 2219 // Verify that the window is present. 2220 ASSERT_TRUE(browser()); 2221 } 2222 #endif // defined(OS_WIN) 2223 2224 // Tests to ensure that the browser continues running in the background after 2225 // the last window closes. 2226 class RunInBackgroundTest : public BrowserTest { 2227 public: 2228 RunInBackgroundTest() {} 2229 2230 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 2231 command_line->AppendSwitch(switches::kKeepAliveForTest); 2232 } 2233 }; 2234 2235 IN_PROC_BROWSER_TEST_F(RunInBackgroundTest, RunInBackgroundBasicTest) { 2236 // Close the browser window, then open a new one - the browser should keep 2237 // running. 2238 Profile* profile = browser()->profile(); 2239 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); 2240 content::WindowedNotificationObserver observer( 2241 chrome::NOTIFICATION_BROWSER_CLOSED, 2242 content::Source<Browser>(browser())); 2243 chrome::CloseWindow(browser()); 2244 observer.Wait(); 2245 EXPECT_EQ(0u, chrome::GetTotalBrowserCount()); 2246 2247 ui_test_utils::BrowserAddedObserver browser_added_observer; 2248 chrome::NewEmptyWindow(profile, chrome::GetActiveDesktop()); 2249 browser_added_observer.WaitForSingleNewBrowser(); 2250 2251 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); 2252 } 2253 2254 // Tests to ensure that the browser continues running in the background after 2255 // the last window closes. 2256 class NoStartupWindowTest : public BrowserTest { 2257 public: 2258 NoStartupWindowTest() {} 2259 2260 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 2261 command_line->AppendSwitch(switches::kNoStartupWindow); 2262 command_line->AppendSwitch(switches::kKeepAliveForTest); 2263 } 2264 }; 2265 2266 IN_PROC_BROWSER_TEST_F(NoStartupWindowTest, NoStartupWindowBasicTest) { 2267 #if defined(OS_WIN) && defined(USE_ASH) 2268 // kNoStartupWindow doesn't make sense in Metro+Ash. 2269 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 2270 return; 2271 #endif 2272 2273 // No browser window should be started by default. 2274 EXPECT_EQ(0u, chrome::GetTotalBrowserCount()); 2275 2276 // Starting a browser window should work just fine. 2277 ui_test_utils::BrowserAddedObserver browser_added_observer; 2278 CreateBrowser(ProfileManager::GetActiveUserProfile()); 2279 browser_added_observer.WaitForSingleNewBrowser(); 2280 2281 EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); 2282 } 2283 2284 // Chromeos needs to track app windows because it considers them to be part of 2285 // session state. 2286 #if !defined(OS_CHROMEOS) 2287 IN_PROC_BROWSER_TEST_F(NoStartupWindowTest, DontInitSessionServiceForApps) { 2288 #if defined(OS_WIN) && defined(USE_ASH) 2289 // kNoStartupWindow doesn't make sense in Metro+Ash. 2290 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 2291 return; 2292 #endif 2293 2294 Profile* profile = ProfileManager::GetActiveUserProfile(); 2295 2296 SessionService* session_service = 2297 SessionServiceFactory::GetForProfile(profile); 2298 ASSERT_FALSE(session_service->processed_any_commands()); 2299 2300 ui_test_utils::BrowserAddedObserver browser_added_observer; 2301 CreateBrowserForApp("blah", profile); 2302 browser_added_observer.WaitForSingleNewBrowser(); 2303 2304 ASSERT_FALSE(session_service->processed_any_commands()); 2305 } 2306 #endif // !defined(OS_CHROMEOS) 2307 2308 // This test needs to be placed outside the anonymous namespace because we 2309 // need to access private type of Browser. 2310 class AppModeTest : public BrowserTest { 2311 public: 2312 AppModeTest() {} 2313 2314 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 2315 GURL url = ui_test_utils::GetTestUrl( 2316 base::FilePath(), base::FilePath().AppendASCII("title1.html")); 2317 command_line->AppendSwitchASCII(switches::kApp, url.spec()); 2318 } 2319 }; 2320 2321 IN_PROC_BROWSER_TEST_F(AppModeTest, EnableAppModeTest) { 2322 #if defined(OS_WIN) && defined(USE_ASH) 2323 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 2324 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 2325 return; 2326 #endif 2327 2328 // Test that an application browser window loads correctly. 2329 2330 // Verify the browser is in application mode. 2331 EXPECT_TRUE(browser()->is_app()); 2332 } 2333 2334 // Confirm chrome://version contains some expected content. 2335 IN_PROC_BROWSER_TEST_F(BrowserTest, AboutVersion) { 2336 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL)); 2337 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 2338 ASSERT_GT(ui_test_utils::FindInPage(tab, ASCIIToUTF16("WebKit"), true, true, 2339 NULL, NULL), 2340 0); 2341 ASSERT_GT(ui_test_utils::FindInPage(tab, ASCIIToUTF16("OS"), true, true, 2342 NULL, NULL), 2343 0); 2344 ASSERT_GT(ui_test_utils::FindInPage(tab, ASCIIToUTF16("JavaScript"), true, 2345 true, NULL, NULL), 2346 0); 2347 } 2348 2349 static const base::FilePath::CharType* kTestDir = 2350 FILE_PATH_LITERAL("click_modifier"); 2351 static const char kFirstPageTitle[] = "First window"; 2352 static const char kSecondPageTitle[] = "New window!"; 2353 2354 class ClickModifierTest : public InProcessBrowserTest { 2355 public: 2356 ClickModifierTest() { 2357 } 2358 2359 // Returns a url that opens a new window or tab when clicked, via javascript. 2360 GURL GetWindowOpenURL() { 2361 return ui_test_utils::GetTestUrl( 2362 base::FilePath(kTestDir), 2363 base::FilePath(FILE_PATH_LITERAL("window_open.html"))); 2364 } 2365 2366 // Returns a url that follows a simple link when clicked, unless affected by 2367 // modifiers. 2368 GURL GetHrefURL() { 2369 return ui_test_utils::GetTestUrl( 2370 base::FilePath(kTestDir), 2371 base::FilePath(FILE_PATH_LITERAL("href.html"))); 2372 } 2373 2374 base::string16 getFirstPageTitle() { 2375 return ASCIIToUTF16(kFirstPageTitle); 2376 } 2377 2378 base::string16 getSecondPageTitle() { 2379 return ASCIIToUTF16(kSecondPageTitle); 2380 } 2381 2382 // Loads our test page and simulates a single click using the supplied button 2383 // and modifiers. The click will cause either a navigation or the creation of 2384 // a new window or foreground or background tab. We verify that the expected 2385 // disposition occurs. 2386 void RunTest(Browser* browser, 2387 const GURL& url, 2388 int modifiers, 2389 blink::WebMouseEvent::Button button, 2390 WindowOpenDisposition disposition) { 2391 ui_test_utils::NavigateToURL(browser, url); 2392 EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(), 2393 browser->host_desktop_type())); 2394 EXPECT_EQ(1, browser->tab_strip_model()->count()); 2395 content::WebContents* web_contents = 2396 browser->tab_strip_model()->GetActiveWebContents(); 2397 EXPECT_EQ(url, web_contents->GetURL()); 2398 2399 if (disposition == CURRENT_TAB) { 2400 content::WebContents* web_contents = 2401 browser->tab_strip_model()->GetActiveWebContents(); 2402 content::TestNavigationObserver same_tab_observer(web_contents); 2403 SimulateMouseClick(web_contents, modifiers, button); 2404 same_tab_observer.Wait(); 2405 EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(), 2406 browser->host_desktop_type())); 2407 EXPECT_EQ(1, browser->tab_strip_model()->count()); 2408 EXPECT_EQ(getSecondPageTitle(), web_contents->GetTitle()); 2409 return; 2410 } 2411 2412 content::WindowedNotificationObserver observer( 2413 chrome::NOTIFICATION_TAB_ADDED, 2414 content::NotificationService::AllSources()); 2415 SimulateMouseClick(web_contents, modifiers, button); 2416 observer.Wait(); 2417 2418 if (disposition == NEW_WINDOW) { 2419 EXPECT_EQ(2u, chrome::GetBrowserCount(browser->profile(), 2420 browser->host_desktop_type())); 2421 return; 2422 } 2423 2424 EXPECT_EQ(1u, chrome::GetBrowserCount(browser->profile(), 2425 browser->host_desktop_type())); 2426 EXPECT_EQ(2, browser->tab_strip_model()->count()); 2427 web_contents = browser->tab_strip_model()->GetActiveWebContents(); 2428 WaitForLoadStop(web_contents); 2429 if (disposition == NEW_FOREGROUND_TAB) { 2430 EXPECT_EQ(getSecondPageTitle(), web_contents->GetTitle()); 2431 } else { 2432 ASSERT_EQ(NEW_BACKGROUND_TAB, disposition); 2433 EXPECT_EQ(getFirstPageTitle(), web_contents->GetTitle()); 2434 } 2435 } 2436 2437 private: 2438 DISALLOW_COPY_AND_ASSIGN(ClickModifierTest); 2439 }; 2440 2441 // Tests for clicking on elements with handlers that run window.open. 2442 2443 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenBasicClickTest) { 2444 int modifiers = 0; 2445 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft; 2446 WindowOpenDisposition disposition = NEW_FOREGROUND_TAB; 2447 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition); 2448 } 2449 2450 // TODO(ericu): Alt-click behavior on window.open is platform-dependent and not 2451 // well defined. Should we add tests so we know if it changes? 2452 2453 // Shift-clicks open in a new window. 2454 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenShiftClickTest) { 2455 int modifiers = blink::WebInputEvent::ShiftKey; 2456 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft; 2457 WindowOpenDisposition disposition = NEW_WINDOW; 2458 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition); 2459 } 2460 2461 // Control-clicks open in a background tab. 2462 // On OSX meta [the command key] takes the place of control. 2463 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenControlClickTest) { 2464 #if defined(OS_MACOSX) 2465 int modifiers = blink::WebInputEvent::MetaKey; 2466 #else 2467 int modifiers = blink::WebInputEvent::ControlKey; 2468 #endif 2469 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft; 2470 WindowOpenDisposition disposition = NEW_BACKGROUND_TAB; 2471 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition); 2472 } 2473 2474 // Control-shift-clicks open in a foreground tab. 2475 // On OSX meta [the command key] takes the place of control. 2476 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenControlShiftClickTest) { 2477 #if defined(OS_MACOSX) 2478 int modifiers = blink::WebInputEvent::MetaKey; 2479 #else 2480 int modifiers = blink::WebInputEvent::ControlKey; 2481 #endif 2482 modifiers |= blink::WebInputEvent::ShiftKey; 2483 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft; 2484 WindowOpenDisposition disposition = NEW_FOREGROUND_TAB; 2485 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition); 2486 } 2487 2488 // Middle-clicks open in a background tab. 2489 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenMiddleClickTest) { 2490 int modifiers = 0; 2491 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle; 2492 WindowOpenDisposition disposition = NEW_BACKGROUND_TAB; 2493 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition); 2494 } 2495 2496 // Shift-middle-clicks open in a foreground tab. 2497 IN_PROC_BROWSER_TEST_F(ClickModifierTest, WindowOpenShiftMiddleClickTest) { 2498 int modifiers = blink::WebInputEvent::ShiftKey; 2499 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle; 2500 WindowOpenDisposition disposition = NEW_FOREGROUND_TAB; 2501 RunTest(browser(), GetWindowOpenURL(), modifiers, button, disposition); 2502 } 2503 2504 // Tests for clicking on normal links. 2505 2506 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefBasicClickTest) { 2507 int modifiers = 0; 2508 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft; 2509 WindowOpenDisposition disposition = CURRENT_TAB; 2510 RunTest(browser(), GetHrefURL(), modifiers, button, disposition); 2511 } 2512 2513 // TODO(ericu): Alt-click behavior on links is platform-dependent and not well 2514 // defined. Should we add tests so we know if it changes? 2515 2516 // Shift-clicks open in a new window. 2517 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefShiftClickTest) { 2518 int modifiers = blink::WebInputEvent::ShiftKey; 2519 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft; 2520 WindowOpenDisposition disposition = NEW_WINDOW; 2521 RunTest(browser(), GetHrefURL(), modifiers, button, disposition); 2522 } 2523 2524 // Control-clicks open in a background tab. 2525 // On OSX meta [the command key] takes the place of control. 2526 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefControlClickTest) { 2527 #if defined(OS_MACOSX) 2528 int modifiers = blink::WebInputEvent::MetaKey; 2529 #else 2530 int modifiers = blink::WebInputEvent::ControlKey; 2531 #endif 2532 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft; 2533 WindowOpenDisposition disposition = NEW_BACKGROUND_TAB; 2534 RunTest(browser(), GetHrefURL(), modifiers, button, disposition); 2535 } 2536 2537 // Control-shift-clicks open in a foreground tab. 2538 // On OSX meta [the command key] takes the place of control. 2539 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefControlShiftClickTest) { 2540 #if defined(OS_MACOSX) 2541 int modifiers = blink::WebInputEvent::MetaKey; 2542 #else 2543 int modifiers = blink::WebInputEvent::ControlKey; 2544 #endif 2545 modifiers |= blink::WebInputEvent::ShiftKey; 2546 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonLeft; 2547 WindowOpenDisposition disposition = NEW_FOREGROUND_TAB; 2548 RunTest(browser(), GetHrefURL(), modifiers, button, disposition); 2549 } 2550 2551 // Middle-clicks open in a background tab. 2552 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefMiddleClickTest) { 2553 int modifiers = 0; 2554 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle; 2555 WindowOpenDisposition disposition = NEW_BACKGROUND_TAB; 2556 RunTest(browser(), GetHrefURL(), modifiers, button, disposition); 2557 } 2558 2559 // Shift-middle-clicks open in a foreground tab. 2560 IN_PROC_BROWSER_TEST_F(ClickModifierTest, HrefShiftMiddleClickTest) { 2561 int modifiers = blink::WebInputEvent::ShiftKey; 2562 blink::WebMouseEvent::Button button = blink::WebMouseEvent::ButtonMiddle; 2563 WindowOpenDisposition disposition = NEW_FOREGROUND_TAB; 2564 RunTest(browser(), GetHrefURL(), modifiers, button, disposition); 2565 } 2566 2567 IN_PROC_BROWSER_TEST_F(BrowserTest, GetSizeForNewRenderView) { 2568 // The instant extended NTP has javascript that does not work with 2569 // ui_test_utils::NavigateToURL. The NTP rvh reloads when the browser tries 2570 // to navigate away from the page, which causes the WebContents to end up in 2571 // an inconsistent state. (is_loaded = true, last_commited_url=ntp, 2572 // visible_url=title1.html) 2573 browser()->profile()->GetPrefs()->SetBoolean(prefs::kWebKitJavascriptEnabled, 2574 false); 2575 ASSERT_TRUE(test_server()->Start()); 2576 // Create an HTTPS server for cross-site transition. 2577 net::SpawnedTestServer https_test_server(net::SpawnedTestServer::TYPE_HTTPS, 2578 net::SpawnedTestServer::kLocalhost, 2579 base::FilePath(kDocRoot)); 2580 ASSERT_TRUE(https_test_server.Start()); 2581 2582 // Start with NTP. 2583 ui_test_utils::NavigateToURL(browser(), GURL("chrome://newtab")); 2584 ASSERT_EQ(BookmarkBar::DETACHED, browser()->bookmark_bar_state()); 2585 WebContents* web_contents = 2586 browser()->tab_strip_model()->GetActiveWebContents(); 2587 content::RenderViewHost* prev_rvh = web_contents->GetRenderViewHost(); 2588 const int height_inset = 2589 browser()->window()->GetRenderViewHeightInsetWithDetachedBookmarkBar(); 2590 const gfx::Size initial_wcv_size = 2591 web_contents->GetContainerBounds().size(); 2592 RenderViewSizeObserver observer(web_contents, browser()->window()); 2593 2594 // Navigate to a non-NTP page, without resizing WebContentsView. 2595 ui_test_utils::NavigateToURL(browser(), 2596 test_server()->GetURL("files/title1.html")); 2597 ASSERT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state()); 2598 // A new RenderViewHost should be created. 2599 EXPECT_NE(prev_rvh, web_contents->GetRenderViewHost()); 2600 prev_rvh = web_contents->GetRenderViewHost(); 2601 gfx::Size rwhv_create_size0, rwhv_commit_size0, wcv_commit_size0; 2602 observer.GetSizeForRenderViewHost(web_contents->GetRenderViewHost(), 2603 &rwhv_create_size0, 2604 &rwhv_commit_size0, 2605 &wcv_commit_size0); 2606 // The create height of RenderWidgetHostView should include the height inset. 2607 EXPECT_EQ(gfx::Size(initial_wcv_size.width(), 2608 initial_wcv_size.height() + height_inset), 2609 rwhv_create_size0); 2610 // When a navigation entry is committed, the size of RenderWidgetHostView 2611 // should be the same as when it was first created. 2612 EXPECT_EQ(rwhv_create_size0, rwhv_commit_size0); 2613 // Sizes of the current RenderWidgetHostView and WebContentsView should not 2614 // change before and after WebContentsDelegate::DidNavigateMainFramePostCommit 2615 // (implemented by Browser); we obtain the sizes before PostCommit via 2616 // WebContentsObserver::NavigationEntryCommitted (implemented by 2617 // RenderViewSizeObserver). 2618 EXPECT_EQ(rwhv_commit_size0, 2619 web_contents->GetRenderWidgetHostView()->GetViewBounds().size()); 2620 // The behavior differs between OSX and views. 2621 // In OSX, the wcv does not change size until after the commit, when the 2622 // bookmark bar disappears (correct). 2623 // In views, the wcv changes size at commit time. 2624 #if defined(OS_MACOSX) 2625 EXPECT_EQ(gfx::Size(wcv_commit_size0.width(), 2626 wcv_commit_size0.height() + height_inset), 2627 web_contents->GetContainerBounds().size()); 2628 #else 2629 EXPECT_EQ(wcv_commit_size0, web_contents->GetContainerBounds().size()); 2630 #endif 2631 2632 // Navigate to another non-NTP page, without resizing WebContentsView. 2633 ui_test_utils::NavigateToURL(browser(), 2634 https_test_server.GetURL("files/title2.html")); 2635 ASSERT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state()); 2636 // A new RenderVieHost should be created. 2637 EXPECT_NE(prev_rvh, web_contents->GetRenderViewHost()); 2638 gfx::Size rwhv_create_size1, rwhv_commit_size1, wcv_commit_size1; 2639 observer.GetSizeForRenderViewHost(web_contents->GetRenderViewHost(), 2640 &rwhv_create_size1, 2641 &rwhv_commit_size1, 2642 &wcv_commit_size1); 2643 EXPECT_EQ(rwhv_create_size1, rwhv_commit_size1); 2644 EXPECT_EQ(rwhv_commit_size1, 2645 web_contents->GetRenderWidgetHostView()->GetViewBounds().size()); 2646 EXPECT_EQ(wcv_commit_size1, web_contents->GetContainerBounds().size()); 2647 2648 // Navigate from NTP to a non-NTP page, resizing WebContentsView while 2649 // navigation entry is pending. 2650 ui_test_utils::NavigateToURL(browser(), GURL("chrome://newtab")); 2651 gfx::Size wcv_resize_insets(1, 1); 2652 observer.set_wcv_resize_insets(wcv_resize_insets); 2653 ui_test_utils::NavigateToURL(browser(), 2654 test_server()->GetURL("files/title2.html")); 2655 ASSERT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state()); 2656 gfx::Size rwhv_create_size2, rwhv_commit_size2, wcv_commit_size2; 2657 observer.GetSizeForRenderViewHost(web_contents->GetRenderViewHost(), 2658 &rwhv_create_size2, 2659 &rwhv_commit_size2, 2660 &wcv_commit_size2); 2661 2662 // The behavior on OSX and Views is incorrect in this edge case, but they are 2663 // differently incorrect. 2664 // The behavior should be: 2665 // initial wcv size: (100,100) (to choose random numbers) 2666 // initial rwhv size: (100,140) 2667 // commit wcv size: (101, 101) 2668 // commit rwhv size: (101, 141) 2669 // final wcv size: (101, 141) 2670 // final rwhv size: (101, 141) 2671 // 2672 // On OSX, the commit rwhv size is (101, 101) 2673 // On views, the commit wcv size is (101, 141) 2674 // All other sizes are correct. 2675 2676 // The create height of RenderWidgetHostView should include the height inset. 2677 EXPECT_EQ(gfx::Size(initial_wcv_size.width(), 2678 initial_wcv_size.height() + height_inset), 2679 rwhv_create_size2); 2680 gfx::Size exp_commit_size(initial_wcv_size); 2681 2682 #if defined(OS_MACOSX) 2683 exp_commit_size.Enlarge(wcv_resize_insets.width(), 2684 wcv_resize_insets.height()); 2685 #else 2686 exp_commit_size.Enlarge(wcv_resize_insets.width(), 2687 wcv_resize_insets.height() + height_inset); 2688 #endif 2689 EXPECT_EQ(exp_commit_size, rwhv_commit_size2); 2690 EXPECT_EQ(exp_commit_size, wcv_commit_size2); 2691 gfx::Size exp_final_size(initial_wcv_size); 2692 exp_final_size.Enlarge(wcv_resize_insets.width(), 2693 wcv_resize_insets.height() + height_inset); 2694 EXPECT_EQ(exp_final_size, 2695 web_contents->GetRenderWidgetHostView()->GetViewBounds().size()); 2696 EXPECT_EQ(exp_final_size, web_contents->GetContainerBounds().size()); 2697 } 2698