| Index: chrome/browser/tab_restore_service.cc
|
| ===================================================================
|
| --- chrome/browser/tab_restore_service.cc (revision 5928)
|
| +++ chrome/browser/tab_restore_service.cc (working copy)
|
| @@ -4,40 +4,37 @@
|
|
|
| #include "chrome/browser/tab_restore_service.h"
|
|
|
| -#include "chrome/browser/profile.h"
|
| +#include "chrome/browser/browser_list.h"
|
| #include "chrome/browser/navigation_controller.h"
|
| #include "chrome/browser/navigation_entry.h"
|
| +#include "chrome/browser/profile.h"
|
| +#include "chrome/common/stl_util-inl.h"
|
|
|
| using base::Time;
|
|
|
| -// HistoricalTab --------------------------------------------------------------
|
| +// Entry ----------------------------------------------------------------------
|
|
|
| -// ID of the next HistoricalTab.
|
| -static int next_historical_tab_id = 1;
|
| +// ID of the next Entry.
|
| +static int next_entry_id = 1;
|
|
|
| -TabRestoreService::HistoricalTab::HistoricalTab()
|
| - : close_time(Time::Now()),
|
| - from_last_session(false),
|
| - current_navigation_index(-1),
|
| - id(next_historical_tab_id++) {
|
| -}
|
| +TabRestoreService::Entry::Entry() : id(next_entry_id++), type(TAB) {}
|
|
|
| +TabRestoreService::Entry::Entry(Type type) : id(next_entry_id++), type(type) {}
|
| +
|
| // TabRestoreService ----------------------------------------------------------
|
|
|
| -// Max number of tabs we'll keep around.
|
| -static const size_t kMaxTabs = 10;
|
| +// Max number of entries we'll keep around.
|
| +static const size_t kMaxEntries = 10;
|
|
|
| -// Amount of time from when the session starts and when we'll allow loading of
|
| -// the last sessions tabs.
|
| -static const int kLoadFromLastSessionMS = 600000;
|
| -
|
| TabRestoreService::TabRestoreService(Profile* profile)
|
| : profile_(profile),
|
| - loaded_last_session_(false) {
|
| + loaded_last_session_(false),
|
| + restoring_(false) {
|
| }
|
|
|
| TabRestoreService::~TabRestoreService() {
|
| FOR_EACH_OBSERVER(Observer, observer_list_, TabRestoreServiceDestroyed(this));
|
| + STLDeleteElements(&entries_);
|
| }
|
|
|
| void TabRestoreService::AddObserver(Observer* observer) {
|
| @@ -48,107 +45,112 @@
|
| observer_list_.RemoveObserver(observer);
|
| }
|
|
|
| -void TabRestoreService::LoadPreviousSessionTabs() {
|
| - if (!WillLoadPreviousSessionTabs() || IsLoadingPreviousSessionTabs())
|
| +void TabRestoreService::CreateHistoricalTab(NavigationController* tab) {
|
| + if (restoring_)
|
| return;
|
|
|
| - profile_->GetSessionService()->GetLastSession(
|
| - &cancelable_consumer_,
|
| - NewCallback(this, &TabRestoreService::OnGotLastSession));
|
| -}
|
| + Browser* browser = Browser::GetBrowserForController(tab, NULL);
|
| + if (closing_browsers_.find(browser) != closing_browsers_.end())
|
| + return;
|
|
|
| -bool TabRestoreService::IsLoadingPreviousSessionTabs() {
|
| - return cancelable_consumer_.HasPendingRequests();
|
| -}
|
| + Tab* local_tab = new Tab();
|
| + PopulateTabFromController(tab, local_tab);
|
| + entries_.push_front(local_tab);
|
|
|
| -bool TabRestoreService::WillLoadPreviousSessionTabs() {
|
| - return (!loaded_last_session_ && tabs_.size() < kMaxTabs &&
|
| - (Time::Now() - profile_->GetStartTime()).InMilliseconds() <
|
| - kLoadFromLastSessionMS);
|
| + PruneAndNotify();
|
| }
|
|
|
| -void TabRestoreService::CreateHistoricalTab(NavigationController* tab) {
|
| - tabs_.push_front(HistoricalTab());
|
| +void TabRestoreService::BrowserClosing(Browser* browser) {
|
| + if (browser->type() != Browser::TYPE_NORMAL ||
|
| + browser->tab_count() == 0)
|
| + return;
|
|
|
| - PopulateTabFromController(tab, &(tabs_.front()));
|
| + closing_browsers_.insert(browser);
|
|
|
| - while (tabs_.size() > kMaxTabs)
|
| - tabs_.pop_back();
|
| -
|
| - NotifyTabsChanged();
|
| + Window* window = new Window();
|
| + window->selected_tab_index = browser->selected_index();
|
| + window->tabs.resize(browser->tab_count());
|
| + size_t entry_index = 0;
|
| + for (int tab_index = 0; tab_index < browser->tab_count(); ++tab_index) {
|
| + PopulateTabFromController(
|
| + browser->GetTabContentsAt(tab_index)->controller(),
|
| + &(window->tabs[entry_index]));
|
| + if (window->tabs[entry_index].navigations.empty())
|
| + window->tabs.erase(window->tabs.begin() + entry_index);
|
| + else
|
| + entry_index++;
|
| + }
|
| + if (window->tabs.empty()) {
|
| + delete window;
|
| + window = NULL;
|
| + } else {
|
| + entries_.push_front(window);
|
| + PruneAndNotify();
|
| + }
|
| }
|
|
|
| -void TabRestoreService::RemoveHistoricalTabById(int id) {
|
| - for (Tabs::iterator i = tabs_.begin(); i != tabs_.end(); ++i) {
|
| - if (i->id == id) {
|
| - tabs_.erase(i);
|
| - NotifyTabsChanged();
|
| - return;
|
| - }
|
| - }
|
| - // Don't hoark here, we allow an invalid id.
|
| +void TabRestoreService::BrowserClosed(Browser* browser) {
|
| + closing_browsers_.erase(browser);
|
| }
|
|
|
| -void TabRestoreService::ClearHistoricalTabs() {
|
| - tabs_.clear();
|
| +void TabRestoreService::ClearEntries() {
|
| + STLDeleteElements(&entries_);
|
| NotifyTabsChanged();
|
| }
|
|
|
| -void TabRestoreService::OnGotLastSession(SessionService::Handle handle,
|
| - std::vector<SessionWindow*>* windows) {
|
| - DCHECK(!loaded_last_session_);
|
| - loaded_last_session_ = true;
|
| -
|
| - if (tabs_.size() == kMaxTabs)
|
| +void TabRestoreService::RestoreMostRecentEntry(Browser* browser) {
|
| + if (entries_.empty())
|
| return;
|
|
|
| - AddHistoricalTabs(windows);
|
| -
|
| - NotifyTabsChanged();
|
| + RestoreEntryById(browser, entries_.front()->id, false);
|
| }
|
|
|
| -void TabRestoreService::AddHistoricalTabs(
|
| - std::vector<SessionWindow*>* windows) {
|
| - // First pass, extract the selected tabs in each window.
|
| - for (size_t i = 0; i < windows->size(); ++i) {
|
| - SessionWindow* window = (*windows)[i];
|
| - if (window->type == Browser::TYPE_NORMAL) {
|
| - DCHECK(window->selected_tab_index >= 0 &&
|
| - window->selected_tab_index <
|
| - static_cast<int>(window->tabs.size()));
|
| - AppendHistoricalTabFromSessionTab(
|
| - window->tabs[window->selected_tab_index]);
|
| - if (tabs_.size() == kMaxTabs)
|
| - return;
|
| - }
|
| +void TabRestoreService::RestoreEntryById(Browser* browser,
|
| + int id,
|
| + bool replace_existing_tab) {
|
| + Entries::iterator i = GetEntryIteratorById(id);
|
| + if (i == entries_.end()) {
|
| + // Don't hoark here, we allow an invalid id.
|
| + return;
|
| }
|
|
|
| - // Second pass, extract the non-selected tabs.
|
| - for (size_t window_index = 0; window_index < windows->size();
|
| - ++window_index) {
|
| - SessionWindow* window = (*windows)[window_index];
|
| - if (window->type != Browser::TYPE_NORMAL)
|
| - continue; // Ignore popups.
|
| -
|
| - for (size_t tab_index = 0; tab_index < window->tabs.size(); ++tab_index) {
|
| - if (tab_index == window->selected_tab_index)
|
| - continue; // Pass one took care of this tab.
|
| - AppendHistoricalTabFromSessionTab(window->tabs[tab_index]);
|
| - if (tabs_.size() == kMaxTabs)
|
| - return;
|
| + restoring_ = true;
|
| + Entry* entry = *i;
|
| + entries_.erase(i);
|
| + i = entries_.end();
|
| + if (entry->type == TAB) {
|
| + Tab* tab = static_cast<Tab*>(entry);
|
| + if (replace_existing_tab) {
|
| + browser->ReplaceRestoredTab(tab->navigations,
|
| + tab->current_navigation_index);
|
| + } else {
|
| + browser->AddRestoredTab(tab->navigations, browser->tab_count(),
|
| + tab->current_navigation_index, true);
|
| }
|
| + } else if (entry->type == WINDOW) {
|
| + const Window* window = static_cast<Window*>(entry);
|
| + Browser* browser = Browser::Create(profile_);
|
| + for (size_t tab_i = 0; tab_i < window->tabs.size(); ++tab_i) {
|
| + const Tab& tab = window->tabs[tab_i];
|
| + NavigationController* restored_controller =
|
| + browser->AddRestoredTab(tab.navigations, browser->tab_count(),
|
| + tab.current_navigation_index,
|
| + (tab_i == window->selected_tab_index));
|
| + if (restored_controller)
|
| + restored_controller->LoadIfNecessary();
|
| + }
|
| + browser->window()->Show();
|
| + } else {
|
| + NOTREACHED();
|
| }
|
| + delete entry;
|
| + restoring_ = false;
|
| + NotifyTabsChanged();
|
| }
|
|
|
| -void TabRestoreService::AppendHistoricalTabFromSessionTab(
|
| - SessionTab* tab) {
|
| - tabs_.push_back(HistoricalTab());
|
| - PopulateTabFromSessionTab(tab, &(tabs_.back()));
|
| -}
|
| -
|
| void TabRestoreService::PopulateTabFromController(
|
| NavigationController* controller,
|
| - HistoricalTab* tab) {
|
| + Tab* tab) {
|
| const int pending_index = controller->GetPendingEntryIndex();
|
| int entry_count = controller->GetEntryCount();
|
| if (entry_count == 0 && pending_index == 0)
|
| @@ -171,14 +173,24 @@
|
| tab->current_navigation_index = 0;
|
| }
|
|
|
| -void TabRestoreService::PopulateTabFromSessionTab(
|
| - SessionTab* session_tab,
|
| - HistoricalTab* tab) {
|
| - tab->navigations.swap(session_tab->navigations);
|
| - tab->from_last_session = true;
|
| - tab->current_navigation_index = session_tab->current_navigation_index;
|
| -}
|
| -
|
| void TabRestoreService::NotifyTabsChanged() {
|
| FOR_EACH_OBSERVER(Observer, observer_list_, TabRestoreServiceChanged(this));
|
| }
|
| +
|
| +void TabRestoreService::PruneAndNotify() {
|
| + while (entries_.size() > kMaxEntries) {
|
| + delete entries_.back();
|
| + entries_.pop_back();
|
| + }
|
| +
|
| + NotifyTabsChanged();
|
| +}
|
| +
|
| +TabRestoreService::Entries::iterator TabRestoreService::GetEntryIteratorById(
|
| + int id) {
|
| + for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) {
|
| + if ((*i)->id == id)
|
| + return i;
|
| + }
|
| + return entries_.end();
|
| +}
|
|
|