summaryrefslogtreecommitdiffstats
path: root/chrome/browser/tabs
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-21 16:58:39 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-21 16:58:39 +0000
commit0cce15f698f40ee35ab7ded987360ca6c7f44753 (patch)
treea39d3617327df3baa0cce9a49ecc4281a144cc1d /chrome/browser/tabs
parentaef9284447e6e63d30448481e8cdf01ba1ecdf22 (diff)
downloadchromium_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.cc43
-rw-r--r--chrome/browser/tabs/tab_strip_model.h36
-rw-r--r--chrome/browser/tabs/tab_strip_model_unittest.cc42
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;