• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
TabCloseableStateWatcherTest()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
AddTabWithURL(Browser * browser,const GURL & url)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
CanCloseTab(const Browser * browser)47   bool CanCloseTab(const Browser* browser) {
48     return browser->tabstrip_model()->delegate()->CanCloseTab();
49   }
50 
51   // Create popup browser.
CreatePopupBrowser()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.
CreateIncognitoBrowser()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 
NavigateToURL(const GURL & url)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.
NavigateToBeforeUnloadURL()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:
NewTabObserver(Browser * browser)96   explicit NewTabObserver(Browser* browser) : browser_(browser) {
97     browser_->tabstrip_model()->AddObserver(this);
98     ui_test_utils::RunMessageLoop();
99   }
~NewTabObserver()100   virtual ~NewTabObserver() {
101     browser_->tabstrip_model()->RemoveObserver(this);
102   }
103 
104  private:
TabInsertedAt(TabContentsWrapper * contents,int index,bool foreground)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
IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,OneNormalBrowserWithOneTab)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
IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,OneNormalBrowserWithTwoTabs)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).
IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,SecondNonNormalBrowser)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.
IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,CloseCloseableTab)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.
IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,CloseCloseableBrowser)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.
IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,CloseNonCloseableTabAndBrowser)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.
IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,SecondIncognitoBrowser)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).
IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,CloseIncognitoBrowser)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
IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,DISABLED_CloseBrowserWithBeforeUnloadHandlerCancel)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.
IN_PROC_BROWSER_TEST_F(TabCloseableStateWatcherTest,CloseBrowserWithBeforeUnloadHandlerOK)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