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