Home | History | Annotate | Download | only in chromeos
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/tab_closeable_state_watcher.h"
      6 
      7 #include "base/file_path.h"
      8 #include "chrome/browser/profiles/profile.h"
      9 #include "chrome/browser/tabs/tab_strip_model.h"
     10 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
     11 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
     12 #include "chrome/browser/ui/browser.h"
     13 #include "chrome/browser/ui/browser_list.h"
     14 #include "chrome/browser/ui/browser_window.h"
     15 #include "chrome/common/url_constants.h"
     16 #include "chrome/test/in_process_browser_test.h"
     17 #include "chrome/test/ui_test_utils.h"
     18 #include "content/browser/tab_contents/tab_contents.h"
     19 #include "googleurl/src/gurl.h"
     20 #include "testing/gmock/include/gmock/gmock.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 
     23 namespace chromeos {
     24 
     25 class TabCloseableStateWatcherTest : public InProcessBrowserTest {
     26  public:
     27   TabCloseableStateWatcherTest() {
     28     // This test is testing TabCloseStateWatcher, so enable it.
     29     EnableTabCloseableStateWatcher();
     30     blank_url_ = GURL(chrome::kAboutBlankURL);
     31     ntp_url_ = GURL(chrome::kChromeUINewTabURL);
     32     other_url_ = ui_test_utils::GetTestUrl(
     33         FilePath(FilePath::kCurrentDirectory),
     34         FilePath(FILE_PATH_LITERAL("title2.html")));
     35   }
     36 
     37  protected:
     38   // Wrapper for Browser::AddTabWithURL
     39   void AddTabWithURL(Browser* browser, const GURL& url) {
     40     AddTabAtIndexToBrowser(browser, 0, url, PageTransition::TYPED);
     41     // Wait for page to finish loading.
     42     ui_test_utils::WaitForNavigation(
     43         &browser->GetSelectedTabContents()->controller());
     44   }
     45 
     46   // Wrapper for TabCloseableStateWatcher::CanCloseTab
     47   bool CanCloseTab(const Browser* browser) {
     48     return browser->tabstrip_model()->delegate()->CanCloseTab();
     49   }
     50 
     51   // Create popup browser.
     52   Browser* CreatePopupBrowser() {
     53     // This is mostly duplicated from InPocessBrowserTest::CreateBrowser,
     54     // except that a popup browser is created here.
     55     Browser* popup_browser = Browser::CreateForType(Browser::TYPE_POPUP,
     56                                                     browser()->profile());
     57     AddTabWithURL(popup_browser, ntp_url_);
     58     popup_browser->window()->Show();
     59     return popup_browser;
     60   }
     61 
     62   // Create incognito browser.
     63   Browser* CreateIncognitoBrowser() {
     64     // This is mostly duplicated from InPocessBrowserTest::CreateBrowser,
     65     // except that an incognito browser is created here.
     66     Browser* incognito_browser =
     67         Browser::Create(browser()->profile()->GetOffTheRecordProfile());
     68     AddTabWithURL(incognito_browser, ntp_url_);
     69     incognito_browser->window()->Show();
     70     return incognito_browser;
     71   }
     72 
     73   void NavigateToURL(const GURL& url) {
     74     ui_test_utils::NavigateToURL(browser(), url);
     75     ui_test_utils::RunAllPendingInMessageLoop();
     76   }
     77 
     78   // Navigate to URL with BeforeUnload handler.
     79   void NavigateToBeforeUnloadURL() {
     80     const std::string kBeforeUnloadHtml =
     81         "<html><head><title>beforeunload</title></head><body>"
     82         "<script>window.onbeforeunload=function(e){return 'foo'}</script>"
     83         "</body></html>";
     84     NavigateToURL(GURL("data:text/html," + kBeforeUnloadHtml));
     85   }
     86 
     87   // Data members.
     88   GURL blank_url_;
     89   GURL ntp_url_;
     90   GURL other_url_;
     91 };
     92 
     93 // This is used to block until a new tab in the specified browser is inserted.
     94 class NewTabObserver : public TabStripModelObserver {
     95  public:
     96   explicit NewTabObserver(Browser* browser) : browser_(browser) {
     97     browser_->tabstrip_model()->AddObserver(this);
     98     ui_test_utils::RunMessageLoop();
     99   }
    100   virtual ~NewTabObserver() {
    101     browser_->tabstrip_model()->RemoveObserver(this);
    102   }
    103 
    104  private:
    105   virtual void TabInsertedAt(TabContentsWrapper* contents,
    106                              int index,
    107                              bool foreground) {
    108     MessageLoopForUI::current()->Quit();
    109   }
    110 
    111   Browser* browser_;
    112 };
    113 
    114 // Tests with the only tab in the only normal browser:
    115 // - if tab is about:blank, it is closeable
    116 // - if tab is NewTabPage, it is not closeable
    117 // - if tab is other url, it is closeable
    118 IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,
    119                        OneNormalBrowserWithOneTab) {
    120   // Check that default about::blank tab is closeable.
    121   ASSERT_EQ(1, browser()->tab_count());
    122   EXPECT_TRUE(CanCloseTab(browser()));
    123 
    124   // Naviate tab to NewTabPage, and check that it's not closeable.
    125   NavigateToURL(ntp_url_);
    126   EXPECT_FALSE(CanCloseTab(browser()));
    127 
    128   // Navigate tab to any other URL, and check that it's closeable.
    129   NavigateToURL(other_url_);
    130   EXPECT_TRUE(CanCloseTab(browser()));
    131 }
    132 
    133 // Tests with 2 tabs in the only normal browser
    134 // - as long as there's > 1 tab, all tabs in the browser are always closeable
    135 IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,
    136                        OneNormalBrowserWithTwoTabs) {
    137   // 1 NewTabPage with any other tab are closeable.
    138   // First, set up the first NewTabPage.
    139   NavigateToURL(ntp_url_);
    140   EXPECT_FALSE(CanCloseTab(browser()));
    141 
    142   // Add the 2nd tab with blank page.
    143   AddTabWithURL(browser(), blank_url_);
    144   ASSERT_EQ(2, browser()->tab_count());
    145   EXPECT_TRUE(CanCloseTab(browser()));
    146 
    147   // Navigate 2nd tab to other URL.
    148   NavigateToURL(other_url_);
    149   EXPECT_TRUE(CanCloseTab(browser()));
    150 
    151   // Navigate 2nd tab to NewTabPage.
    152   NavigateToURL(ntp_url_);
    153   EXPECT_TRUE(CanCloseTab(browser()));
    154 
    155   // Close 1st NewTabPage.
    156   browser()->tabstrip_model()->CloseTabContentsAt(0,
    157       TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
    158   EXPECT_FALSE(CanCloseTab(browser()));
    159 }
    160 
    161 // Tests with one tab in one normal browser and another non-normal browser.
    162 // - non-normal browser with any tab(s) is always closeable.
    163 // - non-normal browser does not affect closeable state of tab(s) in normal
    164 // browser(s).
    165 IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest, SecondNonNormalBrowser) {
    166   // Open non-normal browser.
    167   Browser* popup_browser = CreatePopupBrowser();
    168   EXPECT_TRUE(CanCloseTab(browser()));
    169   EXPECT_TRUE(CanCloseTab(popup_browser));
    170 
    171   // Navigate to NewTabPage for 1st browser.
    172   NavigateToURL(ntp_url_);
    173   EXPECT_FALSE(CanCloseTab(browser()));
    174   EXPECT_TRUE(CanCloseTab(popup_browser));
    175 
    176   // Close non-normal browser.
    177   popup_browser->CloseWindow();
    178   EXPECT_FALSE(CanCloseTab(browser()));
    179 }
    180 
    181 // Tests closing a closeable tab - tab should be closed, browser should remain
    182 // opened with a NewTabPage.
    183 IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest, CloseCloseableTab) {
    184   EXPECT_EQ(1, browser()->tab_count());
    185   EXPECT_TRUE(CanCloseTab(browser()));
    186   browser()->CloseTab();
    187   EXPECT_EQ(1, browser()->tab_count());
    188   EXPECT_EQ(ntp_url_, browser()->GetSelectedTabContents()->GetURL());
    189 }
    190 
    191 // Tests closing a closeable browser - all tabs in browser should be closed,
    192 // browser should remain opened with a NewTabPage.
    193 IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest, CloseCloseableBrowser) {
    194   EXPECT_EQ(1, browser()->tab_count());
    195   EXPECT_TRUE(CanCloseTab(browser()));
    196   browser()->CloseWindow();
    197   EXPECT_EQ(1u, BrowserList::size());
    198   EXPECT_EQ(browser(), *(BrowserList::begin()));
    199   EXPECT_EQ(1, browser()->tab_count());
    200   EXPECT_EQ(ntp_url_, browser()->GetSelectedTabContents()->GetURL());
    201 }
    202 
    203 // Tests closing a non-closeable tab and hence non-closeable browser - tab and
    204 // browser should remain opened.
    205 IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,
    206                        CloseNonCloseableTabAndBrowser) {
    207   // Close non-closeable tab.
    208   EXPECT_EQ(1, browser()->tab_count());
    209   NavigateToURL(ntp_url_);
    210   EXPECT_FALSE(CanCloseTab(browser()));
    211   TabContents* tab_contents = browser()->GetSelectedTabContents();
    212   browser()->CloseTab();
    213   EXPECT_EQ(1, browser()->tab_count());
    214   EXPECT_EQ(tab_contents, browser()->GetSelectedTabContents());
    215 
    216   // Close browser with non-closeable tab.
    217   browser()->CloseWindow();
    218   EXPECT_EQ(1u, BrowserList::size());
    219   EXPECT_EQ(browser(), *(BrowserList::begin()));
    220   EXPECT_EQ(1, browser()->tab_count());
    221   EXPECT_EQ(tab_contents, browser()->GetSelectedTabContents());
    222 }
    223 
    224 // Tests an incognito browsr with a normal browser.
    225 // - when incognito browser is opened, all browsers (including previously
    226 //   non-clsoeable normal browsers) become closeable.
    227 // - when incognito browser is closed, normal browsers return to adhering to the
    228 //   original closebable rules.
    229 IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest, SecondIncognitoBrowser) {
    230   NavigateToURL(ntp_url_);
    231   EXPECT_FALSE(CanCloseTab(browser()));
    232 
    233   // Open an incognito browser.
    234   Browser* incognito_browser = CreateIncognitoBrowser();
    235   EXPECT_TRUE(incognito_browser->profile()->IsOffTheRecord());
    236   EXPECT_EQ(2u, BrowserList::size());
    237   EXPECT_TRUE(CanCloseTab(browser()));
    238   EXPECT_TRUE(CanCloseTab(incognito_browser));
    239 
    240   // Close incognito browser.
    241   incognito_browser->CloseWindow();
    242   ui_test_utils::RunAllPendingInMessageLoop();
    243   EXPECT_EQ(1u, BrowserList::size());
    244   EXPECT_EQ(browser(), *(BrowserList::begin()));
    245   EXPECT_FALSE(CanCloseTab(browser()));
    246 }
    247 
    248 // Tests closing an incognito browser - the incognito browser should close,
    249 // and a new normal browser opened with a NewTabPage (which is not closeable).
    250 IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest, CloseIncognitoBrowser) {
    251   NavigateToURL(ntp_url_);
    252 
    253   // Open an incognito browser.
    254   Browser* incognito_browser = CreateIncognitoBrowser();
    255   EXPECT_TRUE(incognito_browser->profile()->IsOffTheRecord());
    256   EXPECT_EQ(2u, BrowserList::size());
    257 
    258   // Close 1st normal browser.
    259   browser()->CloseWindow();
    260   ui_test_utils::RunAllPendingInMessageLoop();
    261   EXPECT_EQ(1u, BrowserList::size());
    262   EXPECT_EQ(incognito_browser, *(BrowserList::begin()));
    263   EXPECT_TRUE(CanCloseTab(incognito_browser));
    264 
    265   // Close incognito browser.
    266   incognito_browser->CloseWindow();
    267   Browser* new_browser = ui_test_utils::WaitForNewBrowser();
    268   EXPECT_EQ(1u, BrowserList::size());
    269   EXPECT_FALSE(new_browser->profile()->IsOffTheRecord());
    270   EXPECT_EQ(1, new_browser->tab_count());
    271   EXPECT_EQ(ntp_url_, new_browser->GetSelectedTabContents()->GetURL());
    272 }
    273 
    274 // Tests closing of browser with BeforeUnload handler where user clicks cancel
    275 // (i.e. stay on the page and cancel closing) - browser and its tabs should stay
    276 // the same.
    277 // Sporadically crashing test. See http://crbug.com/79333
    278 IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,
    279                        DISABLED_CloseBrowserWithBeforeUnloadHandlerCancel) {
    280   // Navigate to URL with BeforeUnload handler.
    281   NavigateToBeforeUnloadURL();
    282   EXPECT_TRUE(CanCloseTab(browser()));
    283 
    284   // Close browser, click Cancel in BeforeUnload confirm dialog.
    285   TabContents* tab_contents = browser()->GetSelectedTabContents();
    286   browser()->CloseWindow();
    287   AppModalDialog* confirm = ui_test_utils::WaitForAppModalDialog();
    288   confirm->native_dialog()->CancelAppModalDialog();
    289   ui_test_utils::RunAllPendingInMessageLoop();
    290   EXPECT_EQ(1u, BrowserList::size());
    291   EXPECT_EQ(browser(), *(BrowserList::begin()));
    292   EXPECT_EQ(1, browser()->tab_count());
    293   EXPECT_EQ(tab_contents, browser()->GetSelectedTabContents());
    294 
    295   // Close the browser.
    296   browser()->CloseWindow();
    297   confirm = ui_test_utils::WaitForAppModalDialog();
    298   confirm->native_dialog()->AcceptAppModalDialog();
    299   ui_test_utils::RunAllPendingInMessageLoop();
    300 }
    301 
    302 // Tests closing of browser with BeforeUnload handler where user clicks OK (i.e.
    303 // leave the page and proceed with closing), all tabs in browser should close,
    304 // browser remains opened with a NewTabPage.
    305 IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,
    306                        CloseBrowserWithBeforeUnloadHandlerOK) {
    307   // Navigate to URL with BeforeUnload handler.
    308   NavigateToBeforeUnloadURL();
    309   EXPECT_TRUE(CanCloseTab(browser()));
    310 
    311   // Close browser, click OK in BeforeUnload confirm dialog.
    312   browser()->CloseWindow();
    313   AppModalDialog* confirm = ui_test_utils::WaitForAppModalDialog();
    314   confirm->native_dialog()->AcceptAppModalDialog();
    315   NewTabObserver new_tab_observer(browser());
    316   EXPECT_EQ(1u, BrowserList::size());
    317   EXPECT_EQ(browser(), *(BrowserList::begin()));
    318   EXPECT_EQ(1, browser()->tab_count());
    319   EXPECT_EQ(ntp_url_, browser()->GetSelectedTabContents()->GetURL());
    320 }
    321 
    322 }  // namespace chromeos
    323