summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/automation/automation_provider.cc11
-rw-r--r--chrome/browser/automation/automation_provider.h1
-rw-r--r--chrome/browser/browser.cc2
-rw-r--r--chrome/browser/browser_list.cc10
-rw-r--r--chrome/browser/browser_list.h4
-rw-r--r--chrome/browser/sessions/tab_restore_service.cc22
-rw-r--r--chrome/browser/sessions/tab_restore_service.h15
-rw-r--r--chrome/browser/tab_restore_uitest.cc127
8 files changed, 187 insertions, 5 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 1845fd7..9823840 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -930,6 +930,7 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
#endif // defined(OS_WIN)
IPC_MESSAGE_HANDLER(AutomationMsg_TabProcessID, GetTabProcessID)
IPC_MESSAGE_HANDLER(AutomationMsg_TabTitle, GetTabTitle)
+ IPC_MESSAGE_HANDLER(AutomationMsg_TabIndex, GetTabIndex)
IPC_MESSAGE_HANDLER(AutomationMsg_TabURL, GetTabURL)
IPC_MESSAGE_HANDLER(AutomationMsg_ShelfVisibility,
GetShelfVisibility)
@@ -1745,6 +1746,16 @@ void AutomationProvider::GetTabTitle(int handle, int* title_string_size,
}
}
+void AutomationProvider::GetTabIndex(int handle, int* tabstrip_index) {
+ *tabstrip_index = -1; // -1 is the error code
+
+ if (tab_tracker_->ContainsHandle(handle)) {
+ NavigationController* tab = tab_tracker_->GetResource(handle);
+ Browser* browser = Browser::GetBrowserForController(tab, NULL);
+ *tabstrip_index = browser->tabstrip_model()->GetIndexOfController(tab);
+ }
+}
+
void AutomationProvider::HandleUnused(const IPC::Message& message, int handle) {
if (window_tracker_->ContainsHandle(handle)) {
window_tracker_->Remove(window_tracker_->GetResource(handle));
diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h
index bf08286..65f8906 100644
--- a/chrome/browser/automation/automation_provider.h
+++ b/chrome/browser/automation/automation_provider.h
@@ -174,6 +174,7 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>,
#endif // defined(OS_WIN)
void GetTabProcessID(int handle, int* process_id);
void GetTabTitle(int handle, int* title_string_size, std::wstring* title);
+ void GetTabIndex(int handle, int* tabstrip_index);
void GetTabURL(int handle, bool* success, GURL* url);
void HandleUnused(const IPC::Message& message, int handle);
void NavigateToURL(int handle, const GURL& url, IPC::Message* reply_message);
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index a8501d9..83cd796 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -554,6 +554,8 @@ TabContents* Browser::AddRestoredTab(
new_tab->controller().RestoreFromState(navigations, selected_navigation);
tabstrip_model_.InsertTabContentsAt(tab_index, new_tab, select, false);
+ if (select)
+ window_->Activate();
if (profile_->HasSessionService()) {
SessionService* session_service = profile_->GetSessionService();
if (session_service)
diff --git a/chrome/browser/browser_list.cc b/chrome/browser/browser_list.cc
index 6665d15..411583b 100644
--- a/chrome/browser/browser_list.cc
+++ b/chrome/browser/browser_list.cc
@@ -211,6 +211,16 @@ Browser* BrowserList::FindBrowserWithType(Profile* p, Browser::Type t) {
}
// static
+Browser* BrowserList::FindBrowserWithID(SessionID::id_type desired_id) {
+ BrowserList::const_iterator i;
+ for (i = BrowserList::begin(); i != BrowserList::end(); ++i) {
+ if ((*i)->session_id().id() == desired_id)
+ return *i;
+ }
+ return NULL;
+}
+
+// static
size_t BrowserList::GetBrowserCountForType(Profile* p, Browser::Type type) {
BrowserList::const_iterator i;
size_t result = 0;
diff --git a/chrome/browser/browser_list.h b/chrome/browser/browser_list.h
index 63ea28d..858e97e 100644
--- a/chrome/browser/browser_list.h
+++ b/chrome/browser/browser_list.h
@@ -55,6 +55,10 @@ class BrowserList {
// is returned. Returns NULL if no such browser currently exists.
static Browser* FindBrowserWithType(Profile* p, Browser::Type t);
+ // Find an existing browser with the provided ID. Returns NULL if no such
+ // browser currently exists.
+ static Browser* FindBrowserWithID(SessionID::id_type desired_id);
+
// Closes all browsers. If use_post is true the windows are closed by way of
// posting a WM_CLOSE message, otherwise the windows are closed directly. In
// almost all cases you'll want to use true, the one exception is ending
diff --git a/chrome/browser/sessions/tab_restore_service.cc b/chrome/browser/sessions/tab_restore_service.cc
index 5892013..d61e42a 100644
--- a/chrome/browser/sessions/tab_restore_service.cc
+++ b/chrome/browser/sessions/tab_restore_service.cc
@@ -130,6 +130,13 @@ void TabRestoreService::CreateHistoricalTab(NavigationController* tab) {
if (local_tab->navigations.empty())
return;
+ // browser may be NULL when running unit tests.
+ if (browser) {
+ local_tab->browser_id = browser->session_id().id();
+ local_tab->tabstrip_index =
+ browser->tabstrip_model()->GetIndexOfController(tab);
+ }
+
AddEntry(local_tab.release(), true, true);
}
@@ -221,8 +228,19 @@ void TabRestoreService::RestoreEntryById(Browser* browser,
browser->ReplaceRestoredTab(tab->navigations,
tab->current_navigation_index);
} else {
- browser->AddRestoredTab(tab->navigations, browser->tab_count(),
- tab->current_navigation_index, true);
+ // Use the tab's former browser and index, if available.
+ Browser* tab_browser = NULL;
+ int tab_index = -1;
+ if (tab->has_browser())
+ tab_browser = BrowserList::FindBrowserWithID(tab->browser_id);
+ if (tab_browser)
+ tab_index = tab->tabstrip_index;
+ else
+ tab_browser = browser;
+ if (tab_index < 0 || tab_index > browser->tab_count())
+ tab_index = browser->tab_count();
+ tab_browser->AddRestoredTab(tab->navigations, tab_index,
+ tab->current_navigation_index, true);
}
} else if (entry->type == WINDOW) {
const Window* window = static_cast<Window*>(entry);
diff --git a/chrome/browser/sessions/tab_restore_service.h b/chrome/browser/sessions/tab_restore_service.h
index b768385..c728652 100644
--- a/chrome/browser/sessions/tab_restore_service.h
+++ b/chrome/browser/sessions/tab_restore_service.h
@@ -63,13 +63,26 @@ class TabRestoreService : public BaseSessionService {
// Represents a previously open tab.
struct Tab : public Entry {
- Tab() : Entry(TAB), current_navigation_index(-1) {}
+ Tab()
+ : Entry(TAB),
+ current_navigation_index(-1),
+ browser_id(0),
+ tabstrip_index(-1) {}
+
+ bool has_browser() const { return browser_id > 0; }
// The navigations.
std::vector<TabNavigation> navigations;
// Index of the selected navigation in navigations.
int current_navigation_index;
+
+ // The ID of the browser to which this tab belonged, so it can be restored
+ // there. May be 0 (an invalid SessionID) when restoring an entire session.
+ SessionID::id_type browser_id;
+
+ // Index within the tab strip. May be -1 for an unknown index.
+ int tabstrip_index;
};
// Represents a previously open window.
diff --git a/chrome/browser/tab_restore_uitest.cc b/chrome/browser/tab_restore_uitest.cc
index 6a16c9b..109c768 100644
--- a/chrome/browser/tab_restore_uitest.cc
+++ b/chrome/browser/tab_restore_uitest.cc
@@ -12,6 +12,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "googleurl/src/gurl.h"
#include "net/base/net_util.h"
@@ -49,6 +50,17 @@ class TabRestoreUITest : public UITest {
action_max_timeout_ms()));
}
+ // Ensure that the given browser occupies the currently active window.
+ void CheckActiveWindow(const BrowserProxy* browser) {
+ // The EXPECT_TRUE may fail during manual debugging, as well as if a user
+ // does other things while running the tests, because Chromium won't be
+ // the foremost application at all.
+ bool is_active = false;
+ scoped_ptr<WindowProxy> window_proxy(browser->GetWindow());
+ ASSERT_TRUE(window_proxy->IsActive(&is_active));
+ EXPECT_TRUE(is_active);
+ }
+
GURL url1_;
GURL url2_;
@@ -56,36 +68,144 @@ class TabRestoreUITest : public UITest {
DISALLOW_EVIL_CONSTRUCTORS(TabRestoreUITest);
};
+// Close the end tab in the current window, then restore it. The tab should be
+// in its original position, and active.
TEST_F(TabRestoreUITest, Basic) {
scoped_ptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
int tab_count;
ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ int starting_tab_count = tab_count;
// Add a tab
browser_proxy->AppendTab(url1_);
ASSERT_TRUE(browser_proxy->WaitForTabCountToBecome(tab_count + 1,
action_max_timeout_ms()));
ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
- scoped_ptr<TabProxy> new_tab(browser_proxy->GetTab(tab_count - 1));
+ ASSERT_EQ(starting_tab_count + 1, tab_count);
+
+ int closed_tab_index = tab_count - 1;
+ scoped_ptr<TabProxy> new_tab(browser_proxy->GetTab(closed_tab_index));
// Make sure we're at url.
new_tab->NavigateToURL(url1_);
// Close the tab.
new_tab->Close(true);
new_tab.reset();
+ ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ ASSERT_EQ(starting_tab_count, tab_count);
RestoreTab();
- // And make sure the URL matches.
+ // And make sure everything looks right.
+ ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ ASSERT_EQ(starting_tab_count + 1, tab_count);
+ ASSERT_EQ(closed_tab_index, GetActiveTabIndex());
ASSERT_EQ(url1_, GetActiveTabURL());
}
+// Close a tab not at the end of the current window, then restore it. The tab
+// should be in its original position, and active.
+TEST_F(TabRestoreUITest, MiddleTab) {
+ scoped_ptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
+
+ int tab_count;
+ ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ int starting_tab_count = tab_count;
+
+ // Add a couple of tabs
+ browser_proxy->AppendTab(url1_);
+ ASSERT_TRUE(browser_proxy->WaitForTabCountToBecome(tab_count + 1,
+ action_max_timeout_ms()));
+ browser_proxy->AppendTab(url1_);
+ ASSERT_TRUE(browser_proxy->WaitForTabCountToBecome(tab_count + 2,
+ action_max_timeout_ms()));
+ browser_proxy->AppendTab(url1_);
+ ASSERT_TRUE(browser_proxy->WaitForTabCountToBecome(tab_count + 3,
+ action_max_timeout_ms()));
+ ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ ASSERT_EQ(starting_tab_count + 3, tab_count);
+
+ // Close one in the middle
+ int closed_tab_index = starting_tab_count + 1;
+ scoped_ptr<TabProxy> new_tab(browser_proxy->GetTab(closed_tab_index));
+ // Make sure we're at url.
+ new_tab->NavigateToURL(url1_);
+ // Close the tab.
+ new_tab->Close(true);
+ new_tab.reset();
+ ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ ASSERT_EQ(starting_tab_count + 2, tab_count);
+
+ RestoreTab();
+
+ // And make sure everything looks right.
+ ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ ASSERT_EQ(starting_tab_count + 3, tab_count);
+ ASSERT_EQ(closed_tab_index, GetActiveTabIndex());
+ ASSERT_EQ(url1_, GetActiveTabURL());
+}
+
+// Close a tab, switch windows, then restore the tab. The tab should be in its
+// original window and position, and active.
TEST_F(TabRestoreUITest, RestoreToDifferentWindow) {
+ scoped_ptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
+
+ CheckActiveWindow(browser_proxy.get());
+
+ int tab_count;
+ ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ int starting_tab_count = tab_count;
+
+ // Add a couple of tabs
+ browser_proxy->AppendTab(url1_);
+ ASSERT_TRUE(browser_proxy->WaitForTabCountToBecome(tab_count + 1,
+ action_max_timeout_ms()));
+ browser_proxy->AppendTab(url1_);
+ ASSERT_TRUE(browser_proxy->WaitForTabCountToBecome(tab_count + 2,
+ action_max_timeout_ms()));
+ browser_proxy->AppendTab(url1_);
+ ASSERT_TRUE(browser_proxy->WaitForTabCountToBecome(tab_count + 3,
+ action_max_timeout_ms()));
+ ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ ASSERT_EQ(starting_tab_count + 3, tab_count);
+
+ // Close one in the middle
+ int closed_tab_index = starting_tab_count + 1;
+ scoped_ptr<TabProxy> new_tab(browser_proxy->GetTab(closed_tab_index));
+ // Make sure we're at url.
+ new_tab->NavigateToURL(url1_);
+ // Close the tab.
+ new_tab->Close(true);
+ new_tab.reset();
+ ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ ASSERT_EQ(starting_tab_count + 2, tab_count);
+
+ // Create a new browser.
+ ASSERT_TRUE(automation()->OpenNewBrowserWindow(false));
+ ASSERT_TRUE(automation()->WaitForWindowCountToBecome(
+ 2, action_max_timeout_ms()));
+
+ CheckActiveWindow(automation()->GetBrowserWindow(1));
+
+ RestoreTab();
+
+ // And make sure everything looks right.
+ CheckActiveWindow(browser_proxy.get());
+ ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
+ EXPECT_EQ(starting_tab_count + 3, tab_count);
+ ASSERT_EQ(closed_tab_index, GetActiveTabIndex());
+ ASSERT_EQ(url1_, GetActiveTabURL());
+}
+
+// Close a tab, open a new window, close the first window, then restore the
+// tab. It should be at the end of the current (new) window's tabstrip.
+TEST_F(TabRestoreUITest, RestoreFromClosedWindow) {
// This test is disabled on win2k. See bug 1215881.
if (win_util::GetWinVersion() == win_util::WINVERSION_2000)
return;
scoped_ptr<BrowserProxy> browser_proxy(automation()->GetBrowserWindow(0));
+ CheckActiveWindow(browser_proxy.get());
int tab_count;
ASSERT_TRUE(browser_proxy->GetTabCount(&tab_count));
@@ -106,6 +226,7 @@ TEST_F(TabRestoreUITest, RestoreToDifferentWindow) {
ASSERT_TRUE(automation()->OpenNewBrowserWindow(false));
ASSERT_TRUE(automation()->WaitForWindowCountToBecome(
2, action_max_timeout_ms()));
+ CheckActiveWindow(automation()->GetBrowserWindow(1));
// Close the first browser.
EXPECT_TRUE(tab_proxy->Close(true));
@@ -118,7 +239,9 @@ TEST_F(TabRestoreUITest, RestoreToDifferentWindow) {
RestoreTab();
+ // Tab should be at the end of the current (only) window.
browser_proxy.reset(automation()->GetBrowserWindow(0));
+ CheckActiveWindow(browser_proxy.get());
tab_proxy.reset(browser_proxy->GetActiveTab());
// And make sure the URLs matches.
ASSERT_EQ(url2_, GetActiveTabURL());