OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if defined(OS_POSIX) | 5 #if defined(OS_POSIX) |
6 #include <signal.h> | 6 #include <signal.h> |
7 #endif | 7 #endif |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/process_util.h" | 11 #include "base/process_util.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #include "chrome/browser/net/url_request_mock_util.h" | 13 #include "chrome/browser/net/url_request_mock_util.h" |
14 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h" | 14 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h" |
15 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" | 15 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" |
16 #include "chrome/browser/ui/browser.h" | 16 #include "chrome/browser/ui/browser.h" |
17 #include "chrome/browser/ui/browser_commands.h" | 17 #include "chrome/browser/ui/browser_commands.h" |
18 #include "chrome/browser/ui/browser_list.h" | 18 #include "chrome/browser/ui/browser_list.h" |
19 #include "chrome/browser/ui/browser_tabstrip.h" | 19 #include "chrome/browser/ui/browser_tabstrip.h" |
| 20 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
20 #include "chrome/common/chrome_notification_types.h" | 21 #include "chrome/common/chrome_notification_types.h" |
21 #include "chrome/common/chrome_switches.h" | 22 #include "chrome/common/chrome_switches.h" |
22 #include "chrome/test/base/in_process_browser_test.h" | 23 #include "chrome/test/base/in_process_browser_test.h" |
23 #include "chrome/test/base/ui_test_utils.h" | 24 #include "chrome/test/base/ui_test_utils.h" |
24 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
25 #include "content/public/browser/notification_service.h" | 26 #include "content/public/browser/notification_service.h" |
26 #include "content/public/browser/web_contents.h" | 27 #include "content/public/browser/web_contents.h" |
27 #include "content/public/test/browser_test_utils.h" | 28 #include "content/public/test/browser_test_utils.h" |
28 #include "content/test/net/url_request_mock_http_job.h" | 29 #include "content/test/net/url_request_mock_http_job.h" |
29 #include "net/url_request/url_request_test_util.h" | 30 #include "net/url_request/url_request_test_util.h" |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 | 404 |
404 content::WindowedNotificationObserver tab_close_observer( | 405 content::WindowedNotificationObserver tab_close_observer( |
405 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 406 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
406 content::NotificationService::AllSources()); | 407 content::NotificationService::AllSources()); |
407 chrome::CloseTab(browser()); | 408 chrome::CloseTab(browser()); |
408 tab_close_observer.Wait(); | 409 tab_close_observer.Wait(); |
409 | 410 |
410 CheckTitle("only_one_unload"); | 411 CheckTitle("only_one_unload"); |
411 } | 412 } |
412 | 413 |
| 414 |
| 415 class FastUnloadTest : public UnloadTest { |
| 416 public: |
| 417 virtual void SetUpInProcessBrowserTestFixture() { |
| 418 ASSERT_TRUE(test_server()->Start()); |
| 419 } |
| 420 |
| 421 virtual void TearDownInProcessBrowserTestFixture() { |
| 422 test_server()->Stop(); |
| 423 } |
| 424 |
| 425 GURL GetUrl(const std::string& name) { |
| 426 return GURL(test_server()->GetURL( |
| 427 "files/fast_tab_close/" + name + ".html")); |
| 428 } |
| 429 |
| 430 void NavigateToPage(const char* name) { |
| 431 ui_test_utils::NavigateToURL(browser(), GetUrl(name)); |
| 432 CheckTitle(name); |
| 433 } |
| 434 |
| 435 void NavigateToPageInNewTab(const char* name) { |
| 436 ui_test_utils::NavigateToURLWithDisposition( |
| 437 browser(), GetUrl(name), NEW_FOREGROUND_TAB, |
| 438 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); |
| 439 CheckTitle(name); |
| 440 } |
| 441 |
| 442 std::string GetActiveTabCookies(const char* name) { |
| 443 content::WebContents* contents = chrome::GetActiveWebContents(browser()); |
| 444 return content::GetCookies(contents->GetBrowserContext(), GetUrl(name)); |
| 445 } |
| 446 }; |
| 447 |
| 448 class FastTabCloseTabStripModelObserver : public TabStripModelObserver { |
| 449 public: |
| 450 FastTabCloseTabStripModelObserver(TabStripModel* model, |
| 451 base::RunLoop* run_loop) |
| 452 : model_(model), |
| 453 run_loop_(run_loop) { |
| 454 model_->AddObserver(this); |
| 455 } |
| 456 |
| 457 ~FastTabCloseTabStripModelObserver() { |
| 458 model_->RemoveObserver(this); |
| 459 } |
| 460 |
| 461 // TabStripModelObserver: |
| 462 virtual void TabDetachedAt(content::WebContents* contents, |
| 463 int index) OVERRIDE { |
| 464 run_loop_->Quit(); |
| 465 } |
| 466 |
| 467 private: |
| 468 TabStripModel* const model_; |
| 469 base::RunLoop* const run_loop_; |
| 470 }; |
| 471 |
| 472 |
| 473 // Test that fast-tab-close works when closing a tab with an unload handler |
| 474 // (http://crbug.com/142458). |
| 475 IN_PROC_BROWSER_TEST_F(FastUnloadTest, UnloadHidden) { |
| 476 NavigateToPage("no_listeners"); |
| 477 NavigateToPageInNewTab("unload_sets_cookie"); |
| 478 EXPECT_EQ("", GetActiveTabCookies("no_listeners")); |
| 479 |
| 480 { |
| 481 base::RunLoop run_loop; |
| 482 FastTabCloseTabStripModelObserver observer( |
| 483 browser()->tab_strip_model(), &run_loop); |
| 484 chrome::CloseTab(browser()); |
| 485 run_loop.Run(); |
| 486 } |
| 487 |
| 488 // Check that the browser only has the original tab. |
| 489 CheckTitle("no_listeners"); |
| 490 EXPECT_EQ(1, browser()->tab_count()); |
| 491 |
| 492 // Show that the web contents to go away after the was removed. |
| 493 // Without unload-detached, this times-out because it happens earlier. |
| 494 content::WindowedNotificationObserver contents_destroyed_observer( |
| 495 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 496 content::NotificationService::AllSources()); |
| 497 contents_destroyed_observer.Wait(); |
| 498 |
| 499 // Browser still has the same tab. |
| 500 CheckTitle("no_listeners"); |
| 501 EXPECT_EQ(1, browser()->tab_count()); |
| 502 EXPECT_EQ("unloaded=ohyeah", GetActiveTabCookies("no_listeners")); |
| 503 } |
| 504 |
| 505 // Test that fast-tab-close does not break a solo tab. |
| 506 IN_PROC_BROWSER_TEST_F(FastUnloadTest, PRE_ClosingLastTabFinishesUnload) { |
| 507 // The unload handler sleeps before setting the cookie to catch cases when |
| 508 // unload handlers are not allowed to run to completion. (For example, |
| 509 // using the detached handler for the tab and then closing the browser.) |
| 510 NavigateToPage("unload_sleep_before_cookie"); |
| 511 EXPECT_EQ(1, browser()->tab_count()); |
| 512 EXPECT_EQ("", GetActiveTabCookies("unload_sleep_before_cookie")); |
| 513 |
| 514 content::WindowedNotificationObserver window_observer( |
| 515 chrome::NOTIFICATION_BROWSER_CLOSED, |
| 516 content::NotificationService::AllSources()); |
| 517 chrome::CloseTab(browser()); |
| 518 window_observer.Wait(); |
| 519 } |
| 520 IN_PROC_BROWSER_TEST_F(FastUnloadTest, ClosingLastTabFinishesUnload) { |
| 521 // Check for cookie set in unload handler of PRE_ test. |
| 522 NavigateToPage("no_listeners"); |
| 523 EXPECT_EQ("unloaded=ohyeah", GetActiveTabCookies("no_listeners")); |
| 524 } |
| 525 |
| 526 // Test that fast-tab-close does not break window close. |
| 527 IN_PROC_BROWSER_TEST_F(FastUnloadTest, PRE_WindowCloseFinishesUnload) { |
| 528 NavigateToPage("no_listeners"); |
| 529 |
| 530 // The unload handler sleeps before setting the cookie to catch cases when |
| 531 // unload handlers are not allowed to run to completion. Without the sleep, |
| 532 // the cookie can get set even if the browser does not wait for |
| 533 // the unload handler to finish. |
| 534 NavigateToPageInNewTab("unload_sleep_before_cookie"); |
| 535 EXPECT_EQ(2, browser()->tab_count()); |
| 536 EXPECT_EQ("", GetActiveTabCookies("no_listeners")); |
| 537 |
| 538 content::WindowedNotificationObserver window_observer( |
| 539 chrome::NOTIFICATION_BROWSER_CLOSED, |
| 540 content::NotificationService::AllSources()); |
| 541 chrome::CloseWindow(browser()); |
| 542 window_observer.Wait(); |
| 543 } |
| 544 IN_PROC_BROWSER_TEST_F(FastUnloadTest, WindowCloseFinishesUnload) { |
| 545 // Check for cookie set in unload during PRE_ test. |
| 546 NavigateToPage("no_listeners"); |
| 547 EXPECT_EQ("unloaded=ohyeah", GetActiveTabCookies("no_listeners")); |
| 548 } |
| 549 |
| 550 // Test that a tab crash during unload does not break window close. |
| 551 IN_PROC_BROWSER_TEST_F(FastUnloadTest, WindowCloseAfterUnloadCrash) { |
| 552 NavigateToPage("no_listeners"); |
| 553 NavigateToPageInNewTab("unload_sets_cookie"); |
| 554 content::WebContents* unload_contents = |
| 555 chrome::GetActiveWebContents(browser()); |
| 556 EXPECT_EQ("", GetActiveTabCookies("no_listeners")); |
| 557 |
| 558 { |
| 559 base::RunLoop run_loop; |
| 560 FastTabCloseTabStripModelObserver observer( |
| 561 browser()->tab_strip_model(), &run_loop); |
| 562 chrome::CloseTab(browser()); |
| 563 run_loop.Run(); |
| 564 } |
| 565 |
| 566 // Check that the browser only has the original tab. |
| 567 CheckTitle("no_listeners"); |
| 568 EXPECT_EQ(1, browser()->tab_count()); |
| 569 |
| 570 CrashTab(unload_contents); |
| 571 |
| 572 // Check that the browser only has the original tab. |
| 573 CheckTitle("no_listeners"); |
| 574 EXPECT_EQ(1, browser()->tab_count()); |
| 575 |
| 576 content::WindowedNotificationObserver window_observer( |
| 577 chrome::NOTIFICATION_BROWSER_CLOSED, |
| 578 content::NotificationService::AllSources()); |
| 579 chrome::CloseWindow(browser()); |
| 580 window_observer.Wait(); |
| 581 } |
| 582 |
| 583 IN_PROC_BROWSER_TEST_F(FastUnloadTest, WindowCloseAfterBeforeUnloadCrash) { |
| 584 // Tests makes no sense in single-process mode since the renderer is hung. |
| 585 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) |
| 586 return; |
| 587 |
| 588 NavigateToDataURL(BEFORE_UNLOAD_HTML, "beforeunload"); |
| 589 content::WebContents* beforeunload_contents = |
| 590 chrome::GetActiveWebContents(browser()); |
| 591 |
| 592 content::WindowedNotificationObserver window_observer( |
| 593 chrome::NOTIFICATION_BROWSER_CLOSED, |
| 594 content::NotificationService::AllSources()); |
| 595 chrome::CloseWindow(browser()); |
| 596 CrashTab(beforeunload_contents); |
| 597 window_observer.Wait(); |
| 598 } |
| 599 |
413 // TODO(ojan): Add tests for unload/beforeunload that have multiple tabs | 600 // TODO(ojan): Add tests for unload/beforeunload that have multiple tabs |
414 // and multiple windows. | 601 // and multiple windows. |
OLD | NEW |