diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-21 16:58:39 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-21 16:58:39 +0000 |
commit | 0cce15f698f40ee35ab7ded987360ca6c7f44753 (patch) | |
tree | a39d3617327df3baa0cce9a49ecc4281a144cc1d /chrome/browser/tabs | |
parent | aef9284447e6e63d30448481e8cdf01ba1ecdf22 (diff) | |
download | chromium_src-0cce15f698f40ee35ab7ded987360ca6c7f44753.zip chromium_src-0cce15f698f40ee35ab7ded987360ca6c7f44753.tar.gz chromium_src-0cce15f698f40ee35ab7ded987360ca6c7f44753.tar.bz2 |
Adds ability to determine if a tab was explicitly closed by the
user. This will be used to determine if the tab should be restored on
startup or not.
BUG=4923
TEST=none
Review URL: http://codereview.chromium.org/2087012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47923 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/tabs')
-rw-r--r-- | chrome/browser/tabs/tab_strip_model.cc | 43 | ||||
-rw-r--r-- | chrome/browser/tabs/tab_strip_model.h | 36 | ||||
-rw-r--r-- | chrome/browser/tabs/tab_strip_model_unittest.cc | 42 |
3 files changed, 74 insertions, 47 deletions
diff --git a/chrome/browser/tabs/tab_strip_model.cc b/chrome/browser/tabs/tab_strip_model.cc index be154f6..a60268b 100644 --- a/chrome/browser/tabs/tab_strip_model.cc +++ b/chrome/browser/tabs/tab_strip_model.cc @@ -160,7 +160,7 @@ void TabStripModel::ReplaceNavigationControllerAt( InsertTabContentsAt(index + 1, controller->tab_contents(), true, true); std::vector<int> closing_tabs; closing_tabs.push_back(index); - InternalCloseTabs(closing_tabs, false); + InternalCloseTabs(closing_tabs, CLOSE_NONE); } TabContents* TabStripModel::DetachTabContentsAt(int index) { @@ -263,13 +263,13 @@ void TabStripModel::CloseAllTabs() { std::vector<int> closing_tabs; for (int i = count() - 1; i >= 0; --i) closing_tabs.push_back(i); - InternalCloseTabs(closing_tabs, true); + InternalCloseTabs(closing_tabs, CLOSE_CREATE_HISTORICAL_TAB); } -bool TabStripModel::CloseTabContentsAt(int index) { +bool TabStripModel::CloseTabContentsAt(int index, uint32 close_types) { std::vector<int> closing_tabs; closing_tabs.push_back(index); - return InternalCloseTabs(closing_tabs, true); + return InternalCloseTabs(closing_tabs, close_types); } bool TabStripModel::TabsAreLoading() const { @@ -527,7 +527,7 @@ void TabStripModel::AddTabContents(TabContents* contents, } void TabStripModel::CloseSelectedTab() { - CloseTabContentsAt(selected_index_); + CloseTabContentsAt(selected_index_, CLOSE_CREATE_HISTORICAL_TAB); } void TabStripModel::SelectNextTab() { @@ -641,14 +641,15 @@ void TabStripModel::ExecuteContextMenuCommand( case CommandCloseTab: UserMetrics::RecordAction(UserMetricsAction("TabContextMenu_CloseTab"), profile_); - CloseTabContentsAt(context_index); + CloseTabContentsAt(context_index, CLOSE_CREATE_HISTORICAL_TAB | + CLOSE_USER_GESTURE); break; case CommandCloseOtherTabs: { UserMetrics::RecordAction( UserMetricsAction("TabContextMenu_CloseOtherTabs"), profile_); InternalCloseTabs(GetIndicesClosedByCommand(context_index, command_id), - true); + CLOSE_CREATE_HISTORICAL_TAB); break; } case CommandCloseTabsToRight: { @@ -656,7 +657,7 @@ void TabStripModel::ExecuteContextMenuCommand( UserMetricsAction("TabContextMenu_CloseTabsToRight"), profile_); InternalCloseTabs(GetIndicesClosedByCommand(context_index, command_id), - true); + CLOSE_CREATE_HISTORICAL_TAB); break; } case CommandCloseTabsOpenedBy: { @@ -664,7 +665,7 @@ void TabStripModel::ExecuteContextMenuCommand( UserMetricsAction("TabContextMenu_CloseTabsOpenedBy"), profile_); InternalCloseTabs(GetIndicesClosedByCommand(context_index, command_id), - true); + CLOSE_CREATE_HISTORICAL_TAB); break; } case CommandRestoreTab: { @@ -792,8 +793,8 @@ bool TabStripModel::IsNewTabAtEndOfTabStrip(TabContents* contents) const { contents->controller().entry_count() == 1; } -bool TabStripModel::InternalCloseTabs(std::vector<int> indices, - bool create_historical_tabs) { +bool TabStripModel::InternalCloseTabs(const std::vector<int>& indices, + uint32 close_types) { bool retval = true; // We only try the fast shutdown path if the whole browser process is *not* @@ -833,13 +834,27 @@ bool TabStripModel::InternalCloseTabs(std::vector<int> indices, TabContents* detached_contents = GetContentsAt(indices[i]); detached_contents->OnCloseStarted(); - if (!delegate_->CanCloseContentsAt(indices[i]) || - delegate_->RunUnloadListenerBeforeClosing(detached_contents)) { + if (!delegate_->CanCloseContentsAt(indices[i])) { retval = false; continue; } - InternalCloseTab(detached_contents, indices[i], create_historical_tabs); + // Update the explicitly closed state. If the unload handlers cancel the + // close the state is reset in Browser. We don't update the explicitly + // closed state if already marked as explicitly closed as unload handlers + // call back to this if the close is allowed. + if (!detached_contents->closed_by_user_gesture()) { + detached_contents->set_closed_by_user_gesture( + close_types & CLOSE_USER_GESTURE); + } + + if (delegate_->RunUnloadListenerBeforeClosing(detached_contents)) { + retval = false; + continue; + } + + InternalCloseTab(detached_contents, indices[i], + (close_types & CLOSE_CREATE_HISTORICAL_TAB) != 0); } return retval; diff --git a/chrome/browser/tabs/tab_strip_model.h b/chrome/browser/tabs/tab_strip_model.h index bbfde0d..5ef9cdb 100644 --- a/chrome/browser/tabs/tab_strip_model.h +++ b/chrome/browser/tabs/tab_strip_model.h @@ -287,6 +287,19 @@ class TabStripModel : public NotificationObserver { INSERT_BEFORE, }; + // Used to specify what should happen when the tab is closed. + enum CloseTypes { + CLOSE_NONE = 0, + + // Indicates the tab was closed by the user. If true, + // TabContents::set_closed_by_user_gesture(true) is invoked. + CLOSE_USER_GESTURE = 1 << 0, + + // If true the history is recorded so that the tab can be reopened later. + // You almost always want to set this. + CLOSE_CREATE_HISTORICAL_TAB = 1 << 1, + }; + static const int kNoTab = -1; // Construct a TabStripModel with a delegate to help it do certain things @@ -365,11 +378,11 @@ class TabStripModel : public NotificationObserver { // Closes the TabContents at the specified index. This causes the TabContents // to be destroyed, but it may not happen immediately (e.g. if it's a - // TabContents). + // TabContents). |close_types| is a bitmask of CloseTypes. // Returns true if the TabContents was closed immediately, false if it was not // closed (we may be waiting for a response from an onunload handler, or // waiting for the user to confirm closure). - bool CloseTabContentsAt(int index); + bool CloseTabContentsAt(int index, uint32 close_types); // Replaces the entire state of a the tab at index by switching in a // different NavigationController. This is used through the recently @@ -612,24 +625,23 @@ class TabStripModel : public NotificationObserver { bool IsNewTabAtEndOfTabStrip(TabContents* contents) const; // Closes the TabContents at the specified indices. This causes the - // TabContents to be destroyed, but it may not happen immediately. - // If the page in question has an unload event the - // TabContents will not be destroyed until after the event has completed, - // which will then call back into this method. - // - // The boolean parameter create_historical_tab controls whether to - // record these tabs and their history for reopening recently closed - // tabs. + // TabContents to be destroyed, but it may not happen immediately. If the + // page in question has an unload event the TabContents will not be destroyed + // until after the event has completed, which will then call back into this + // method. // // Returns true if the TabContents were closed immediately, false if we are // waiting for the result of an onunload handler. - bool InternalCloseTabs(std::vector<int> indices, - bool create_historical_tabs); + bool InternalCloseTabs(const std::vector<int>& indices, uint32 close_types); // Invoked from InternalCloseTabs and when an extension is removed for an app // tab. Notifies observers of TabClosingAt and deletes |contents|. If // |create_historical_tabs| is true, CreateHistoricalTab is invoked on the // delegate. + // + // The boolean parameter create_historical_tab controls whether to + // record these tabs and their history for reopening recently closed + // tabs. void InternalCloseTab(TabContents* contents, int index, bool create_historical_tabs); diff --git a/chrome/browser/tabs/tab_strip_model_unittest.cc b/chrome/browser/tabs/tab_strip_model_unittest.cc index faf3bd7..1a5d747 100644 --- a/chrome/browser/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/tabs/tab_strip_model_unittest.cc @@ -414,13 +414,13 @@ TEST_F(TabStripModelTest, TestBasicAPI) { { // Let's test nothing happens when the delegate veto the close. delegate.set_can_close(false); - EXPECT_FALSE(tabstrip.CloseTabContentsAt(2)); + EXPECT_FALSE(tabstrip.CloseTabContentsAt(2, TabStripModel::CLOSE_NONE)); EXPECT_EQ(3, tabstrip.count()); EXPECT_EQ(0, observer.GetStateCount()); // Now let's close for real. delegate.set_can_close(true); - EXPECT_TRUE(tabstrip.CloseTabContentsAt(2)); + EXPECT_TRUE(tabstrip.CloseTabContentsAt(2, TabStripModel::CLOSE_NONE)); EXPECT_EQ(2, tabstrip.count()); EXPECT_EQ(3, observer.GetStateCount()); @@ -789,11 +789,11 @@ TEST_F(TabStripModelTest, TestSelectOnClose) { EXPECT_EQ(0, tabstrip.selected_index()); tabstrip.SelectTabContentsAt(2, false); EXPECT_EQ(2, tabstrip.selected_index()); - tabstrip.CloseTabContentsAt(2); + tabstrip.CloseTabContentsAt(2, TabStripModel::CLOSE_NONE); EXPECT_EQ(2, tabstrip.selected_index()); - tabstrip.CloseTabContentsAt(2); + tabstrip.CloseTabContentsAt(2, TabStripModel::CLOSE_NONE); EXPECT_EQ(1, tabstrip.selected_index()); - tabstrip.CloseTabContentsAt(1); + tabstrip.CloseTabContentsAt(1, TabStripModel::CLOSE_NONE); EXPECT_EQ(0, tabstrip.selected_index()); // Finally test that when a tab has no "siblings" that the opener is @@ -804,7 +804,7 @@ TEST_F(TabStripModelTest, TestSelectOnClose) { TabContents* opened_contents = CreateTabContents(); tabstrip.InsertTabContentsAt(2, opened_contents, true, true); EXPECT_EQ(2, tabstrip.selected_index()); - tabstrip.CloseTabContentsAt(2); + tabstrip.CloseTabContentsAt(2, TabStripModel::CLOSE_NONE); EXPECT_EQ(0, tabstrip.selected_index()); tabstrip.CloseAllTabs(); @@ -1197,7 +1197,7 @@ TEST_F(TabStripModelTest, AppendContentsReselectionTest) { TabContents* target_blank_contents = CreateTabContents(); tabstrip.AppendTabContents(target_blank_contents, true); EXPECT_EQ(2, tabstrip.selected_index()); - tabstrip.CloseTabContentsAt(2); + tabstrip.CloseTabContentsAt(2, TabStripModel::CLOSE_NONE); EXPECT_EQ(0, tabstrip.selected_index()); // clean up after ourselves @@ -1234,19 +1234,19 @@ TEST_F(TabStripModelTest, ReselectionConsidersChildrenTest) { EXPECT_EQ(page_a_a_a_contents, strip.GetTabContentsAt(2)); // Close page A.A - strip.CloseTabContentsAt(strip.selected_index()); + strip.CloseTabContentsAt(strip.selected_index(), TabStripModel::CLOSE_NONE); // Page A.A.A should be selected, NOT A.B EXPECT_EQ(page_a_a_a_contents, strip.GetSelectedTabContents()); // Close page A.A.A - strip.CloseTabContentsAt(strip.selected_index()); + strip.CloseTabContentsAt(strip.selected_index(), TabStripModel::CLOSE_NONE); // Page A.B should be selected EXPECT_EQ(page_a_b_contents, strip.GetSelectedTabContents()); // Close page A.B - strip.CloseTabContentsAt(strip.selected_index()); + strip.CloseTabContentsAt(strip.selected_index(), TabStripModel::CLOSE_NONE); // Page A should be selected EXPECT_EQ(page_a_contents, strip.GetSelectedTabContents()); @@ -1285,7 +1285,7 @@ TEST_F(TabStripModelTest, AddTabContents_NewTabAtEndOfStripInheritsGroup) { // Close the New Tab that was just opened. We should be returned to page B's // Tab... - strip.CloseTabContentsAt(4); + strip.CloseTabContentsAt(4, TabStripModel::CLOSE_NONE); EXPECT_EQ(1, strip.selected_index()); @@ -1299,7 +1299,7 @@ TEST_F(TabStripModelTest, AddTabContents_NewTabAtEndOfStripInheritsGroup) { EXPECT_EQ(4, strip.selected_index()); // Close the Tab. Selection should shift back to page B's Tab. - strip.CloseTabContentsAt(4); + strip.CloseTabContentsAt(4, TabStripModel::CLOSE_NONE); EXPECT_EQ(1, strip.selected_index()); @@ -1315,7 +1315,7 @@ TEST_F(TabStripModelTest, AddTabContents_NewTabAtEndOfStripInheritsGroup) { EXPECT_EQ(4, strip.selected_index()); // Close the Tab. The next-adjacent should be selected. - strip.CloseTabContentsAt(4); + strip.CloseTabContentsAt(4, TabStripModel::CLOSE_NONE); EXPECT_EQ(3, strip.selected_index()); @@ -1354,7 +1354,7 @@ TEST_F(TabStripModelTest, NavigationForgetsOpeners) { strip.TabNavigating(page_d_contents, PageTransition::LINK); // Close page D, page C should be selected. (part of same group). - strip.CloseTabContentsAt(3); + strip.CloseTabContentsAt(3, TabStripModel::CLOSE_NONE); EXPECT_EQ(2, strip.selected_index()); // Tell the TabStripModel that we are navigating in page C via a bookmark. @@ -1362,7 +1362,7 @@ TEST_F(TabStripModelTest, NavigationForgetsOpeners) { // Close page C, page E should be selected. (C is no longer part of the // A-B-C-D group, selection moves to the right). - strip.CloseTabContentsAt(2); + strip.CloseTabContentsAt(2, TabStripModel::CLOSE_NONE); EXPECT_EQ(page_e_contents, strip.GetTabContentsAt(strip.selected_index())); strip.CloseAllTabs(); @@ -1402,7 +1402,7 @@ TEST_F(TabStripModelTest, NavigationForgettingDoesntAffectNewTab) { // At this point, if we close this tab the last selected one should be // re-selected. - strip.CloseTabContentsAt(strip.count() - 1); + strip.CloseTabContentsAt(strip.count() - 1, TabStripModel::CLOSE_NONE); EXPECT_EQ(page_c_contents, strip.GetTabContentsAt(strip.selected_index())); // TEST 2: If the user is in a group of tabs and opens a new tab at the end @@ -1421,7 +1421,7 @@ TEST_F(TabStripModelTest, NavigationForgettingDoesntAffectNewTab) { strip.SelectTabContentsAt(strip.count() - 1, true); // Now close the last tab. The next adjacent should be selected. - strip.CloseTabContentsAt(strip.count() - 1); + strip.CloseTabContentsAt(strip.count() - 1, TabStripModel::CLOSE_NONE); EXPECT_EQ(page_d_contents, strip.GetTabContentsAt(strip.selected_index())); strip.CloseAllTabs(); @@ -1475,7 +1475,7 @@ TEST_F(TabStripModelTest, FastShutdown) { tabstrip.AppendTabContents(contents1, true); tabstrip.AppendTabContents(contents2, true); - tabstrip.CloseTabContentsAt(1); + tabstrip.CloseTabContentsAt(1, TabStripModel::CLOSE_NONE); EXPECT_FALSE(contents1->GetRenderProcessHost()->fast_shutdown_started()); EXPECT_EQ(1, tabstrip.count()); @@ -1803,7 +1803,7 @@ TEST_F(TabStripModelTest, Phantom) { observer.ClearStates(); - tabstrip.CloseTabContentsAt(0); + tabstrip.CloseTabContentsAt(0, TabStripModel::CLOSE_NONE); // The tabcontents should have changed. TabContents* old_contents1 = contents1; @@ -1838,7 +1838,7 @@ TEST_F(TabStripModelTest, Phantom) { observer.ClearStates(); // Close the second tab, which should make it phantom. - tabstrip.CloseTabContentsAt(1); + tabstrip.CloseTabContentsAt(1, TabStripModel::CLOSE_NONE); // The tabcontents should have changed. TabContents* new_contents2 = tabstrip.GetTabContentsAt(1); @@ -1860,7 +1860,7 @@ TEST_F(TabStripModelTest, Phantom) { observer.ClearStates(); // Close the last tab, we should get a tabstrip empty notification. - tabstrip.CloseTabContentsAt(2); + tabstrip.CloseTabContentsAt(2, TabStripModel::CLOSE_NONE); // The tabcontents should have changed. TabContents* old_contents3 = contents3; |